Author: Richard Plangger <[email protected]> Branch: s390x-backend Changeset: r82807:9ff14f05a92d Date: 2016-03-06 10:24 +0100 http://bitbucket.org/pypy/pypy/changeset/9ff14f05a92d/
Log: catchup with default diff --git a/pypy/doc/contributor.rst b/pypy/doc/contributor.rst --- a/pypy/doc/contributor.rst +++ b/pypy/doc/contributor.rst @@ -11,29 +11,29 @@ Amaury Forgeot d'Arc Antonio Cuni Samuele Pedroni + Matti Picus Alex Gaynor Brian Kearns - Matti Picus Philip Jenvey Michael Hudson + Ronan Lamy David Schneider + Manuel Jacob Holger Krekel Christian Tismer Hakan Ardo - Manuel Jacob - Ronan Lamy Benjamin Peterson + Richard Plangger Anders Chrigstrom Eric van Riet Paap Wim Lavrijsen - Richard Plangger Richard Emslie Alexander Schremmer Dan Villiom Podlaski Christiansen + Remi Meier Lukas Diekmann Sven Hager Anders Lehmann - Remi Meier Aurelien Campeas Niklaus Haldimann Camillo Bruni @@ -42,8 +42,8 @@ Romain Guillebert Leonardo Santagada Seo Sanghyeon + Ronny Pfannschmidt Justin Peel - Ronny Pfannschmidt David Edelsohn Anders Hammarquist Jakub Gustak @@ -65,6 +65,7 @@ Tyler Wade Michael Foord Stephan Diehl + Vincent Legoll Stefan Schwarzer Valentino Volonghi Tomek Meka @@ -75,9 +76,9 @@ Jean-Paul Calderone Timo Paulssen Squeaky + Marius Gedminas Alexandre Fayolle Simon Burton - Marius Gedminas Martin Matusiak Konstantin Lopuhin Wenzhu Man @@ -86,16 +87,20 @@ Ivan Sichmann Freitas Greg Price Dario Bertini + Stefano Rivera Mark Pearse Simon Cross Andreas Stührk - Stefano Rivera + Edd Barrett Jean-Philippe St. Pierre Guido van Rossum Pavel Vinogradov + Jeremy Thurgood Paweł Piotr Przeradowski + Spenser Bauman Paul deGrandis Ilya Osadchiy + marky1991 Tobias Oberstein Adrian Kuhn Boris Feigin @@ -104,14 +109,12 @@ Georg Brandl Bert Freudenberg Stian Andreassen - Edd Barrett + Tobias Pape Wanja Saatkamp Gerald Klix Mike Blume - Tobias Pape Oscar Nierstrasz Stefan H. Muller - Jeremy Thurgood Rami Chowdhury Eugene Oden Henry Mason @@ -123,6 +126,8 @@ Lukas Renggli Guenter Jantzen Ned Batchelder + Tim Felgentreff + Anton Gulenko Amit Regmi Ben Young Nicolas Chauvat @@ -132,12 +137,12 @@ Nicholas Riley Jason Chu Igor Trindade Oliveira - Tim Felgentreff + Yichao Yu Rocco Moretti Gintautas Miliauskas Michael Twomey Lucian Branescu Mihaila - Yichao Yu + Devin Jeanpierre Gabriel Lavoie Olivier Dormond Jared Grubb @@ -161,33 +166,33 @@ Stanislaw Halik Mikael Schönenberg Berkin Ilbeyi - Elmo M?ntynen + Elmo Mäntynen + Faye Zhao Jonathan David Riehl Anders Qvist Corbin Simpson Chirag Jadwani Beatrice During Alex Perry - Vincent Legoll + Vaibhav Sood Alan McIntyre - Spenser Bauman + William Leslie Alexander Sedov Attila Gobi + Jasper.Schulz Christopher Pope - Devin Jeanpierre - Vaibhav Sood Christian Tismer Marc Abramowitz Dan Stromberg Arjun Naik Valentina Mukhamedzhanova Stefano Parmesan + Mark Young Alexis Daboville Jens-Uwe Mager Carl Meyer Karl Ramm Pieter Zieschang - Anton Gulenko Gabriel Lukas Vacek Andrew Dalke @@ -195,6 +200,7 @@ Jakub Stasiak Nathan Taylor Vladimir Kryachko + Omer Katz Jacek Generowicz Alejandro J. Cura Jacob Oscarson @@ -209,6 +215,7 @@ Lars Wassermann Philipp Rustemeuer Henrik Vendelbo + Richard Lancaster Dan Buch Miguel de Val Borro Artur Lisiecki @@ -220,18 +227,18 @@ Tomo Cocoa Kim Jin Su Toni Mattis + Amber Brown Lucas Stadler Julian Berman Markus Holtermann roberto@goyle Yury V. Zaytsev Anna Katrina Dominguez - William Leslie Bobby Impollonia - Faye Zhao [email protected] Andrew Thompson Yusei Tahara + Aaron Tubbs Ben Darnell Roberto De Ioris Juan Francisco Cantero Hurtado @@ -243,6 +250,7 @@ Christopher Armstrong Michael Hudson-Doyle Anders Sigfridsson + Nikolay Zinov Yasir Suhail Jason Michalski [email protected] @@ -252,6 +260,7 @@ Gustavo Niemeyer Stephan Busemann Rafał Gałczyński + Matt Bogosian Christian Muirhead Berker Peksag James Lan @@ -286,9 +295,9 @@ Stefan Marr jiaaro Mads Kiilerich - Richard Lancaster opassembler.py Antony Lee + Jason Madden Yaroslav Fedevych Jim Hunziker Markus Unterwaditzer @@ -297,6 +306,7 @@ squeaky Zearin soareschen + Jonas Pfannschmidt Kurt Griffiths Mike Bayer Matthew Miller @@ -311,4 +321,3 @@ Julien Phalip Roman Podoliaka Dan Loewenherz - diff --git a/pypy/doc/index-of-release-notes.rst b/pypy/doc/index-of-release-notes.rst --- a/pypy/doc/index-of-release-notes.rst +++ b/pypy/doc/index-of-release-notes.rst @@ -6,6 +6,7 @@ .. toctree:: + release-5.0.0.rst release-4.0.1.rst release-4.0.0.rst release-2.6.1.rst diff --git a/pypy/doc/index-of-whatsnew.rst b/pypy/doc/index-of-whatsnew.rst --- a/pypy/doc/index-of-whatsnew.rst +++ b/pypy/doc/index-of-whatsnew.rst @@ -7,6 +7,7 @@ .. toctree:: whatsnew-head.rst + whatsnew-5.0.0.rst whatsnew-4.0.1.rst whatsnew-4.0.0.rst whatsnew-2.6.1.rst diff --git a/pypy/doc/release-5.0.0.rst b/pypy/doc/release-5.0.0.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/release-5.0.0.rst @@ -0,0 +1,225 @@ +========== +PyPy 5.0.0 +========== + +We have released PyPy 5.0.0, about three months after PyPy 4.0.0. +We encourage all users of PyPy to update to this version. Apart from the usual +bug fixes, there is an ongoing effort to improve the warmup time and memory +usage of JIT-related metadata. The exact effects depend vastly on the program +you're running and can range from insignificant to warmup being up to 30% +faster and memory dropping by about 30%. + +We also merged a major upgrade to our C-API layer (cpyext), simplifying the +interaction between c-level objects and PyPy interpreter level objects. As a +result, lxml with its cython compiled component `passes all tests`_ on PyPy + +Users who have gotten used to vmprof_ on Linux, and those on other platforms +who have not yet tried its awesomeness, will be happy to hear that vmprof +now just works on MacOS and Windows too, in both PyPy (built-in support) and +CPython (as an installed module). + +You can download the PyPy 5.0.0 release here: + + http://pypy.org/download.html + +We would like to thank our donors for the continued support of the PyPy +project. + +We would also like to thank our contributors and +encourage new people to join the project. PyPy has many +layers and we need help with all of them: `PyPy`_ and `RPython`_ documentation +improvements, tweaking popular `modules`_ to run on pypy, or general `help`_ +with making RPython's JIT even better. + +CFFI +==== + +While not applicable only to PyPy, `cffi`_ is arguably our most significant +contribution to the python ecosystem. PyPy 5.0.0 ships with +`cffi-1.5.2`_ which now allows embedding PyPy (or cpython) in a c program. + +.. _`PyPy`: http://doc.pypy.org +.. _`RPython`: https://rpython.readthedocs.org +.. _`cffi`: https://cffi.readthedocs.org +.. _`cffi-1.5.2`: http://cffi.readthedocs.org/en/latest/whatsnew.html#v1-5-2 +.. _`modules`: http://doc.pypy.org/en/latest/project-ideas.html#make-more-python-modules-pypy-friendly +.. _`help`: http://doc.pypy.org/en/latest/project-ideas.html +.. _`numpy`: https://bitbucket.org/pypy/numpy +.. _`passes all tests`: https://bitbucket.org/pypy/compatibility/wiki/lxml +.. _vmprof: http://vmprof.readthedocs.org + +What is PyPy? +============= + +PyPy is a very compliant Python interpreter, almost a drop-in replacement for +CPython 2.7. It's fast (`pypy and cpython 2.7.x`_ performance comparison) +due to its integrated tracing JIT compiler. + +We also welcome developers of other +`dynamic languages`_ to see what RPython can do for them. + +This release supports **x86** machines on most common operating systems +(Linux 32/64, Mac OS X 64, Windows 32, OpenBSD, freebsd), +newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux, and the +big- and little-endian variants of **ppc64** running Linux. + +.. _`pypy and cpython 2.7.x`: http://speed.pypy.org +.. _`dynamic languages`: http://pypyjs.org + +Other Highlights (since 4.0.1 released in November 2015) +========================================================= + +* New features: + + * Support embedding PyPy in a C-program via cffi and static callbacks in cffi. + This deprecates the old method of embedding PyPy + + * Refactor vmprof to work cross-operating-system, deprecate using buggy + libunwind on Linux platforms. Vmprof even works on Windows now. + + * Support more of the C-API type slots, like tp_getattro, and fix C-API + macros, functions, and structs such as _PyLong_FromByteArray(), + PyString_GET_SIZE, f_locals in PyFrameObject, Py_NAN, co_filename in + PyCodeObject + + * Use a more stable approach for allocating PyObjects in cpyext. (see + `blog post`_). Once the PyObject corresponding to a PyPy object is created, + it stays around at the same location until the death of the PyPy object. + Done with a little bit of custom GC support. It allows us to kill the + notion of "borrowing" inside cpyext, reduces 4 dictionaries down to 1, and + significantly simplifies the whole approach (which is why it is a new + feature while technically a refactoring) and allows PyPy to support the + populart lxml module (as of the *next* release) with no PyPy specific + patches needed + + * Make the default filesystem encoding ASCII, like CPython + + * Use `hypothesis`_ in test creation, which is great for randomizing tests + +* Bug Fixes + + * Backport always using os.urandom for uuid4 from cpython + + * More completely support datetime, optimize timedelta creation + + * Fix for issue 2185 which caused an inconsistent list of operations to be + generated by the unroller, appeared in a complicated DJango app + + * Fix an elusive issue with stacklets on shadowstack which showed up when + forgetting stacklets without resuming them + + * Fix entrypoint() which now acquires the GIL + + * Fix direct_ffi_call() so failure does not bail out before setting CALL_MAY_FORCE + + * Fix (de)pickling long values by simplifying the implementation + + * Fix RPython rthread so that objects stored as threadlocal do not force minor + GC collection and are kept alive automatically. This improves perfomance of + short-running Python callbacks and prevents resetting such object between + calls + + * Support floats as parameters to itertools.isslice() + + * Check for the existence of CODESET, ignoring it should have prevented PyPy + from working on FreeBSD + + * Fix for corner case (likely shown by Krakatau) for consecutive guards with + interdependencies + + * Fix applevel bare class method comparisons which should fix pretty printing + in IPython + + * Issues reported with our previous release were resolved_ after reports from users on + our issue tracker at https://bitbucket.org/pypy/pypy/issues or on IRC at + #pypy + +* Numpy: + + * Updates to numpy 1.10.2 (incompatibilities and not-implemented features + still exist) + + * Support dtype=(('O', spec)) union while disallowing record arrays with + mixed object, non-object values + + * Remove all traces of micronumpy from cpyext if --withoutmod-micronumpy option used + + * Support indexing filtering with a boolean ndarray + +* Performance improvements and refactorings: + + * Refactor and improve exception analysis in the annotator + + * Improve the performace of struct.unpack; unpacking of floats and doubles + is now about 15 times faster and 64 bit integers faster by a factor of 2 + + * Remove unnecessary special handling of space.wrap(). + + * Improve the memory signature of numbering instances in the JIT. This should + massively decrease the amount of memory consumed by the JIT, which is + significant for most programs. Also compress the numberings using variable- + size encoding + + * Support list-resizing setslice operations in RPython + + * Tweak the trace-too-long heuristic for multiple jit drivers + + * Refactor bookkeeping (such a cool word - three double letters) in the + annotater + + * Refactor wrappers for OS functions from rtyper to rlib and simplify them + + * Simplify backend loading instructions to only use four variants + + * Optimize string concatination + + * Simplify GIL handling in non-jitted code + + * Use INT_LSHIFT instead of INT_MUL when possible + + * Improve struct.unpack by casting directly from the underlying buffer. + Unpacking floats and doubles is about 15 times faster, and integer types + about 50% faster (on 64 bit integers). This was then subsequently + improved further in optimizeopt.py. + + * Refactor naming in optimizeopt + + * Change GraphAnalyzer to use a more precise way to recognize external + functions and fix null pointer handling, generally clean up external + function handling + + * Optimize global lookups + + * Optimize two-tuple lookups in mapdict + + * Remove pure variants of ``getfield_gc_*`` operations from the JIT by + determining purity while tracing + + * Refactor databasing + + * Simplify bootstrapping in cpyext + + * Refactor rtyper debug code into python.rtyper.debug + + * Seperate structmember.h from Python.h Also enhance creating api functions + to specify which header file they appear in (previously only pypy_decl.h) + + * Reduce all guards from int_floordiv_ovf if one of the arguments is constant + + * Fix tokenizer to enforce universal newlines, needed for Python 3 support + + * Identify permutations of attributes at instance creation, reducing the + number of bridges created + + * Greatly improve re.sub() performance + +.. _resolved: http://doc.pypy.org/en/latest/whatsnew-5.0.0.html +.. _`hypothesis`: http://hypothesis.readthedocs.org +.. _`blog post`: http://morepypy.blogspot.com/2016/02/c-api-support-update.html + +Please update, and continue to help us make PyPy better. + +Cheers + +The PyPy Team + diff --git a/pypy/doc/whatsnew-5.0.0.rst b/pypy/doc/whatsnew-5.0.0.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/whatsnew-5.0.0.rst @@ -0,0 +1,192 @@ +========================= +What's new in PyPy 4.1.+ +========================= + +.. this is a revision shortly after release-4.0.1 +.. startrev: 4b5c840d0da2 + +Fixed ``_PyLong_FromByteArray()``, which was buggy. + +Fixed a crash with stacklets (or greenlets) on non-Linux machines +which showed up if you forget stacklets without resuming them. + +.. branch: numpy-1.10 + +Fix tests to run cleanly with -A and start to fix micronumpy for upstream numpy +which is now 1.10.2 + +.. branch: osx-flat-namespace + +Fix the cpyext tests on OSX by linking with -flat_namespace + +.. branch: anntype + +Refactor and improve exception analysis in the annotator. + +.. branch: posita/2193-datetime-timedelta-integrals + +Fix issue #2193. ``isinstance(..., int)`` => ``isinstance(..., numbers.Integral)`` +to allow for alternate ``int``-like implementations (e.g., ``future.types.newint``) + +.. branch: faster-rstruct + +Improve the performace of struct.unpack, which now directly reads inside the +string buffer and directly casts the bytes to the appropriate type, when +allowed. Unpacking of floats and doubles is about 15 times faster now, while +for integer types it's up to ~50% faster for 64bit integers. + +.. branch: wrap-specialisation + +Remove unnecessary special handling of space.wrap(). + +.. branch: compress-numbering + +Improve the memory signature of numbering instances in the JIT. This should massively +decrease the amount of memory consumed by the JIT, which is significant for most programs. + +.. branch: fix-trace-too-long-heuristic + +Improve the heuristic when disable trace-too-long + +.. branch: fix-setslice-can-resize + +Make rlist's ll_listsetslice() able to resize the target list to help +simplify objspace/std/listobject.py. Was issue #2196. + +.. branch: anntype2 + +A somewhat random bunch of changes and fixes following up on branch 'anntype'. Highlights: + +- Implement @doubledispatch decorator and use it for intersection() and difference(). + +- Turn isinstance into a SpaceOperation + +- Create a few direct tests of the fundamental annotation invariant in test_model.py + +- Remove bookkeeper attribute from DictDef and ListDef. + +.. branch: cffi-static-callback + +.. branch: vecopt-absvalue + +- Enhancement. Removed vector fields from AbstractValue. + +.. branch: memop-simplify2 + +Simplification. Backends implement too many loading instructions, only having a slightly different interface. +Four new operations (gc_load/gc_load_indexed, gc_store/gc_store_indexed) replace all the +commonly known loading operations + +.. branch: more-rposix + +Move wrappers for OS functions from `rpython/rtyper` to `rpython/rlib` and +turn them into regular RPython functions. Most RPython-compatible `os.*` +functions are now directly accessible as `rpython.rposix.*`. + +.. branch: always-enable-gil + +Simplify a bit the GIL handling in non-jitted code. Fixes issue #2205. + +.. branch: flowspace-cleanups + +Trivial cleanups in flowspace.operation : fix comment & duplicated method + +.. branch: test-AF_NETLINK + +Add a test for pre-existing AF_NETLINK support. Was part of issue #1942. + +.. branch: small-cleanups-misc + +Trivial misc cleanups: typo, whitespace, obsolete comments + +.. branch: cpyext-slotdefs +.. branch: fix-missing-canraise +.. branch: whatsnew + +.. branch: fix-2211 + +Fix the cryptic exception message when attempting to use extended slicing +in rpython. Was issue #2211. + +.. branch: ec-keepalive + +Optimize the case where, in a new C-created thread, we keep invoking +short-running Python callbacks. (CFFI on CPython has a hack to achieve +the same result.) This can also be seen as a bug fix: previously, +thread-local objects would be reset between two such calls. + +.. branch: globals-quasiimmut + +Optimize global lookups. + +.. branch: cffi-static-callback-embedding + +Updated to CFFI 1.5, which supports a new way to do embedding. +Deprecates http://pypy.readthedocs.org/en/latest/embedding.html. + +.. branch: fix-cpython-ssl-tests-2.7 + +Fix SSL tests by importing cpython's patch + +.. branch: remove-getfield-pure + +Remove pure variants of ``getfield_gc_*`` operations from the JIT. Relevant +optimizations instead consult the field descriptor to determine the purity of +the operation. Additionally, pure ``getfield`` operations are now handled +entirely by `rpython/jit/metainterp/optimizeopt/heap.py` rather than +`rpython/jit/metainterp/optimizeopt/pure.py`, which can result in better codegen +for traces containing a large number of pure getfield operations. + +.. branch: exctrans + +Try to ensure that no new functions get annotated during the 'source_c' phase. +Refactor sandboxing to operate at a higher level. + +.. branch: cpyext-bootstrap + +.. branch: vmprof-newstack + +Refactor vmprof to work cross-operating-system. + +.. branch: seperate-strucmember_h + +Seperate structmember.h from Python.h Also enhance creating api functions +to specify which header file they appear in (previously only pypy_decl.h) + +.. branch: llimpl + +Refactor register_external(), remove running_on_llinterp mechanism and +apply sandbox transform on externals at the end of annotation. + +.. branch: cffi-embedding-win32 + +.. branch: windows-vmprof-support + +vmprof should work on Windows. + + +.. branch: reorder-map-attributes + +When creating instances and adding attributes in several different orders +depending on some condition, the JIT would create too much code. This is now +fixed. + +.. branch: cpyext-gc-support-2 + +Improve CPython C API support, which means lxml now runs unmodified +(after removing pypy hacks, pending pull request) + +.. branch: look-inside-tuple-hash + +Look inside tuple hash, improving mdp benchmark + +.. branch: vlen-resume + +Compress resume data, saving 10-20% of memory consumed by the JIT + +.. branch: issue-2248 + +.. branch: ndarray-setitem-filtered + +Fix boolean-array indexing in micronumpy + 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 @@ -184,10 +184,6 @@ Compress resume data, saving 10-20% of memory consumed by the JIT -.. branch: memop-simplify3 - -Further simplifying the backend operations malloc_cond_varsize and zero_array. - .. branch: s390x-backend The jit compiler backend implementation for the s390x architecutre. diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py --- a/pypy/interpreter/function.py +++ b/pypy/interpreter/function.py @@ -13,6 +13,9 @@ from pypy.interpreter.argument import Arguments from rpython.rlib import jit +from rpython.rlib.rarithmetic import LONG_BIT +from rpython.rlib.rbigint import rbigint + funccallunrolling = unrolling_iterable(range(4)) @@ -557,6 +560,26 @@ return space.w_False return space.eq(self.w_function, w_other.w_function) + def is_w(self, space, other): + if not isinstance(other, Method): + return False + return (self.w_instance is other.w_instance and + self.w_function is other.w_function and + self.w_class is other.w_class) + + def immutable_unique_id(self, space): + from pypy.objspace.std.util import IDTAG_METHOD as tag + from pypy.objspace.std.util import IDTAG_SHIFT + if self.w_instance is not None: + id = space.bigint_w(space.id(self.w_instance)) + id = id.lshift(LONG_BIT) + else: + id = rbigint.fromint(0) + id = id.or_(space.bigint_w(space.id(self.w_function))) + id = id.lshift(LONG_BIT).or_(space.bigint_w(space.id(self.w_class))) + id = id.lshift(IDTAG_SHIFT).int_or_(tag) + return space.newlong_from_rbigint(id) + def descr_method_hash(self): space = self.space w_result = space.hash(self.w_function) diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py --- a/pypy/interpreter/test/test_app_main.py +++ b/pypy/interpreter/test/test_app_main.py @@ -133,7 +133,7 @@ self.check(['-S', '-tO', '--info'], {}, output_contains='translation') self.check(['-S', '-tO', '--version'], {}, output_contains='Python') self.check(['-S', '-tOV'], {}, output_contains='Python') - self.check(['--jit', 'foobar', '-S'], {}, sys_argv=[''], + self.check(['--jit', 'off', '-S'], {}, sys_argv=[''], run_stdin=True, no_site=1) self.check(['-c', 'pass'], {}, sys_argv=['-c'], run_command='pass') self.check(['-cpass'], {}, sys_argv=['-c'], run_command='pass') diff --git a/pypy/interpreter/test/test_function.py b/pypy/interpreter/test/test_function.py --- a/pypy/interpreter/test/test_function.py +++ b/pypy/interpreter/test/test_function.py @@ -1,5 +1,4 @@ - -import unittest +import pytest from pypy.interpreter import eval from pypy.interpreter.function import Function, Method, descr_function_get from pypy.interpreter.pycode import PyCode @@ -187,6 +186,7 @@ raises( TypeError, func, 42, {'arg1': 23}) + @pytest.mark.skipif("config.option.runappdirect") def test_kwargs_nondict_mapping(self): class Mapping: def keys(self): @@ -257,6 +257,14 @@ meth = func.__get__(obj, object) assert meth() == obj + def test_none_get_interaction(self): + skip("XXX issue #2083") + assert type(None).__repr__(None) == 'None' + + def test_none_get_interaction_2(self): + f = None.__repr__ + assert f() == 'None' + def test_no_get_builtin(self): assert not hasattr(dir, '__get__') class A(object): @@ -284,6 +292,7 @@ raises(TypeError, len, s, some_unknown_keyword=s) raises(TypeError, len, s, s, some_unknown_keyword=s) + @pytest.mark.skipif("config.option.runappdirect") def test_call_error_message(self): try: len() @@ -325,6 +334,7 @@ f = lambda: 42 assert f.func_doc is None + @pytest.mark.skipif("config.option.runappdirect") def test_setstate_called_with_wrong_args(self): f = lambda: 42 # not sure what it should raise, since CPython doesn't have setstate @@ -550,6 +560,37 @@ assert A().m == X() assert X() == A().m + @pytest.mark.skipif("config.option.runappdirect") + def test_method_identity(self): + class A(object): + def m(self): + pass + def n(self): + pass + + class B(A): + pass + + class X(object): + def __eq__(self, other): + return True + + a = A() + a2 = A() + assert a.m is a.m + assert id(a.m) == id(a.m) + assert a.m is not a.n + assert id(a.m) != id(a.n) + assert a.m is not a2.m + assert id(a.m) != id(a2.m) + + assert A.m is A.m + assert id(A.m) == id(A.m) + assert A.m is not A.n + assert id(A.m) != id(A.n) + assert A.m is not B.m + assert id(A.m) != id(B.m) + class TestMethod: def setup_method(self, method): diff --git a/pypy/module/__builtin__/descriptor.py b/pypy/module/__builtin__/descriptor.py --- a/pypy/module/__builtin__/descriptor.py +++ b/pypy/module/__builtin__/descriptor.py @@ -79,6 +79,7 @@ W_Super.typedef = TypeDef( 'super', __new__ = interp2app(descr_new_super), + __thisclass__ = interp_attrproperty_w("w_starttype", W_Super), __getattribute__ = interp2app(W_Super.getattribute), __get__ = interp2app(W_Super.get), __doc__ = """super(type) -> unbound super object diff --git a/pypy/module/__builtin__/test/test_classobj.py b/pypy/module/__builtin__/test/test_classobj.py --- a/pypy/module/__builtin__/test/test_classobj.py +++ b/pypy/module/__builtin__/test/test_classobj.py @@ -452,7 +452,6 @@ assert a + 1 == 2 assert a + 1.1 == 2 - def test_binaryop_calls_coerce_always(self): l = [] class A: @@ -1076,6 +1075,16 @@ assert (D() > A()) == 'D:A.gt' assert (D() >= A()) == 'D:A.ge' + def test_override___int__(self): + class F(float): + def __int__(self): + return 666 + f = F(-12.3) + assert int(f) == 666 + # on cpython, this calls float_trunc() in floatobject.c + # which ends up calling PyFloat_AS_DOUBLE((PyFloatObject*) f) + assert float.__int__(f) == -12 + class AppTestOldStyleClassBytesDict(object): def setup_class(cls): diff --git a/pypy/module/__builtin__/test/test_descriptor.py b/pypy/module/__builtin__/test/test_descriptor.py --- a/pypy/module/__builtin__/test/test_descriptor.py +++ b/pypy/module/__builtin__/test/test_descriptor.py @@ -214,7 +214,7 @@ c = C() assert C.goo(1) == (C, 1) assert c.goo(1) == (C, 1) - + assert c.foo(1) == (c, 1) class D(C): pass @@ -238,6 +238,17 @@ meth = classmethod(1).__get__(1) raises(TypeError, meth) + def test_super_thisclass(self): + class A(object): + pass + + assert super(A, A()).__thisclass__ is A + + class B(A): + pass + + assert super(B, B()).__thisclass__ is B + assert super(A, B()).__thisclass__ is A def test_property_docstring(self): assert property.__doc__.startswith('property') diff --git a/pypy/module/_collections/app_defaultdict.py b/pypy/module/_collections/app_defaultdict.py --- a/pypy/module/_collections/app_defaultdict.py +++ b/pypy/module/_collections/app_defaultdict.py @@ -12,6 +12,7 @@ class defaultdict(dict): __slots__ = ['default_factory'] + __module__ = 'collections' def __init__(self, *args, **kwds): if len(args) > 0: diff --git a/pypy/module/_collections/test/test_defaultdict.py b/pypy/module/_collections/test/test_defaultdict.py --- a/pypy/module/_collections/test/test_defaultdict.py +++ b/pypy/module/_collections/test/test_defaultdict.py @@ -14,6 +14,12 @@ d[5].append(44) assert l == [42, 43] and l2 == [44] + def test_module(self): + from _collections import defaultdict + assert repr(defaultdict) in ( + "<class 'collections.defaultdict'>", # on PyPy + "<type 'collections.defaultdict'>") # on CPython + def test_keyerror_without_factory(self): from _collections import defaultdict for d1 in [defaultdict(), defaultdict(None)]: diff --git a/pypy/module/_sre/interp_sre.py b/pypy/module/_sre/interp_sre.py --- a/pypy/module/_sre/interp_sre.py +++ b/pypy/module/_sre/interp_sre.py @@ -7,6 +7,7 @@ from pypy.interpreter.error import OperationError from rpython.rlib.rarithmetic import intmask from rpython.rlib import jit +from rpython.rlib.rstring import StringBuilder, UnicodeBuilder # ____________________________________________________________ # @@ -36,6 +37,8 @@ if 0 <= start <= end: if isinstance(ctx, rsre_core.BufMatchContext): return space.wrap(ctx._buffer.getslice(start, end, 1, end-start)) + if isinstance(ctx, rsre_core.StrMatchContext): + return space.wrap(ctx._string[start:end]) elif isinstance(ctx, rsre_core.UnicodeMatchContext): return space.wrap(ctx._unicodestr[start:end]) else: @@ -98,8 +101,8 @@ space.wrap("cannot copy this pattern object")) def make_ctx(self, w_string, pos=0, endpos=sys.maxint): - """Make a BufMatchContext or a UnicodeMatchContext for searching - in the given w_string object.""" + """Make a StrMatchContext, BufMatchContext or a UnicodeMatchContext for + searching in the given w_string object.""" space = self.space if pos < 0: pos = 0 @@ -113,6 +116,14 @@ endpos = len(unicodestr) return rsre_core.UnicodeMatchContext(self.code, unicodestr, pos, endpos, self.flags) + elif space.isinstance_w(w_string, space.w_str): + str = space.str_w(w_string) + if pos > len(str): + pos = len(str) + if endpos > len(str): + endpos = len(str) + return rsre_core.StrMatchContext(self.code, str, + pos, endpos, self.flags) else: buf = space.readbuf_w(w_string) size = buf.getlength() @@ -216,6 +227,11 @@ def subx(self, w_ptemplate, w_string, count): space = self.space + # use a (much faster) string/unicode builder if w_ptemplate and + # w_string are both string or both unicode objects, and if w_ptemplate + # is a literal + use_builder = False + filter_as_unicode = filter_as_string = None if space.is_true(space.callable(w_ptemplate)): w_filter = w_ptemplate filter_is_callable = True @@ -223,6 +239,8 @@ if space.isinstance_w(w_ptemplate, space.w_unicode): filter_as_unicode = space.unicode_w(w_ptemplate) literal = u'\\' not in filter_as_unicode + use_builder = ( + space.isinstance_w(w_string, space.w_unicode) and literal) else: try: filter_as_string = space.str_w(w_ptemplate) @@ -232,6 +250,8 @@ literal = False else: literal = '\\' not in filter_as_string + use_builder = ( + space.isinstance_w(w_string, space.w_str) and literal) if literal: w_filter = w_ptemplate filter_is_callable = False @@ -242,19 +262,44 @@ space.wrap(self), w_ptemplate) filter_is_callable = space.is_true(space.callable(w_filter)) # + # XXX this is a bit of a mess, but it improves performance a lot ctx = self.make_ctx(w_string) - sublist_w = [] + sublist_w = strbuilder = unicodebuilder = None + if use_builder: + if filter_as_unicode is not None: + unicodebuilder = UnicodeBuilder(ctx.end) + else: + assert filter_as_string is not None + strbuilder = StringBuilder(ctx.end) + else: + sublist_w = [] n = last_pos = 0 while not count or n < count: + sub_jitdriver.jit_merge_point( + self=self, + use_builder=use_builder, + filter_is_callable=filter_is_callable, + filter_type=type(w_filter), + ctx=ctx, + w_filter=w_filter, + strbuilder=strbuilder, + unicodebuilder=unicodebuilder, + filter_as_string=filter_as_string, + filter_as_unicode=filter_as_unicode, + count=count, + w_string=w_string, + n=n, last_pos=last_pos, sublist_w=sublist_w + ) + space = self.space if not searchcontext(space, ctx): break if last_pos < ctx.match_start: - sublist_w.append(slice_w(space, ctx, last_pos, - ctx.match_start, space.w_None)) + _sub_append_slice( + ctx, space, use_builder, sublist_w, + strbuilder, unicodebuilder, last_pos, ctx.match_start) start = ctx.match_end if start == ctx.match_start: start += 1 - nextctx = ctx.fresh_copy(start) if not (last_pos == ctx.match_start == ctx.match_end and n > 0): # the above ignores empty matches on latest position @@ -262,28 +307,71 @@ w_match = self.getmatch(ctx, True) w_piece = space.call_function(w_filter, w_match) if not space.is_w(w_piece, space.w_None): + assert strbuilder is None and unicodebuilder is None + assert not use_builder sublist_w.append(w_piece) else: - sublist_w.append(w_filter) + if use_builder: + if strbuilder is not None: + assert filter_as_string is not None + strbuilder.append(filter_as_string) + else: + assert unicodebuilder is not None + assert filter_as_unicode is not None + unicodebuilder.append(filter_as_unicode) + else: + sublist_w.append(w_filter) last_pos = ctx.match_end n += 1 elif last_pos >= ctx.end: break # empty match at the end: finished - ctx = nextctx + ctx.reset(start) if last_pos < ctx.end: - sublist_w.append(slice_w(space, ctx, last_pos, ctx.end, - space.w_None)) + _sub_append_slice(ctx, space, use_builder, sublist_w, + strbuilder, unicodebuilder, last_pos, ctx.end) + if use_builder: + if strbuilder is not None: + return space.wrap(strbuilder.build()), n + else: + assert unicodebuilder is not None + return space.wrap(unicodebuilder.build()), n + else: + if space.isinstance_w(w_string, space.w_unicode): + w_emptystr = space.wrap(u'') + else: + w_emptystr = space.wrap('') + w_item = space.call_method(w_emptystr, 'join', + space.newlist(sublist_w)) + return w_item, n - if space.isinstance_w(w_string, space.w_unicode): - w_emptystr = space.wrap(u'') - else: - w_emptystr = space.wrap('') - w_item = space.call_method(w_emptystr, 'join', - space.newlist(sublist_w)) - return w_item, n +sub_jitdriver = jit.JitDriver( + reds="""count n last_pos + ctx w_filter + strbuilder unicodebuilder + filter_as_string + filter_as_unicode + w_string sublist_w + self""".split(), + greens=["filter_is_callable", "use_builder", "filter_type", "ctx.pattern"]) +def _sub_append_slice(ctx, space, use_builder, sublist_w, + strbuilder, unicodebuilder, start, end): + if use_builder: + if isinstance(ctx, rsre_core.BufMatchContext): + assert strbuilder is not None + return strbuilder.append(ctx._buffer.getslice(start, end, 1, end-start)) + if isinstance(ctx, rsre_core.StrMatchContext): + assert strbuilder is not None + return strbuilder.append_slice(ctx._string, start, end) + elif isinstance(ctx, rsre_core.UnicodeMatchContext): + assert unicodebuilder is not None + return unicodebuilder.append_slice(ctx._unicodestr, start, end) + assert 0, "unreachable" + else: + sublist_w.append(slice_w(space, ctx, start, end, space.w_None)) + @unwrap_spec(flags=int, groups=int, w_groupindex=WrappedDefault(None), w_indexgroup=WrappedDefault(None)) def SRE_Pattern__new__(space, w_subtype, w_pattern, flags, w_code, @@ -482,6 +570,8 @@ ctx = self.ctx if isinstance(ctx, rsre_core.BufMatchContext): return space.wrap(ctx._buffer.as_str()) + elif isinstance(ctx, rsre_core.StrMatchContext): + return space.wrap(ctx._string) elif isinstance(ctx, rsre_core.UnicodeMatchContext): return space.wrap(ctx._unicodestr) else: diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h --- a/pypy/module/cpyext/include/patchlevel.h +++ b/pypy/module/cpyext/include/patchlevel.h @@ -29,8 +29,8 @@ #define PY_VERSION "2.7.10" /* PyPy version as a string */ -#define PYPY_VERSION "4.1.0-alpha0" -#define PYPY_VERSION_NUM 0x04010000 +#define PYPY_VERSION "5.1.0-alpha0" +#define PYPY_VERSION_NUM 0x05010000 /* Defined to mean a PyPy where cpyext holds more regular references to PyObjects, e.g. staying alive as long as the internal PyPy object diff --git a/pypy/module/micronumpy/concrete.py b/pypy/module/micronumpy/concrete.py --- a/pypy/module/micronumpy/concrete.py +++ b/pypy/module/micronumpy/concrete.py @@ -298,7 +298,14 @@ except IndexError: # not a single result chunks = self._prepare_slice_args(space, w_index) - return new_view(space, orig_arr, chunks) + copy = False + if isinstance(chunks[0], BooleanChunk): + # numpy compatibility + copy = True + w_ret = new_view(space, orig_arr, chunks) + if copy: + w_ret = w_ret.descr_copy(space, space.wrap(w_ret.get_order())) + return w_ret def descr_setitem(self, space, orig_arr, w_index, w_value): try: diff --git a/pypy/module/micronumpy/ndarray.py b/pypy/module/micronumpy/ndarray.py --- a/pypy/module/micronumpy/ndarray.py +++ b/pypy/module/micronumpy/ndarray.py @@ -22,7 +22,8 @@ from pypy.module.micronumpy.flagsobj import W_FlagsObject from pypy.module.micronumpy.strides import ( get_shape_from_iterable, shape_agreement, shape_agreement_multiple, - is_c_contiguous, is_f_contiguous, calc_strides, new_view) + is_c_contiguous, is_f_contiguous, calc_strides, new_view, BooleanChunk, + SliceChunk) from pypy.module.micronumpy.casting import can_cast_array from pypy.module.micronumpy.descriptor import get_dtype_cache @@ -204,7 +205,13 @@ if iter_shape is None: # w_index is a list of slices, return a view chunks = self.implementation._prepare_slice_args(space, w_index) - return new_view(space, self, chunks) + copy = False + if isinstance(chunks[0], BooleanChunk): + copy = True + w_ret = new_view(space, self, chunks) + if copy: + w_ret = w_ret.descr_copy(space, space.wrap(w_ret.get_order())) + return w_ret shape = res_shape + self.get_shape()[len(indexes):] w_res = W_NDimArray.from_shape(space, shape, self.get_dtype(), self.get_order(), w_instance=self) @@ -220,8 +227,24 @@ if iter_shape is None: # w_index is a list of slices chunks = self.implementation._prepare_slice_args(space, w_index) - view = new_view(space, self, chunks) - view.implementation.setslice(space, val_arr) + dim = -1 + view = self + for i, c in enumerate(chunks): + if isinstance(c, BooleanChunk): + dim = i + idx = c.w_idx + chunks.pop(i) + chunks.insert(0, SliceChunk(space.newslice(space.wrap(0), + space.w_None, space.w_None))) + break + if dim > 0: + view = self.implementation.swapaxes(space, self, 0, dim) + if dim >= 0: + view = new_view(space, self, chunks) + view.setitem_filter(space, idx, val_arr) + else: + view = new_view(space, self, chunks) + view.implementation.setslice(space, val_arr) return if support.product(iter_shape) == 0: return diff --git a/pypy/module/micronumpy/strides.py b/pypy/module/micronumpy/strides.py --- a/pypy/module/micronumpy/strides.py +++ b/pypy/module/micronumpy/strides.py @@ -97,22 +97,19 @@ # filter by axis dim filtr = chunks[dim] assert isinstance(filtr, BooleanChunk) + # XXX this creates a new array, and fails in setitem w_arr = w_arr.getitem_filter(space, filtr.w_idx, axis=dim) arr = w_arr.implementation chunks[dim] = SliceChunk(space.newslice(space.wrap(0), - space.wrap(-1), space.w_None)) + space.w_None, space.w_None)) r = calculate_slice_strides(space, arr.shape, arr.start, arr.get_strides(), arr.get_backstrides(), chunks) else: r = calculate_slice_strides(space, arr.shape, arr.start, arr.get_strides(), arr.get_backstrides(), chunks) shape, start, strides, backstrides = r - w_ret = W_NDimArray.new_slice(space, start, strides[:], backstrides[:], + return W_NDimArray.new_slice(space, start, strides[:], backstrides[:], shape[:], arr, w_arr) - if dim == 0: - # Do not return a view - return w_ret.descr_copy(space, space.wrap(w_ret.get_order())) - return w_ret @jit.unroll_safe def _extend_shape(old_shape, chunks): diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py --- a/pypy/module/micronumpy/test/test_ndarray.py +++ b/pypy/module/micronumpy/test/test_ndarray.py @@ -2582,8 +2582,10 @@ assert b.base is None b = a[:, np.array([True, False, True])] assert b.base is not None + a[np.array([True, False]), 0] = 100 b = a[np.array([True, False]), 0] - assert (b ==[0]).all() + assert b.shape == (1,) + assert (b ==[100]).all() def test_scalar_indexing(self): import numpy as np diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py b/pypy/module/pypyjit/test_pypy_c/test_00_model.py --- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py +++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py @@ -68,9 +68,12 @@ pipe.returncode,)) if stderr.startswith('SKIP:'): py.test.skip(stderr) - if stderr.startswith('debug_alloc.h:'): # lldebug builds - stderr = '' + #if stderr.startswith('debug_alloc.h:'): # lldebug builds + # stderr = '' #assert not stderr + if stderr: + print '*** stderr of the subprocess: ***' + print stderr # if discard_stdout_before_last_line: stdout = stdout.splitlines(True)[-1] diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py --- a/pypy/module/sys/version.py +++ b/pypy/module/sys/version.py @@ -10,7 +10,7 @@ #XXX # sync CPYTHON_VERSION with patchlevel.h, package.py CPYTHON_API_VERSION = 1013 #XXX # sync with include/modsupport.h -PYPY_VERSION = (4, 1, 0, "alpha", 0) #XXX # sync patchlevel.h +PYPY_VERSION = (5, 1, 0, "alpha", 0) #XXX # sync patchlevel.h import pypy diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py b/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py --- a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py +++ b/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py @@ -33,8 +33,12 @@ pythonpath.insert(0, cffi_base) return os.pathsep.join(pythonpath) -def setup_module(mod): - mod.org_env = os.environ.copy() +def copy_away_env(): + global org_env + try: + org_env + except NameError: + org_env = os.environ.copy() class EmbeddingTests: @@ -122,6 +126,7 @@ os.chdir(curdir) def patch_environment(self): + copy_away_env() path = self.get_path() # for libpypy-c.dll or Python27.dll path = os.path.split(sys.executable)[0] + os.path.pathsep + path diff --git a/pypy/objspace/std/complexobject.py b/pypy/objspace/std/complexobject.py --- a/pypy/objspace/std/complexobject.py +++ b/pypy/objspace/std/complexobject.py @@ -266,11 +266,12 @@ return None from rpython.rlib.longlong2float import float2longlong from pypy.objspace.std.util import IDTAG_COMPLEX as tag + from pypy.objspace.std.util import IDTAG_SHIFT real = space.float_w(space.getattr(self, space.wrap("real"))) imag = space.float_w(space.getattr(self, space.wrap("imag"))) real_b = rbigint.fromrarith_int(float2longlong(real)) imag_b = rbigint.fromrarith_int(r_ulonglong(float2longlong(imag))) - val = real_b.lshift(64).or_(imag_b).lshift(3).int_or_(tag) + val = real_b.lshift(64).or_(imag_b).lshift(IDTAG_SHIFT).int_or_(tag) return space.newlong_from_rbigint(val) def int(self, space): diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py --- a/pypy/objspace/std/floatobject.py +++ b/pypy/objspace/std/floatobject.py @@ -160,15 +160,11 @@ return self.floatval def int(self, space): + # this is a speed-up only, for space.int(w_float). if (type(self) is not W_FloatObject and space.is_overloaded(self, space.w_float, '__int__')): return W_Root.int(self, space) - try: - value = ovfcheck_float_to_int(self.floatval) - except OverflowError: - return space.long(self) - else: - return space.newint(value) + return self.descr_trunc(space) def is_w(self, space, w_other): from rpython.rlib.longlong2float import float2longlong @@ -185,9 +181,10 @@ return None from rpython.rlib.longlong2float import float2longlong from pypy.objspace.std.util import IDTAG_FLOAT as tag + from pypy.objspace.std.util import IDTAG_SHIFT val = float2longlong(space.float_w(self)) b = rbigint.fromrarith_int(val) - b = b.lshift(3).int_or_(tag) + b = b.lshift(IDTAG_SHIFT).int_or_(tag) return space.newlong_from_rbigint(b) def __repr__(self): @@ -424,9 +421,8 @@ "cannot convert float NaN to integer") def descr_trunc(self, space): - whole = math.modf(self.floatval)[1] try: - value = ovfcheck_float_to_int(whole) + value = ovfcheck_float_to_int(self.floatval) except OverflowError: return self.descr_long(space) else: @@ -661,7 +657,7 @@ __format__ = interp2app(W_FloatObject.descr_format), __coerce__ = interp2app(W_FloatObject.descr_coerce), __nonzero__ = interp2app(W_FloatObject.descr_nonzero), - __int__ = interp2app(W_FloatObject.int), + __int__ = interp2app(W_FloatObject.descr_trunc), __float__ = interp2app(W_FloatObject.descr_float), __long__ = interp2app(W_FloatObject.descr_long), __trunc__ = interp2app(W_FloatObject.descr_trunc), diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py --- a/pypy/objspace/std/intobject.py +++ b/pypy/objspace/std/intobject.py @@ -24,7 +24,7 @@ from pypy.interpreter.typedef import TypeDef from pypy.objspace.std import newformat from pypy.objspace.std.util import ( - BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_INT, wrap_parsestringerror) + BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_INT, IDTAG_SHIFT, wrap_parsestringerror) SENTINEL = object() @@ -46,7 +46,7 @@ if self.user_overridden_class: return None b = space.bigint_w(self) - b = b.lshift(3).int_or_(IDTAG_INT) + b = b.lshift(IDTAG_SHIFT).int_or_(IDTAG_INT) return space.newlong_from_rbigint(b) def int(self, space): diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py --- a/pypy/objspace/std/longobject.py +++ b/pypy/objspace/std/longobject.py @@ -16,7 +16,7 @@ from pypy.objspace.std import newformat from pypy.objspace.std.intobject import W_AbstractIntObject from pypy.objspace.std.util import ( - BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_LONG, wrap_parsestringerror) + BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_LONG, IDTAG_SHIFT, wrap_parsestringerror) def delegate_other(func): @@ -45,7 +45,7 @@ if self.user_overridden_class: return None b = space.bigint_w(self) - b = b.lshift(3).int_or_(IDTAG_LONG) + b = b.lshift(IDTAG_SHIFT).int_or_(IDTAG_LONG) return space.newlong_from_rbigint(b) def unwrap(self, space): diff --git a/pypy/objspace/std/test/test_kwargsdict.py b/pypy/objspace/std/test/test_kwargsdict.py --- a/pypy/objspace/std/test/test_kwargsdict.py +++ b/pypy/objspace/std/test/test_kwargsdict.py @@ -118,10 +118,16 @@ def test_delitem(self): pass # delitem devolves for now + def test_setdefault_fast(self): + pass # not based on hashing at all + class TestDevolvedKwargsDictImplementation(BaseTestDevolvedDictImplementation): get_impl = get_impl StrategyClass = KwargsDictStrategy + def test_setdefault_fast(self): + pass # not based on hashing at all + class AppTestKwargsDictStrategy(object): def setup_class(cls): diff --git a/pypy/objspace/std/test/test_obj.py b/pypy/objspace/std/test/test_obj.py --- a/pypy/objspace/std/test/test_obj.py +++ b/pypy/objspace/std/test/test_obj.py @@ -172,15 +172,15 @@ def test_id_on_primitives(self): if self.cpython_apptest: skip("cpython behaves differently") - assert id(1) == (1 << 3) + 1 - assert id(1l) == (1 << 3) + 3 + assert id(1) == (1 << 4) + 1 + assert id(1l) == (1 << 4) + 3 class myint(int): pass assert id(myint(1)) != id(1) assert id(1.0) & 7 == 5 assert id(-0.0) != id(0.0) - assert hex(id(2.0)) == '0x20000000000000005L' + assert hex(id(2.0)) == '0x40000000000000005L' assert id(0.0) == 5 def test_id_on_strs(self): diff --git a/pypy/objspace/std/util.py b/pypy/objspace/std/util.py --- a/pypy/objspace/std/util.py +++ b/pypy/objspace/std/util.py @@ -2,11 +2,13 @@ from pypy.interpreter.error import OperationError, oefmt +IDTAG_SHIFT = 4 IDTAG_INT = 1 IDTAG_LONG = 3 IDTAG_FLOAT = 5 IDTAG_COMPLEX = 7 +IDTAG_METHOD = 9 CMP_OPS = dict(lt='<', le='<=', eq='==', ne='!=', gt='>', ge='>=') BINARY_BITWISE_OPS = {'and': '&', 'lshift': '<<', 'or': '|', 'rshift': '>>', diff --git a/pypy/tool/release/force-builds.py b/pypy/tool/release/force-builds.py --- a/pypy/tool/release/force-builds.py +++ b/pypy/tool/release/force-builds.py @@ -9,7 +9,7 @@ modified by PyPy team """ -import os, sys, urllib +import os, sys, urllib, subprocess from twisted.internet import reactor, defer from twisted.python import log @@ -83,4 +83,9 @@ (options, args) = parser.parse_args() if not options.branch: parser.error("branch option required") + try: + subprocess.check_call(['hg','id','-r', options.branch]) + except subprocess.CalledProcessError: + print 'branch', options.branch, 'could not be found in local repository' + sys.exit(-1) main(options.branch, options.server, user=options.user) diff --git a/rpython/doc/translation.rst b/rpython/doc/translation.rst --- a/rpython/doc/translation.rst +++ b/rpython/doc/translation.rst @@ -33,7 +33,7 @@ The RPython translation toolchain never sees Python source code or syntax trees, but rather starts with the *code objects* that define the behaviour of the function objects one gives it as input. The -`bytecode evaluator`_ and the :ref:`flow graph builder<flow-graphs>` work through these +:ref:`flow graph builder<flow-graphs>` works through these code objects using `abstract interpretation`_ to produce a control flow graph (one per function): yet another representation of the source program, but one which is suitable for applying type inference @@ -85,7 +85,6 @@ .. _PDF color version: _static/translation.pdf -.. _bytecode evaluator: interpreter.html .. _abstract interpretation: http://en.wikipedia.org/wiki/Abstract_interpretation diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -576,7 +576,9 @@ if cpu.supports_floats: def func(f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9): + seen.append((f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9)) return f0 + f1 + f2 + f3 + f4 + f5 + f6 + float(i0 + i1) + f7 + f8 + f9 + seen = [] F = lltype.Float I = lltype.Signed FUNC = self.FuncType([F] * 7 + [I] + [F] + [I] + [F]* 2, F) @@ -585,13 +587,15 @@ calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo.MOST_GENERAL) funcbox = self.get_funcbox(cpu, func_ptr) - args = ([boxfloat(.1) for i in range(7)] + - [InputArgInt(1), boxfloat(.2), InputArgInt(2), boxfloat(.3), - boxfloat(.4)]) + args = ([boxfloat(.0), boxfloat(.1), boxfloat(.2), boxfloat(.3), + boxfloat(.4), boxfloat(.5), boxfloat(.6), + InputArgInt(1), boxfloat(.7), InputArgInt(2), boxfloat(.8), + boxfloat(.9)]) res = self.execute_operation(rop.CALL_F, [funcbox] + args, 'float', descr=calldescr) - assert abs(longlong.getrealfloat(res) - 4.6) < 0.0001 + assert seen == [(.0, .1, .2, .3, .4, .5, .6, 1, .7, 2, .8, .9)] + assert abs(longlong.getrealfloat(res) - 7.5) < 0.0001 def test_call_many_arguments(self): # Test calling a function with a large number of arguments (more than diff --git a/rpython/rtyper/test/test_rdict.py b/rpython/rtyper/test/test_rdict.py --- a/rpython/rtyper/test/test_rdict.py +++ b/rpython/rtyper/test/test_rdict.py @@ -59,19 +59,6 @@ yield -def not_really_random(): - """A random-ish generator, which also generates nice patterns from time to time. - Could be useful to detect problems associated with specific usage patterns.""" - import random - x = random.random() - print 'random seed: %r' % (x,) - for i in range(12000): - r = 3.4 + i/20000.0 - x = r*x - x*x - assert 0 <= x < 4 - yield x - - class BaseTestRDict(BaseRtypingTest): def test_dict_creation(self): def createdict(i): @@ -1048,7 +1035,7 @@ s_BA_dic = s.items[1] r_AB_dic = rtyper.getrepr(s_AB_dic) - r_BA_dic = rtyper.getrepr(s_AB_dic) + r_BA_dic = rtyper.getrepr(s_BA_dic) assert r_AB_dic.lowleveltype == r_BA_dic.lowleveltype @@ -1166,50 +1153,51 @@ st_keys = sampled_from(keytypes_s) st_values = sampled_from(keytypes_s + [SomeString(can_be_None=True)]) -class Space(object): +class MappingSpace(object): def __init__(self, s_key, s_value): self.s_key = s_key self.s_value = s_value rtyper = PseudoRTyper() r_key = s_key.rtyper_makerepr(rtyper) r_value = s_value.rtyper_makerepr(rtyper) - dictrepr = rdict.DictRepr(rtyper, r_key, r_value, + dictrepr = self.MappingRepr(rtyper, r_key, r_value, DictKey(None, s_key), DictValue(None, s_value)) dictrepr.setup() - self.l_dict = rdict.ll_newdict(dictrepr.DICT) - self.reference = {} + self.l_dict = self.newdict(dictrepr) + self.reference = self.new_reference() self.ll_key = r_key.convert_const self.ll_value = r_value.convert_const def setitem(self, key, value): ll_key = self.ll_key(key) ll_value = self.ll_value(value) - rdict.ll_dict_setitem(self.l_dict, ll_key, ll_value) + self.ll_setitem(self.l_dict, ll_key, ll_value) self.reference[key] = value - assert rdict.ll_contains(self.l_dict, ll_key) + assert self.ll_contains(self.l_dict, ll_key) def delitem(self, key): ll_key = self.ll_key(key) - rdict.ll_dict_delitem(self.l_dict, ll_key) + self.ll_delitem(self.l_dict, ll_key) del self.reference[key] - assert not rdict.ll_contains(self.l_dict, ll_key) + assert not self.ll_contains(self.l_dict, ll_key) def copydict(self): - self.l_dict = rdict.ll_copy(self.l_dict) + self.l_dict = self.ll_copy(self.l_dict) + assert self.ll_len(self.l_dict) == len(self.reference) def cleardict(self): - rdict.ll_clear(self.l_dict) + self.ll_clear(self.l_dict) self.reference.clear() - assert rdict.ll_dict_len(self.l_dict) == 0 + assert self.ll_len(self.l_dict) == 0 def fullcheck(self): - assert rdict.ll_dict_len(self.l_dict) == len(self.reference) + assert self.ll_len(self.l_dict) == len(self.reference) for key, value in self.reference.iteritems(): - assert (rdict.ll_dict_getitem(self.l_dict, self.ll_key(key)) == + assert (self.ll_getitem(self.l_dict, self.ll_key(key)) == self.ll_value(value)) -class StressTest(GenericStateMachine): +class MappingSM(GenericStateMachine): def __init__(self): self.space = None @@ -1239,7 +1227,7 @@ def execute_step(self, action): if action.method == 'setup': - self.space = Space(*action.args) + self.space = self.Space(*action.args) self.st_keys = ann2strategy(self.space.s_key) self.st_values = ann2strategy(self.space.s_value) return @@ -1250,5 +1238,24 @@ if self.space: self.space.fullcheck() + +class DictSpace(MappingSpace): + MappingRepr = rdict.DictRepr + new_reference = dict + ll_getitem = staticmethod(rdict.ll_dict_getitem) + ll_setitem = staticmethod(rdict.ll_dict_setitem) + ll_delitem = staticmethod(rdict.ll_dict_delitem) + ll_len = staticmethod(rdict.ll_dict_len) + ll_contains = staticmethod(rdict.ll_contains) + ll_copy = staticmethod(rdict.ll_copy) + ll_clear = staticmethod(rdict.ll_clear) + + def newdict(self, repr): + return rdict.ll_newdict(repr.DICT) + +class DictSM(MappingSM): + Space = DictSpace + def test_hypothesis(): - run_state_machine_as_test(StressTest, settings(max_examples=500, stateful_step_count=100)) + run_state_machine_as_test( + DictSM, settings(max_examples=500, stateful_step_count=100)) diff --git a/rpython/rtyper/test/test_rordereddict.py b/rpython/rtyper/test/test_rordereddict.py --- a/rpython/rtyper/test/test_rordereddict.py +++ b/rpython/rtyper/test/test_rordereddict.py @@ -1,14 +1,18 @@ - import py from collections import OrderedDict +from hypothesis import settings +from hypothesis.stateful import run_state_machine_as_test + from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rtyper.lltypesystem import rordereddict, rstr from rpython.rlib.rarithmetic import intmask from rpython.rtyper.annlowlevel import llstr, hlstr -from rpython.rtyper.test.test_rdict import BaseTestRDict +from rpython.rtyper.test.test_rdict import ( + BaseTestRDict, MappingSpace, MappingSM) from rpython.rlib import objectmodel +rodct = rordereddict def get_indexes(ll_d): return ll_d.indexes._obj.container._as_ptr() @@ -330,124 +334,48 @@ assert res == 6 -class TestStress: +class ODictSpace(MappingSpace): + MappingRepr = rodct.OrderedDictRepr + new_reference = OrderedDict + ll_getitem = staticmethod(rodct.ll_dict_getitem) + ll_setitem = staticmethod(rodct.ll_dict_setitem) + ll_delitem = staticmethod(rodct.ll_dict_delitem) + ll_len = staticmethod(rodct.ll_dict_len) + ll_contains = staticmethod(rodct.ll_dict_contains) + ll_copy = staticmethod(rodct.ll_dict_copy) + ll_clear = staticmethod(rodct.ll_dict_clear) - def test_stress(self): - from rpython.annotator.dictdef import DictKey, DictValue - from rpython.annotator import model as annmodel - from rpython.rtyper import rint - from rpython.rtyper.test.test_rdict import not_really_random - rodct = rordereddict - dictrepr = rodct.OrderedDictRepr( - None, rint.signed_repr, rint.signed_repr, - DictKey(None, annmodel.SomeInteger()), - DictValue(None, annmodel.SomeInteger())) - dictrepr.setup() - l_dict = rodct.ll_newdict(dictrepr.DICT) - referencetable = [None] * 400 - referencelength = 0 - value = 0 + def newdict(self, repr): + return rodct.ll_newdict(repr.DICT) - def complete_check(): - for n, refvalue in zip(range(len(referencetable)), referencetable): - try: - gotvalue = rodct.ll_dict_getitem(l_dict, n) - except KeyError: - assert refvalue is None - else: - assert gotvalue == refvalue + def get_keys(self): + DICT = lltype.typeOf(self.l_dict).TO + ITER = rordereddict.get_ll_dictiter(lltype.Ptr(DICT)) + ll_iter = rordereddict.ll_dictiter(ITER, self.l_dict) + ll_dictnext = rordereddict._ll_dictnext + keys_ll = [] + while True: + try: + num = ll_dictnext(ll_iter) + keys_ll.append(self.l_dict.entries[num].key) + except StopIteration: + break + return keys_ll - for x in not_really_random(): - n = int(x*100.0) # 0 <= x < 400 - op = repr(x)[-1] - if op <= '2' and referencetable[n] is not None: - rodct.ll_dict_delitem(l_dict, n) - referencetable[n] = None - referencelength -= 1 - elif op <= '6': - rodct.ll_dict_setitem(l_dict, n, value) - if referencetable[n] is None: - referencelength += 1 - referencetable[n] = value - value += 1 - else: - try: - gotvalue = rodct.ll_dict_getitem(l_dict, n) - except KeyError: - assert referencetable[n] is None - else: - assert gotvalue == referencetable[n] - if 1.38 <= x <= 1.39: - complete_check() - print 'current dict length:', referencelength - assert l_dict.num_live_items == referencelength - complete_check() + def fullcheck(self): + # overridden to also check key order + assert self.ll_len(self.l_dict) == len(self.reference) + keys_ll = self.get_keys() + assert len(keys_ll) == len(self.reference) + for key, ll_key in zip(self.reference, keys_ll): + assert self.ll_key(key) == ll_key + assert (self.ll_getitem(self.l_dict, self.ll_key(key)) == + self.ll_value(self.reference[key])) - def test_stress_2(self): - yield self.stress_combination, True, False - yield self.stress_combination, False, True - yield self.stress_combination, False, False - yield self.stress_combination, True, True - def stress_combination(self, key_can_be_none, value_can_be_none): - from rpython.rtyper.lltypesystem.rstr import string_repr - from rpython.annotator.dictdef import DictKey, DictValue - from rpython.annotator import model as annmodel - from rpython.rtyper.test.test_rdict import not_really_random - rodct = rordereddict +class ODictSM(MappingSM): + Space = ODictSpace - print - print "Testing combination with can_be_None: keys %s, values %s" % ( - key_can_be_none, value_can_be_none) - - class PseudoRTyper: - cache_dummy_values = {} - dictrepr = rodct.OrderedDictRepr( - PseudoRTyper(), string_repr, string_repr, - DictKey(None, annmodel.SomeString(key_can_be_none)), - DictValue(None, annmodel.SomeString(value_can_be_none))) - dictrepr.setup() - print dictrepr.lowleveltype - #for key, value in dictrepr.DICTENTRY._adtmeths.items(): - # print ' %s = %s' % (key, value) - l_dict = rodct.ll_newdict(dictrepr.DICT) - referencetable = [None] * 400 - referencelength = 0 - values = not_really_random() - keytable = [string_repr.convert_const("foo%d" % n) - for n in range(len(referencetable))] - - def complete_check(): - for n, refvalue in zip(range(len(referencetable)), referencetable): - try: - gotvalue = rodct.ll_dict_getitem(l_dict, keytable[n]) - except KeyError: - assert refvalue is None - else: - assert gotvalue == refvalue - - for x in not_really_random(): - n = int(x*100.0) # 0 <= x < 400 - op = repr(x)[-1] - if op <= '2' and referencetable[n] is not None: - rodct.ll_dict_delitem(l_dict, keytable[n]) - referencetable[n] = None - referencelength -= 1 - elif op <= '6': - ll_value = string_repr.convert_const(str(values.next())) - rodct.ll_dict_setitem(l_dict, keytable[n], ll_value) - if referencetable[n] is None: - referencelength += 1 - referencetable[n] = ll_value - else: - try: - gotvalue = rodct.ll_dict_getitem(l_dict, keytable[n]) - except KeyError: - assert referencetable[n] is None - else: - assert gotvalue == referencetable[n] - if 1.38 <= x <= 1.39: - complete_check() - print 'current dict length:', referencelength - assert l_dict.num_live_items == referencelength - complete_check() +def test_hypothesis(): + run_state_machine_as_test( + ODictSM, settings(max_examples=500, stateful_step_count=100)) _______________________________________________ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
