summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dev-python/paste/Manifest2
-rw-r--r--dev-python/paste/files/paste-1.7.5.1-email-mime.patch19
-rw-r--r--dev-python/paste/files/paste-1.7.5.1-fix-tests-for-pypy.patch24
-rw-r--r--dev-python/paste/files/paste-1.7.5.1-hmac.patch11
-rw-r--r--dev-python/paste/files/paste-1.7.5.1-python27-lambda.patch12
-rw-r--r--dev-python/paste/files/paste-1.7.5.1-rfc822.patch14
-rw-r--r--dev-python/paste/files/paste-1.7.5.1-types.patch57
-rw-r--r--dev-python/paste/files/paste-1.7.5.1-unbundle-stdlib.patch1211
-rw-r--r--dev-python/paste/files/paste-1.7.5.1-unbundle-tempita.patch1860
-rw-r--r--dev-python/paste/files/paste-1.7.5.1-userdict.patch64
-rw-r--r--dev-python/paste/files/paste-2.0.2-unbundle-tempita.patch36
-rw-r--r--dev-python/paste/paste-1.7.5.1-r1.ebuild68
-rw-r--r--dev-python/paste/paste-1.7.5.1-r2.ebuild81
-rw-r--r--dev-python/paste/paste-2.0.2.ebuild72
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
-}