Author: Matti Picus <matti.pi...@gmail.com> Branch: unicode-utf8-py3 Changeset: r95158:5a2d488be5e6 Date: 2018-09-23 16:08 +0300 http://bitbucket.org/pypy/pypy/changeset/5a2d488be5e6/
Log: merge py3.5 into branch diff --git a/lib-python/3/test/test_inspect.py b/lib-python/3/test/test_inspect.py --- a/lib-python/3/test/test_inspect.py +++ b/lib-python/3/test/test_inspect.py @@ -61,6 +61,9 @@ git = mod.StupidGit() +class ExampleClassWithSlot(object): + __slots__ = 'myslot' + class IsTestBase(unittest.TestCase): predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode, inspect.isframe, inspect.isfunction, inspect.ismethod, @@ -131,8 +134,11 @@ self.istest(inspect.iscoroutinefunction, 'coroutine_function_example') if hasattr(types, 'MemberDescriptorType'): - self.istest(inspect.ismemberdescriptor, - 'type(lambda: None).__globals__') + # App-level slots are member descriptors on both PyPy and + # CPython, but the various built-in attributes are all + # getsetdescriptors on PyPy. So check ismemberdescriptor() + # with an app-level slot. + self.istest(inspect.ismemberdescriptor, 'ExampleClassWithSlot.myslot') else: self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days)) diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py --- a/lib_pypy/_ctypes/function.py +++ b/lib_pypy/_ctypes/function.py @@ -486,6 +486,8 @@ return cobj, cobj._to_ffi_param(), type(cobj) def _convert_args_for_callback(self, argtypes, args): + from _ctypes.structure import StructOrUnion + # assert len(argtypes) == len(args) newargs = [] for argtype, arg in zip(argtypes, args): @@ -495,6 +497,10 @@ param = param._get_buffer_value() elif self._is_primitive(argtype): param = param.value + elif isinstance(param, StructOrUnion): # not a *pointer* to struct + newparam = StructOrUnion.__new__(type(param)) + param._copy_to(newparam._buffer.buffer) + param = newparam newargs.append(param) return newargs diff --git a/lib_pypy/cffi/setuptools_ext.py b/lib_pypy/cffi/setuptools_ext.py --- a/lib_pypy/cffi/setuptools_ext.py +++ b/lib_pypy/cffi/setuptools_ext.py @@ -162,6 +162,17 @@ module_path = module_name.split('.') module_path[-1] += '.py' generate_mod(os.path.join(self.build_lib, *module_path)) + def get_source_files(self): + # This is called from 'setup.py sdist' only. Exclude + # the generate .py module in this case. + saved_py_modules = self.py_modules + try: + if saved_py_modules: + self.py_modules = [m for m in saved_py_modules + if m != module_name] + return base_class.get_source_files(self) + finally: + self.py_modules = saved_py_modules dist.cmdclass['build_py'] = build_py_make_mod # distutils and setuptools have no notion I could find of a @@ -171,6 +182,7 @@ # the module. So we add it here, which gives a few apparently # harmless warnings about not finding the file outside the # build directory. + # Then we need to hack more in get_source_files(); see above. if dist.py_modules is None: dist.py_modules = [] dist.py_modules.append(module_name) diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -36,7 +36,10 @@ Small refactorings in the Python parser. +.. branch: fix-readme-typo + .. branch: unicode-utf8-re + .. branch: utf8-io Utf8 handling for unicode diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py --- a/pypy/module/__builtin__/functional.py +++ b/pypy/module/__builtin__/functional.py @@ -108,101 +108,99 @@ max_jitdriver = jit.JitDriver(name='max', greens=['has_key', 'has_item', 'w_type'], reds='auto') -def make_min_max(unroll): - @specialize.arg(2) - def min_max_impl(space, args, implementation_of): - if implementation_of == "max": - compare = space.gt - jitdriver = max_jitdriver +@specialize.arg(4) +def min_max_sequence(space, w_sequence, w_key, w_default, implementation_of): + if implementation_of == "max": + compare = space.gt + jitdriver = max_jitdriver + else: + compare = space.lt + jitdriver = min_jitdriver + w_iter = space.iter(w_sequence) + w_type = space.type(w_iter) + has_key = w_key is not None + has_item = False + w_max_item = w_default + w_max_val = None + while True: + jitdriver.jit_merge_point(has_key=has_key, has_item=has_item, + w_type=w_type) + try: + w_item = space.next(w_iter) + except OperationError as e: + if not e.match(space, space.w_StopIteration): + raise + break + if has_key: + w_compare_with = space.call_function(w_key, w_item) else: - compare = space.lt - jitdriver = min_jitdriver - any_kwds = bool(args.keywords) - args_w = args.arguments_w - if len(args_w) > 1: - if unroll and len(args_w) == 2 and not any_kwds: - # a fast path for the common case, useful for interpreted - # mode and to reduce the length of the jit trace - w0, w1 = args_w - if space.is_true(compare(w1, w0)): - return w1 - else: - return w0 - w_sequence = space.newtuple(args_w) - elif len(args_w): - w_sequence = args_w[0] + w_compare_with = w_item + if (not has_item or + space.is_true(compare(w_compare_with, w_max_val))): + has_item = True + w_max_item = w_item + w_max_val = w_compare_with + if w_max_item is None: + raise oefmt(space.w_ValueError, "arg is an empty sequence") + return w_max_item + +@specialize.arg(3) +@jit.look_inside_iff(lambda space, args_w, w_key, implementation_of: + jit.loop_unrolling_heuristic(args_w, len(args_w), 3)) +def min_max_multiple_args(space, args_w, w_key, implementation_of): + # case of multiple arguments (at least two). We unroll it if there + # are 2 or 3 arguments. + if implementation_of == "max": + compare = space.gt + else: + compare = space.lt + w_max_item = args_w[0] + if w_key is not None: + w_max_val = space.call_function(w_key, w_max_item) + else: + w_max_val = w_max_item + for i in range(1, len(args_w)): + w_item = args_w[i] + if w_key is not None: + w_compare_with = space.call_function(w_key, w_item) else: - raise oefmt(space.w_TypeError, - "%s() expects at least one argument", - implementation_of) - w_key = None - w_default = None - if any_kwds: - kwds = args.keywords - for n in range(len(kwds)): - if kwds[n] == "key": - w_key = args.keywords_w[n] - elif kwds[n] == "default": - w_default = args.keywords_w[n] - else: - raise oefmt(space.w_TypeError, - "%s() got unexpected keyword argument", - implementation_of) + w_compare_with = w_item + if space.is_true(compare(w_compare_with, w_max_val)): + w_max_item = w_item + w_max_val = w_compare_with + return w_max_item - if w_default is not None and len(args_w) > 1: - raise oefmt(space.w_TypeError, - "Cannot specify a default for %s() with multiple positional arguments", - implementation_of) - - w_iter = space.iter(w_sequence) - w_type = space.type(w_iter) - has_key = w_key is not None - has_item = False - w_max_item = None - w_max_val = None - while True: - if not unroll: - jitdriver.jit_merge_point(has_key=has_key, has_item=has_item, w_type=w_type) - try: - w_item = space.next(w_iter) - except OperationError as e: - if not e.match(space, space.w_StopIteration): - raise - break - if has_key: - w_compare_with = space.call_function(w_key, w_item) - else: - w_compare_with = w_item - if not has_item or \ - space.is_true(compare(w_compare_with, w_max_val)): - has_item = True - w_max_item = w_item - w_max_val = w_compare_with - if w_max_item is None: - if w_default is not None: - w_max_item = w_default - else: - raise oefmt(space.w_ValueError, "arg is an empty sequence") - return w_max_item - if unroll: - min_max_impl = jit.unroll_safe(min_max_impl) - return min_max_impl - -min_max_unroll = make_min_max(True) -min_max_normal = make_min_max(False) - +@jit.unroll_safe # the loop over kwds @specialize.arg(2) def min_max(space, args, implementation_of): - # the 'normal' version includes a JIT merge point, which will make a - # new loop (from the interpreter or from another JIT loop). If we - # give exactly two arguments to the call to max(), or a JIT virtual - # list of arguments, then we pick the 'unroll' version with no JIT - # merge point. - if jit.isvirtual(args.arguments_w) or len(args.arguments_w) == 2: - return min_max_unroll(space, args, implementation_of) + w_key = None + w_default = None + if bool(args.keywords): + kwds = args.keywords + for n in range(len(kwds)): + if kwds[n] == "key": + w_key = args.keywords_w[n] + elif kwds[n] == "default": + w_default = args.keywords_w[n] + else: + raise oefmt(space.w_TypeError, + "%s() got unexpected keyword argument", + implementation_of) + # + args_w = args.arguments_w + if len(args_w) > 1: + if w_default is not None: + raise oefmt(space.w_TypeError, + "Cannot specify a default for %s() with multiple " + "positional arguments", implementation_of) + return min_max_multiple_args(space, args_w, w_key, implementation_of) + elif len(args_w): + return min_max_sequence(space, args_w[0], w_key, w_default, + implementation_of) else: - return min_max_normal(space, args, implementation_of) -min_max._always_inline = True + raise oefmt(space.w_TypeError, + "%s() expects at least one argument", + implementation_of) def max(space, __args__): """max(iterable[, key=func]) -> value diff --git a/pypy/module/__builtin__/test/test_functional.py b/pypy/module/__builtin__/test/test_functional.py --- a/pypy/module/__builtin__/test/test_functional.py +++ b/pypy/module/__builtin__/test/test_functional.py @@ -654,6 +654,10 @@ raises(TypeError, max, 1, default=0) raises(TypeError, max, default=1) + def test_max_list_and_key(self): + assert max(["100", "50", "30", "-200"], key=int) == "100" + assert max("100", "50", "30", "-200", key=int) == "100" + try: from hypothesis import given, strategies, example 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 @@ -3957,6 +3957,7 @@ z3 = cast(BVoidP, 0) z4 = cast(BUCharP, 0) with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") newp(new_pointer_type(BIntP), z1) # warn assert len(w) == 1 newp(new_pointer_type(BVoidP), z1) # fine diff --git a/pypy/module/pypyjit/test_pypy_c/test_min_max.py b/pypy/module/pypyjit/test_pypy_c/test_min_max.py --- a/pypy/module/pypyjit/test_pypy_c/test_min_max.py +++ b/pypy/module/pypyjit/test_pypy_c/test_min_max.py @@ -30,37 +30,42 @@ sa = 0 while i < 30000: lst = range(i % 1000 + 2) - sa += max(*lst) # ID: max + sa += max(*lst) # ID: callmax i += 1 return sa log = self.run(main, []) assert log.result == main() loop, = log.loops_by_filename(self.filepath) - assert loop.match(""" + assert loop.match_by_id('callmax', """ ... - p76 = call_assembler_r(..., descr=...) + p76 = call_may_force_r(_, _, _, _, descr=...) ... """) - loop2 = log.loops[0] - loop2.match(''' - ... - label(..., descr=...) - ... - label(..., descr=...) - guard_not_invalidated? - i17 = int_ge(i11, i7) - guard_false(i17, descr=...) - p18 = getarrayitem_gc_r(p5, i11, descr=...) - i19 = int_add(i11, 1) - setfield_gc(p2, i19, descr=...) - guard_nonnull_class(p18, ConstClass(W_IntObject), descr=...) - i20 = getfield_gc_i(p18, descr=...) - i21 = int_gt(i20, i14) - guard_true(i21, descr=...) - jump(..., descr=...) - ''') - # XXX could be "guard_class(p18)" instead; we lost somewhere - # the information that it cannot be null. + + #----- the following logic used to check the content of the assembly + #----- generated for the loop in max(), but now we no longer produce + #----- any custom assembly in this case. It used to say + #----- 'call_assembler_r' above, and now it says 'call_may_force_r'. + #loop2 = log.loops[0] + #loop2.match(''' + #... + #label(..., descr=...) + #... + #label(..., descr=...) + #guard_not_invalidated? + #i17 = int_ge(i11, i7) + #guard_false(i17, descr=...) + #p18 = getarrayitem_gc_r(p5, i11, descr=...) + #i19 = int_add(i11, 1) + #setfield_gc(p2, i19, descr=...) + #guard_nonnull_class(p18, ConstClass(W_IntObject), descr=...) + #i20 = getfield_gc_i(p18, descr=...) + #i21 = int_gt(i20, i14) + #guard_true(i21, descr=...) + #jump(..., descr=...) + #''') + ## XXX could be "guard_class(p18)" instead; we lost somewhere + ## the information that it cannot be null. def test_iter_max(self): def main(): diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py @@ -1387,6 +1387,7 @@ ffi = FFI(backend=self.Backend()) ffi.cdef("enum foo;") with warnings.catch_warnings(record=True) as log: + warnings.simplefilter("always") n = ffi.cast("enum foo", -1) assert int(n) == 0xffffffff assert str(log[0].message) == ( diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_function.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_function.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_function.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_function.py @@ -46,14 +46,14 @@ assert x != math.sin(1.23) # rounding effects assert abs(x - math.sin(1.23)) < 1E-6 - def test_sin_no_return_value(self): + def test_lround_no_return_value(self): # check that 'void'-returning functions work too ffi = FFI(backend=self.Backend()) ffi.cdef(""" - void sin(double x); + void lround(double x); """) m = ffi.dlopen(lib_m) - x = m.sin(1.23) + x = m.lround(1.23) assert x is None def test_dlopen_filename(self): diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_callbacks.py b/pypy/module/test_lib_pypy/ctypes_tests/test_callbacks.py --- a/pypy/module/test_lib_pypy/ctypes_tests/test_callbacks.py +++ b/pypy/module/test_lib_pypy/ctypes_tests/test_callbacks.py @@ -160,15 +160,17 @@ proto = CFUNCTYPE(c_int, RECT) def callback(point): + point.left *= -1 return point.left+point.top+point.right+point.bottom cbp = proto(callback) - rect = RECT(1000,100,10,1) + rect = RECT(-1000,100,10,1) res = cbp(rect) assert res == 1111 + assert rect.left == -1000 # must not have been changed! def test_callback_from_c_with_struct_argument(self): import conftest diff --git a/rpython/translator/platform/windows.py b/rpython/translator/platform/windows.py --- a/rpython/translator/platform/windows.py +++ b/rpython/translator/platform/windows.py @@ -186,7 +186,7 @@ self.cc = cc # detect version of current compiler - returncode, stdout, stderr = _run_subprocess(self.cc, '', + returncode, stdout, stderr = _run_subprocess(self.cc, [], env=self.c_environ) r = re.search(r'Microsoft.+C/C\+\+.+\s([0-9]+)\.([0-9]+).*', stderr) if r is not None: @@ -196,7 +196,7 @@ self.version = 0 # Try to find a masm assembler - returncode, stdout, stderr = _run_subprocess('ml.exe', '', + returncode, stdout, stderr = _run_subprocess('ml.exe', [], env=self.c_environ) r = re.search('Macro Assembler', stderr) if r is None and os.path.exists('c:/masm32/bin/ml.exe'): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit