diff options
-rw-r--r-- | dev-python/paste/Manifest | 2 | ||||
-rw-r--r-- | dev-python/paste/files/paste-1.7.5.1-email-mime.patch | 19 | ||||
-rw-r--r-- | dev-python/paste/files/paste-1.7.5.1-fix-tests-for-pypy.patch | 24 | ||||
-rw-r--r-- | dev-python/paste/files/paste-1.7.5.1-hmac.patch | 11 | ||||
-rw-r--r-- | dev-python/paste/files/paste-1.7.5.1-python27-lambda.patch | 12 | ||||
-rw-r--r-- | dev-python/paste/files/paste-1.7.5.1-rfc822.patch | 14 | ||||
-rw-r--r-- | dev-python/paste/files/paste-1.7.5.1-types.patch | 57 | ||||
-rw-r--r-- | dev-python/paste/files/paste-1.7.5.1-unbundle-stdlib.patch | 1211 | ||||
-rw-r--r-- | dev-python/paste/files/paste-1.7.5.1-unbundle-tempita.patch | 1860 | ||||
-rw-r--r-- | dev-python/paste/files/paste-1.7.5.1-userdict.patch | 64 | ||||
-rw-r--r-- | dev-python/paste/files/paste-2.0.2-unbundle-tempita.patch | 36 | ||||
-rw-r--r-- | dev-python/paste/paste-1.7.5.1-r1.ebuild | 68 | ||||
-rw-r--r-- | dev-python/paste/paste-1.7.5.1-r2.ebuild | 81 | ||||
-rw-r--r-- | dev-python/paste/paste-2.0.2.ebuild | 72 |
14 files changed, 0 insertions, 3531 deletions
diff --git a/dev-python/paste/Manifest b/dev-python/paste/Manifest index 5c3ad8466e3c..1f740ff2cc66 100644 --- a/dev-python/paste/Manifest +++ b/dev-python/paste/Manifest @@ -1,3 +1 @@ -DIST Paste-1.7.5.1.tar.gz 523304 SHA256 11645842ba8ec986ae8cfbe4c6cacff5c35f0f4527abf4f5581ae8b4ad49c0b6 SHA512 058a86dec41f132c22b14f3bc882d9c02c04bb0cc9ea5fc5371911698c3d7a89859742a4b806ad388c7fe37289b816db16c50bce21f56c8371293c4d91b5ccb6 WHIRLPOOL 5928a6f20c136a77576b653df34337f1eb110845b8d53d7637eeb6c792fe7f10fe622adefec382378aef16c1abee91c37e90e5fe17dbaa07046681a393f6c5c8 -DIST Paste-2.0.2.tar.gz 627842 SHA256 adac3ac893a2dac6b8ffd49901377dd6819e05be3436b374d698641071daba99 SHA512 32eddeab1bab9d0b1a30848d89613b40ed02a77912f7ef5a86880e1c1a860c5637cd45114bd58cc5ac84410a569ede67e6ebd7afd2007c588433d54d6940f529 WHIRLPOOL 08c997079e632b92e592211d942298235228ec22b997d549f608552f139a941cdd47a5c2da859867c279cab0ad7f388823f1af163ed7ea8aeaaa7558407e3750 DIST Paste-2.0.3.tar.gz 643935 SHA256 2346a347824c32641bf020c17967b49ae74d3310ec1bc9b958d4b84e2d985218 SHA512 174b06d77bc6e1d4079e8de7df40412ffda098364efd4e3f915f858be1188c8a6fb546fe4ab981ccc067ec77b7171083b2469e7db6fc3b777d5a24151c928362 WHIRLPOOL 0aa15c2c6ffdbf965f3763d296e28c75337d9e582ad8623d70a9a4df572457247d583682b7ecddc5206b1a997f22e4f46f68b013a1ca646b0d6d08559ac1447e diff --git a/dev-python/paste/files/paste-1.7.5.1-email-mime.patch b/dev-python/paste/files/paste-1.7.5.1-email-mime.patch deleted file mode 100644 index 4c06997b0809..000000000000 --- a/dev-python/paste/files/paste-1.7.5.1-email-mime.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- a/paste/exceptions/reporter.py -+++ b/paste/exceptions/reporter.py -@@ -1,8 +1,14 @@ - # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) - # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php - --from email.MIMEText import MIMEText --from email.MIMEMultipart import MIMEMultipart -+try: -+ from email.MIMEText import MIMEText -+except: -+ from email.mime.text import MIMEText -+try: -+ from email.MIMEMultipart import MIMEMultipart -+except: -+ from email.mime.multipart import MIMEMultipart - import smtplib - import time - try: diff --git a/dev-python/paste/files/paste-1.7.5.1-fix-tests-for-pypy.patch b/dev-python/paste/files/paste-1.7.5.1-fix-tests-for-pypy.patch deleted file mode 100644 index b5e9430c3bb9..000000000000 --- a/dev-python/paste/files/paste-1.7.5.1-fix-tests-for-pypy.patch +++ /dev/null @@ -1,24 +0,0 @@ -Ignore the exception detail for two exceptions that are slightly -different on pypy. - -diff -r 7f90a96378ed tests/test_template.txt ---- a/tests/test_template.txt Mon Mar 05 21:14:08 2012 +0100 -+++ b/tests/test_template.txt Wed May 16 23:29:46 2012 +0200 -@@ -6,7 +6,7 @@ - 'Hi Ian' - >>> Template('Hi {{repr(name)}}').substitute(name='Ian') - "Hi 'Ian'" -- >>> Template('Hi {{name+1}}').substitute(name='Ian') -+ >>> Template('Hi {{name+1}}').substitute(name='Ian') #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - TypeError: cannot concatenate 'str' and 'int' objects at line 1 column 6 -@@ -125,7 +125,7 @@ - >>> sub('{{default x=1}}{{x}}') - '1' - >>> # The normal case: -- >>> sub('{{x}}') -+ >>> sub('{{x}}') #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - NameError: name 'x' is not defined at line 1 column 3 diff --git a/dev-python/paste/files/paste-1.7.5.1-hmac.patch b/dev-python/paste/files/paste-1.7.5.1-hmac.patch deleted file mode 100644 index c86d0f977cfe..000000000000 --- a/dev-python/paste/files/paste-1.7.5.1-hmac.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/paste/auth/cookie.py -+++ b/paste/auth/cookie.py -@@ -52,7 +52,7 @@ - - def make_time(value): - return time.strftime("%Y%m%d%H%M", time.gmtime(value)) --_signature_size = len(hmac.new('x', 'x', sha1).digest()) -+_signature_size = len(hmac.new(b'x', b'x', sha1).digest()) - _header_size = _signature_size + len(make_time(time.time())) - - # @@: Should this be using urllib.quote? diff --git a/dev-python/paste/files/paste-1.7.5.1-python27-lambda.patch b/dev-python/paste/files/paste-1.7.5.1-python27-lambda.patch deleted file mode 100644 index 91dcad137153..000000000000 --- a/dev-python/paste/files/paste-1.7.5.1-python27-lambda.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -r 30425672adf7 paste/auth/cookie.py ---- a/paste/auth/cookie.py Wed Jun 23 17:15:45 2010 -0500 -+++ b/paste/auth/cookie.py Mon Aug 02 20:06:43 2010 -0700 -@@ -62,7 +62,7 @@ - _decode = [(v, k) for (k, v) in _encode] - _decode.reverse() - def encode(s, sublist = _encode): -- return reduce((lambda a, (b, c): a.replace(b, c)), sublist, str(s)) -+ return reduce((lambda a, b: a.replace(b[0], b[1])), sublist, str(s)) - decode = lambda s: encode(s, _decode) - - class CookieTooLarge(RuntimeError): diff --git a/dev-python/paste/files/paste-1.7.5.1-rfc822.patch b/dev-python/paste/files/paste-1.7.5.1-rfc822.patch deleted file mode 100644 index e0950fcaabef..000000000000 --- a/dev-python/paste/files/paste-1.7.5.1-rfc822.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- a/paste/httpheaders.py -+++ b/paste/httpheaders.py -@@ -137,7 +137,10 @@ - import mimetypes - import urllib2 - import re --from rfc822 import formatdate, parsedate_tz, mktime_tz -+try: -+ from rfc822 import formatdate, parsedate_tz, mktime_tz -+except ImportError: -+ from email.utils import formatdate, parsedate_tz, mktime_tz - from time import time as now - from httpexceptions import HTTPBadRequest - diff --git a/dev-python/paste/files/paste-1.7.5.1-types.patch b/dev-python/paste/files/paste-1.7.5.1-types.patch deleted file mode 100644 index 87ea53c39648..000000000000 --- a/dev-python/paste/files/paste-1.7.5.1-types.patch +++ /dev/null @@ -1,57 +0,0 @@ ---- a/paste/lint.py -+++ b/paste/lint.py -@@ -111,7 +111,6 @@ - - import re - import sys --from types import DictType, StringType, TupleType, ListType - import warnings - - header_re = re.compile(r'^[a-zA-Z][a-zA-Z0-9\-_]*$') -@@ -282,7 +281,7 @@ - "Iterator garbage collected without being closed") - - def check_environ(environ): -- assert type(environ) is DictType, ( -+ assert isinstance(environ,dict), ( - "Environment is not of the right type: %r (environment: %r)" - % (type(environ), environ)) - -@@ -309,11 +308,11 @@ - if '.' in key: - # Extension, we don't care about its type - continue -- assert type(environ[key]) is StringType, ( -+ assert isinstance(environ[key], str), ( - "Environmental variable %s is not a string: %r (value: %r)" - % (key, type(environ[key]), environ[key])) - -- assert type(environ['wsgi.version']) is TupleType, ( -+ assert isinstance(environ['wsgi.version'], tuple), ( - "wsgi.version should be a tuple (%r)" % environ['wsgi.version']) - assert environ['wsgi.url_scheme'] in ('http', 'https'), ( - "wsgi.url_scheme unknown: %r" % environ['wsgi.url_scheme']) -@@ -359,7 +358,7 @@ - % (wsgi_errors, attr)) - - def check_status(status): -- assert type(status) is StringType, ( -+ assert isinstance(status, str), ( - "Status must be a string (not %r)" % status) - # Implicitly check that we can turn it into an integer: - status_code = status.split(None, 1)[0] -@@ -374,12 +373,12 @@ - % status, WSGIWarning) - - def check_headers(headers): -- assert type(headers) is ListType, ( -+ assert isinstance(headers,list), ( - "Headers (%r) must be of type list: %r" - % (headers, type(headers))) - header_names = {} - for item in headers: -- assert type(item) is TupleType, ( -+ assert isinstance(item, tuple), ( - "Individual headers (%r) must be of type tuple: %r" - % (item, type(item))) - assert len(item) == 2 diff --git a/dev-python/paste/files/paste-1.7.5.1-unbundle-stdlib.patch b/dev-python/paste/files/paste-1.7.5.1-unbundle-stdlib.patch deleted file mode 100644 index b389df2482c7..000000000000 --- a/dev-python/paste/files/paste-1.7.5.1-unbundle-stdlib.patch +++ /dev/null @@ -1,1211 +0,0 @@ ---- a/paste/debug/fsdiff.py -+++ b/paste/debug/fsdiff.py -@@ -12,7 +12,10 @@ - import os - from fnmatch import fnmatch - from datetime import datetime --from paste.util.UserDict24 import IterableUserDict -+try: -+ from UserDict import IterableUserDict -+except ImportError: -+ from paste.util.UserDict24 import IterableUserDict - import operator - import re - ---- a/paste/debug/doctest_webapp.py -+++ b/paste/debug/doctest_webapp.py -@@ -8,10 +8,7 @@ - These are functions for use when doctest-testing a document. - """ - --try: -- import subprocess --except ImportError: -- from paste.util import subprocess24 as subprocess -+import subprocess - import doctest - import os - import sys ---- a/paste/debug/wdg_validate.py -+++ b/paste/debug/wdg_validate.py -@@ -6,10 +6,7 @@ - """ - - from cStringIO import StringIO --try: -- import subprocess --except ImportError: -- from paste.util import subprocess24 as subprocess -+import subprocess - from paste.response import header_value - import re - import cgi ---- a/paste/fixture.py -+++ b/paste/fixture.py -@@ -26,10 +26,7 @@ - except ImportError: - from StringIO import StringIO - import re --try: -- import subprocess --except ImportError: -- from paste.util import subprocess24 as subprocess -+import subprocess - - from paste import wsgilib - from paste import lint ---- a/paste/util/subprocess24.py -+++ /dev/null -@@ -1,1152 +0,0 @@ --# subprocess - Subprocesses with accessible I/O streams --# --# For more information about this module, see PEP 324. --# --# This module should remain compatible with Python 2.2, see PEP 291. --# --# Copyright (c) 2003-2005 by Peter Astrand <astrand@lysator.liu.se> --# --# Licensed to PSF under a Contributor Agreement. --# See http://www.python.org/2.4/license for licensing details. -- --r"""subprocess - Subprocesses with accessible I/O streams -- --This module allows you to spawn processes, connect to their --input/output/error pipes, and obtain their return codes. This module --intends to replace several other, older modules and functions, like: -- --os.system --os.spawn* --os.popen* --popen2.* --commands.* -- --Information about how the subprocess module can be used to replace these --modules and functions can be found below. -- -- -- --Using the subprocess module --=========================== --This module defines one class called Popen: -- --class Popen(args, bufsize=0, executable=None, -- stdin=None, stdout=None, stderr=None, -- preexec_fn=None, close_fds=False, shell=False, -- cwd=None, env=None, universal_newlines=False, -- startupinfo=None, creationflags=0): -- -- --Arguments are: -- --args should be a string, or a sequence of program arguments. The --program to execute is normally the first item in the args sequence or --string, but can be explicitly set by using the executable argument. -- --On UNIX, with shell=False (default): In this case, the Popen class --uses os.execvp() to execute the child program. args should normally --be a sequence. A string will be treated as a sequence with the string --as the only item (the program to execute). -- --On UNIX, with shell=True: If args is a string, it specifies the --command string to execute through the shell. If args is a sequence, --the first item specifies the command string, and any additional items --will be treated as additional shell arguments. -- --On Windows: the Popen class uses CreateProcess() to execute the child --program, which operates on strings. If args is a sequence, it will be --converted to a string using the list2cmdline method. Please note that --not all MS Windows applications interpret the command line the same --way: The list2cmdline is designed for applications using the same --rules as the MS C runtime. -- --bufsize, if given, has the same meaning as the corresponding argument --to the built-in open() function: 0 means unbuffered, 1 means line --buffered, any other positive value means use a buffer of --(approximately) that size. A negative bufsize means to use the system --default, which usually means fully buffered. The default value for --bufsize is 0 (unbuffered). -- --stdin, stdout and stderr specify the executed programs' standard --input, standard output and standard error file handles, respectively. --Valid values are PIPE, an existing file descriptor (a positive --integer), an existing file object, and None. PIPE indicates that a --new pipe to the child should be created. With None, no redirection --will occur; the child's file handles will be inherited from the --parent. Additionally, stderr can be STDOUT, which indicates that the --stderr data from the applications should be captured into the same --file handle as for stdout. -- --If preexec_fn is set to a callable object, this object will be called --in the child process just before the child is executed. -- --If close_fds is true, all file descriptors except 0, 1 and 2 will be --closed before the child process is executed. -- --if shell is true, the specified command will be executed through the --shell. -- --If cwd is not None, the current directory will be changed to cwd --before the child is executed. -- --If env is not None, it defines the environment variables for the new --process. -- --If universal_newlines is true, the file objects stdout and stderr are --opened as a text files, but lines may be terminated by any of '\n', --the Unix end-of-line convention, '\r', the Macintosh convention or --'\r\n', the Windows convention. All of these external representations --are seen as '\n' by the Python program. Note: This feature is only --available if Python is built with universal newline support (the --default). Also, the newlines attribute of the file objects stdout, --stdin and stderr are not updated by the communicate() method. -- --The startupinfo and creationflags, if given, will be passed to the --underlying CreateProcess() function. They can specify things such as --appearance of the main window and priority for the new process. --(Windows only) -- -- --This module also defines two shortcut functions: -- --call(*args, **kwargs): -- Run command with arguments. Wait for command to complete, then -- return the returncode attribute. The arguments are the same as for -- the Popen constructor. Example: -- -- retcode = call(["ls", "-l"]) -- -- --Exceptions ------------ --Exceptions raised in the child process, before the new program has --started to execute, will be re-raised in the parent. Additionally, --the exception object will have one extra attribute called --'child_traceback', which is a string containing traceback information --from the childs point of view. -- --The most common exception raised is OSError. This occurs, for --example, when trying to execute a non-existent file. Applications --should prepare for OSErrors. -- --A ValueError will be raised if Popen is called with invalid arguments. -- -- --Security ---------- --Unlike some other popen functions, this implementation will never call --/bin/sh implicitly. This means that all characters, including shell --metacharacters, can safely be passed to child processes. -- -- --Popen objects --============= --Instances of the Popen class have the following methods: -- --poll() -- Check if child process has terminated. Returns returncode -- attribute. -- --wait() -- Wait for child process to terminate. Returns returncode attribute. -- --communicate(input=None) -- Interact with process: Send data to stdin. Read data from stdout -- and stderr, until end-of-file is reached. Wait for process to -- terminate. The optional stdin argument should be a string to be -- sent to the child process, or None, if no data should be sent to -- the child. -- -- communicate() returns a tuple (stdout, stderr). -- -- Note: The data read is buffered in memory, so do not use this -- method if the data size is large or unlimited. -- --The following attributes are also available: -- --stdin -- If the stdin argument is PIPE, this attribute is a file object -- that provides input to the child process. Otherwise, it is None. -- --stdout -- If the stdout argument is PIPE, this attribute is a file object -- that provides output from the child process. Otherwise, it is -- None. -- --stderr -- If the stderr argument is PIPE, this attribute is file object that -- provides error output from the child process. Otherwise, it is -- None. -- --pid -- The process ID of the child process. -- --returncode -- The child return code. A None value indicates that the process -- hasn't terminated yet. A negative value -N indicates that the -- child was terminated by signal N (UNIX only). -- -- --Replacing older functions with the subprocess module --==================================================== --In this section, "a ==> b" means that b can be used as a replacement --for a. -- --Note: All functions in this section fail (more or less) silently if --the executed program cannot be found; this module raises an OSError --exception. -- --In the following examples, we assume that the subprocess module is --imported with "from subprocess import *". -- -- --Replacing /bin/sh shell backquote ----------------------------------- --output=`mycmd myarg` --==> --output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0] -- -- --Replacing shell pipe line --------------------------- --output=`dmesg | grep hda` --==> --p1 = Popen(["dmesg"], stdout=PIPE) --p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) --output = p2.communicate()[0] -- -- --Replacing os.system() ----------------------- --sts = os.system("mycmd" + " myarg") --==> --p = Popen("mycmd" + " myarg", shell=True) --sts = os.waitpid(p.pid, 0) -- --Note: -- --* Calling the program through the shell is usually not required. -- --* It's easier to look at the returncode attribute than the -- exitstatus. -- --A more real-world example would look like this: -- --try: -- retcode = call("mycmd" + " myarg", shell=True) -- if retcode < 0: -- print >>sys.stderr, "Child was terminated by signal", -retcode -- else: -- print >>sys.stderr, "Child returned", retcode --except OSError, e: -- print >>sys.stderr, "Execution failed:", e -- -- --Replacing os.spawn* --------------------- --P_NOWAIT example: -- --pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg") --==> --pid = Popen(["/bin/mycmd", "myarg"]).pid -- -- --P_WAIT example: -- --retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg") --==> --retcode = call(["/bin/mycmd", "myarg"]) -- -- --Vector example: -- --os.spawnvp(os.P_NOWAIT, path, args) --==> --Popen([path] + args[1:]) -- -- --Environment example: -- --os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env) --==> --Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"}) -- -- --Replacing os.popen* --------------------- --pipe = os.popen(cmd, mode='r', bufsize) --==> --pipe = Popen(cmd, shell=True, bufsize=bufsize, stdout=PIPE).stdout -- --pipe = os.popen(cmd, mode='w', bufsize) --==> --pipe = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE).stdin -- -- --(child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize) --==> --p = Popen(cmd, shell=True, bufsize=bufsize, -- stdin=PIPE, stdout=PIPE, close_fds=True) --(child_stdin, child_stdout) = (p.stdin, p.stdout) -- -- --(child_stdin, -- child_stdout, -- child_stderr) = os.popen3(cmd, mode, bufsize) --==> --p = Popen(cmd, shell=True, bufsize=bufsize, -- stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) --(child_stdin, -- child_stdout, -- child_stderr) = (p.stdin, p.stdout, p.stderr) -- -- --(child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize) --==> --p = Popen(cmd, shell=True, bufsize=bufsize, -- stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True) --(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout) -- -- --Replacing popen2.* -------------------- --Note: If the cmd argument to popen2 functions is a string, the command --is executed through /bin/sh. If it is a list, the command is directly --executed. -- --(child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode) --==> --p = Popen(["somestring"], shell=True, bufsize=bufsize -- stdin=PIPE, stdout=PIPE, close_fds=True) --(child_stdout, child_stdin) = (p.stdout, p.stdin) -- -- --(child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode) --==> --p = Popen(["mycmd", "myarg"], bufsize=bufsize, -- stdin=PIPE, stdout=PIPE, close_fds=True) --(child_stdout, child_stdin) = (p.stdout, p.stdin) -- --The popen2.Popen3 and popen3.Popen4 basically works as subprocess.Popen, --except that: -- --* subprocess.Popen raises an exception if the execution fails --* the capturestderr argument is replaced with the stderr argument. --* stdin=PIPE and stdout=PIPE must be specified. --* popen2 closes all filedescriptors by default, but you have to specify -- close_fds=True with subprocess.Popen. -- -- --""" -- --import sys --mswindows = (sys.platform == "win32") -- --import os --import types --import traceback -- --if mswindows: -- import threading -- import msvcrt -- ## @@: Changed in Paste -- ## Since this module is only used on pre-python-2.4 systems, they probably -- ## don't have _subprocess installed, but hopefully have the win32 stuff -- ## installed. -- if 1: # <-- change this to use pywin32 instead of the _subprocess driver -- import pywintypes -- from win32api import GetStdHandle, STD_INPUT_HANDLE, \ -- STD_OUTPUT_HANDLE, STD_ERROR_HANDLE -- from win32api import GetCurrentProcess, DuplicateHandle, \ -- GetModuleFileName, GetVersion -- from win32con import DUPLICATE_SAME_ACCESS, SW_HIDE -- from win32pipe import CreatePipe -- from win32process import CreateProcess, STARTUPINFO, \ -- GetExitCodeProcess, STARTF_USESTDHANDLES, \ -- STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE -- from win32event import WaitForSingleObject, INFINITE, WAIT_OBJECT_0 -- else: -- from _subprocess import * -- class STARTUPINFO: -- dwFlags = 0 -- hStdInput = None -- hStdOutput = None -- hStdError = None -- class pywintypes: -- error = IOError --else: -- import select -- import errno -- import fcntl -- import pickle -- --__all__ = ["Popen", "PIPE", "STDOUT", "call"] -- --try: -- MAXFD = os.sysconf("SC_OPEN_MAX") --except: -- MAXFD = 256 -- --# True/False does not exist on 2.2.0 --try: -- False --except NameError: -- False = 0 -- True = 1 -- --_active = [] -- --def _cleanup(): -- for inst in _active[:]: -- inst.poll() -- --PIPE = -1 --STDOUT = -2 -- -- --def call(*args, **kwargs): -- """Run command with arguments. Wait for command to complete, then -- return the returncode attribute. -- -- The arguments are the same as for the Popen constructor. Example: -- -- retcode = call(["ls", "-l"]) -- """ -- return Popen(*args, **kwargs).wait() -- -- --def list2cmdline(seq): -- """ -- Translate a sequence of arguments into a command line -- string, using the same rules as the MS C runtime: -- -- 1) Arguments are delimited by white space, which is either a -- space or a tab. -- -- 2) A string surrounded by double quotation marks is -- interpreted as a single argument, regardless of white space -- contained within. A quoted string can be embedded in an -- argument. -- -- 3) A double quotation mark preceded by a backslash is -- interpreted as a literal double quotation mark. -- -- 4) Backslashes are interpreted literally, unless they -- immediately precede a double quotation mark. -- -- 5) If backslashes immediately precede a double quotation mark, -- every pair of backslashes is interpreted as a literal -- backslash. If the number of backslashes is odd, the last -- backslash escapes the next double quotation mark as -- described in rule 3. -- """ -- -- # See -- # http://msdn.microsoft.com/library/en-us/vccelng/htm/progs_12.asp -- result = [] -- needquote = False -- for arg in seq: -- bs_buf = [] -- -- # Add a space to separate this argument from the others -- if result: -- result.append(' ') -- -- needquote = (" " in arg) or ("\t" in arg) -- if needquote: -- result.append('"') -- -- for c in arg: -- if c == '\\': -- # Don't know if we need to double yet. -- bs_buf.append(c) -- elif c == '"': -- # Double backspaces. -- result.append('\\' * len(bs_buf)*2) -- bs_buf = [] -- result.append('\\"') -- else: -- # Normal char -- if bs_buf: -- result.extend(bs_buf) -- bs_buf = [] -- result.append(c) -- -- # Add remaining backspaces, if any. -- if bs_buf: -- result.extend(bs_buf) -- -- if needquote: -- result.extend(bs_buf) -- result.append('"') -- -- return ''.join(result) -- -- --class Popen(object): -- def __init__(self, args, bufsize=0, executable=None, -- stdin=None, stdout=None, stderr=None, -- preexec_fn=None, close_fds=False, shell=False, -- cwd=None, env=None, universal_newlines=False, -- startupinfo=None, creationflags=0): -- """Create new Popen instance.""" -- _cleanup() -- -- if not isinstance(bufsize, (int, long)): -- raise TypeError("bufsize must be an integer") -- -- if mswindows: -- if preexec_fn is not None: -- raise ValueError("preexec_fn is not supported on Windows " -- "platforms") -- if close_fds: -- raise ValueError("close_fds is not supported on Windows " -- "platforms") -- else: -- # POSIX -- if startupinfo is not None: -- raise ValueError("startupinfo is only supported on Windows " -- "platforms") -- if creationflags != 0: -- raise ValueError("creationflags is only supported on Windows " -- "platforms") -- -- self.stdin = None -- self.stdout = None -- self.stderr = None -- self.pid = None -- self.returncode = None -- self.universal_newlines = universal_newlines -- -- # Input and output objects. The general principle is like -- # this: -- # -- # Parent Child -- # ------ ----- -- # p2cwrite ---stdin---> p2cread -- # c2pread <--stdout--- c2pwrite -- # errread <--stderr--- errwrite -- # -- # On POSIX, the child objects are file descriptors. On -- # Windows, these are Windows file handles. The parent objects -- # are file descriptors on both platforms. The parent objects -- # are None when not using PIPEs. The child objects are None -- # when not redirecting. -- -- (p2cread, p2cwrite, -- c2pread, c2pwrite, -- errread, errwrite) = self._get_handles(stdin, stdout, stderr) -- -- self._execute_child(args, executable, preexec_fn, close_fds, -- cwd, env, universal_newlines, -- startupinfo, creationflags, shell, -- p2cread, p2cwrite, -- c2pread, c2pwrite, -- errread, errwrite) -- -- if p2cwrite: -- self.stdin = os.fdopen(p2cwrite, 'wb', bufsize) -- if c2pread: -- if universal_newlines: -- self.stdout = os.fdopen(c2pread, 'rU', bufsize) -- else: -- self.stdout = os.fdopen(c2pread, 'rb', bufsize) -- if errread: -- if universal_newlines: -- self.stderr = os.fdopen(errread, 'rU', bufsize) -- else: -- self.stderr = os.fdopen(errread, 'rb', bufsize) -- -- _active.append(self) -- -- -- def _translate_newlines(self, data): -- data = data.replace("\r\n", "\n") -- data = data.replace("\r", "\n") -- return data -- -- -- if mswindows: -- # -- # Windows methods -- # -- def _get_handles(self, stdin, stdout, stderr): -- """Construct and return tupel with IO objects: -- p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite -- """ -- if stdin == None and stdout == None and stderr == None: -- return (None, None, None, None, None, None) -- -- p2cread, p2cwrite = None, None -- c2pread, c2pwrite = None, None -- errread, errwrite = None, None -- -- if stdin == None: -- p2cread = GetStdHandle(STD_INPUT_HANDLE) -- elif stdin == PIPE: -- p2cread, p2cwrite = CreatePipe(None, 0) -- # Detach and turn into fd -- p2cwrite = p2cwrite.Detach() -- p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0) -- elif type(stdin) == types.IntType: -- p2cread = msvcrt.get_osfhandle(stdin) -- else: -- # Assuming file-like object -- p2cread = msvcrt.get_osfhandle(stdin.fileno()) -- p2cread = self._make_inheritable(p2cread) -- -- if stdout == None: -- c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE) -- elif stdout == PIPE: -- c2pread, c2pwrite = CreatePipe(None, 0) -- # Detach and turn into fd -- c2pread = c2pread.Detach() -- c2pread = msvcrt.open_osfhandle(c2pread, 0) -- elif type(stdout) == types.IntType: -- c2pwrite = msvcrt.get_osfhandle(stdout) -- else: -- # Assuming file-like object -- c2pwrite = msvcrt.get_osfhandle(stdout.fileno()) -- c2pwrite = self._make_inheritable(c2pwrite) -- -- if stderr == None: -- errwrite = GetStdHandle(STD_ERROR_HANDLE) -- elif stderr == PIPE: -- errread, errwrite = CreatePipe(None, 0) -- # Detach and turn into fd -- errread = errread.Detach() -- errread = msvcrt.open_osfhandle(errread, 0) -- elif stderr == STDOUT: -- errwrite = c2pwrite -- elif type(stderr) == types.IntType: -- errwrite = msvcrt.get_osfhandle(stderr) -- else: -- # Assuming file-like object -- errwrite = msvcrt.get_osfhandle(stderr.fileno()) -- errwrite = self._make_inheritable(errwrite) -- -- return (p2cread, p2cwrite, -- c2pread, c2pwrite, -- errread, errwrite) -- -- -- def _make_inheritable(self, handle): -- """Return a duplicate of handle, which is inheritable""" -- return DuplicateHandle(GetCurrentProcess(), handle, -- GetCurrentProcess(), 0, 1, -- DUPLICATE_SAME_ACCESS) -- -- -- def _find_w9xpopen(self): -- """Find and return absolut path to w9xpopen.exe""" -- w9xpopen = os.path.join(os.path.dirname(GetModuleFileName(0)), -- "w9xpopen.exe") -- if not os.path.exists(w9xpopen): -- # Eeek - file-not-found - possibly an embedding -- # situation - see if we can locate it in sys.exec_prefix -- w9xpopen = os.path.join(os.path.dirname(sys.exec_prefix), -- "w9xpopen.exe") -- if not os.path.exists(w9xpopen): -- raise RuntimeError("Cannot locate w9xpopen.exe, which is " -- "needed for Popen to work with your " -- "shell or platform.") -- return w9xpopen -- -- -- def _execute_child(self, args, executable, preexec_fn, close_fds, -- cwd, env, universal_newlines, -- startupinfo, creationflags, shell, -- p2cread, p2cwrite, -- c2pread, c2pwrite, -- errread, errwrite): -- """Execute program (MS Windows version)""" -- -- if not isinstance(args, types.StringTypes): -- args = list2cmdline(args) -- -- # Process startup details -- default_startupinfo = STARTUPINFO() -- if startupinfo == None: -- startupinfo = default_startupinfo -- if not None in (p2cread, c2pwrite, errwrite): -- startupinfo.dwFlags |= STARTF_USESTDHANDLES -- startupinfo.hStdInput = p2cread -- startupinfo.hStdOutput = c2pwrite -- startupinfo.hStdError = errwrite -- -- if shell: -- default_startupinfo.dwFlags |= STARTF_USESHOWWINDOW -- default_startupinfo.wShowWindow = SW_HIDE -- comspec = os.environ.get("COMSPEC", "cmd.exe") -- args = comspec + " /c " + args -- if (GetVersion() >= 0x80000000L or -- os.path.basename(comspec).lower() == "command.com"): -- # Win9x, or using command.com on NT. We need to -- # use the w9xpopen intermediate program. For more -- # information, see KB Q150956 -- # (http://web.archive.org/web/20011105084002/http://support.microsoft.com/support/kb/articles/Q150/9/56.asp) -- w9xpopen = self._find_w9xpopen() -- args = '"%s" %s' % (w9xpopen, args) -- # Not passing CREATE_NEW_CONSOLE has been known to -- # cause random failures on win9x. Specifically a -- # dialog: "Your program accessed mem currently in -- # use at xxx" and a hopeful warning about the -- # stability of your system. Cost is Ctrl+C wont -- # kill children. -- creationflags |= CREATE_NEW_CONSOLE -- -- # Start the process -- try: -- hp, ht, pid, tid = CreateProcess(executable, args, -- # no special security -- None, None, -- # must inherit handles to pass std -- # handles -- 1, -- creationflags, -- env, -- cwd, -- startupinfo) -- except pywintypes.error, e: -- # Translate pywintypes.error to WindowsError, which is -- # a subclass of OSError. FIXME: We should really -- # translate errno using _sys_errlist (or simliar), but -- # how can this be done from Python? -- raise WindowsError(*e.args) -- -- # Retain the process handle, but close the thread handle -- self._handle = hp -- self.pid = pid -- ht.Close() -- -- # Child is launched. Close the parent's copy of those pipe -- # handles that only the child should have open. You need -- # to make sure that no handles to the write end of the -- # output pipe are maintained in this process or else the -- # pipe will not close when the child process exits and the -- # ReadFile will hang. -- if p2cread != None: -- p2cread.Close() -- if c2pwrite != None: -- c2pwrite.Close() -- if errwrite != None: -- errwrite.Close() -- -- -- def poll(self): -- """Check if child process has terminated. Returns returncode -- attribute.""" -- if self.returncode == None: -- if WaitForSingleObject(self._handle, 0) == WAIT_OBJECT_0: -- self.returncode = GetExitCodeProcess(self._handle) -- _active.remove(self) -- return self.returncode -- -- -- def wait(self): -- """Wait for child process to terminate. Returns returncode -- attribute.""" -- if self.returncode == None: -- obj = WaitForSingleObject(self._handle, INFINITE) -- self.returncode = GetExitCodeProcess(self._handle) -- _active.remove(self) -- return self.returncode -- -- -- def _readerthread(self, fh, buffer): -- buffer.append(fh.read()) -- -- -- def communicate(self, input=None): -- """Interact with process: Send data to stdin. Read data from -- stdout and stderr, until end-of-file is reached. Wait for -- process to terminate. The optional input argument should be a -- string to be sent to the child process, or None, if no data -- should be sent to the child. -- -- communicate() returns a tuple (stdout, stderr).""" -- stdout = None # Return -- stderr = None # Return -- -- if self.stdout: -- stdout = [] -- stdout_thread = threading.Thread(target=self._readerthread, -- args=(self.stdout, stdout)) -- stdout_thread.setDaemon(True) -- stdout_thread.start() -- if self.stderr: -- stderr = [] -- stderr_thread = threading.Thread(target=self._readerthread, -- args=(self.stderr, stderr)) -- stderr_thread.setDaemon(True) -- stderr_thread.start() -- -- if self.stdin: -- if input != None: -- self.stdin.write(input) -- self.stdin.close() -- -- if self.stdout: -- stdout_thread.join() -- if self.stderr: -- stderr_thread.join() -- -- # All data exchanged. Translate lists into strings. -- if stdout != None: -- stdout = stdout[0] -- if stderr != None: -- stderr = stderr[0] -- -- # Translate newlines, if requested. We cannot let the file -- # object do the translation: It is based on stdio, which is -- # impossible to combine with select (unless forcing no -- # buffering). -- if self.universal_newlines and hasattr(open, 'newlines'): -- if stdout: -- stdout = self._translate_newlines(stdout) -- if stderr: -- stderr = self._translate_newlines(stderr) -- -- self.wait() -- return (stdout, stderr) -- -- else: -- # -- # POSIX methods -- # -- def _get_handles(self, stdin, stdout, stderr): -- """Construct and return tupel with IO objects: -- p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite -- """ -- p2cread, p2cwrite = None, None -- c2pread, c2pwrite = None, None -- errread, errwrite = None, None -- -- if stdin == None: -- pass -- elif stdin == PIPE: -- p2cread, p2cwrite = os.pipe() -- elif type(stdin) == types.IntType: -- p2cread = stdin -- else: -- # Assuming file-like object -- p2cread = stdin.fileno() -- -- if stdout == None: -- pass -- elif stdout == PIPE: -- c2pread, c2pwrite = os.pipe() -- elif type(stdout) == types.IntType: -- c2pwrite = stdout -- else: -- # Assuming file-like object -- c2pwrite = stdout.fileno() -- -- if stderr == None: -- pass -- elif stderr == PIPE: -- errread, errwrite = os.pipe() -- elif stderr == STDOUT: -- errwrite = c2pwrite -- elif type(stderr) == types.IntType: -- errwrite = stderr -- else: -- # Assuming file-like object -- errwrite = stderr.fileno() -- -- return (p2cread, p2cwrite, -- c2pread, c2pwrite, -- errread, errwrite) -- -- -- def _set_cloexec_flag(self, fd): -- try: -- cloexec_flag = fcntl.FD_CLOEXEC -- except AttributeError: -- cloexec_flag = 1 -- -- old = fcntl.fcntl(fd, fcntl.F_GETFD) -- fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag) -- -- -- def _close_fds(self, but): -- for i in range(3, MAXFD): -- if i == but: -- continue -- try: -- os.close(i) -- except: -- pass -- -- -- def _execute_child(self, args, executable, preexec_fn, close_fds, -- cwd, env, universal_newlines, -- startupinfo, creationflags, shell, -- p2cread, p2cwrite, -- c2pread, c2pwrite, -- errread, errwrite): -- """Execute program (POSIX version)""" -- -- if isinstance(args, types.StringTypes): -- args = [args] -- -- if shell: -- args = ["/bin/sh", "-c"] + args -- -- if executable == None: -- executable = args[0] -- -- # For transferring possible exec failure from child to parent -- # The first char specifies the exception type: 0 means -- # OSError, 1 means some other error. -- errpipe_read, errpipe_write = os.pipe() -- self._set_cloexec_flag(errpipe_write) -- -- self.pid = os.fork() -- if self.pid == 0: -- # Child -- try: -- # Close parent's pipe ends -- if p2cwrite: -- os.close(p2cwrite) -- if c2pread: -- os.close(c2pread) -- if errread: -- os.close(errread) -- os.close(errpipe_read) -- -- # Dup fds for child -- if p2cread: -- os.dup2(p2cread, 0) -- if c2pwrite: -- os.dup2(c2pwrite, 1) -- if errwrite: -- os.dup2(errwrite, 2) -- -- # Close pipe fds. Make sure we doesn't close the same -- # fd more than once. -- if p2cread: -- os.close(p2cread) -- if c2pwrite and c2pwrite not in (p2cread,): -- os.close(c2pwrite) -- if errwrite and errwrite not in (p2cread, c2pwrite): -- os.close(errwrite) -- -- # Close all other fds, if asked for -- if close_fds: -- self._close_fds(but=errpipe_write) -- -- if cwd != None: -- os.chdir(cwd) -- -- if preexec_fn: -- apply(preexec_fn) -- -- if env == None: -- os.execvp(executable, args) -- else: -- os.execvpe(executable, args, env) -- -- except: -- exc_type, exc_value, tb = sys.exc_info() -- # Save the traceback and attach it to the exception object -- exc_lines = traceback.format_exception(exc_type, -- exc_value, -- tb) -- exc_value.child_traceback = ''.join(exc_lines) -- os.write(errpipe_write, pickle.dumps(exc_value)) -- -- # This exitcode won't be reported to applications, so it -- # really doesn't matter what we return. -- os._exit(255) -- -- # Parent -- os.close(errpipe_write) -- if p2cread and p2cwrite: -- os.close(p2cread) -- if c2pwrite and c2pread: -- os.close(c2pwrite) -- if errwrite and errread: -- os.close(errwrite) -- -- # Wait for exec to fail or succeed; possibly raising exception -- data = os.read(errpipe_read, 1048576) # Exceptions limited to 1 MB -- os.close(errpipe_read) -- if data != "": -- os.waitpid(self.pid, 0) -- child_exception = pickle.loads(data) -- raise child_exception -- -- -- def _handle_exitstatus(self, sts): -- if os.WIFSIGNALED(sts): -- self.returncode = -os.WTERMSIG(sts) -- elif os.WIFEXITED(sts): -- self.returncode = os.WEXITSTATUS(sts) -- else: -- # Should never happen -- raise RuntimeError("Unknown child exit status!") -- -- _active.remove(self) -- -- -- def poll(self): -- """Check if child process has terminated. Returns returncode -- attribute.""" -- if self.returncode == None: -- try: -- pid, sts = os.waitpid(self.pid, os.WNOHANG) -- if pid == self.pid: -- self._handle_exitstatus(sts) -- except os.error: -- pass -- return self.returncode -- -- -- def wait(self): -- """Wait for child process to terminate. Returns returncode -- attribute.""" -- if self.returncode == None: -- pid, sts = os.waitpid(self.pid, 0) -- self._handle_exitstatus(sts) -- return self.returncode -- -- -- def communicate(self, input=None): -- """Interact with process: Send data to stdin. Read data from -- stdout and stderr, until end-of-file is reached. Wait for -- process to terminate. The optional input argument should be a -- string to be sent to the child process, or None, if no data -- should be sent to the child. -- -- communicate() returns a tuple (stdout, stderr).""" -- read_set = [] -- write_set = [] -- stdout = None # Return -- stderr = None # Return -- -- if self.stdin: -- # Flush stdio buffer. This might block, if the user has -- # been writing to .stdin in an uncontrolled fashion. -- self.stdin.flush() -- if input: -- write_set.append(self.stdin) -- else: -- self.stdin.close() -- if self.stdout: -- read_set.append(self.stdout) -- stdout = [] -- if self.stderr: -- read_set.append(self.stderr) -- stderr = [] -- -- while read_set or write_set: -- rlist, wlist, xlist = select.select(read_set, write_set, []) -- -- if self.stdin in wlist: -- # When select has indicated that the file is writable, -- # we can write up to PIPE_BUF bytes without risk -- # blocking. POSIX defines PIPE_BUF >= 512 -- bytes_written = os.write(self.stdin.fileno(), input[:512]) -- input = input[bytes_written:] -- if not input: -- self.stdin.close() -- write_set.remove(self.stdin) -- -- if self.stdout in rlist: -- data = os.read(self.stdout.fileno(), 1024) -- if data == "": -- self.stdout.close() -- read_set.remove(self.stdout) -- stdout.append(data) -- -- if self.stderr in rlist: -- data = os.read(self.stderr.fileno(), 1024) -- if data == "": -- self.stderr.close() -- read_set.remove(self.stderr) -- stderr.append(data) -- -- # All data exchanged. Translate lists into strings. -- if stdout != None: -- stdout = ''.join(stdout) -- if stderr != None: -- stderr = ''.join(stderr) -- -- # Translate newlines, if requested. We cannot let the file -- # object do the translation: It is based on stdio, which is -- # impossible to combine with select (unless forcing no -- # buffering). -- if self.universal_newlines and hasattr(open, 'newlines'): -- if stdout: -- stdout = self._translate_newlines(stdout) -- if stderr: -- stderr = self._translate_newlines(stderr) -- -- self.wait() -- return (stdout, stderr) -- -- --def _demo_posix(): -- # -- # Example 1: Simple redirection: Get process list -- # -- plist = Popen(["ps"], stdout=PIPE).communicate()[0] -- print "Process list:" -- print plist -- -- # -- # Example 2: Change uid before executing child -- # -- if os.getuid() == 0: -- p = Popen(["id"], preexec_fn=lambda: os.setuid(100)) -- p.wait() -- -- # -- # Example 3: Connecting several subprocesses -- # -- print "Looking for 'hda'..." -- p1 = Popen(["dmesg"], stdout=PIPE) -- p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) -- print repr(p2.communicate()[0]) -- -- # -- # Example 4: Catch execution error -- # -- print -- print "Trying a weird file..." -- try: -- print Popen(["/this/path/does/not/exist"]).communicate() -- except OSError, e: -- if e.errno == errno.ENOENT: -- print "The file didn't exist. I thought so..." -- print "Child traceback:" -- print e.child_traceback -- else: -- print "Error", e.errno -- else: -- print >>sys.stderr, "Gosh. No error." -- -- --def _demo_windows(): -- # -- # Example 1: Connecting several subprocesses -- # -- print "Looking for 'PROMPT' in set output..." -- p1 = Popen("set", stdout=PIPE, shell=True) -- p2 = Popen('find "PROMPT"', stdin=p1.stdout, stdout=PIPE) -- print repr(p2.communicate()[0]) -- -- # -- # Example 2: Simple execution of program -- # -- print "Executing calc..." -- p = Popen("calc") -- p.wait() -- -- --if __name__ == "__main__": -- if mswindows: -- _demo_windows() -- else: -- _demo_posix() diff --git a/dev-python/paste/files/paste-1.7.5.1-unbundle-tempita.patch b/dev-python/paste/files/paste-1.7.5.1-unbundle-tempita.patch deleted file mode 100644 index 689973fd88a8..000000000000 --- a/dev-python/paste/files/paste-1.7.5.1-unbundle-tempita.patch +++ /dev/null @@ -1,1860 +0,0 @@ -Index: Paste-1.7.4/paste/util/looper/__init__.py -=================================================================== ---- /dev/null -+++ Paste-1.7.4/paste/util/looper/__init__.py -@@ -0,0 +1,4 @@ -+try: -+ from tempita._looper import * -+except ImportError: -+ from _looper import * -Index: Paste-1.7.4/paste/util/looper/_looper.py -=================================================================== ---- /dev/null -+++ Paste-1.7.4/paste/util/looper/_looper.py -@@ -0,0 +1,152 @@ -+""" -+Helper for looping over sequences, particular in templates. -+ -+Often in a loop in a template it's handy to know what's next up, -+previously up, if this is the first or last item in the sequence, etc. -+These can be awkward to manage in a normal Python loop, but using the -+looper you can get a better sense of the context. Use like:: -+ -+ >>> for loop, item in looper(['a', 'b', 'c']): -+ ... print loop.number, item -+ ... if not loop.last: -+ ... print '---' -+ 1 a -+ --- -+ 2 b -+ --- -+ 3 c -+ -+""" -+ -+__all__ = ['looper'] -+ -+class looper(object): -+ """ -+ Helper for looping (particularly in templates) -+ -+ Use this like:: -+ -+ for loop, item in looper(seq): -+ if loop.first: -+ ... -+ """ -+ -+ def __init__(self, seq): -+ self.seq = seq -+ -+ def __iter__(self): -+ return looper_iter(self.seq) -+ -+ def __repr__(self): -+ return '<%s for %r>' % ( -+ self.__class__.__name__, self.seq) -+ -+class looper_iter(object): -+ -+ def __init__(self, seq): -+ self.seq = list(seq) -+ self.pos = 0 -+ -+ def __iter__(self): -+ return self -+ -+ def next(self): -+ if self.pos >= len(self.seq): -+ raise StopIteration -+ result = loop_pos(self.seq, self.pos), self.seq[self.pos] -+ self.pos += 1 -+ return result -+ -+class loop_pos(object): -+ -+ def __init__(self, seq, pos): -+ self.seq = seq -+ self.pos = pos -+ -+ def __repr__(self): -+ return '<loop pos=%r at %r>' % ( -+ self.seq[pos], pos) -+ -+ def index(self): -+ return self.pos -+ index = property(index) -+ -+ def number(self): -+ return self.pos + 1 -+ number = property(number) -+ -+ def item(self): -+ return self.seq[self.pos] -+ item = property(item) -+ -+ def next(self): -+ try: -+ return self.seq[self.pos+1] -+ except IndexError: -+ return None -+ next = property(next) -+ -+ def previous(self): -+ if self.pos == 0: -+ return None -+ return self.seq[self.pos-1] -+ previous = property(previous) -+ -+ def odd(self): -+ return not self.pos % 2 -+ odd = property(odd) -+ -+ def even(self): -+ return self.pos % 2 -+ even = property(even) -+ -+ def first(self): -+ return self.pos == 0 -+ first = property(first) -+ -+ def last(self): -+ return self.pos == len(self.seq)-1 -+ last = property(last) -+ -+ def length(self): -+ return len(self.seq) -+ length = property(length) -+ -+ def first_group(self, getter=None): -+ """ -+ Returns true if this item is the start of a new group, -+ where groups mean that some attribute has changed. The getter -+ can be None (the item itself changes), an attribute name like -+ ``'.attr'``, a function, or a dict key or list index. -+ """ -+ if self.first: -+ return True -+ return self._compare_group(self.item, self.previous, getter) -+ -+ def last_group(self, getter=None): -+ """ -+ Returns true if this item is the end of a new group, -+ where groups mean that some attribute has changed. The getter -+ can be None (the item itself changes), an attribute name like -+ ``'.attr'``, a function, or a dict key or list index. -+ """ -+ if self.last: -+ return True -+ return self._compare_group(self.item, self.next, getter) -+ -+ def _compare_group(self, item, other, getter): -+ if getter is None: -+ return item != other -+ elif (isinstance(getter, basestring) -+ and getter.startswith('.')): -+ getter = getter[1:] -+ if getter.endswith('()'): -+ getter = getter[:-2] -+ return getattr(item, getter)() != getattr(other, getter)() -+ else: -+ return getattr(item, getter) != getattr(other, getter) -+ elif callable(getter): -+ return getter(item) != getter(other) -+ else: -+ return item[getter] != other[getter] -+ -Index: Paste-1.7.4/paste/util/looper.py -=================================================================== ---- Paste-1.7.4.orig/paste/util/looper.py -+++ /dev/null -@@ -1,152 +0,0 @@ --""" --Helper for looping over sequences, particular in templates. -- --Often in a loop in a template it's handy to know what's next up, --previously up, if this is the first or last item in the sequence, etc. --These can be awkward to manage in a normal Python loop, but using the --looper you can get a better sense of the context. Use like:: -- -- >>> for loop, item in looper(['a', 'b', 'c']): -- ... print loop.number, item -- ... if not loop.last: -- ... print '---' -- 1 a -- --- -- 2 b -- --- -- 3 c -- --""" -- --__all__ = ['looper'] -- --class looper(object): -- """ -- Helper for looping (particularly in templates) -- -- Use this like:: -- -- for loop, item in looper(seq): -- if loop.first: -- ... -- """ -- -- def __init__(self, seq): -- self.seq = seq -- -- def __iter__(self): -- return looper_iter(self.seq) -- -- def __repr__(self): -- return '<%s for %r>' % ( -- self.__class__.__name__, self.seq) -- --class looper_iter(object): -- -- def __init__(self, seq): -- self.seq = list(seq) -- self.pos = 0 -- -- def __iter__(self): -- return self -- -- def next(self): -- if self.pos >= len(self.seq): -- raise StopIteration -- result = loop_pos(self.seq, self.pos), self.seq[self.pos] -- self.pos += 1 -- return result -- --class loop_pos(object): -- -- def __init__(self, seq, pos): -- self.seq = seq -- self.pos = pos -- -- def __repr__(self): -- return '<loop pos=%r at %r>' % ( -- self.seq[pos], pos) -- -- def index(self): -- return self.pos -- index = property(index) -- -- def number(self): -- return self.pos + 1 -- number = property(number) -- -- def item(self): -- return self.seq[self.pos] -- item = property(item) -- -- def next(self): -- try: -- return self.seq[self.pos+1] -- except IndexError: -- return None -- next = property(next) -- -- def previous(self): -- if self.pos == 0: -- return None -- return self.seq[self.pos-1] -- previous = property(previous) -- -- def odd(self): -- return not self.pos % 2 -- odd = property(odd) -- -- def even(self): -- return self.pos % 2 -- even = property(even) -- -- def first(self): -- return self.pos == 0 -- first = property(first) -- -- def last(self): -- return self.pos == len(self.seq)-1 -- last = property(last) -- -- def length(self): -- return len(self.seq) -- length = property(length) -- -- def first_group(self, getter=None): -- """ -- Returns true if this item is the start of a new group, -- where groups mean that some attribute has changed. The getter -- can be None (the item itself changes), an attribute name like -- ``'.attr'``, a function, or a dict key or list index. -- """ -- if self.first: -- return True -- return self._compare_group(self.item, self.previous, getter) -- -- def last_group(self, getter=None): -- """ -- Returns true if this item is the end of a new group, -- where groups mean that some attribute has changed. The getter -- can be None (the item itself changes), an attribute name like -- ``'.attr'``, a function, or a dict key or list index. -- """ -- if self.last: -- return True -- return self._compare_group(self.item, self.next, getter) -- -- def _compare_group(self, item, other, getter): -- if getter is None: -- return item != other -- elif (isinstance(getter, basestring) -- and getter.startswith('.')): -- getter = getter[1:] -- if getter.endswith('()'): -- getter = getter[:-2] -- return getattr(item, getter)() != getattr(other, getter)() -- else: -- return getattr(item, getter) != getattr(other, getter) -- elif callable(getter): -- return getter(item) != getter(other) -- else: -- return item[getter] != other[getter] -- -Index: Paste-1.7.4/paste/util/template/__init__.py -=================================================================== ---- /dev/null -+++ Paste-1.7.4/paste/util/template/__init__.py -@@ -0,0 +1,6 @@ -+try: -+ from tempita import * -+ from tempita import paste_script_template_renderer -+except ImportError: -+ from _template import * -+ from _template import paste_script_template_renderer -Index: Paste-1.7.4/paste/util/template/_template.py -=================================================================== ---- /dev/null -+++ Paste-1.7.4/paste/util/template/_template.py -@@ -0,0 +1,758 @@ -+""" -+A small templating language -+ -+This implements a small templating language for use internally in -+Paste and Paste Script. This language implements if/elif/else, -+for/continue/break, expressions, and blocks of Python code. The -+syntax is:: -+ -+ {{any expression (function calls etc)}} -+ {{any expression | filter}} -+ {{for x in y}}...{{endfor}} -+ {{if x}}x{{elif y}}y{{else}}z{{endif}} -+ {{py:x=1}} -+ {{py: -+ def foo(bar): -+ return 'baz' -+ }} -+ {{default var = default_value}} -+ {{# comment}} -+ -+You use this with the ``Template`` class or the ``sub`` shortcut. -+The ``Template`` class takes the template string and the name of -+the template (for errors) and a default namespace. Then (like -+``string.Template``) you can call the ``tmpl.substitute(**kw)`` -+method to make a substitution (or ``tmpl.substitute(a_dict)``). -+ -+``sub(content, **kw)`` substitutes the template immediately. You -+can use ``__name='tmpl.html'`` to set the name of the template. -+ -+If there are syntax errors ``TemplateError`` will be raised. -+""" -+ -+import re -+import sys -+import cgi -+import urllib -+from paste.util.looper import looper -+ -+__all__ = ['TemplateError', 'Template', 'sub', 'HTMLTemplate', -+ 'sub_html', 'html', 'bunch'] -+ -+token_re = re.compile(r'\{\{|\}\}') -+in_re = re.compile(r'\s+in\s+') -+var_re = re.compile(r'^[a-z_][a-z0-9_]*$', re.I) -+ -+class TemplateError(Exception): -+ """Exception raised while parsing a template -+ """ -+ -+ def __init__(self, message, position, name=None): -+ self.message = message -+ self.position = position -+ self.name = name -+ -+ def __str__(self): -+ msg = '%s at line %s column %s' % ( -+ self.message, self.position[0], self.position[1]) -+ if self.name: -+ msg += ' in %s' % self.name -+ return msg -+ -+class _TemplateContinue(Exception): -+ pass -+ -+class _TemplateBreak(Exception): -+ pass -+ -+class Template(object): -+ -+ default_namespace = { -+ 'start_braces': '{{', -+ 'end_braces': '}}', -+ 'looper': looper, -+ } -+ -+ default_encoding = 'utf8' -+ -+ def __init__(self, content, name=None, namespace=None): -+ self.content = content -+ self._unicode = isinstance(content, unicode) -+ self.name = name -+ self._parsed = parse(content, name=name) -+ if namespace is None: -+ namespace = {} -+ self.namespace = namespace -+ -+ def from_filename(cls, filename, namespace=None, encoding=None): -+ f = open(filename, 'rb') -+ c = f.read() -+ f.close() -+ if encoding: -+ c = c.decode(encoding) -+ return cls(content=c, name=filename, namespace=namespace) -+ -+ from_filename = classmethod(from_filename) -+ -+ def __repr__(self): -+ return '<%s %s name=%r>' % ( -+ self.__class__.__name__, -+ hex(id(self))[2:], self.name) -+ -+ def substitute(self, *args, **kw): -+ if args: -+ if kw: -+ raise TypeError( -+ "You can only give positional *or* keyword arguments") -+ if len(args) > 1: -+ raise TypeError( -+ "You can only give on positional argument") -+ kw = args[0] -+ ns = self.default_namespace.copy() -+ ns.update(self.namespace) -+ ns.update(kw) -+ result = self._interpret(ns) -+ return result -+ -+ def _interpret(self, ns): -+ __traceback_hide__ = True -+ parts = [] -+ self._interpret_codes(self._parsed, ns, out=parts) -+ return ''.join(parts) -+ -+ def _interpret_codes(self, codes, ns, out): -+ __traceback_hide__ = True -+ for item in codes: -+ if isinstance(item, basestring): -+ out.append(item) -+ else: -+ self._interpret_code(item, ns, out) -+ -+ def _interpret_code(self, code, ns, out): -+ __traceback_hide__ = True -+ name, pos = code[0], code[1] -+ if name == 'py': -+ self._exec(code[2], ns, pos) -+ elif name == 'continue': -+ raise _TemplateContinue() -+ elif name == 'break': -+ raise _TemplateBreak() -+ elif name == 'for': -+ vars, expr, content = code[2], code[3], code[4] -+ expr = self._eval(expr, ns, pos) -+ self._interpret_for(vars, expr, content, ns, out) -+ elif name == 'cond': -+ parts = code[2:] -+ self._interpret_if(parts, ns, out) -+ elif name == 'expr': -+ parts = code[2].split('|') -+ base = self._eval(parts[0], ns, pos) -+ for part in parts[1:]: -+ func = self._eval(part, ns, pos) -+ base = func(base) -+ out.append(self._repr(base, pos)) -+ elif name == 'default': -+ var, expr = code[2], code[3] -+ if var not in ns: -+ result = self._eval(expr, ns, pos) -+ ns[var] = result -+ elif name == 'comment': -+ return -+ else: -+ assert 0, "Unknown code: %r" % name -+ -+ def _interpret_for(self, vars, expr, content, ns, out): -+ __traceback_hide__ = True -+ for item in expr: -+ if len(vars) == 1: -+ ns[vars[0]] = item -+ else: -+ if len(vars) != len(item): -+ raise ValueError( -+ 'Need %i items to unpack (got %i items)' -+ % (len(vars), len(item))) -+ for name, value in zip(vars, item): -+ ns[name] = value -+ try: -+ self._interpret_codes(content, ns, out) -+ except _TemplateContinue: -+ continue -+ except _TemplateBreak: -+ break -+ -+ def _interpret_if(self, parts, ns, out): -+ __traceback_hide__ = True -+ # @@: if/else/else gets through -+ for part in parts: -+ assert not isinstance(part, basestring) -+ name, pos = part[0], part[1] -+ if name == 'else': -+ result = True -+ else: -+ result = self._eval(part[2], ns, pos) -+ if result: -+ self._interpret_codes(part[3], ns, out) -+ break -+ -+ def _eval(self, code, ns, pos): -+ __traceback_hide__ = True -+ try: -+ value = eval(code, ns) -+ return value -+ except: -+ exc_info = sys.exc_info() -+ e = exc_info[1] -+ if getattr(e, 'args'): -+ arg0 = e.args[0] -+ else: -+ arg0 = str(e) -+ e.args = (self._add_line_info(arg0, pos),) -+ raise exc_info[0], e, exc_info[2] -+ -+ def _exec(self, code, ns, pos): -+ __traceback_hide__ = True -+ try: -+ exec code in ns -+ except: -+ exc_info = sys.exc_info() -+ e = exc_info[1] -+ e.args = (self._add_line_info(e.args[0], pos),) -+ raise exc_info[0], e, exc_info[2] -+ -+ def _repr(self, value, pos): -+ __traceback_hide__ = True -+ try: -+ if value is None: -+ return '' -+ if self._unicode: -+ try: -+ value = unicode(value) -+ except UnicodeDecodeError: -+ value = str(value) -+ else: -+ value = str(value) -+ except: -+ exc_info = sys.exc_info() -+ e = exc_info[1] -+ e.args = (self._add_line_info(e.args[0], pos),) -+ raise exc_info[0], e, exc_info[2] -+ else: -+ if self._unicode and isinstance(value, str): -+ if not self.decode_encoding: -+ raise UnicodeDecodeError( -+ 'Cannot decode str value %r into unicode ' -+ '(no default_encoding provided)' % value) -+ value = value.decode(self.default_encoding) -+ elif not self._unicode and isinstance(value, unicode): -+ if not self.decode_encoding: -+ raise UnicodeEncodeError( -+ 'Cannot encode unicode value %r into str ' -+ '(no default_encoding provided)' % value) -+ value = value.encode(self.default_encoding) -+ return value -+ -+ -+ def _add_line_info(self, msg, pos): -+ msg = "%s at line %s column %s" % ( -+ msg, pos[0], pos[1]) -+ if self.name: -+ msg += " in file %s" % self.name -+ return msg -+ -+def sub(content, **kw): -+ name = kw.get('__name') -+ tmpl = Template(content, name=name) -+ return tmpl.substitute(kw) -+ return result -+ -+def paste_script_template_renderer(content, vars, filename=None): -+ tmpl = Template(content, name=filename) -+ return tmpl.substitute(vars) -+ -+class bunch(dict): -+ -+ def __init__(self, **kw): -+ for name, value in kw.items(): -+ setattr(self, name, value) -+ -+ def __setattr__(self, name, value): -+ self[name] = value -+ -+ def __getattr__(self, name): -+ try: -+ return self[name] -+ except KeyError: -+ raise AttributeError(name) -+ -+ def __getitem__(self, key): -+ if 'default' in self: -+ try: -+ return dict.__getitem__(self, key) -+ except KeyError: -+ return dict.__getitem__(self, 'default') -+ else: -+ return dict.__getitem__(self, key) -+ -+ def __repr__(self): -+ items = [ -+ (k, v) for k, v in self.items()] -+ items.sort() -+ return '<%s %s>' % ( -+ self.__class__.__name__, -+ ' '.join(['%s=%r' % (k, v) for k, v in items])) -+ -+############################################################ -+## HTML Templating -+############################################################ -+ -+class html(object): -+ def __init__(self, value): -+ self.value = value -+ def __str__(self): -+ return self.value -+ def __repr__(self): -+ return '<%s %r>' % ( -+ self.__class__.__name__, self.value) -+ -+def html_quote(value): -+ if value is None: -+ return '' -+ if not isinstance(value, basestring): -+ if hasattr(value, '__unicode__'): -+ value = unicode(value) -+ else: -+ value = str(value) -+ value = cgi.escape(value, 1) -+ if isinstance(value, unicode): -+ value = value.encode('ascii', 'xmlcharrefreplace') -+ return value -+ -+def url(v): -+ if not isinstance(v, basestring): -+ if hasattr(v, '__unicode__'): -+ v = unicode(v) -+ else: -+ v = str(v) -+ if isinstance(v, unicode): -+ v = v.encode('utf8') -+ return urllib.quote(v) -+ -+def attr(**kw): -+ kw = kw.items() -+ kw.sort() -+ parts = [] -+ for name, value in kw: -+ if value is None: -+ continue -+ if name.endswith('_'): -+ name = name[:-1] -+ parts.append('%s="%s"' % (html_quote(name), html_quote(value))) -+ return html(' '.join(parts)) -+ -+class HTMLTemplate(Template): -+ -+ default_namespace = Template.default_namespace.copy() -+ default_namespace.update(dict( -+ html=html, -+ attr=attr, -+ url=url, -+ )) -+ -+ def _repr(self, value, pos): -+ plain = Template._repr(self, value, pos) -+ if isinstance(value, html): -+ return plain -+ else: -+ return html_quote(plain) -+ -+def sub_html(content, **kw): -+ name = kw.get('__name') -+ tmpl = HTMLTemplate(content, name=name) -+ return tmpl.substitute(kw) -+ return result -+ -+ -+############################################################ -+## Lexing and Parsing -+############################################################ -+ -+def lex(s, name=None, trim_whitespace=True): -+ """ -+ Lex a string into chunks: -+ -+ >>> lex('hey') -+ ['hey'] -+ >>> lex('hey {{you}}') -+ ['hey ', ('you', (1, 7))] -+ >>> lex('hey {{') -+ Traceback (most recent call last): -+ ... -+ TemplateError: No }} to finish last expression at line 1 column 7 -+ >>> lex('hey }}') -+ Traceback (most recent call last): -+ ... -+ TemplateError: }} outside expression at line 1 column 7 -+ >>> lex('hey {{ {{') -+ Traceback (most recent call last): -+ ... -+ TemplateError: {{ inside expression at line 1 column 10 -+ -+ """ -+ in_expr = False -+ chunks = [] -+ last = 0 -+ last_pos = (1, 1) -+ for match in token_re.finditer(s): -+ expr = match.group(0) -+ pos = find_position(s, match.end()) -+ if expr == '{{' and in_expr: -+ raise TemplateError('{{ inside expression', position=pos, -+ name=name) -+ elif expr == '}}' and not in_expr: -+ raise TemplateError('}} outside expression', position=pos, -+ name=name) -+ if expr == '{{': -+ part = s[last:match.start()] -+ if part: -+ chunks.append(part) -+ in_expr = True -+ else: -+ chunks.append((s[last:match.start()], last_pos)) -+ in_expr = False -+ last = match.end() -+ last_pos = pos -+ if in_expr: -+ raise TemplateError('No }} to finish last expression', -+ name=name, position=last_pos) -+ part = s[last:] -+ if part: -+ chunks.append(part) -+ if trim_whitespace: -+ chunks = trim_lex(chunks) -+ return chunks -+ -+statement_re = re.compile(r'^(?:if |elif |else |for |py:)') -+single_statements = ['endif', 'endfor', 'continue', 'break'] -+trail_whitespace_re = re.compile(r'\n[\t ]*$') -+lead_whitespace_re = re.compile(r'^[\t ]*\n') -+ -+def trim_lex(tokens): -+ r""" -+ Takes a lexed set of tokens, and removes whitespace when there is -+ a directive on a line by itself: -+ -+ >>> tokens = lex('{{if x}}\nx\n{{endif}}\ny', trim_whitespace=False) -+ >>> tokens -+ [('if x', (1, 3)), '\nx\n', ('endif', (3, 3)), '\ny'] -+ >>> trim_lex(tokens) -+ [('if x', (1, 3)), 'x\n', ('endif', (3, 3)), 'y'] -+ """ -+ for i in range(len(tokens)): -+ current = tokens[i] -+ if isinstance(tokens[i], basestring): -+ # we don't trim this -+ continue -+ item = current[0] -+ if not statement_re.search(item) and item not in single_statements: -+ continue -+ if not i: -+ prev = '' -+ else: -+ prev = tokens[i-1] -+ if i+1 >= len(tokens): -+ next = '' -+ else: -+ next = tokens[i+1] -+ if (not isinstance(next, basestring) -+ or not isinstance(prev, basestring)): -+ continue -+ if ((not prev or trail_whitespace_re.search(prev)) -+ and (not next or lead_whitespace_re.search(next))): -+ if prev: -+ m = trail_whitespace_re.search(prev) -+ # +1 to leave the leading \n on: -+ prev = prev[:m.start()+1] -+ tokens[i-1] = prev -+ if next: -+ m = lead_whitespace_re.search(next) -+ next = next[m.end():] -+ tokens[i+1] = next -+ return tokens -+ -+ -+def find_position(string, index): -+ """Given a string and index, return (line, column)""" -+ leading = string[:index].splitlines() -+ return (len(leading), len(leading[-1])+1) -+ -+def parse(s, name=None): -+ r""" -+ Parses a string into a kind of AST -+ -+ >>> parse('{{x}}') -+ [('expr', (1, 3), 'x')] -+ >>> parse('foo') -+ ['foo'] -+ >>> parse('{{if x}}test{{endif}}') -+ [('cond', (1, 3), ('if', (1, 3), 'x', ['test']))] -+ >>> parse('series->{{for x in y}}x={{x}}{{endfor}}') -+ ['series->', ('for', (1, 11), ('x',), 'y', ['x=', ('expr', (1, 27), 'x')])] -+ >>> parse('{{for x, y in z:}}{{continue}}{{endfor}}') -+ [('for', (1, 3), ('x', 'y'), 'z', [('continue', (1, 21))])] -+ >>> parse('{{py:x=1}}') -+ [('py', (1, 3), 'x=1')] -+ >>> parse('{{if x}}a{{elif y}}b{{else}}c{{endif}}') -+ [('cond', (1, 3), ('if', (1, 3), 'x', ['a']), ('elif', (1, 12), 'y', ['b']), ('else', (1, 23), None, ['c']))] -+ -+ Some exceptions:: -+ -+ >>> parse('{{continue}}') -+ Traceback (most recent call last): -+ ... -+ TemplateError: continue outside of for loop at line 1 column 3 -+ >>> parse('{{if x}}foo') -+ Traceback (most recent call last): -+ ... -+ TemplateError: No {{endif}} at line 1 column 3 -+ >>> parse('{{else}}') -+ Traceback (most recent call last): -+ ... -+ TemplateError: else outside of an if block at line 1 column 3 -+ >>> parse('{{if x}}{{for x in y}}{{endif}}{{endfor}}') -+ Traceback (most recent call last): -+ ... -+ TemplateError: Unexpected endif at line 1 column 25 -+ >>> parse('{{if}}{{endif}}') -+ Traceback (most recent call last): -+ ... -+ TemplateError: if with no expression at line 1 column 3 -+ >>> parse('{{for x y}}{{endfor}}') -+ Traceback (most recent call last): -+ ... -+ TemplateError: Bad for (no "in") in 'x y' at line 1 column 3 -+ >>> parse('{{py:x=1\ny=2}}') -+ Traceback (most recent call last): -+ ... -+ TemplateError: Multi-line py blocks must start with a newline at line 1 column 3 -+ """ -+ tokens = lex(s, name=name) -+ result = [] -+ while tokens: -+ next, tokens = parse_expr(tokens, name) -+ result.append(next) -+ return result -+ -+def parse_expr(tokens, name, context=()): -+ if isinstance(tokens[0], basestring): -+ return tokens[0], tokens[1:] -+ expr, pos = tokens[0] -+ expr = expr.strip() -+ if expr.startswith('py:'): -+ expr = expr[3:].lstrip(' \t') -+ if expr.startswith('\n'): -+ expr = expr[1:] -+ else: -+ if '\n' in expr: -+ raise TemplateError( -+ 'Multi-line py blocks must start with a newline', -+ position=pos, name=name) -+ return ('py', pos, expr), tokens[1:] -+ elif expr in ('continue', 'break'): -+ if 'for' not in context: -+ raise TemplateError( -+ 'continue outside of for loop', -+ position=pos, name=name) -+ return (expr, pos), tokens[1:] -+ elif expr.startswith('if '): -+ return parse_cond(tokens, name, context) -+ elif (expr.startswith('elif ') -+ or expr == 'else'): -+ raise TemplateError( -+ '%s outside of an if block' % expr.split()[0], -+ position=pos, name=name) -+ elif expr in ('if', 'elif', 'for'): -+ raise TemplateError( -+ '%s with no expression' % expr, -+ position=pos, name=name) -+ elif expr in ('endif', 'endfor'): -+ raise TemplateError( -+ 'Unexpected %s' % expr, -+ position=pos, name=name) -+ elif expr.startswith('for '): -+ return parse_for(tokens, name, context) -+ elif expr.startswith('default '): -+ return parse_default(tokens, name, context) -+ elif expr.startswith('#'): -+ return ('comment', pos, tokens[0][0]), tokens[1:] -+ return ('expr', pos, tokens[0][0]), tokens[1:] -+ -+def parse_cond(tokens, name, context): -+ start = tokens[0][1] -+ pieces = [] -+ context = context + ('if',) -+ while 1: -+ if not tokens: -+ raise TemplateError( -+ 'Missing {{endif}}', -+ position=start, name=name) -+ if (isinstance(tokens[0], tuple) -+ and tokens[0][0] == 'endif'): -+ return ('cond', start) + tuple(pieces), tokens[1:] -+ next, tokens = parse_one_cond(tokens, name, context) -+ pieces.append(next) -+ -+def parse_one_cond(tokens, name, context): -+ (first, pos), tokens = tokens[0], tokens[1:] -+ content = [] -+ if first.endswith(':'): -+ first = first[:-1] -+ if first.startswith('if '): -+ part = ('if', pos, first[3:].lstrip(), content) -+ elif first.startswith('elif '): -+ part = ('elif', pos, first[5:].lstrip(), content) -+ elif first == 'else': -+ part = ('else', pos, None, content) -+ else: -+ assert 0, "Unexpected token %r at %s" % (first, pos) -+ while 1: -+ if not tokens: -+ raise TemplateError( -+ 'No {{endif}}', -+ position=pos, name=name) -+ if (isinstance(tokens[0], tuple) -+ and (tokens[0][0] == 'endif' -+ or tokens[0][0].startswith('elif ') -+ or tokens[0][0] == 'else')): -+ return part, tokens -+ next, tokens = parse_expr(tokens, name, context) -+ content.append(next) -+ -+def parse_for(tokens, name, context): -+ first, pos = tokens[0] -+ tokens = tokens[1:] -+ context = ('for',) + context -+ content = [] -+ assert first.startswith('for ') -+ if first.endswith(':'): -+ first = first[:-1] -+ first = first[3:].strip() -+ match = in_re.search(first) -+ if not match: -+ raise TemplateError( -+ 'Bad for (no "in") in %r' % first, -+ position=pos, name=name) -+ vars = first[:match.start()] -+ if '(' in vars: -+ raise TemplateError( -+ 'You cannot have () in the variable section of a for loop (%r)' -+ % vars, position=pos, name=name) -+ vars = tuple([ -+ v.strip() for v in first[:match.start()].split(',') -+ if v.strip()]) -+ expr = first[match.end():] -+ while 1: -+ if not tokens: -+ raise TemplateError( -+ 'No {{endfor}}', -+ position=pos, name=name) -+ if (isinstance(tokens[0], tuple) -+ and tokens[0][0] == 'endfor'): -+ return ('for', pos, vars, expr, content), tokens[1:] -+ next, tokens = parse_expr(tokens, name, context) -+ content.append(next) -+ -+def parse_default(tokens, name, context): -+ first, pos = tokens[0] -+ assert first.startswith('default ') -+ first = first.split(None, 1)[1] -+ parts = first.split('=', 1) -+ if len(parts) == 1: -+ raise TemplateError( -+ "Expression must be {{default var=value}}; no = found in %r" % first, -+ position=pos, name=name) -+ var = parts[0].strip() -+ if ',' in var: -+ raise TemplateError( -+ "{{default x, y = ...}} is not supported", -+ position=pos, name=name) -+ if not var_re.search(var): -+ raise TemplateError( -+ "Not a valid variable name for {{default}}: %r" -+ % var, position=pos, name=name) -+ expr = parts[1].strip() -+ return ('default', pos, var, expr), tokens[1:] -+ -+_fill_command_usage = """\ -+%prog [OPTIONS] TEMPLATE arg=value -+ -+Use py:arg=value to set a Python value; otherwise all values are -+strings. -+""" -+ -+def fill_command(args=None): -+ import sys, optparse, pkg_resources, os -+ if args is None: -+ args = sys.argv[1:] -+ dist = pkg_resources.get_distribution('Paste') -+ parser = optparse.OptionParser( -+ version=str(dist), -+ usage=_fill_command_usage) -+ parser.add_option( -+ '-o', '--output', -+ dest='output', -+ metavar="FILENAME", -+ help="File to write output to (default stdout)") -+ parser.add_option( -+ '--html', -+ dest='use_html', -+ action='store_true', -+ help="Use HTML style filling (including automatic HTML quoting)") -+ parser.add_option( -+ '--env', -+ dest='use_env', -+ action='store_true', -+ help="Put the environment in as top-level variables") -+ options, args = parser.parse_args(args) -+ if len(args) < 1: -+ print 'You must give a template filename' -+ print dir(parser) -+ assert 0 -+ template_name = args[0] -+ args = args[1:] -+ vars = {} -+ if options.use_env: -+ vars.update(os.environ) -+ for value in args: -+ if '=' not in value: -+ print 'Bad argument: %r' % value -+ sys.exit(2) -+ name, value = value.split('=', 1) -+ if name.startswith('py:'): -+ name = name[:3] -+ value = eval(value) -+ vars[name] = value -+ if template_name == '-': -+ template_content = sys.stdin.read() -+ template_name = '<stdin>' -+ else: -+ f = open(template_name, 'rb') -+ template_content = f.read() -+ f.close() -+ if options.use_html: -+ TemplateClass = HTMLTemplate -+ else: -+ TemplateClass = Template -+ template = TemplateClass(template_content, name=template_name) -+ result = template.substitute(vars) -+ if options.output: -+ f = open(options.output, 'wb') -+ f.write(result) -+ f.close() -+ else: -+ sys.stdout.write(result) -+ -+if __name__ == '__main__': -+ from paste.util.template import fill_command -+ fill_command() -+ -+ -Index: Paste-1.7.4/paste/util/template.py -=================================================================== ---- Paste-1.7.4.orig/paste/util/template.py -+++ /dev/null -@@ -1,758 +0,0 @@ --""" --A small templating language -- --This implements a small templating language for use internally in --Paste and Paste Script. This language implements if/elif/else, --for/continue/break, expressions, and blocks of Python code. The --syntax is:: -- -- {{any expression (function calls etc)}} -- {{any expression | filter}} -- {{for x in y}}...{{endfor}} -- {{if x}}x{{elif y}}y{{else}}z{{endif}} -- {{py:x=1}} -- {{py: -- def foo(bar): -- return 'baz' -- }} -- {{default var = default_value}} -- {{# comment}} -- --You use this with the ``Template`` class or the ``sub`` shortcut. --The ``Template`` class takes the template string and the name of --the template (for errors) and a default namespace. Then (like --``string.Template``) you can call the ``tmpl.substitute(**kw)`` --method to make a substitution (or ``tmpl.substitute(a_dict)``). -- --``sub(content, **kw)`` substitutes the template immediately. You --can use ``__name='tmpl.html'`` to set the name of the template. -- --If there are syntax errors ``TemplateError`` will be raised. --""" -- --import re --import sys --import cgi --import urllib --from paste.util.looper import looper -- --__all__ = ['TemplateError', 'Template', 'sub', 'HTMLTemplate', -- 'sub_html', 'html', 'bunch'] -- --token_re = re.compile(r'\{\{|\}\}') --in_re = re.compile(r'\s+in\s+') --var_re = re.compile(r'^[a-z_][a-z0-9_]*$', re.I) -- --class TemplateError(Exception): -- """Exception raised while parsing a template -- """ -- -- def __init__(self, message, position, name=None): -- self.message = message -- self.position = position -- self.name = name -- -- def __str__(self): -- msg = '%s at line %s column %s' % ( -- self.message, self.position[0], self.position[1]) -- if self.name: -- msg += ' in %s' % self.name -- return msg -- --class _TemplateContinue(Exception): -- pass -- --class _TemplateBreak(Exception): -- pass -- --class Template(object): -- -- default_namespace = { -- 'start_braces': '{{', -- 'end_braces': '}}', -- 'looper': looper, -- } -- -- default_encoding = 'utf8' -- -- def __init__(self, content, name=None, namespace=None): -- self.content = content -- self._unicode = isinstance(content, unicode) -- self.name = name -- self._parsed = parse(content, name=name) -- if namespace is None: -- namespace = {} -- self.namespace = namespace -- -- def from_filename(cls, filename, namespace=None, encoding=None): -- f = open(filename, 'rb') -- c = f.read() -- f.close() -- if encoding: -- c = c.decode(encoding) -- return cls(content=c, name=filename, namespace=namespace) -- -- from_filename = classmethod(from_filename) -- -- def __repr__(self): -- return '<%s %s name=%r>' % ( -- self.__class__.__name__, -- hex(id(self))[2:], self.name) -- -- def substitute(self, *args, **kw): -- if args: -- if kw: -- raise TypeError( -- "You can only give positional *or* keyword arguments") -- if len(args) > 1: -- raise TypeError( -- "You can only give on positional argument") -- kw = args[0] -- ns = self.default_namespace.copy() -- ns.update(self.namespace) -- ns.update(kw) -- result = self._interpret(ns) -- return result -- -- def _interpret(self, ns): -- __traceback_hide__ = True -- parts = [] -- self._interpret_codes(self._parsed, ns, out=parts) -- return ''.join(parts) -- -- def _interpret_codes(self, codes, ns, out): -- __traceback_hide__ = True -- for item in codes: -- if isinstance(item, basestring): -- out.append(item) -- else: -- self._interpret_code(item, ns, out) -- -- def _interpret_code(self, code, ns, out): -- __traceback_hide__ = True -- name, pos = code[0], code[1] -- if name == 'py': -- self._exec(code[2], ns, pos) -- elif name == 'continue': -- raise _TemplateContinue() -- elif name == 'break': -- raise _TemplateBreak() -- elif name == 'for': -- vars, expr, content = code[2], code[3], code[4] -- expr = self._eval(expr, ns, pos) -- self._interpret_for(vars, expr, content, ns, out) -- elif name == 'cond': -- parts = code[2:] -- self._interpret_if(parts, ns, out) -- elif name == 'expr': -- parts = code[2].split('|') -- base = self._eval(parts[0], ns, pos) -- for part in parts[1:]: -- func = self._eval(part, ns, pos) -- base = func(base) -- out.append(self._repr(base, pos)) -- elif name == 'default': -- var, expr = code[2], code[3] -- if var not in ns: -- result = self._eval(expr, ns, pos) -- ns[var] = result -- elif name == 'comment': -- return -- else: -- assert 0, "Unknown code: %r" % name -- -- def _interpret_for(self, vars, expr, content, ns, out): -- __traceback_hide__ = True -- for item in expr: -- if len(vars) == 1: -- ns[vars[0]] = item -- else: -- if len(vars) != len(item): -- raise ValueError( -- 'Need %i items to unpack (got %i items)' -- % (len(vars), len(item))) -- for name, value in zip(vars, item): -- ns[name] = value -- try: -- self._interpret_codes(content, ns, out) -- except _TemplateContinue: -- continue -- except _TemplateBreak: -- break -- -- def _interpret_if(self, parts, ns, out): -- __traceback_hide__ = True -- # @@: if/else/else gets through -- for part in parts: -- assert not isinstance(part, basestring) -- name, pos = part[0], part[1] -- if name == 'else': -- result = True -- else: -- result = self._eval(part[2], ns, pos) -- if result: -- self._interpret_codes(part[3], ns, out) -- break -- -- def _eval(self, code, ns, pos): -- __traceback_hide__ = True -- try: -- value = eval(code, ns) -- return value -- except: -- exc_info = sys.exc_info() -- e = exc_info[1] -- if getattr(e, 'args'): -- arg0 = e.args[0] -- else: -- arg0 = str(e) -- e.args = (self._add_line_info(arg0, pos),) -- raise exc_info[0], e, exc_info[2] -- -- def _exec(self, code, ns, pos): -- __traceback_hide__ = True -- try: -- exec code in ns -- except: -- exc_info = sys.exc_info() -- e = exc_info[1] -- e.args = (self._add_line_info(e.args[0], pos),) -- raise exc_info[0], e, exc_info[2] -- -- def _repr(self, value, pos): -- __traceback_hide__ = True -- try: -- if value is None: -- return '' -- if self._unicode: -- try: -- value = unicode(value) -- except UnicodeDecodeError: -- value = str(value) -- else: -- value = str(value) -- except: -- exc_info = sys.exc_info() -- e = exc_info[1] -- e.args = (self._add_line_info(e.args[0], pos),) -- raise exc_info[0], e, exc_info[2] -- else: -- if self._unicode and isinstance(value, str): -- if not self.decode_encoding: -- raise UnicodeDecodeError( -- 'Cannot decode str value %r into unicode ' -- '(no default_encoding provided)' % value) -- value = value.decode(self.default_encoding) -- elif not self._unicode and isinstance(value, unicode): -- if not self.decode_encoding: -- raise UnicodeEncodeError( -- 'Cannot encode unicode value %r into str ' -- '(no default_encoding provided)' % value) -- value = value.encode(self.default_encoding) -- return value -- -- -- def _add_line_info(self, msg, pos): -- msg = "%s at line %s column %s" % ( -- msg, pos[0], pos[1]) -- if self.name: -- msg += " in file %s" % self.name -- return msg -- --def sub(content, **kw): -- name = kw.get('__name') -- tmpl = Template(content, name=name) -- return tmpl.substitute(kw) -- return result -- --def paste_script_template_renderer(content, vars, filename=None): -- tmpl = Template(content, name=filename) -- return tmpl.substitute(vars) -- --class bunch(dict): -- -- def __init__(self, **kw): -- for name, value in kw.items(): -- setattr(self, name, value) -- -- def __setattr__(self, name, value): -- self[name] = value -- -- def __getattr__(self, name): -- try: -- return self[name] -- except KeyError: -- raise AttributeError(name) -- -- def __getitem__(self, key): -- if 'default' in self: -- try: -- return dict.__getitem__(self, key) -- except KeyError: -- return dict.__getitem__(self, 'default') -- else: -- return dict.__getitem__(self, key) -- -- def __repr__(self): -- items = [ -- (k, v) for k, v in self.items()] -- items.sort() -- return '<%s %s>' % ( -- self.__class__.__name__, -- ' '.join(['%s=%r' % (k, v) for k, v in items])) -- --############################################################ --## HTML Templating --############################################################ -- --class html(object): -- def __init__(self, value): -- self.value = value -- def __str__(self): -- return self.value -- def __repr__(self): -- return '<%s %r>' % ( -- self.__class__.__name__, self.value) -- --def html_quote(value): -- if value is None: -- return '' -- if not isinstance(value, basestring): -- if hasattr(value, '__unicode__'): -- value = unicode(value) -- else: -- value = str(value) -- value = cgi.escape(value, 1) -- if isinstance(value, unicode): -- value = value.encode('ascii', 'xmlcharrefreplace') -- return value -- --def url(v): -- if not isinstance(v, basestring): -- if hasattr(v, '__unicode__'): -- v = unicode(v) -- else: -- v = str(v) -- if isinstance(v, unicode): -- v = v.encode('utf8') -- return urllib.quote(v) -- --def attr(**kw): -- kw = kw.items() -- kw.sort() -- parts = [] -- for name, value in kw: -- if value is None: -- continue -- if name.endswith('_'): -- name = name[:-1] -- parts.append('%s="%s"' % (html_quote(name), html_quote(value))) -- return html(' '.join(parts)) -- --class HTMLTemplate(Template): -- -- default_namespace = Template.default_namespace.copy() -- default_namespace.update(dict( -- html=html, -- attr=attr, -- url=url, -- )) -- -- def _repr(self, value, pos): -- plain = Template._repr(self, value, pos) -- if isinstance(value, html): -- return plain -- else: -- return html_quote(plain) -- --def sub_html(content, **kw): -- name = kw.get('__name') -- tmpl = HTMLTemplate(content, name=name) -- return tmpl.substitute(kw) -- return result -- -- --############################################################ --## Lexing and Parsing --############################################################ -- --def lex(s, name=None, trim_whitespace=True): -- """ -- Lex a string into chunks: -- -- >>> lex('hey') -- ['hey'] -- >>> lex('hey {{you}}') -- ['hey ', ('you', (1, 7))] -- >>> lex('hey {{') -- Traceback (most recent call last): -- ... -- TemplateError: No }} to finish last expression at line 1 column 7 -- >>> lex('hey }}') -- Traceback (most recent call last): -- ... -- TemplateError: }} outside expression at line 1 column 7 -- >>> lex('hey {{ {{') -- Traceback (most recent call last): -- ... -- TemplateError: {{ inside expression at line 1 column 10 -- -- """ -- in_expr = False -- chunks = [] -- last = 0 -- last_pos = (1, 1) -- for match in token_re.finditer(s): -- expr = match.group(0) -- pos = find_position(s, match.end()) -- if expr == '{{' and in_expr: -- raise TemplateError('{{ inside expression', position=pos, -- name=name) -- elif expr == '}}' and not in_expr: -- raise TemplateError('}} outside expression', position=pos, -- name=name) -- if expr == '{{': -- part = s[last:match.start()] -- if part: -- chunks.append(part) -- in_expr = True -- else: -- chunks.append((s[last:match.start()], last_pos)) -- in_expr = False -- last = match.end() -- last_pos = pos -- if in_expr: -- raise TemplateError('No }} to finish last expression', -- name=name, position=last_pos) -- part = s[last:] -- if part: -- chunks.append(part) -- if trim_whitespace: -- chunks = trim_lex(chunks) -- return chunks -- --statement_re = re.compile(r'^(?:if |elif |else |for |py:)') --single_statements = ['endif', 'endfor', 'continue', 'break'] --trail_whitespace_re = re.compile(r'\n[\t ]*$') --lead_whitespace_re = re.compile(r'^[\t ]*\n') -- --def trim_lex(tokens): -- r""" -- Takes a lexed set of tokens, and removes whitespace when there is -- a directive on a line by itself: -- -- >>> tokens = lex('{{if x}}\nx\n{{endif}}\ny', trim_whitespace=False) -- >>> tokens -- [('if x', (1, 3)), '\nx\n', ('endif', (3, 3)), '\ny'] -- >>> trim_lex(tokens) -- [('if x', (1, 3)), 'x\n', ('endif', (3, 3)), 'y'] -- """ -- for i in range(len(tokens)): -- current = tokens[i] -- if isinstance(tokens[i], basestring): -- # we don't trim this -- continue -- item = current[0] -- if not statement_re.search(item) and item not in single_statements: -- continue -- if not i: -- prev = '' -- else: -- prev = tokens[i-1] -- if i+1 >= len(tokens): -- next = '' -- else: -- next = tokens[i+1] -- if (not isinstance(next, basestring) -- or not isinstance(prev, basestring)): -- continue -- if ((not prev or trail_whitespace_re.search(prev)) -- and (not next or lead_whitespace_re.search(next))): -- if prev: -- m = trail_whitespace_re.search(prev) -- # +1 to leave the leading \n on: -- prev = prev[:m.start()+1] -- tokens[i-1] = prev -- if next: -- m = lead_whitespace_re.search(next) -- next = next[m.end():] -- tokens[i+1] = next -- return tokens -- -- --def find_position(string, index): -- """Given a string and index, return (line, column)""" -- leading = string[:index].splitlines() -- return (len(leading), len(leading[-1])+1) -- --def parse(s, name=None): -- r""" -- Parses a string into a kind of AST -- -- >>> parse('{{x}}') -- [('expr', (1, 3), 'x')] -- >>> parse('foo') -- ['foo'] -- >>> parse('{{if x}}test{{endif}}') -- [('cond', (1, 3), ('if', (1, 3), 'x', ['test']))] -- >>> parse('series->{{for x in y}}x={{x}}{{endfor}}') -- ['series->', ('for', (1, 11), ('x',), 'y', ['x=', ('expr', (1, 27), 'x')])] -- >>> parse('{{for x, y in z:}}{{continue}}{{endfor}}') -- [('for', (1, 3), ('x', 'y'), 'z', [('continue', (1, 21))])] -- >>> parse('{{py:x=1}}') -- [('py', (1, 3), 'x=1')] -- >>> parse('{{if x}}a{{elif y}}b{{else}}c{{endif}}') -- [('cond', (1, 3), ('if', (1, 3), 'x', ['a']), ('elif', (1, 12), 'y', ['b']), ('else', (1, 23), None, ['c']))] -- -- Some exceptions:: -- -- >>> parse('{{continue}}') -- Traceback (most recent call last): -- ... -- TemplateError: continue outside of for loop at line 1 column 3 -- >>> parse('{{if x}}foo') -- Traceback (most recent call last): -- ... -- TemplateError: No {{endif}} at line 1 column 3 -- >>> parse('{{else}}') -- Traceback (most recent call last): -- ... -- TemplateError: else outside of an if block at line 1 column 3 -- >>> parse('{{if x}}{{for x in y}}{{endif}}{{endfor}}') -- Traceback (most recent call last): -- ... -- TemplateError: Unexpected endif at line 1 column 25 -- >>> parse('{{if}}{{endif}}') -- Traceback (most recent call last): -- ... -- TemplateError: if with no expression at line 1 column 3 -- >>> parse('{{for x y}}{{endfor}}') -- Traceback (most recent call last): -- ... -- TemplateError: Bad for (no "in") in 'x y' at line 1 column 3 -- >>> parse('{{py:x=1\ny=2}}') -- Traceback (most recent call last): -- ... -- TemplateError: Multi-line py blocks must start with a newline at line 1 column 3 -- """ -- tokens = lex(s, name=name) -- result = [] -- while tokens: -- next, tokens = parse_expr(tokens, name) -- result.append(next) -- return result -- --def parse_expr(tokens, name, context=()): -- if isinstance(tokens[0], basestring): -- return tokens[0], tokens[1:] -- expr, pos = tokens[0] -- expr = expr.strip() -- if expr.startswith('py:'): -- expr = expr[3:].lstrip(' \t') -- if expr.startswith('\n'): -- expr = expr[1:] -- else: -- if '\n' in expr: -- raise TemplateError( -- 'Multi-line py blocks must start with a newline', -- position=pos, name=name) -- return ('py', pos, expr), tokens[1:] -- elif expr in ('continue', 'break'): -- if 'for' not in context: -- raise TemplateError( -- 'continue outside of for loop', -- position=pos, name=name) -- return (expr, pos), tokens[1:] -- elif expr.startswith('if '): -- return parse_cond(tokens, name, context) -- elif (expr.startswith('elif ') -- or expr == 'else'): -- raise TemplateError( -- '%s outside of an if block' % expr.split()[0], -- position=pos, name=name) -- elif expr in ('if', 'elif', 'for'): -- raise TemplateError( -- '%s with no expression' % expr, -- position=pos, name=name) -- elif expr in ('endif', 'endfor'): -- raise TemplateError( -- 'Unexpected %s' % expr, -- position=pos, name=name) -- elif expr.startswith('for '): -- return parse_for(tokens, name, context) -- elif expr.startswith('default '): -- return parse_default(tokens, name, context) -- elif expr.startswith('#'): -- return ('comment', pos, tokens[0][0]), tokens[1:] -- return ('expr', pos, tokens[0][0]), tokens[1:] -- --def parse_cond(tokens, name, context): -- start = tokens[0][1] -- pieces = [] -- context = context + ('if',) -- while 1: -- if not tokens: -- raise TemplateError( -- 'Missing {{endif}}', -- position=start, name=name) -- if (isinstance(tokens[0], tuple) -- and tokens[0][0] == 'endif'): -- return ('cond', start) + tuple(pieces), tokens[1:] -- next, tokens = parse_one_cond(tokens, name, context) -- pieces.append(next) -- --def parse_one_cond(tokens, name, context): -- (first, pos), tokens = tokens[0], tokens[1:] -- content = [] -- if first.endswith(':'): -- first = first[:-1] -- if first.startswith('if '): -- part = ('if', pos, first[3:].lstrip(), content) -- elif first.startswith('elif '): -- part = ('elif', pos, first[5:].lstrip(), content) -- elif first == 'else': -- part = ('else', pos, None, content) -- else: -- assert 0, "Unexpected token %r at %s" % (first, pos) -- while 1: -- if not tokens: -- raise TemplateError( -- 'No {{endif}}', -- position=pos, name=name) -- if (isinstance(tokens[0], tuple) -- and (tokens[0][0] == 'endif' -- or tokens[0][0].startswith('elif ') -- or tokens[0][0] == 'else')): -- return part, tokens -- next, tokens = parse_expr(tokens, name, context) -- content.append(next) -- --def parse_for(tokens, name, context): -- first, pos = tokens[0] -- tokens = tokens[1:] -- context = ('for',) + context -- content = [] -- assert first.startswith('for ') -- if first.endswith(':'): -- first = first[:-1] -- first = first[3:].strip() -- match = in_re.search(first) -- if not match: -- raise TemplateError( -- 'Bad for (no "in") in %r' % first, -- position=pos, name=name) -- vars = first[:match.start()] -- if '(' in vars: -- raise TemplateError( -- 'You cannot have () in the variable section of a for loop (%r)' -- % vars, position=pos, name=name) -- vars = tuple([ -- v.strip() for v in first[:match.start()].split(',') -- if v.strip()]) -- expr = first[match.end():] -- while 1: -- if not tokens: -- raise TemplateError( -- 'No {{endfor}}', -- position=pos, name=name) -- if (isinstance(tokens[0], tuple) -- and tokens[0][0] == 'endfor'): -- return ('for', pos, vars, expr, content), tokens[1:] -- next, tokens = parse_expr(tokens, name, context) -- content.append(next) -- --def parse_default(tokens, name, context): -- first, pos = tokens[0] -- assert first.startswith('default ') -- first = first.split(None, 1)[1] -- parts = first.split('=', 1) -- if len(parts) == 1: -- raise TemplateError( -- "Expression must be {{default var=value}}; no = found in %r" % first, -- position=pos, name=name) -- var = parts[0].strip() -- if ',' in var: -- raise TemplateError( -- "{{default x, y = ...}} is not supported", -- position=pos, name=name) -- if not var_re.search(var): -- raise TemplateError( -- "Not a valid variable name for {{default}}: %r" -- % var, position=pos, name=name) -- expr = parts[1].strip() -- return ('default', pos, var, expr), tokens[1:] -- --_fill_command_usage = """\ --%prog [OPTIONS] TEMPLATE arg=value -- --Use py:arg=value to set a Python value; otherwise all values are --strings. --""" -- --def fill_command(args=None): -- import sys, optparse, pkg_resources, os -- if args is None: -- args = sys.argv[1:] -- dist = pkg_resources.get_distribution('Paste') -- parser = optparse.OptionParser( -- version=str(dist), -- usage=_fill_command_usage) -- parser.add_option( -- '-o', '--output', -- dest='output', -- metavar="FILENAME", -- help="File to write output to (default stdout)") -- parser.add_option( -- '--html', -- dest='use_html', -- action='store_true', -- help="Use HTML style filling (including automatic HTML quoting)") -- parser.add_option( -- '--env', -- dest='use_env', -- action='store_true', -- help="Put the environment in as top-level variables") -- options, args = parser.parse_args(args) -- if len(args) < 1: -- print 'You must give a template filename' -- print dir(parser) -- assert 0 -- template_name = args[0] -- args = args[1:] -- vars = {} -- if options.use_env: -- vars.update(os.environ) -- for value in args: -- if '=' not in value: -- print 'Bad argument: %r' % value -- sys.exit(2) -- name, value = value.split('=', 1) -- if name.startswith('py:'): -- name = name[:3] -- value = eval(value) -- vars[name] = value -- if template_name == '-': -- template_content = sys.stdin.read() -- template_name = '<stdin>' -- else: -- f = open(template_name, 'rb') -- template_content = f.read() -- f.close() -- if options.use_html: -- TemplateClass = HTMLTemplate -- else: -- TemplateClass = Template -- template = TemplateClass(template_content, name=template_name) -- result = template.substitute(vars) -- if options.output: -- f = open(options.output, 'wb') -- f.write(result) -- f.close() -- else: -- sys.stdout.write(result) -- --if __name__ == '__main__': -- from paste.util.template import fill_command -- fill_command() -- -- diff --git a/dev-python/paste/files/paste-1.7.5.1-userdict.patch b/dev-python/paste/files/paste-1.7.5.1-userdict.patch deleted file mode 100644 index 061f38a52828..000000000000 --- a/dev-python/paste/files/paste-1.7.5.1-userdict.patch +++ /dev/null @@ -1,64 +0,0 @@ ---- a/paste/debug/fsdiff.py -+++ b/paste/debug/fsdiff.py -@@ -12,10 +12,14 @@ - import os - from fnmatch import fnmatch - from datetime import datetime -+ - try: -- from UserDict import IterableUserDict -+ import collections.UserDict as IterableUserDict - except ImportError: -- from paste.util.UserDict24 import IterableUserDict -+ try: -+ from UserDict import IterableUserDict -+ except ImportError: -+ from paste.util.UserDict24 import IterableUserDict - import operator - import re - ---- a/paste/request.py -+++ b/paste/request.py -@@ -22,10 +22,12 @@ - from StringIO import StringIO - import urlparse - import urllib -+ - try: - from UserDict import DictMixin - except ImportError: -- from paste.util.UserDict24 import DictMixin -+ from collections import MutableMapping as DictMixin -+ - from paste.util.multidict import MultiDict - - __all__ = ['get_cookies', 'get_cookie_dict', 'parse_querystring', ---- a/paste/urlmap.py -+++ b/paste/urlmap.py -@@ -4,7 +4,10 @@ - Map URL prefixes to WSGI applications. See ``URLMap`` - """ - --from UserDict import DictMixin -+try: -+ from UserDict import DictMixin -+except ImportError: -+ from collections import MutableMapping as DictMixin - import re - import os - import cgi ---- a/paste/util/multidict.py -+++ b/paste/util/multidict.py -@@ -3,7 +3,11 @@ - import cgi - import copy - import sys --from UserDict import DictMixin -+ -+try: -+ from UserDict import DictMixin -+except ImportError: -+ from collections import MutableMapping as DictMixin - - class MultiDict(DictMixin): - diff --git a/dev-python/paste/files/paste-2.0.2-unbundle-tempita.patch b/dev-python/paste/files/paste-2.0.2-unbundle-tempita.patch deleted file mode 100644 index eef7abb4108e..000000000000 --- a/dev-python/paste/files/paste-2.0.2-unbundle-tempita.patch +++ /dev/null @@ -1,36 +0,0 @@ - paste/util/looper/__init__.py | 4 ++++ - paste/util/{looper.py => looper/_looper.py} | 0 - paste/util/template/__init__.py | 6 ++++++ - paste/util/{template.py => template/_template.py} | 0 - 4 files changed, 10 insertions(+) - -diff --git a/paste/util/looper/__init__.py b/paste/util/looper/__init__.py -new file mode 100644 -index 0000000..77d7e80 ---- /dev/null -+++ b/paste/util/looper/__init__.py -@@ -0,0 +1,4 @@ -+try: -+ from tempita._looper import * -+except ImportError: -+ from _looper import * -diff --git a/paste/util/looper.py b/paste/util/looper/_looper.py -similarity index 100% -rename from paste/util/looper.py -rename to paste/util/looper/_looper.py -diff --git a/paste/util/template/__init__.py b/paste/util/template/__init__.py -new file mode 100644 -index 0000000..a0a5730 ---- /dev/null -+++ b/paste/util/template/__init__.py -@@ -0,0 +1,6 @@ -+try: -+ from tempita import * -+ from tempita import paste_script_template_renderer -+except ImportError: -+ from _template import * -+ from _template import paste_script_template_renderer -diff --git a/paste/util/template.py b/paste/util/template/_template.py -similarity index 100% -rename from paste/util/template.py -rename to paste/util/template/_template.py diff --git a/dev-python/paste/paste-1.7.5.1-r1.ebuild b/dev-python/paste/paste-1.7.5.1-r1.ebuild deleted file mode 100644 index 73404bc36123..000000000000 --- a/dev-python/paste/paste-1.7.5.1-r1.ebuild +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 1999-2017 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 - -EAPI=5 - -PYTHON_COMPAT=( python2_7 ) - -inherit distutils-r1 - -MY_PN="Paste" -MY_P="${MY_PN}-${PV}" - -DESCRIPTION="Tools for using a Web Server Gateway Interface stack" -HOMEPAGE="http://pythonpaste.org https://pypi.python.org/pypi/Paste" -SRC_URI="mirror://pypi/${MY_PN:0:1}/${MY_PN}/${MY_P}.tar.gz" - -LICENSE="MIT" -SLOT="0" -KEYWORDS="amd64 ~ppc ~ppc64 x86 ~amd64-linux ~x86-linux ~x64-macos ~x86-macos ~sparc-solaris" -IUSE="doc flup openid" - -RDEPEND="dev-python/setuptools[${PYTHON_USEDEP}] - flup? ( dev-python/flup[${PYTHON_USEDEP}] ) - openid? ( dev-python/python-openid[${PYTHON_USEDEP}] )" -DEPEND="${RDEPEND} - doc? ( dev-python/sphinx[${PYTHON_USEDEP}] )" - -S="${WORKDIR}/${MY_P}" - -python_prepare_all() { - # Disable failing tests. - rm -f tests/test_cgiapp.py - sed \ - -e "s/test_find_file/_&/" \ - -e "s/test_deep/_&/" \ - -e "s/test_static_parser/_&/" \ - -i tests/test_urlparser.py || die "sed failed" - - # Remove a test that runs against the paste website. - rm -f tests/test_proxy.py - - local PATCHES=( - "${FILESDIR}/${P}-fix-tests-for-pypy.patch" - ) - - distutils-r1_python_prepare_all -} - -python_compile() { - distutils-r1_python_compile egg_info --egg-base "${BUILD_DIR}/lib" -} - -python_compile_all() { - use doc && esetup.py build_sphinx -} - -python_test() { - nosetests -P || die "Tests fail with ${EPYTHON}" -} - -python_install() { - distutils-r1_python_install egg_info --egg-base "${BUILD_DIR}/lib" -} - -python_install_all() { - use doc && local HTML_DOCS=( "${BUILD_DIR}"/sphinx/html/. ) - distutils-r1_python_install_all -} diff --git a/dev-python/paste/paste-1.7.5.1-r2.ebuild b/dev-python/paste/paste-1.7.5.1-r2.ebuild deleted file mode 100644 index 97d245743463..000000000000 --- a/dev-python/paste/paste-1.7.5.1-r2.ebuild +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright 1999-2017 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 - -EAPI=5 - -PYTHON_COMPAT=( python2_7 ) -# notes wrt py-3 compatibility: -# Debian ships paste for py3 using 2to3. Many tests fail when using such converted code and -# the fact that the errors are sometimes nested inside paste indicate that the -# result is indeed broken. Upstream is not responsive nor interested in porting. - -inherit distutils-r1 - -MY_PN="Paste" -MY_P="${MY_PN}-${PV}" - -DESCRIPTION="Tools for using a Web Server Gateway Interface stack" -HOMEPAGE="http://pythonpaste.org https://pypi.python.org/pypi/Paste" -SRC_URI="mirror://pypi/${MY_PN:0:1}/${MY_PN}/${MY_P}.tar.gz" - -LICENSE="MIT" -SLOT="0" -KEYWORDS="~amd64 ~ppc ~ppc64 ~x86 ~amd64-linux ~x86-linux ~x64-macos ~x86-macos ~sparc-solaris" -IUSE="doc flup openid" - -RDEPEND="dev-python/setuptools[${PYTHON_USEDEP}] - >=dev-python/tempita-0.5.2_pre20130828[${PYTHON_USEDEP}] - flup? ( dev-python/flup[${PYTHON_USEDEP}] ) - openid? ( dev-python/python-openid[${PYTHON_USEDEP}] )" -DEPEND="${RDEPEND} - doc? ( dev-python/sphinx[${PYTHON_USEDEP}] )" - -S="${WORKDIR}/${MY_P}" - -python_prepare_all() { - # Disable failing tests. - rm -f tests/test_cgiapp.py - sed \ - -e "s/test_find_file/_&/" \ - -e "s/test_deep/_&/" \ - -e "s/test_static_parser/_&/" \ - -i tests/test_urlparser.py || die "sed failed" - - # Remove a test that runs against the paste website. - rm -f tests/test_proxy.py - - local PATCHES=( - "${FILESDIR}/${P}-fix-tests-for-pypy.patch" - "${FILESDIR}/${P}-python27-lambda.patch" - "${FILESDIR}/${P}-unbundle-stdlib.patch" - "${FILESDIR}/${P}-unbundle-tempita.patch" - "${FILESDIR}/${P}-userdict.patch" - "${FILESDIR}/${P}-rfc822.patch" - "${FILESDIR}/${P}-email-mime.patch" - "${FILESDIR}/${P}-types.patch" - "${FILESDIR}/${P}-hmac.patch" - ) - - distutils-r1_python_prepare_all -} - -python_compile() { - distutils-r1_python_compile egg_info --egg-base "${BUILD_DIR}/lib" -} - -python_compile_all() { - use doc && esetup.py build_sphinx -} - -python_test() { - nosetests -P || die "Tests fail with ${EPYTHON}" -} - -python_install() { - distutils-r1_python_install egg_info --egg-base "${BUILD_DIR}/lib" -} - -python_install_all() { - use doc && local HTML_DOCS=( "${BUILD_DIR}"/sphinx/html/. ) - distutils-r1_python_install_all -} diff --git a/dev-python/paste/paste-2.0.2.ebuild b/dev-python/paste/paste-2.0.2.ebuild deleted file mode 100644 index 0dd0762b9fb3..000000000000 --- a/dev-python/paste/paste-2.0.2.ebuild +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright 1999-2017 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 - -EAPI=5 - -PYTHON_COMPAT=( python2_7 python3_{4,5} ) - -inherit distutils-r1 - -MY_PN="Paste" -MY_P="${MY_PN}-${PV}" - -DESCRIPTION="Tools for using a Web Server Gateway Interface stack" -HOMEPAGE="http://pythonpaste.org https://pypi.python.org/pypi/Paste" -SRC_URI="mirror://pypi/${MY_PN:0:1}/${MY_PN}/${MY_P}.tar.gz" - -LICENSE="MIT" -SLOT="0" -KEYWORDS="amd64 ~arm64 ~ppc ~ppc64 x86 ~amd64-linux ~x86-linux ~x64-macos ~x86-macos ~sparc-solaris" -IUSE="doc flup openid" - -RDEPEND=" - dev-python/six[${PYTHON_USEDEP}] - >=dev-python/tempita-0.5.2_pre20130828[${PYTHON_USEDEP}] - flup? ( dev-python/flup[$(python_gen_usedep 'python2*')] ) - openid? ( dev-python/python-openid[$(python_gen_usedep 'python2*')] )" -DEPEND="${RDEPEND} - dev-python/setuptools[${PYTHON_USEDEP}] - doc? ( dev-python/sphinx[${PYTHON_USEDEP}] )" - -S="${WORKDIR}/${MY_P}" - -python_prepare_all() { - # Disable failing tests. - rm -f tests/test_cgiapp.py || die - sed \ - -e "s/test_find_file/_&/" \ - -e "s/test_deep/_&/" \ - -e "s/test_static_parser/_&/" \ - -i tests/test_urlparser.py || die "sed failed" - - # Remove a test that runs against the paste website. - rm -f tests/test_proxy.py || die - - local PATCHES=( - "${FILESDIR}"/${PN}-1.7.5.1-fix-tests-for-pypy.patch - "${FILESDIR}"/${P}-unbundle-tempita.patch - ) - - distutils-r1_python_prepare_all -} - -python_compile() { - distutils-r1_python_compile egg_info --egg-base "${BUILD_DIR}/lib" -} - -python_compile_all() { - use doc && esetup.py build_sphinx -} - -python_test() { - nosetests -P -v || die "Tests fail with ${EPYTHON}" -} - -python_install() { - distutils-r1_python_install egg_info --egg-base "${BUILD_DIR}/lib" -} - -python_install_all() { - use doc && local HTML_DOCS=( "${BUILD_DIR}"/sphinx/html/. ) - distutils-r1_python_install_all -} |