Rev 5316: Make decorators importable in Python 3 - needed a helper function which the py library already supplied (Thanks Benjamin Peterson for the pointer). in http://bazaar.launchpad.net/~lifeless/bzr/py3

Robert Collins robertc at robertcollins.net
Tue Jun 22 20:34:32 BST 2010


At http://bazaar.launchpad.net/~lifeless/bzr/py3

------------------------------------------------------------
revno: 5316
revision-id: robertc at robertcollins.net-20100622193430-atz2o7lrwfilttid
parent: robertc at robertcollins.net-20100622190553-ry6w5n3ji2pex0no
committer: Robert Collins <robertc at robertcollins.net>
branch nick: py3
timestamp: Wed 2010-06-23 07:34:30 +1200
message:
  Make decorators importable in Python 3 - needed a helper function which the py library already supplied (Thanks Benjamin Peterson for the pointer).
=== modified file 'NEWS'
--- a/NEWS	2010-06-21 04:16:16 +0000
+++ b/NEWS	2010-06-22 19:34:30 +0000
@@ -163,6 +163,9 @@
 
 * Improved ``bzrlib.urlutils`` to handle lp:foo/bar URLs. (Gordon Tyler)
 
+* A copy of the ``py`` library ``_builtin`` module has been included for
+  its python version compatibility support. (Robert Collins)
+
 Testing
 *******
 

=== modified file 'bzrlib/decorators.py'
--- a/bzrlib/decorators.py	2010-02-17 17:11:16 +0000
+++ b/bzrlib/decorators.py	2010-06-22 19:34:30 +0000
@@ -24,6 +24,7 @@
 
 import sys
 
+from bzrlib.util.py._builtin import _reraise
 from bzrlib import trace
 
 
@@ -114,7 +115,7 @@
                 }
     func_def = template % variables
 
-    exec func_def in locals()
+    exec(func_def, locals=locals())
 
     read_locked.__doc__ = unbound.__doc__
     read_locked.__name__ = unbound.__name__
@@ -144,7 +145,7 @@
             try:
                 self.unlock()
             finally:
-                raise exc_info[0], exc_info[1], exc_info[2]
+                _reraise(*exc_info)
         else:
             self.unlock()
             return result
@@ -179,7 +180,7 @@
                 }
     func_def = template % variables
 
-    exec func_def in locals()
+    exec(func_def, locals=locals())
 
     write_locked.__doc__ = unbound.__doc__
     write_locked.__name__ = unbound.__name__
@@ -197,7 +198,7 @@
             try:
                 self.unlock()
             finally:
-                raise exc_info[0], exc_info[1], exc_info[2]
+                _reraise(*exc_info)
         else:
             self.unlock()
             return result

=== modified file 'bzrlib/util/__init__.py'
--- a/bzrlib/util/__init__.py	2005-09-19 06:05:19 +0000
+++ b/bzrlib/util/__init__.py	2010-06-22 19:34:30 +0000
@@ -0,0 +1,1 @@
+"""Helper libraries bzr has included - they have their own licences."""

=== added directory 'bzrlib/util/py'
=== added file 'bzrlib/util/py/__init__.py'
--- a/bzrlib/util/py/__init__.py	1970-01-01 00:00:00 +0000
+++ b/bzrlib/util/py/__init__.py	2010-06-22 19:34:30 +0000
@@ -0,0 +1,15 @@
+"""
+py.test and pylib: rapid testing and development utils
+
+this module uses apipkg.py for lazy-loading sub modules
+and classes.  The initpkg-dictionary  below specifies
+name->value mappings where value can be another namespace
+dictionary or an import path.  
+
+(c) Holger Krekel and others, 2004-2010
+
+MIT licenced at the time of inclusion (2010623).
+
+Included in bzrlib for the _builtin module (which supplies python2<->3
+compatibility glue.
+"""

=== added file 'bzrlib/util/py/_builtin.py'
--- a/bzrlib/util/py/_builtin.py	1970-01-01 00:00:00 +0000
+++ b/bzrlib/util/py/_builtin.py	2010-06-22 19:34:30 +0000
@@ -0,0 +1,234 @@
+"""
+py.test and pylib: rapid testing and development utils
+
+this module uses apipkg.py for lazy-loading sub modules
+and classes.  The initpkg-dictionary  below specifies
+name->value mappings where value can be another namespace
+dictionary or an import path.  
+
+(c) Holger Krekel and others, 2004-2010
+
+MIT licenced at the time of inclusion (2010623).
+
+Included in bzrlib for the _builtin module (which supplies python2<->3
+compatibility glue.
+
+Copied at revision r1797:5c9a85575454 and not modified beyond this docstring.
+"""
+
+import sys
+
+try:
+    reversed = reversed
+except NameError:
+    def reversed(sequence):
+        """reversed(sequence) -> reverse iterator over values of the sequence
+
+        Return a reverse iterator
+        """
+        if hasattr(sequence, '__reversed__'):
+            return sequence.__reversed__()
+        if not hasattr(sequence, '__getitem__'):
+            raise TypeError("argument to reversed() must be a sequence")
+        return reversed_iterator(sequence)
+
+    class reversed_iterator(object):
+
+        def __init__(self, seq):
+            self.seq = seq
+            self.remaining = len(seq)
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            i = self.remaining
+            if i > 0:
+                i -= 1
+                item = self.seq[i]
+                self.remaining = i
+                return item
+            raise StopIteration
+
+        def __length_hint__(self):
+            return self.remaining
+
+try:
+    sorted = sorted
+except NameError:
+    builtin_cmp = cmp # need to use cmp as keyword arg
+
+    def sorted(iterable, cmp=None, key=None, reverse=0):
+        use_cmp = None
+        if key is not None:
+            if cmp is None:
+                def use_cmp(x, y):
+                    return builtin_cmp(x[0], y[0])
+            else:
+                def use_cmp(x, y):
+                    return cmp(x[0], y[0])
+            l = [(key(element), element) for element in iterable]
+        else:
+            if cmp is not None:
+                use_cmp = cmp
+            l = list(iterable)
+        if use_cmp is not None:
+            l.sort(use_cmp)
+        else:
+            l.sort()
+        if reverse:
+            l.reverse()
+        if key is not None:
+            return [element for (_, element) in l]
+        return l
+
+try:
+    set, frozenset = set, frozenset
+except NameError:
+    from sets import set, frozenset 
+
+# pass through
+enumerate = enumerate 
+
+try:
+    BaseException = BaseException
+except NameError:
+    BaseException = Exception
+
+try:
+    GeneratorExit = GeneratorExit
+except NameError:
+    class GeneratorExit(Exception):
+        """ This exception is never raised, it is there to make it possible to
+        write code compatible with CPython 2.5 even in lower CPython
+        versions."""
+        pass
+    GeneratorExit.__module__ = 'exceptions'
+
+if sys.version_info >= (3, 0):
+    exec ("print_ = print ; exec_=exec")
+    import builtins
+
+    # some backward compatibility helpers 
+    _basestring = str 
+    def _totext(obj, encoding=None):
+        if isinstance(obj, bytes):
+            obj = obj.decode(encoding)
+        elif not isinstance(obj, str):
+            obj = str(obj)
+        return obj
+
+    def _isbytes(x): 
+        return isinstance(x, bytes)
+    def _istext(x): 
+        return isinstance(x, str)
+
+    def _getimself(function):
+        return getattr(function, '__self__', None)
+
+    def _getfuncdict(function):
+        return getattr(function, "__dict__", None)
+
+    def _getcode(function):
+        return getattr(function, "__code__", None)
+
+    def execfile(fn, globs=None, locs=None):
+        if globs is None:
+            back = sys._getframe(1)
+            globs = back.f_globals
+            locs = back.f_locals
+            del back
+        elif locs is None:
+            locs = globs
+        fp = open(fn, "rb")
+        try:
+            source = fp.read()
+        finally:
+            fp.close()
+        co = compile(source, fn, "exec", dont_inherit=True)
+        exec_(co, globs, locs)
+
+    def callable(obj):
+        return hasattr(obj, "__call__")
+
+else:
+    import __builtin__ as builtins
+    _totext = unicode 
+    _basestring = basestring
+    execfile = execfile
+    callable = callable
+    def _isbytes(x): 
+        return isinstance(x, str)
+    def _istext(x): 
+        return isinstance(x, unicode)
+
+    def _getimself(function):
+        return getattr(function, 'im_self', None)
+
+    def _getfuncdict(function):
+        return getattr(function, "__dict__", None)
+
+    def _getcode(function):
+        try:
+            return getattr(function, "__code__")
+        except AttributeError:
+            return getattr(function, "func_code", None)
+
+    def print_(*args, **kwargs):
+        """ minimal backport of py3k print statement. """ 
+        sep = ' '
+        if 'sep' in kwargs:
+            sep = kwargs.pop('sep')
+        end = '\n'
+        if 'end' in kwargs:
+            end = kwargs.pop('end')
+        file = 'file' in kwargs and kwargs.pop('file') or sys.stdout
+        if kwargs:
+            args = ", ".join([str(x) for x in kwargs])
+            raise TypeError("invalid keyword arguments: %s" % args)
+        at_start = True
+        for x in args:
+            if not at_start:
+                file.write(sep)
+            file.write(str(x))
+            at_start = False
+        file.write(end)
+
+    def exec_(obj, globals=None, locals=None):
+        """ minimal backport of py3k exec statement. """ 
+        __tracebackhide__ = True
+        if globals is None: 
+            frame = sys._getframe(1)
+            globals = frame.f_globals 
+            if locals is None:
+                locals = frame.f_locals
+        elif locals is None:
+            locals = globals
+        exec2(obj, globals, locals) 
+
+if sys.version_info >= (3,0):
+    exec ("""
+def _reraise(cls, val, tb):
+    __tracebackhide__ = True
+    assert hasattr(val, '__traceback__')
+    raise val
+""")
+else:
+    exec ("""
+def _reraise(cls, val, tb):
+    __tracebackhide__ = True
+    raise cls, val, tb
+def exec2(obj, globals, locals):
+    __tracebackhide__ = True
+    exec obj in globals, locals 
+""")
+
+def _tryimport(*names):
+    """ return the first successfully imported module. """ 
+    assert names
+    for name in names:
+        try:
+            return __import__(name, None, None, '__doc__')
+        except ImportError:
+            excinfo = sys.exc_info()
+    _reraise(*excinfo)




More information about the bazaar-commits mailing list