Permalink
Browse files

Added support for Python 2.5.

  • Loading branch information...
malthe committed Feb 25, 2011
1 parent 8d7211b commit 325607b0ad856b576e1db374ad4364596d49fd99
View
@@ -3,3 +3,5 @@ Copyright (c) 2011 Malthe Borch and Contributors. All Rights Reserved.
Portions (c) Zope Foundation and contributors (http://www.zope.org/).
Portions (c) Edgewall Software.
+
+Portions (c) 2008 Armin Ronacher.
View
@@ -130,3 +130,56 @@ licensed under this license):
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Portions of the code in Chameleon are supplied under the Python
+License (headers within individiual files indicate that these portions
+are licensed under this license):
+
+ PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
+ --------------------------------------------
+
+ 1. This LICENSE AGREEMENT is between the Python Software Foundation
+ ("PSF"), and the Individual or Organization ("Licensee") accessing and
+ otherwise using this software ("Python") in source or binary form and
+ its associated documentation.
+
+ 2. Subject to the terms and conditions of this License Agreement, PSF
+ hereby grants Licensee a nonexclusive, royalty-free, world-wide
+ license to reproduce, analyze, test, perform and/or display publicly,
+ prepare derivative works, distribute, and otherwise use Python
+ alone or in any derivative version, provided, however, that PSF's
+ License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
+ 2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved"
+ are retained in Python alone or in any derivative version prepared
+ by Licensee.
+
+ 3. In the event Licensee prepares a derivative work that is based on
+ or incorporates Python or any part thereof, and wants to make
+ the derivative work available to others as provided herein, then
+ Licensee hereby agrees to include in any such work a brief summary of
+ the changes made to Python.
+
+ 4. PSF is making Python available to Licensee on an "AS IS"
+ basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+ IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
+ DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+ FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
+ INFRINGE ANY THIRD PARTY RIGHTS.
+
+ 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+ FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+ A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
+ OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+ 6. This License Agreement will automatically terminate upon a material
+ breach of its terms and conditions.
+
+ 7. Nothing in this License Agreement shall be deemed to create any
+ relationship of agency, partnership, or joint venture between PSF and
+ Licensee. This License Agreement does not grant permission to use PSF
+ trademarks or trade name in a trademark sense to endorse or promote
+ products or services of Licensee, or any third party.
+
+ 8. By copying, installing or otherwise using Python, Licensee
+ agrees to be bound by the terms and conditions of this License
+ Agreement.
View
@@ -16,15 +16,15 @@ Platforms
This library has been successfully tested on the following platforms:
-* Python 2.6
-* Python 3.1
-* PyPy (fastforward-branch)
+* Python 2.5, 2.6, 2.7
+* Python 3.1, 3.2
+* PyPy
What's New in 2.x
------------------
The 2.x series is a complete rewrite of the library and supports both
-Python 2.6+ and Python 3.1+ with a single source code.
+Python 2.5+ and Python 3.1+ with a single source code.
For most users it should be an easy upgrade, however note that at
present, there is no engine for the Genshi language.
@@ -53,7 +53,8 @@ Expression engine
The expression engine has been redesigned to make it easier to
understand and extend.
-The engine is built on the new ``ast`` module.
+The engine is built on the ``ast`` module (available since Python 2.6;
+backports included for Python 2.5).
Performance
~~~~~~~~~~~
View
@@ -20,6 +20,7 @@
install_requires.append("ordereddict")
install_requires.append("unittest2")
+
class Benchmark(test):
description = "Run benchmarks"
user_options = []
View
@@ -0,0 +1,138 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright 2008 by Armin Ronacher.
+# License: Python License.
+#
+
+import _ast
+
+from _ast import *
+
+
+def fix_missing_locations(node):
+ """
+ When you compile a node tree with compile(), the compiler expects lineno and
+ col_offset attributes for every node that supports them. This is rather
+ tedious to fill in for generated nodes, so this helper adds these attributes
+ recursively where not already set, by setting them to the values of the
+ parent node. It works recursively starting at *node*.
+ """
+ def _fix(node, lineno, col_offset):
+ if 'lineno' in node._attributes:
+ if not hasattr(node, 'lineno'):
+ node.lineno = lineno
+ else:
+ lineno = node.lineno
+ if 'col_offset' in node._attributes:
+ if not hasattr(node, 'col_offset'):
+ node.col_offset = col_offset
+ else:
+ col_offset = node.col_offset
+ for child in iter_child_nodes(node):
+ _fix(child, lineno, col_offset)
+ _fix(node, 1, 0)
+ return node
+
+
+def iter_child_nodes(node):
+ """
+ Yield all direct child nodes of *node*, that is, all fields that are nodes
+ and all items of fields that are lists of nodes.
+ """
+ for name, field in iter_fields(node):
+ if isinstance(field, AST):
+ yield field
+ elif isinstance(field, list):
+ for item in field:
+ if isinstance(item, AST):
+ yield item
+
+
+def iter_fields(node):
+ """
+ Yield a tuple of ``(fieldname, value)`` for each field in ``node._fields``
+ that is present on *node*.
+ """
+
+ for field in node._fields or ():
+ try:
+ yield field, getattr(node, field)
+ except AttributeError:
+ pass
+
+
+def walk(node):
+ """
+ Recursively yield all child nodes of *node*, in no specified order. This is
+ useful if you only want to modify nodes in place and don't care about the
+ context.
+ """
+ from collections import deque
+ todo = deque([node])
+ while todo:
+ node = todo.popleft()
+ todo.extend(iter_child_nodes(node))
+ yield node
+
+
+class NodeVisitor(object):
+ """
+ A node visitor base class that walks the abstract syntax tree and calls a
+ visitor function for every node found. This function may return a value
+ which is forwarded by the `visit` method.
+
+ This class is meant to be subclassed, with the subclass adding visitor
+ methods.
+
+ Per default the visitor functions for the nodes are ``'visit_'`` +
+ class name of the node. So a `TryFinally` node visit function would
+ be `visit_TryFinally`. This behavior can be changed by overriding
+ the `visit` method. If no visitor function exists for a node
+ (return value `None`) the `generic_visit` visitor is used instead.
+
+ Don't use the `NodeVisitor` if you want to apply changes to nodes during
+ traversing. For this a special visitor exists (`NodeTransformer`) that
+ allows modifications.
+ """
+
+ def visit(self, node):
+ """Visit a node."""
+ method = 'visit_' + node.__class__.__name__
+ visitor = getattr(self, method, self.generic_visit)
+ return visitor(node)
+
+ def generic_visit(self, node):
+ """Called if no explicit visitor function exists for a node."""
+ for field, value in iter_fields(node):
+ if isinstance(value, list):
+ for item in value:
+ if isinstance(item, AST):
+ self.visit(item)
+ elif isinstance(value, AST):
+ self.visit(value)
+
+class AST(object):
+ _fields = ()
+ _attributes = 'lineno', 'col_offset'
+
+ def __init__(self, *args, **kwargs):
+ self.__dict__.update(kwargs)
+ self._fields = self._fields or ()
+ for name, value in zip(self._fields, args):
+ setattr(self, name, value)
+
+
+for name, cls in _ast.__dict__.items():
+ if isinstance(cls, type) and issubclass(cls, _ast.AST):
+ try:
+ cls.__bases__ = (AST, ) + cls.__bases__
+ except TypeError:
+ pass
+
+class ExceptHandler(AST, _ast.AST):
+ _fields = "type", "name", "body"
+
+
+del _ast
+
+
View
@@ -13,7 +13,11 @@
"""Support classes for generating code from abstract syntax trees."""
-import ast
+try:
+ import ast
+except ImportError:
+ from chameleon import ast24 as ast
+
import threading
# This would ideally be a ``weakref.WeakKeyDictionary``, but certain
View
@@ -1,4 +1,8 @@
-import ast
+try:
+ import ast
+except ImportError:
+ from chameleon import ast24 as ast
+
import inspect
import textwrap
import types
@@ -72,8 +76,8 @@ def visit_Name(self, node):
source = textwrap.dedent(inspect.getsource(function))
argspec = inspect.getargspec(function)
- args = argspec.args
- defaults = argspec.defaults or ()
+ args = argspec[0]
+ defaults = argspec[3] or ()
return wrapper
@@ -1,11 +1,15 @@
import re
-import ast
import itertools
import functools
import logging
try:
- fast_string = str
+ import ast
+except ImportError:
+ from chameleon import ast24 as ast
+
+try:
+ fast_string = bytes = str
str = unicode
except NameError:
long = int
View
@@ -1,5 +1,3 @@
-import re
-
try:
from collections import OrderedDict
except ImportError:
@@ -10,13 +8,8 @@
except NameError:
long = int
-from .exc import LanguageError
-from .exc import ParseError
from .tokenize import iter_xml
from .parser import ElementParser
-from .utils import decode_htmlentities
-from .compiler import identifier
-from .nodes import *
from .namespaces import XML_NS
from .namespaces import XMLNS_NS
View
@@ -0,0 +1,16 @@
+def lookup_attr(obj, key):
+ try:
+ return getattr(obj, key)
+ except AttributeError, exc:
+ try:
+ get = obj.__getitem__
+ except AttributeError:
+ raise exc
+ try:
+ return get(key)
+ except KeyError:
+ raise exc
+
+
+def next(iter):
+ return iter.next()
View
@@ -0,0 +1,12 @@
+def lookup_attr(obj, key):
+ try:
+ return getattr(obj, key)
+ except AttributeError as exc:
+ try:
+ get = obj.__getitem__
+ except AttributeError:
+ raise exc
+ try:
+ return get(key)
+ except KeyError:
+ raise exc
View
@@ -26,6 +26,12 @@
except ImportError:
from ordereddict import OrderedDict
+
+try:
+ next
+except NameError:
+ from chameleon.py25 import next
+
try:
# optional library: `zope.interface`
import interfaces
Oops, something went wrong.

0 comments on commit 325607b

Please sign in to comment.