Author: mattip <matti.pi...@gmail.com>
Branch: release-2.5.x
Changeset: r76363:0b5d7c30ef74
Date: 2015-03-13 16:12 +0200
http://bitbucket.org/pypy/pypy/changeset/0b5d7c30ef74/

Log:    merge default into branch

diff --git a/lib_pypy/cffi.egg-info b/lib_pypy/cffi.egg-info
--- a/lib_pypy/cffi.egg-info
+++ b/lib_pypy/cffi.egg-info
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: cffi
-Version: 0.9.1
+Version: 0.9.2
 Summary: Foreign Function Interface for Python calling C code.
 Home-page: http://cffi.readthedocs.org
 Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
 from .api import FFI, CDefError, FFIError
 from .ffiplatform import VerificationError, VerificationMissing
 
-__version__ = "0.9.1"
-__version_info__ = (0, 9, 1)
+__version__ = "0.9.2"
+__version_info__ = (0, 9, 2)
 
 # The verifier module file names are based on the CRC32 of a string that
 # contains the following version number.  It may be older than __version__
diff --git a/pypy/module/_cffi_backend/__init__.py 
b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -2,7 +2,7 @@
 from pypy.interpreter.mixedmodule import MixedModule
 from rpython.rlib import rdynload
 
-VERSION = "0.9.1"
+VERSION = "0.9.2"
 
 
 class Module(MixedModule):
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py 
b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -3247,6 +3247,88 @@
     cast(p, c)[1] += 500
     assert list(a) == [10000, 20500, 30000]
 
+def test_from_buffer_not_str_unicode_bytearray():
+    BChar = new_primitive_type("char")
+    BCharP = new_pointer_type(BChar)
+    BCharA = new_array_type(BCharP, None)
+    py.test.raises(TypeError, from_buffer, BCharA, b"foo")
+    py.test.raises(TypeError, from_buffer, BCharA, u"foo")
+    py.test.raises(TypeError, from_buffer, BCharA, bytearray(b"foo"))
+    try:
+        from __builtin__ import buffer
+    except ImportError:
+        pass
+    else:
+        py.test.raises(TypeError, from_buffer, BCharA, buffer(b"foo"))
+        py.test.raises(TypeError, from_buffer, BCharA, buffer(u"foo"))
+        py.test.raises(TypeError, from_buffer, BCharA,
+                       buffer(bytearray(b"foo")))
+    try:
+        from __builtin__ import memoryview
+    except ImportError:
+        pass
+    else:
+        py.test.raises(TypeError, from_buffer, BCharA, memoryview(b"foo"))
+        py.test.raises(TypeError, from_buffer, BCharA,
+                       memoryview(bytearray(b"foo")))
+
+def test_from_buffer_more_cases():
+    try:
+        from _cffi_backend import _testbuff
+    except ImportError:
+        py.test.skip("not for pypy")
+    BChar = new_primitive_type("char")
+    BCharP = new_pointer_type(BChar)
+    BCharA = new_array_type(BCharP, None)
+    #
+    def check1(bufobj, expected):
+        c = from_buffer(BCharA, bufobj)
+        assert typeof(c) is BCharA
+        if sys.version_info >= (3,):
+            expected = [bytes(c, "ascii") for c in expected]
+        assert list(c) == list(expected)
+    #
+    def check(methods, expected, expected_for_memoryview=None):
+        if sys.version_info >= (3,):
+            if methods <= 7:
+                return
+            if expected_for_memoryview is not None:
+                expected = expected_for_memoryview
+        class X(object):
+            pass
+        _testbuff(X, methods)
+        bufobj = X()
+        check1(bufobj, expected)
+        try:
+            from __builtin__ import buffer
+            bufobjb = buffer(bufobj)
+        except (TypeError, ImportError):
+            pass
+        else:
+            check1(bufobjb, expected)
+        try:
+            bufobjm = memoryview(bufobj)
+        except (TypeError, NameError):
+            pass
+        else:
+            check1(bufobjm, expected_for_memoryview or expected)
+    #
+    check(1, "RDB")
+    check(2, "WRB")
+    check(4, "CHB")
+    check(8, "GTB")
+    check(16, "ROB")
+    #
+    check(1 | 2,  "RDB")
+    check(1 | 4,  "RDB")
+    check(2 | 4,  "CHB")
+    check(1 | 8,  "RDB", "GTB")
+    check(1 | 16, "RDB", "ROB")
+    check(2 | 8,  "WRB", "GTB")
+    check(2 | 16, "WRB", "ROB")
+    check(4 | 8,  "CHB", "GTB")
+    check(4 | 16, "CHB", "ROB")
+
 def test_version():
     # this test is here mostly for PyPy
-    assert __version__ == "0.9.1"
+    assert __version__ == "0.9.2"
diff --git a/pypy/module/array/interp_array.py 
b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -700,7 +700,8 @@
 
         @rgc.must_be_light_finalizer
         def __del__(self):
-            lltype.free(self.buffer, flavor='raw')
+            if self.buffer:
+                lltype.free(self.buffer, flavor='raw')
 
         def setlen(self, size, zero=False, overallocate=True):
             if size > 0:
diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_zdistutils.py 
b/pypy/module/test_lib_pypy/cffi_tests/test_zdistutils.py
--- a/pypy/module/test_lib_pypy/cffi_tests/test_zdistutils.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/test_zdistutils.py
@@ -165,7 +165,8 @@
         assert lib.sin(12.3) == math.sin(12.3)
         v = ffi.verifier
         ext = v.get_extension()
-        assert 'distutils.extension.Extension' in str(ext.__class__)
+        assert 'distutils.extension.Extension' in str(ext.__class__) or \
+               'setuptools.extension.Extension' in str(ext.__class__)
         assert ext.sources == [maybe_relative_path(v.sourcefilename)]
         assert ext.name == v.get_module_name()
         assert ext.define_macros == [('TEST_EXTENSION_OBJECT', '1')]
@@ -194,7 +195,8 @@
         assert lib.test1eoes(7.0) == 42.0
         v = ffi.verifier
         ext = v.get_extension()
-        assert 'distutils.extension.Extension' in str(ext.__class__)
+        assert 'distutils.extension.Extension' in str(ext.__class__) or \
+               'setuptools.extension.Extension' in str(ext.__class__)
         assert ext.sources == [maybe_relative_path(v.sourcefilename),
                                extra_source]
         assert ext.name == v.get_module_name()
diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py 
b/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py
--- a/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py
@@ -4,6 +4,9 @@
 import subprocess
 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
 
+if sys.platform == 'win32':
+    py.test.skip('snippets do not run on win32')
+
 def create_venv(name):
     tmpdir = udir.join(name)
     try:
@@ -13,6 +16,23 @@
     except OSError as e:
         py.test.skip("Cannot execute virtualenv: %s" % (e,))
 
+    try:
+        deepcopy = os.symlink
+    except:
+        import shutil, errno
+        def deepcopy(src, dst):
+            try:
+                shutil.copytree(src, dst)
+            except OSError as e:
+                if e.errno in (errno.ENOTDIR, errno.EINVAL):
+                    shutil.copy(src, dst)
+                else:
+                    print('got errno')
+                    print(e.errno)
+                    print('not')
+                    print(errno.ENOTDIR)
+                    raise
+
     site_packages = None
     for dirpath, dirnames, filenames in os.walk(str(tmpdir)):
         if os.path.basename(dirpath) == 'site-packages':
@@ -32,7 +52,7 @@
                 modules += ('ply',)   # needed for older versions of pycparser
         for module in modules:
             target = imp.find_module(module)[1]
-            os.symlink(target, os.path.join(site_packages,
+            deepcopy(target, os.path.join(site_packages,
                                             os.path.basename(target)))
     return tmpdir
 
@@ -51,7 +71,11 @@
     python_f.write(py.code.Source(python_snippet))
     try:
         os.chdir(str(SNIPPET_DIR.join(dirname)))
-        vp = str(venv_dir.join('bin/python'))
+        if os.name == 'nt':
+            bindir = 'Scripts'
+        else:
+            bindir = 'bin'
+        vp = str(venv_dir.join(bindir).join('python'))
         subprocess.check_call((vp, 'setup.py', 'clean'))
         subprocess.check_call((vp, 'setup.py', 'install'))
         subprocess.check_call((vp, str(python_f)))
diff --git a/rpython/annotator/bookkeeper.py b/rpython/annotator/bookkeeper.py
--- a/rpython/annotator/bookkeeper.py
+++ b/rpython/annotator/bookkeeper.py
@@ -12,7 +12,7 @@
     SomeBuiltin, SomePBC, SomeInteger, TLS, SomeUnicodeCodePoint,
     s_None, s_ImpossibleValue, SomeBool, SomeTuple,
     SomeImpossibleValue, SomeUnicodeString, SomeList, HarmlesslyBlocked,
-    SomeWeakRef, SomeByteArray, SomeConstantType)
+    SomeWeakRef, SomeByteArray, SomeConstantType, SomeProperty)
 from rpython.annotator.classdef import InstanceSource, ClassDef
 from rpython.annotator.listdef import ListDef, ListItem
 from rpython.annotator.dictdef import DictDef
@@ -301,6 +301,8 @@
                 s1 = self.immutablevalue(x1)
                 assert isinstance(s1, SomeInstance)
                 result = SomeWeakRef(s1.classdef)
+        elif tp is property:
+            return SomeProperty(x)
         elif ishashable(x) and x in BUILTIN_ANALYZERS:
             _module = getattr(x,"__module__","unknown")
             result = SomeBuiltin(BUILTIN_ANALYZERS[x], methodname="%s.%s" % 
(_module, x.__name__))
diff --git a/rpython/annotator/description.py b/rpython/annotator/description.py
--- a/rpython/annotator/description.py
+++ b/rpython/annotator/description.py
@@ -482,6 +482,19 @@
                 self.all_enforced_attrs = []    # no attribute allowed
 
     def add_source_attribute(self, name, value, mixin=False):
+        if isinstance(value, property):
+            # special case for property object
+            if value.fget is not None:
+                newname = name + '__getter__'
+                func = func_with_new_name(value.fget, newname)
+                self.add_source_attribute(newname, func, mixin)
+            if value.fset is not None:
+                newname = name + '__setter__'
+                func = func_with_new_name(value.fset, newname)
+                self.add_source_attribute(newname, func, mixin)
+            self.classdict[name] = Constant(value)
+            return
+
         if isinstance(value, types.FunctionType):
             # for debugging
             if not hasattr(value, 'class_'):
diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py
--- a/rpython/annotator/model.py
+++ b/rpython/annotator/model.py
@@ -587,6 +587,19 @@
         return False
 
 
+class SomeProperty(SomeObject):
+    # used for union error only 
+    immutable = True
+    knowntype = type(property)
+
+    def __init__(self, prop):
+        self.fget = prop.fget
+        self.fset = prop.fset
+
+    def can_be_none(self):
+        return False
+
+
 s_None = SomeNone()
 s_Bool = SomeBool()
 s_Int = SomeInteger()
diff --git a/rpython/annotator/test/test_annrpython.py 
b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -4326,6 +4326,82 @@
         assert isinstance(s, annmodel.SomeString)
         assert not s.can_be_none()
 
+    def test_property_getter(self):
+        class O1(object):
+            def __init__(self, x):
+                self._x = x
+            @property
+            def x(self):
+                return self._x
+        def f(n):
+            o = O1(n)
+            return o.x + getattr(o, 'x')
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [int])
+        assert isinstance(s, annmodel.SomeInteger)
+        op = list(graphof(a, f).iterblocks())[0].operations
+        i = 0
+        c = 0
+        while i < len(op):
+            if op[i].opname == 'getattr':
+                c += 1
+                assert op[i].args[1].value == 'x__getter__'
+                i += 1
+                assert i < len(op) and op[i].opname == 'simple_call' and \
+                            op[i].args[0] == op[i - 1].result
+            i += 1
+        assert c == 2
+
+    def test_property_setter(self):
+        class O2(object):
+            def __init__(self):
+                self._x = 0
+            def set_x(self, v):
+                self._x = v
+            x = property(fset=set_x)
+        def f(n):
+            o = O2()
+            o.x = n
+            setattr(o, 'x', n)
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [int])
+        op = list(graphof(a, f).iterblocks())[0].operations
+        i = 0
+        c = 0
+        while i < len(op):
+            if op[i].opname == 'getattr':
+                c += 1
+                assert op[i].args[1].value == 'x__setter__'
+                i += 1
+                assert i < len(op) and op[i].opname == 'simple_call' and \
+                            op[i].args[0] == op[i - 1].result and 
len(op[i].args) == 2
+            i += 1
+        assert c == 2
+
+    def test_property_unionerr(self):
+        class O1(object):
+            def __init__(self, x):
+                self._x = x
+            @property
+            def x(self):
+                return self._x
+        class O2(O1):
+            def set_x(self, v):
+                self._x = v
+            x = property(fset=set_x)
+        def f1(n):
+            o = O2(n)
+            return o.x
+        def f2(n):
+            o = O2(n)
+            o.x = 20
+        a = self.RPythonAnnotator()
+        with py.test.raises(annmodel.UnionError) as exc:
+            a.build_types(f1, [int])
+        a = self.RPythonAnnotator()
+        with py.test.raises(annmodel.UnionError) as exc:
+            a.build_types(f2, [int])
+
 
 def g(n):
     return [0, 1, 2, n]
diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py
--- a/rpython/annotator/unaryop.py
+++ b/rpython/annotator/unaryop.py
@@ -5,7 +5,7 @@
 from __future__ import absolute_import
 
 from rpython.flowspace.operation import op
-from rpython.flowspace.model import const
+from rpython.flowspace.model import const, Constant
 from rpython.annotator.model import (SomeObject, SomeInteger, SomeBool,
     SomeString, SomeChar, SomeList, SomeDict, SomeTuple, SomeImpossibleValue,
     SomeUnicodeCodePoint, SomeInstance, SomeBuiltin, SomeBuiltinMethod,
@@ -715,6 +715,50 @@
             op.simple_call(get_setslice.result, v_start, v_stop, v_iterable)]
 
 
+def _find_property_meth(s_obj, attr, meth):
+    result = []
+    for clsdef in s_obj.classdef.getmro():
+        dct = clsdef.classdesc.classdict
+        if attr not in dct:
+            continue
+        obj = dct[attr]
+        if (not isinstance(obj, Constant) or 
+                not isinstance(obj.value, property)):
+            return
+        result.append(getattr(obj.value, meth))
+    return result
+
+
+@op.getattr.register_transform(SomeInstance)
+def getattr_SomeInstance(annotator, v_obj, v_attr):
+    s_attr = annotator.annotation(v_attr)
+    if not s_attr.is_constant() or not isinstance(s_attr.const, str):
+        return
+    attr = s_attr.const
+    getters = _find_property_meth(annotator.annotation(v_obj), attr, 'fget')
+    if getters:
+        if all(getters):
+            get_getter = op.getattr(v_obj, const(attr + '__getter__'))
+            return [get_getter, op.simple_call(get_getter.result)]
+        elif not any(getters):
+            raise AnnotatorError("Attribute %r is unreadable" % attr)
+
+
+@op.setattr.register_transform(SomeInstance)
+def setattr_SomeInstance(annotator, v_obj, v_attr, v_value):
+    s_attr = annotator.annotation(v_attr)
+    if not s_attr.is_constant() or not isinstance(s_attr.const, str):
+        return
+    attr = s_attr.const
+    setters = _find_property_meth(annotator.annotation(v_obj), attr, 'fset')
+    if setters:
+        if all(setters):
+            get_setter = op.getattr(v_obj, const(attr + '__setter__'))
+            return [get_setter, op.simple_call(get_setter.result, v_value)]
+        elif not any(setters):
+            raise AnnotatorError("Attribute %r is unwritable" % attr)
+
+
 class __extend__(SomeBuiltin):
     def call(self, args, implicit_init=False):
         args_s, kwds = args.unpack()
diff --git a/rpython/doc/arm.rst b/rpython/doc/arm.rst
--- a/rpython/doc/arm.rst
+++ b/rpython/doc/arm.rst
@@ -160,5 +160,5 @@
 
 The gcrootfinder option is needed to work around `issue 1377`_ and the 
jit-backend works around `issue 1376`_
 
-.. _issue 1377: https://bugs.pypy.org/issue1377
-.. _issue 1376: https://bugs.pypy.org/issue1376
+.. _issue 1377: https://bitbucket.org/pypy/pypy/issue/1377
+.. _issue 1376: https://bitbucket.org/pypy/pypy/issue/1376
diff --git a/rpython/doc/conf.py b/rpython/doc/conf.py
--- a/rpython/doc/conf.py
+++ b/rpython/doc/conf.py
@@ -59,16 +59,16 @@
 
 # General information about the project.
 project = u'RPython'
-copyright = u'2013, The PyPy Project'
+copyright = u'2015, The PyPy Project'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
 # The short X.Y version.
-version = '2.0'
+version = '2.5'
 # The full version, including alpha/beta/rc tags.
-release = '2.0-beta1'
+release = '2.5.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/rpython/flowspace/flowcontext.py b/rpython/flowspace/flowcontext.py
--- a/rpython/flowspace/flowcontext.py
+++ b/rpython/flowspace/flowcontext.py
@@ -772,15 +772,10 @@
 
     def FOR_ITER(self, target):
         w_iterator = self.peekvalue()
-        try:
-            w_nextitem = op.next(w_iterator).eval(self)
-            self.pushvalue(w_nextitem)
-        except Raise as e:
-            if self.exception_match(e.w_exc.w_type, const(StopIteration)):
-                self.popvalue()
-                return target
-            else:
-                raise
+        self.blockstack.append(IterBlock(self, target))
+        w_nextitem = op.next(w_iterator).eval(self)
+        self.blockstack.pop()
+        self.pushvalue(w_nextitem)
 
     def SETUP_LOOP(self, target):
         block = LoopBlock(self, target)
@@ -1333,6 +1328,16 @@
         ctx.last_exception = w_exc
         return self.handlerposition   # jump to the handler
 
+class IterBlock(ExceptBlock):
+    """A pseudo-block to catch the StopIteration inside FOR_ITER"""
+    def handle(self, ctx, unroller):
+        w_exc = unroller.w_exc
+        if ctx.exception_match(w_exc.w_type, const(StopIteration)):
+            ctx.popvalue()
+            return self.handlerposition
+        else:
+            return ctx.unroll(unroller)
+
 class FinallyBlock(FrameBlock):
     """A try:finally: block.  Stores the position of the exception handler."""
 
diff --git a/rpython/flowspace/operation.py b/rpython/flowspace/operation.py
--- a/rpython/flowspace/operation.py
+++ b/rpython/flowspace/operation.py
@@ -555,7 +555,7 @@
     opname = 'next'
     arity = 1
     can_overflow = False
-    canraise = []
+    canraise = [StopIteration, RuntimeError]
     pyfunc = staticmethod(next)
 
     def eval(self, ctx):
@@ -571,9 +571,7 @@
                 else:
                     ctx.replace_in_stack(it, next_unroller)
                     return const(v)
-        w_item = ctx.do_op(self)
-        ctx.recorder.guessexception(ctx, StopIteration, RuntimeError)
-        return w_item
+        return HLOperation.eval(self, ctx)
 
 class GetAttr(SingleDispatchMixin, HLOperation):
     opname = 'getattr'
diff --git a/rpython/translator/c/src/mem.c b/rpython/translator/c/src/mem.c
--- a/rpython/translator/c/src/mem.c
+++ b/rpython/translator/c/src/mem.c
@@ -29,6 +29,8 @@
 RPY_EXTERN
 void pypy_debug_alloc_stop(void *addr)
 {
+  if (!addr)
+       return;
   struct pypy_debug_alloc_s **p;
   for (p = &pypy_debug_alloc_list; *p; p = &((*p)->next))
     if ((*p)->addr == addr)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to