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