Codebase list pypy3 / d25a7da
New upstream version 7.3.4~rc2+dfsg Stefano Rivera 3 years ago
84 changed file(s) with 1971 addition(s) and 1036 deletion(s). Raw diff Collapse all Expand all
9898 Alex Martelli
9999 Spenser Bauman
100100 Michal Bendowski
101 nulano
101 Ondrej Baranovič
102102 Jan de Mooij
103103 Stefan Beyer
104104 Tyler Wade
114114 Devin Jeanpierre
115115 Bob Ippolito
116116 Bruno Gola
117 nulano
118117 David Malcolm
119118 Yannick Jadoul
120119 Squeaky
3737 def close(self):
3838 with _lock:
3939 if self.__ll_dbm:
40 lib.gdbm_close(self.__ll_dbm)
40 lib.pygdbm_close(self.__ll_dbm)
4141 self.__ll_dbm = None
4242
4343 def __raise_from_errno(self):
1010 #define GDBM_NOLOCK ...
1111 #define GDBM_REPLACE ...
1212
13 void* gdbm_open(char *, int, int, int, void (*)());
14 void gdbm_close(void*);
13 typedef struct gdbm_file_info *GDBM_FILE;
14
15 GDBM_FILE gdbm_open(const char *, int, int, int, void (*)(const char *));
1516
1617 typedef struct {
1718 char *dptr;
1819 int dsize;
1920 } datum;
2021
21 datum gdbm_fetch(void*, datum);
22 datum gdbm_fetch(GDBM_FILE, datum);
2223 datum pygdbm_fetch(void*, char*, int);
23 int gdbm_delete(void*, datum);
24 int gdbm_store(void*, datum, datum, int);
25 int gdbm_exists(void*, datum);
26 int pygdbm_exists(void*, char*, int);
24 int gdbm_delete(GDBM_FILE, datum);
25 int gdbm_store(GDBM_FILE, datum, datum, int);
26 int gdbm_exists(GDBM_FILE, datum);
27 int pygdbm_exists(GDBM_FILE, char*, int);
28 void pygdbm_close(GDBM_FILE);
2729
28 int gdbm_reorganize(void*);
30 int gdbm_reorganize(GDBM_FILE);
2931
30 datum gdbm_firstkey(void*);
31 datum gdbm_nextkey(void*, datum);
32 void gdbm_sync(void*);
32 datum gdbm_firstkey(GDBM_FILE);
33 datum gdbm_nextkey(GDBM_FILE, datum);
34 void gdbm_sync(GDBM_FILE);
3335
34 char* gdbm_strerror(int);
35 int gdbm_errno;
36 const char* gdbm_strerror(int);
37 extern int gdbm_errno;
3638
39 /* Needed to release returned values */
3740 void free(void*);
3841 ''')
3942
5760 datum key = {dptr, dsize};
5861 return gdbm_exists(gdbm_file, key);
5962 }
63
64 static void pygdbm_close(GDBM_FILE gdbm_file) {
65 /*
66 * In verison 17, void gdbm_close() became int gdbm_close()
67 * Work around that by wrapping the function
68 */
69 gdbm_close(gdbm_file);
70 }
6071 ''', libraries=['gdbm'], **kwds)
6172
6273
00 from __future__ import print_function
1 import sys, shutil, os, tempfile, hashlib, collections
1 import collections
2 import hashlib
3 import os
4 import platform
5 import shutil
6 import sys
27 import sysconfig
8 import tempfile
39 from os.path import join
410
511 try:
5460 # without an _ssl module, but the OpenSSL download site redirect HTTP
5561 # to HTTPS
5662 cffi_dependencies = {
57 'lzma': ('http://distfiles.macports.org/xz/xz-5.2.5.tar.bz2',
63 '_ssl': ('http://distfiles.macports.org/openssl/openssl-1.1.1k.tar.gz',
64 '892a0875b9872acd04a9fde79b1f943075d5ea162415de3047c327df33fbaee5',
65 [['./config', '--prefix=/usr', 'no-shared'],
66 ['make', '-s', '-j', str(multiprocessing.cpu_count())],
67 ['make', 'install', 'DESTDIR={}/'.format(deps_destdir)],
68 ]),
69 }
70 if sys.platform == 'darwin' or platform.machine() == 'aarch64':
71 # TODO: use these on x86 after upgrading Docker images to manylinux2014
72 cffi_dependencies['_gdbm'] = (
73 # this does not compile on the x86 buildbot, linker is missing '_history_list'
74 'http://distfiles.macports.org/gdbm/gdbm-1.18.1.tar.gz',
75 '86e613527e5dba544e73208f42b78b7c022d4fa5a6d5498bf18c8d6f745b91dc',
76 [configure_args + ['--without-readline'],
77 ['make', '-s', '-j', str(multiprocessing.cpu_count())],
78 ['make', 'install', 'DESTDIR={}/'.format(deps_destdir)],
79 ])
80 cffi_dependencies['lzma'] = (
81 # this does not compile on the linux64 buildbot, needs -fPIC
82 'http://distfiles.macports.org/xz/xz-5.2.5.tar.bz2',
5883 '5117f930900b341493827d63aa910ff5e011e0b994197c3b71c08a20228a42df',
5984 [configure_args,
6085 ['make', '-s', '-j', str(multiprocessing.cpu_count())],
6186 ['make', 'install', 'DESTDIR={}/'.format(deps_destdir)],
62 ]),
63 '_ssl': ('http://distfiles.macports.org/openssl/openssl-1.1.1f.tar.gz',
64 '186c6bfe6ecfba7a5b48c47f8a1673d0f3b0e5ba2e25602dd23b629975da3f35',
65 [['./config', '--prefix=/usr', 'no-shared'],
66 ['make', '-s', '-j', str(multiprocessing.cpu_count())],
67 ['make', 'install', 'DESTDIR={}/'.format(deps_destdir)],
68 ]),
69 # this does not compile on the buildbot, linker is missing '_history_list'
70 'gdbm': ('http://distfiles.macports.org/gdbm/gdbm-1.18.1.tar.gz',
71 '86e613527e5dba544e73208f42b78b7c022d4fa5a6d5498bf18c8d6f745b91dc',
72 [configure_args + ['--without-readline'],
73 ['make', '-s', '-j', str(multiprocessing.cpu_count())],
74 ['make', 'install', 'DESTDIR={}/'.format(deps_destdir)],
75 ]),
76 }
77
87 ])
7888
7989 def _unpack_tarfile(filename, extract_dir):
8090 """Unpack tar/tar.gz/tar.bz2/tar.xz `filename` to `extract_dir`
170180 def create_cffi_import_libraries(pypy_c, options, basedir, only=None,
171181 embed_dependencies=False, rebuild=False):
172182 from rpython.tool.runsubprocess import run_subprocess
183 print('calling create_cffi_import_libraries with "embed_dependencies"', embed_dependencies)
173184
174185 shutil.rmtree(str(join(basedir,'lib_pypy','__pycache__')),
175186 ignore_errors=True)
183194 env['INCLUDE'] = externals_path + r'\include;' + env.get('INCLUDE', '')
184195 env['LIB'] = externals_path + r'\lib;' + env.get('LIB', '')
185196 env['PATH'] = externals_path + r'\bin;' + env.get('PATH', '')
197 else:
198 env['CFLAGS'] = '-fPIC ' + env.get('CFLAGS', '')
186199 status, stdout, stderr = run_subprocess(str(pypy_c), ['-c', 'import setuptools'])
187200 if status != 0:
188201 status, stdout, stderr = run_subprocess(str(pypy_c), ['-m', 'ensurepip'])
8787
8888 # not ported yet
8989 if IS_64_BITS:
90 for name in ["_cppyy", "micronumpy"]:
90 for name in ["_cppyy", "micronumpy", "_hpy_universal"]:
9191 if name in working_modules:
9292 working_modules.remove(name)
9393
9898 if "_cppyy" in working_modules:
9999 working_modules.remove("_cppyy") # depends on ctypes
100100
101 if 1 or sys.platform.startswith('linux') and sys.maxsize <= 2**31:
101 if sys.platform.startswith('linux') and sys.maxsize <= 2**31:
102102 # _hpy_universal needs tweaking to work on 32-bit linux
103103 working_modules.remove('_hpy_universal')
104104
9696 - ``strategy(dict or list or set)``: Return the underlying strategy currently
9797 used by the object
9898
99 - ``list_get_physical_size(obj)``: Return the physical (ie overallocated
100 size) of the underlying list
101
99102 - ``specialized_zip_2_lists``
100103 - ``locals_to_fast``
101104 - ``set_code_callback``
4848 'sphinx.ext.ifconfig',
4949 'sphinx.ext.graphviz',
5050 'pypyconfig',
51 'sphinx_affiliates']
51 # 'sphinx_affiliates',
52 ]
5253
5354 # Canonical URL (including the '/') so searching from rpython docs finds these
5455 affiliate_options = {
6464 Alex Martelli
6565 Spenser Bauman
6666 Michal Bendowski
67 nulano
67 Ondrej Baranovič
6868 Jan de Mooij
6969 Stefan Beyer
7070 Tyler Wade
55
66 .. toctree::
77
8 release-v7.3.4.rst
89 release-v7.3.3.rst
910 release-v7.3.2.rst
1011 release-v7.3.1.rst
66 .. toctree::
77
88 whatsnew-head.rst
9 whatsnew-pypy2-7.3.4.rst
910 whatsnew-pypy2-7.3.3.rst
1011 whatsnew-pypy2-7.3.2.rst
1112 whatsnew-pypy2-7.3.1.rst
4142 whatsnew-1.9.rst
4243
4344
45 CPython 3.7 compatible versions
46 -------------------------------
47
48 .. toctree::
49 whatsnew-pypy3-head.rst
50 whatsnew-pypy3-7.3.4.rst
51
4452 CPython 3.6 compatible versions
4553 -------------------------------
4654
88 .. _`PyPy blog`: https://pypy.org/blog
99
1010 ..
11 Changelog up to commit d414fb8186a7
12
13
14 -The PyPy team is proud to release the version 7.3.4 of PyPy, which includes
11 Changelog up to commit 9c11d242d78c
12
13
14 The PyPy team is proud to release the version 7.3.4 of PyPy, which includes
1515 two different interpreters:
1616
1717 - PyPy2.7, which is an interpreter supporting the syntax and the features of
2020
2121 - PyPy3.7, which is an interpreter supporting the syntax and the features of
2222 Python 3.7, including the stdlib for CPython 3.7.10. We no longer refer to
23 this as beta-quality
23 this as beta-quality as the last incompatibilities with CPython (in the
24 ``re`` module) have been fixed.
25
26 We are no longer releasing a Python3.6 version, as we focus on updating to
27 Python 3.8. We have begun streaming the advances towards this goal on Saturday
28 evenings European time on https://www.twitch.tv/pypyproject. If Python3.6 is
29 important to you, please reach out as we could offer sponsored longer term
30 support.
2431
2532 The interpreters are based on much the same codebase, thus the multiple
2633 release. This is a micro release, all APIs are compatible with the 7.3
27 releases, but read on to find out what is new.
28
29 ..
30 The major new feature is prelminary support for the Universal mode of HPy: a
31 new way of writing c-extension modules to totally encapsulate the `PyObject*`.
32 The goal, as laid out in the `HPy blog post`_, is to enable a migration path
33 for c-extension authors who wish their code to be performant on alternative
34 interpreters like GraalPython_ (written on top of the Java virtual machine),
35 RustPython_, and PyPy. Thanks to Oracle for sponsoring work on HPy.
34 releases. Highlights of the release include binary **Windows 64** support,
35 faster numerical instance fields, and a preliminary HPy backend.
36
37 A new contributor (Ondrej Baranovič - thanks!) took us up on the challenge to get
38 `windows 64-bit`_ support. The work has been merged and for the first time we
39 are releasing a 64-bit Windows binary package.
40
41 The release contains the biggest change to `PyPy's implementation of the
42 instances of user-defined classes`_ in many years. The optimization was
43 motivated by the report of performance problems running a `numerical particle
44 emulation`_. We implemented an optimization that stores ``int`` and ``float``
45 instance fields in an unboxed way, as long as these fields are type-stable
46 (meaning that the same field always stores the same type, using the principle
47 of `type freezing`_). This gives significant performance improvements on
48 numerical pure-Python code, and other code where instances store many integers
49 or floating point numbers.
50
51 .. _`PyPy's implementation of the instances of user-defined classes`:
52 https://www.pypy.org/posts/2010/11/efficiently-implementing-python-objects-3838329944323946932.html
53 .. _`numerical particle emulation`: https://github.com/paugier/nbabel
54 .. _`type freezing`: https://www.csl.cornell.edu/~cbatten/pdfs/cheng-type-freezing-cgo2020.pdf
55
56 There were also a number of optimizations for methods around strings and bytes,
57 following user reported performance problems. If you are unhappy with PyPy's
58 performance on some code of yours, please report `an issue`_!
59
60 .. _`an issue`: https://foss.heptapod.net/pypy/pypy/-/issues/
61
62 A major new feature is prelminary support for the Universal mode of HPy: a
63 new way of writing c-extension modules to totally encapsulate ``PyObject*``.
64 The goal, as laid out in the `HPy documentation`_ and recent `HPy blog post`_,
65 is to enable a migration path
66 for c-extension authors who wish their code to be performant on alternative
67 interpreters like GraalPython_ (written on top of the Java virtual machine),
68 RustPython_, and PyPy. Thanks to Oracle and IBM for sponsoring work on HPy.
3669
3770 Several issues exposed in the 7.3.3 release were fixed. Many of them came from the
3871 great work ongoing to ship PyPy-compatible binary packages in `conda-forge`_.
3972 A big shout out to them for taking this on.
4073
41 There are also some significant performance improvements around maps
42 (dictionaries), ints, strings, btyes and more. These were done as users
43 reported reproducible performance problems.
44
4574 Development of PyPy takes place on https://foss.heptapod.net/pypy/pypy.
4675 We have seen an increase in the number of drive-by contributors who are able to
4776 use gitlab + mercurial to create merge requests.
4877
49 We also have begun streaming the advances towards PyPy3.8 on Saturday evenings
50 European time on https://www.twitch.tv/pypyproject.
51
5278 The `CFFI`_ backend has been updated to version 1.14.5 and the cppyy_ backend
53 to 1.14.2. We recommend using CFFI rather than c-extensions to interact with C,
79 to 1.14.2. We recommend using CFFI rather than C-extensions to interact with C,
5480 and using cppyy for performant wrapping of C++ code for Python.
5581
56 A new contributor took us up on the challenge to get `windows 64-bit`_ support.
57 The work has been merged and for the first time we are releasing a 64-bit
58 windows binary package.
59
60 As always, this release fixed several issues and bugs. We strongly recommend
61 updating. Many of the fixes are the direct result of end-user bug reports, so
62 please continue reporting issues as they crop up.
82 As always, we strongly recommend updating to the latest versions. Many fixes
83 are the direct result of end-user bug reports, so please continue reporting
84 issues as they crop up.
6385
6486 You can find links to download the v7.3.4 releases here:
6587
6991 project. If PyPy is not quite good enough for your needs, we are available for
7092 direct consulting work. If PyPy is helping you out, we would love to hear about
7193 it and encourage submissions to our `renovated blog site`_ via a pull request
72 to www.github.com://pypy/pypy.org
94 to https://github.com/pypy/pypy.org
7395
7496 We would also like to thank our contributors and encourage new people to join
7597 the project. PyPy has many layers and we need help with all of them: `PyPy`_
7698 and `RPython`_ documentation improvements, tweaking popular modules to run
77 on pypy, or general `help`_ with making RPython's JIT even better. Since the
99 on PyPy, or general `help`_ with making RPython's JIT even better. Since the
78100 previous release, we have accepted contributions from 10 new contributors,
79 thanks for pitching in.
80
81 If you are a python library maintainer and use c-extensions, please consider
101 thanks for pitching in, and welcome to the project!
102
103 If you are a python library maintainer and use C-extensions, please consider
82104 making a cffi / cppyy version of your library that would be performant on PyPy.
83105 In any case both `cibuildwheel`_ and the `multibuild system`_ support
84106 building wheels for PyPy.
90112 .. _`cppyy`: https://cppyy.readthedocs.io
91113 .. _`multibuild system`: https://github.com/matthew-brett/multibuild
92114 .. _`cibuildwheel`: https://github.com/joerick/cibuildwheel
93 .. _`blog post`: https://morepypy.blogspot.com/2020/02/pypy-and-cffi-have-moved-to-heptapod.html
115 .. _`blog post`: https://pypy.org/blog/2020/02/pypy-and-cffi-have-moved-to-heptapod.html
94116 .. _`conda-forge`: https://conda-forge.org/blog//2020/03/10/pypy
95117 .. _`documented changes`: https://docs.python.org/3/whatsnew/3.7.html#re
96118 .. _`PyPy 3.7 wiki`: https://foss.heptapod.net/pypy/pypy/-/wikis/py3.7%20status
97119 .. _`wheels on PyPI`: https://pypi.org/project/numpy/#files
98120 .. _`windows 64-bit`: https://foss.heptapod.net/pypy/pypy/-/issues/2073#note_141389
99 .. _`HPy blog post`: https://morepypy.blogspot.com/2019/12/hpy-kick-off-sprint-report.html
121 .. _`HPy documentation`: https://hpy.readthedocs.io/en/latest/
122 .. _`HPy blog post`: https://hpyproject.org/blog/posts/2021/03/hello-hpy/
100123 .. _`GraalPython`: https://github.com/graalvm/graalpython
101124 .. _`RustPython`: https://github.com/RustPython/RustPython
102125 .. _`renovated blog site`: https://pypy.org/blog
132155 =========
133156
134157 Bugfixes shared across versions
135 ------------------------------
158 -------------------------------
136159 - Test, fix xml default attribute values (issue 3333_, `bpo 42151`_)
137 - Update the ``re`` module to the Python3.7 implementation
138 - Truncate ``REG_SZ`` at first ``NULL`` in ``winreg`` to match ``reg.exe``
139 behaviour (`bpo 25778`_)
140 - Rename ``_hashlib.Hash`` to ``HASH`` to match cpython
160 - Rename ``_hashlib.Hash`` to ``HASH`` to match CPython
141161 - Fix loading system libraries with ctypes on macOS Big Sur (issue 3314)
142162 - Fix ``__thread_id`` in greenlets (issue 3381_)
143163 - Reject XML entity declarations in plist files (`bpo 42051`_)
144 - Make compare_digest more constant-time (`bpo-40791`_)
164 - Make compare_digest more constant-time (`bpo 40791`_)
145165 - Only use '&' as a query string separator in url parsing (`bpo 42967`_)
146166 - Fix `__r*__` reverse methods on weakref proxies
167 - Restore pickle of dict iterators on default (python2.7)
147168
148169 Speedups and enhancements shared across versions
149170 ------------------------------------------------
151172 officializes the fact that you can raise RPython exceptions from llhelpers,
152173 and makes it possible to specify what is the C value to return in case of
153174 errors. Useful for HPY_
154 - Introduce a new RPython decorator ``@never_allocates`` which ensures a class
175 - Introduce a new RPython decorator ``@never_allocate`` which ensures a class
155176 is **never** instantiated at runtime. Useful for objects that are required to
156177 be constant-folded away
157178 - Upstream internal ``cparser`` tool from ``pypy/`` to ``rpython/``
169190 - Copy manifest from CPython and link it into ``pypy.exe`` (issue 3363)
170191 - Preserve ``None`` passed as ``REG_BINARY`` instead of crashing or changing it
171192 to an empty string in ``winreg`` (`bpo 21151`_)
193 - Add ``REG_QWORD*`` and ``Reg{Dis,En}ableReflectionKey``, and
194 ``RegDeleteKeyEx`` to ``winreg``
172195 - Backport msvc detection from python3, which probably breaks using Visual
173196 Studio 2008 (MSVC9, or the version that used to be used to build CPython2.7
174197 on Windows)
188211 - Fast path for ``unicode.upper/lower``, ``unicodedb.toupper/lower`` for ascii,
189212 latin-1
190213 - Add a JIT driver for ``re.split``
191 - Expose ``os.memfd_create`` on linux for glibc>2.27 (not on portable builds)
214 - Expose ``os.memfd_create`` on Linux for glibc>2.27 (not on portable builds)
192215 - Add a shortcut for ``re.sub`` doing zero replacements
193 for things like escaping characters)
194
195 C-API (cpyext) and c-extensions
216 for things like escaping characters)
217 - Expose the physical size of a list in ``__pypy__.list_get_physical_size``
218 - Clean up the icon bundled with the exe in windows
219 - Add a fast path for ``list[:] = l2``
220 - Update packaged OpenSSL to 1.1.1k
221 - Make ARM builds portable
222
223 C-API (cpyext) and C-extensions
196224 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
197225 - make order of arguments of ``PyDescr_NewGetSet`` consistent with CPython,
198226 related to issue 2267_
204232 - Fix ``PyObject_Format`` for type objects (issue 3404_)
205233 - Move ``inttypes.h`` into ``pyport.h`` (issue 3407_)
206234 - Sync ``Py_.*Flags`` values with ``sys.flags`` (issue 3409_)
235 - Make ``PyUnicode_Check`` a macro, but still export the function from
236 the shared library for backwards compatibility
207237
208238
209239 Python 3.7+
210240 -----------
241 - Update the ``re`` module to the Python 3.7 implementation
211242 - Fix the ``crypt`` thread lock (issue 3395_) and fix input encoding (issue
212243 3378_)
213244 - Fixes ``utf_8_decode`` for ``final=False`` (issue 3348_)
214245 - Test, fix for ``time.strftime(u'%y\ud800%m', time.localtime(192039127))``
215 - ``CALL_FUNCTION_KW`` pops a constant tuple from the stack, and uses
216 fixedview, which loses the constness
246 - ``CALL_FUNCTION_KW`` with keyword arguments is now much faster, because the
247 data structure storing the arguments can be removed by the JIT
217248 - Fix the ``repr`` of subclasses
218249 - Better error message for ``object.__init__`` with too many parameters
219250 - Fix bug in ``codecs`` where using a function from the parser turns warnings
228259 - Hang on to ``servername_callback`` handle in ``_ssl`` so it will not be
229260 deleted until the context is deleted (issue 3396)
230261 - Implement ``set_wakeup_fd(warn_on_full_buffer)`` (issue 3227_)
231 - Add ``REG_QWORD*`` and ``Reg{Dis,En}ableReflectionKey``, and
232 ``RegDeleteKeyEx`` to ``winreg``
233262 - Round-trip invalid UTF-16 data in ``winreg`` without a ``UnicodeDecodeError``
234263 (issue 3342_)
264 - Truncate ``REG_SZ`` at first ``NULL`` in ``winreg`` to match ``reg.exe``
265 behaviour (`bpo 25778`_)
235266 - Fix for surrogates in ``winreg`` input value (issue 3345_)
236267 - In ``sysconfig``, ``INCLUDEPY`` and ``INCLUDEDIR`` should point to the
237268 original directory even in a virtualenv (issue 3364_)
245276 - Generalize venv to copy all ``*.exe`` and ``*.dll`` for windows
246277 - The evaluation order of keys and values of *large* dict literals was wrong in
247278 3.7 (in lower versions it was the same way, but in 3.7 the evaluation order
248 of *small* dicts changed (issue 3380_)
249 - Cache the imported ``re`` module (going through ``__import__`` is
279 of *small* dicts changed), issue 3380_
280 - Cache the imported ``re`` module in ``_sre`` (going through ``__import__`` is
250281 unfortunately quite expensive on 3.x)
251282 - Mention a repeated keyword argument in the error message
252283 - Stop emitting the ``STORE_ANNOTATION`` and ``BINARY_DIVIDE`` bytecodes,
255286 ``pip install --local``
256287 - No longer call ``eval()`` on content received via HTTP in CJK codec tests (`bpo 41944`_)
257288 - Add missing `c_/f_/contiguous` flags on memoryview
258 - Fix ``xml.ElementTree.extend`` not working on iterators (issue 3181_, `bpo-43399`_)
289 - Fix ``xml.ElementTree.extend`` not working on iterators (issue 3181_, `bpo 43399`_)
259290 - `Python -m` now adds *starting* directory to `sys.path` (`bpo 33053`_)
260 - Reimplement ``heapq.merge()`` using a linked tournamet tree (`bpo 38938`_)
291 - Reimplement ``heapq.merge()`` using a linked tournament tree (`bpo 38938`_)
292 - Fix shring of cursors in ``sqllite3`` (issues 3351_ and 3403_)
293 - Fix remaining ``sqllite3`` incompatibilities
294 - Fix ``CALL_METHOD_KW`` to not lose the immutability of the keyword name tuple
261295
262296 Python 3.7 C-API
263297 ~~~~~~~~~~~~~~~~
268302 - Clean up some ``char *`` -> ``const char *`` misnaming (issue 3362)
269303 - Accept ``NULL`` input to ``PyLong_AsUnsignedLongLongMask``
270304 - Add ``PyImport_GetModule`` (issue 3385_)
271 - Converting utf-8 to 1-byte buffers must consider latin-1 encoding (`issue 3413`_)
305 - Converting utf-8 to 1-byte buffers must consider latin-1 encoding (issue `3413`_)
272306 - Fix value of ``.__module__`` and ``.__name__`` on the result of
273307 ``PyType_FromSpec``
308 - Add missing ``PyFile_FromFd``
274309
275310 .. _2267: https://foss.heptapod.net/pypy/pypy/-/issues/2267
311 .. _2371: https://foss.heptapod.net/pypy/pypy/-/issues/2371
276312 .. _3172: https://foss.heptapod.net/pypy/pypy/-/issues/3172
277313 .. _3181: https://foss.heptapod.net/pypy/pypy/-/issues/3181
278314 .. _3227: https://foss.heptapod.net/pypy/pypy/-/issues/3227
281317 .. _3342: https://foss.heptapod.net/pypy/pypy/-/issues/3342
282318 .. _3345: https://foss.heptapod.net/pypy/pypy/-/issues/3345
283319 .. _3348: https://foss.heptapod.net/pypy/pypy/-/issues/3348
320 .. _3351: https://foss.heptapod.net/pypy/pypy/-/issues/3351
284321 .. _3355: https://foss.heptapod.net/pypy/pypy/-/issues/3355
285322 .. _3357: https://foss.heptapod.net/pypy/pypy/-/issues/3357
286323 .. _3359: https://foss.heptapod.net/pypy/pypy/-/issues/3359
296333 .. _3395: https://foss.heptapod.net/pypy/pypy/-/issues/3395
297334 .. _3396: https://foss.heptapod.net/pypy/pypy/-/issues/3396
298335 .. _3400: https://foss.heptapod.net/pypy/pypy/-/issues/3400
336 .. _3403: https://foss.heptapod.net/pypy/pypy/-/issues/3403
299337 .. _3404: https://foss.heptapod.net/pypy/pypy/-/issues/3404
300338 .. _3407: https://foss.heptapod.net/pypy/pypy/-/issues/3407
301339 .. _3409: https://foss.heptapod.net/pypy/pypy/-/issues/3409
340 .. _3413: https://foss.heptapod.net/pypy/pypy/-/issues/3413
302341
303342 .. _`merge request 723`: https://foss.heptapod.net/pypy/pypy/-/merge_request/723
304343
305344 .. _`bpo 21151`: https://bugs.python.org/issue21151
345 .. _`bpo 25778`: https://bugs.python.org/issue25778
306346 .. _`bpo 28732`: https://bugs.python.org/issue28732
307347 .. _`bpo 30024`: https://bugs.python.org/issue30024
308348 .. _`bpo 31286`: https://bugs.python.org/issue31286
3232
3333 .. _SECCOMP: https://code.google.com/p/seccompsandbox/wiki/overview
3434 .. _pysandbox: https://mail.python.org/pipermail/python-dev/2013-November/130132.html
35 .. _sandbloxlib: https://foss.heptapod.net/pypy/sandboxlib
35 .. _sandboxlib: https://foss.heptapod.net/pypy/sandboxlib
3636
3737 Another point of comparison: if we were instead to try to plug CPython
3838 into a special virtualizing C library, we would get a result
9292 'John Witulski': ['witulski'],
9393 'Andrew Lawrence': ['andrew.lawrence@siemens.com', 'andrewjlawrence'],
9494 'Batuhan Taskaya': ['isidentical'],
95 'Ondrej Baranovič': ['nulano'],
9596 }
9697
9798 alias_map = {}
00 ============================
1 What's new in PyPy2.7 7.3.3+
1 What's new in PyPy2.7 7.3.4+
22 ============================
33
4 .. this is a revision shortly after release-pypy-7.3.3
5 .. startrev: de512cf13506
6
7 .. branch: rpython-error_value
8 .. branch: hpy-error-value
9
10 Introduce @rlib.objectmodel.llhelper_error_value, will is used by HPy
11
12 .. branch: new-ci-image
13
14 CI: Add a Dockerfile for CI to prevent hitting pull limits on docker hub
15
16 .. branch: issue-3333
17
18 Fix xml.etree.ElementTree assigning default attribute values: issue 3333
19
20 .. branch: rpython-rsre-for-37
21
22 Support for the new format of regular expressions in Python 3.7
23
24 .. branch: rpy-cparser
25
26 Upstream internal cparser tool from pypy/ to rpython/
4 .. this is a revision shortly after release-pypy-7.3.4
5 .. startrev: 9c11d242d78c
276
287
29 .. branch: win64
30
31 Change rpython and pypy to enable translating 64-bit windows
32
33
34 .. branch: rpython-error_value
35
36 Introduce @rlib.objectmodel.llhelper_error_value, will be used by HPy
37
38 .. branch: add-rffi-constcharpsize2str
39
40 Add ``rffi.constcharpsize2str``
41
42 .. branch: document-win64
43
44 Refactor documentation of win64 from future plans to what was executed
45
46 .. branch: sync-distutils
47
48 Backport msvc detection from python3, which probably breaks using Visual Studio
49 2008 (MSVC9, or the version that used to be used to build CPython2.7 on
50 Windows)
51
52 .. branch: py2.7-winreg
53
54 Backport fixes to winreg adding reflection and fix for passing None (bpo
55 21151).
56
57 .. branch: pymodule_new-const-charp
58
59 Change parameter type of ``PyModule_New`` to ``const char*``, add
60 ``PyModule_Check`` and ``PyModule_CheckExact``
61
62 .. branch: rpython-never-allocate
63
64 Introduce a ``@never_allocate`` class decorator, which ensure that a certain
65 RPython class is never actually instantiated at runtime. Useful to ensure that
66 e.g. it's always constant-folded away
67
68 .. branch: map-improvements
69
70 Optimize instances with integer or float fields to have more efficent field
71 reads and writes. They also use less memory if they have at least two such
72 fields.
73
74 .. branch: win-tcl8.6
75
76 Update the version of Tk/Tcl on windows to 8.6
77
78 .. branch: big-sur-dyld-cache
79
80 Backport changes to ``_ctypes`` needed for maxos BigSur from py3.7
81
82 .. branch: cppyy-packaging
83
84 Updated the API to the latest cppyy_backend (1.14.2), made all types used
85 consistent to avoid void*/long casting problems on Win64, and added several
86 new "builtin" types (wide chars, complex, etc.).
87
88
89 .. branch: intbound-improvements-3
90
91 Refactor the intbound analysis in the JIT
92
93 .. branch: issue-3404
94
95 Fix ``PyObject_Format`` for type objects
96
97
98 .. branch: string-algorithmic-optimizations
99
100 Faster str.replace and bytes.replace implementations.
101
102 .. branch: vmprof-aarch64
103
104 Enable vmprof on arm64
0 ===========================
1 What's new in PyPy2.7 7.3.4
2 ===========================
3
4 .. this is a revision shortly after release-pypy-7.3.3
5 .. startrev: de512cf13506
6
7 .. branch: rpython-error_value
8 .. branch: hpy-error-value
9
10 Introduce @rlib.objectmodel.llhelper_error_value, will is used by HPy
11
12 .. branch: new-ci-image
13
14 CI: Add a Dockerfile for CI to prevent hitting pull limits on docker hub
15
16 .. branch: issue-3333
17
18 Fix xml.etree.ElementTree assigning default attribute values: issue 3333
19
20 .. branch: rpython-rsre-for-37
21
22 Support for the new format of regular expressions in Python 3.7
23
24 .. branch: rpy-cparser
25
26 Upstream internal cparser tool from pypy/ to rpython/
27
28
29 .. branch: win64
30
31 Change rpython and pypy to enable translating 64-bit windows
32
33
34 .. branch: rpython-error_value
35
36 Introduce @rlib.objectmodel.llhelper_error_value, will be used by HPy
37
38 .. branch: add-rffi-constcharpsize2str
39
40 Add ``rffi.constcharpsize2str``
41
42 .. branch: document-win64
43
44 Refactor documentation of win64 from future plans to what was executed
45
46 .. branch: sync-distutils
47
48 Backport msvc detection from python3, which probably breaks using Visual Studio
49 2008 (MSVC9, or the version that used to be used to build CPython2.7 on
50 Windows)
51
52 .. branch: py2.7-winreg
53
54 Backport fixes to winreg adding reflection and fix for passing None (bpo
55 21151).
56
57 .. branch: pymodule_new-const-charp
58
59 Change parameter type of ``PyModule_New`` to ``const char*``, add
60 ``PyModule_Check`` and ``PyModule_CheckExact``
61
62 .. branch: rpython-never-allocate
63
64 Introduce a ``@never_allocate`` class decorator, which ensure that a certain
65 RPython class is never actually instantiated at runtime. Useful to ensure that
66 e.g. it's always constant-folded away
67
68 .. branch: map-improvements
69
70 Optimize instances with integer or float fields to have more efficent field
71 reads and writes. They also use less memory if they have at least two such
72 fields.
73
74 .. branch: win-tcl8.6
75
76 Update the version of Tk/Tcl on windows to 8.6
77
78 .. branch: big-sur-dyld-cache
79
80 Backport changes to ``_ctypes`` needed for maxos BigSur from py3.7
81
82 .. branch: cppyy-packaging
83
84 Updated the API to the latest cppyy_backend (1.14.2), made all types used
85 consistent to avoid void*/long casting problems on Win64, and added several
86 new "builtin" types (wide chars, complex, etc.).
87
88
89 .. branch: intbound-improvements-3
90
91 Refactor the intbound analysis in the JIT
92
93 .. branch: issue-3404
94
95 Fix ``PyObject_Format`` for type objects
96
97
98 .. branch: string-algorithmic-optimizations
99
100 Faster str.replace and bytes.replace implementations.
101
102 .. branch: vmprof-aarch64
103
104 Enable vmprof on arm64
105
106 .. branch: icon-aliasing
107
108 Improve pypy.ico
0 =========================
1 What's new in PyPy3 7.3.4
2 =========================
3
4 .. this is the revision after release-pypy3.6-v7.3.3
5 .. startrev: a57ea1224248
6
7 .. branches merged to py3.6 and are not reported in the test. Re-enable
8 these lines for the release or when fixing the test
9 .. branch: py3.6-resync
10
11 .. branch: fix-crypt-py3-import
12
13 Fix bad merge of crypt cffi module
14
15 .. branch: issue3348
16
17 Fix utf_8_decode for final=False, error=ignore
18
19 .. branch: py3.7-rsre
20
21 Fix rsre module for python 3.7
22
23 .. branch: incremental_decoder
24
25 Fix utf_8_decode for final=False
26
27
28 .. branch: refactor-posonly
29
30 Refactor how positional-only arguments are represented in signature objects,
31 which brings it more in line with Python 3.8, and simplifies the code.
32
33 .. branch: const
34
35 Change `char *`` to ``const char *`` in ``PyStructSequence_Field``,
36 ``PyStructSequence_Desc``, ``PyGetSetDef``, ``wrapperbase``
37
38 .. branch: win64-py3.7
39
40 Merge win64 into this branch
41
42 .. branch: win64-cpyext
43
44 Fix the cpyext module for win64
45
46 .. branch: py3.7-winreg
47
48 Fix various problems with ``winreg``: add ``REG_QWORD``, implement reflection
49 on win64, (bpo-21151) preserve None passed as ``REG_BINARY``, (bpo-25778),
50 truncate ``REG_SZ`` at first ``NULL``, use surrogatepass in ``UTF-16`` decoding
51 (issue 3342).
52
53 .. branch: py3.7-win64-hash
54
55 Prevent overflow in ``_hash_long`` on win64 using method from CPython, and
56 speed it up.
57
58 .. branch: issue-3371
59
60 Allow compiler to inherit flags from ``__future__.annotations``. Fixes
61 ``>>> x : X``
62
63 .. branch: win32consoleio2
64
65 Re-enable ``_io.win32console`` on windows
66
67 .. branch: meth-fastcall
68
69 Implement METH_FASTCALL
70
71 .. branch: py3.7-win64-cpyext-longobject
72
73 Fix ``cpyext.longobject`` for win64
74
75 .. branch: py3.7-big-sur-dyld-cache
76
77 Fix loading system libraries with ctypes on macOS Big Sur. (issue 3314)
78
79 .. branch: map-improvements-3.7
80
81 Port map-improvements to py3.7
82
83 .. branch: win64-hpy
84
85 Enable _hpy_universal on win64
86
87 .. branch: vendor/stdlib-3.7
88
89 Update stdlib to 3.7.10
90
91 .. branch: fix-issue-3181
92
93 Fix ElementTree.extend not working on iterators (issue 3181 and bpo43399)
0 ==========================
1 What's new in PyPy3 7.3.3+
2 ==========================
0 ============================
1 What's new in PyPy3.7 7.3.4+
2 ============================
33
4 .. this is the revision after release-pypy3.6-v7.3.3
5 .. startrev: a57ea1224248
4 .. this is a revision shortly after release-pypy-7.3.4
5 .. startrev: 9c11d242d78c
66
7 .. branches merged to py3.6 and are not reported in the test. Re-enable
8 these lines for the release or when fixing the test
9 .. branch: py3.6-resync
7 .. branch: hpy
108
11 .. branch: fix-crypt-py3-import
12
13 Fix bad merge of crypt cffi module
14
15 .. branch: issue3348
16
17 Fix utf_8_decode for final=False, error=ignore
18
19 .. branch: py3.7-rsre
20
21 Fix rsre module for python 3.7
22
23 .. branch: incremental_decoder
24
25 Fix utf_8_decode for final=False
26
27
28 .. branch: refactor-posonly
29
30 Refactor how positional-only arguments are represented in signature objects,
31 which brings it more in line with Python 3.8, and simplifies the code.
32
33 .. branch: const
34
35 Change `char *`` to ``const char *`` in ``PyStructSequence_Field``,
36 ``PyStructSequence_Desc``, ``PyGetSetDef``, ``wrapperbase``
37
38 .. branch: win64-py3.7
39
40 Merge win64 into this branch
41
42 .. branch: win64-cpyext
43
44 Fix the cpyext module for win64
45
46 .. branch: py3.7-winreg
47
48 Fix various problems with ``winreg``: add ``REG_QWORD``, implement reflection
49 on win64, (bpo-21151) preserve None passed as ``REG_BINARY``, (bpo-25778),
50 truncate ``REG_SZ`` at first ``NULL``, use surrogatepass in ``UTF-16`` decoding
51 (issue 3342).
52
53 .. branch: py3.7-win64-hash
54
55 Prevent overflow in ``_hash_long`` on win64 using method from CPython, and
56 speed it up.
57
58 .. branch: issue-3371
59
60 Allow compiler to inherit flags from ``__future__.annotations``. Fixes
61 ``>>> x : X``
62
63 .. branch: win32consoleio2
64
65 Re-enable ``_io.win32console`` on windows
66
67 .. branch: meth-fastcall
68
69 Implement METH_FASTCALL
70
71 .. branch: py3.7-win64-cpyext-longobject
72
73 Fix ``cpyext.longobject`` for win64
74
75 .. branch: py3.7-big-sur-dyld-cache
76
77 Fix loading system libraries with ctypes on macOS Big Sur. (issue 3314)
78
79 .. branch: map-improvements-3.7
80
81 Port map-improvements to py3.7
82
83 .. branch: win64-hpy
84
85 Enable _hpy_universal on win64
86
87 .. branch: vendor/stdlib-3.7
88
89 Update stdlib to 3.7.10
90
91 .. branch: fix-issue-3181
92
93 Fix ElementTree.extend not working on iterators (issue 3181 and bpo43399)
9 Merge latest hpy
Binary diff not shown
381381 ''' Use cffi to compile cffi interfaces to modules'''
382382 filename = join(pypydir, '..', 'lib_pypy', 'pypy_tools',
383383 'build_cffi_imports.py')
384 if sys.platform == 'darwin':
384 if sys.platform in ('darwin', 'linux', 'linux2'):
385385 argv = [filename, '--embed-dependencies']
386386 else:
387387 argv = [filename,]
295295 def test_pickle_dictiter(self):
296296 import pickle
297297 tdict = {'2':2, '3':3, '5':5}
298 diter = iter(tdict)
299 seen = next(diter)
300 pckl = pickle.dumps(diter)
301 result = pickle.loads(pckl)
302 assert set(result) == (set('235') - set([seen]))
298 diter = iter(tdict)
299 res1 = next(diter)
300 s = pickle.dumps(diter)
301 res2 = next(diter)
302 res3 = next(diter)
303 assert {res1, res2, res3} == set(tdict)
304
305 diter2 = pickle.loads(s)
306 assert set(diter2) == set(tdict) - {res1}
303307
304308 def test_pickle_reversed(self):
305309 import pickle
109109 raise oefmt(space.w_TypeError, "expecting dict or list or set object, or instance of some kind")
110110 return space.newtext(name)
111111
112 def list_get_physical_size(space, w_obj):
113 if not isinstance(w_obj, W_ListObject):
114 raise oefmt(space.w_TypeError, "expected list")
115 return space.newint(w_obj.physical_size())
116
117
112118 def get_console_cp(space):
113119 """get_console_cp()
114120
119119 'newmemoryview' : 'interp_buffer.newmemoryview',
120120 'set_exc_info' : 'interp_magic.set_exc_info',
121121 'utf8content' : 'interp_magic.utf8content',
122 'list_get_physical_size' : 'interp_magic.list_get_physical_size',
122123
123124 'get_contextvar_context' : 'interp_magic.get_contextvar_context',
124125 'set_contextvar_context' : 'interp_magic.set_contextvar_context',
122122 finally:
123123 set_contextvar_context(context)
124124
125 def test_list_get_physical_size(self):
126 from __pypy__ import list_get_physical_size
127 l = [1, 2]
128 l.append(3)
129 assert list_get_physical_size(l) >= 3 # should be 6, but untranslated 3
00 import os.path
1 import functools
12 from pathlib import Path
2 from setuptools import Extension
3 from distutils.errors import DistutilsError, DistutilsSetupError
3 from distutils import log
4 from distutils.command.build import build
5 from distutils.errors import DistutilsError
6 from setuptools.command import bdist_egg as bdist_egg_mod
7 from setuptools.command.build_ext import build_ext
48
59 # NOTE: this file is also imported by PyPy tests, so it must be compatible
610 # with both Python 2.7 and Python 3.x
711
8 _BASE_DIR = Path(__file__).parent
912
1013 class HPyDevel:
11 def __init__(self, base_dir=_BASE_DIR):
14 """ Extra sources for building HPy extensions with hpy.devel. """
15
16 _DEFAULT_BASE_DIR = Path(__file__).parent
17
18 def __init__(self, base_dir=_DEFAULT_BASE_DIR):
1219 self.base_dir = Path(base_dir)
1320 self.include_dir = self.base_dir.joinpath('include')
1421 self.src_dir = self.base_dir.joinpath('src', 'runtime')
15 # extra_sources are needed both in CPython and Universal mode
16 self._extra_sources = [
22
23 def get_extra_include_dirs(self):
24 """ Extra include directories needed by extensions in both CPython and
25 Universal modes.
26 """
27 return list(map(str, [
28 self.include_dir,
29 ]))
30
31 def get_extra_sources(self):
32 """ Extra sources needed by extensions in both CPython and Universal
33 modes.
34 """
35 return list(map(str, [
1736 self.src_dir.joinpath('argparse.c'),
18 ]
19 # ctx_sources are needed only in Universal mode
20 self._ctx_sources = list(self.src_dir.glob('ctx_*.c'))
21
22 def get_extra_sources(self):
23 return list(map(str, self._extra_sources))
37 ]))
2438
2539 def get_ctx_sources(self):
26 return list(map(str, self._ctx_sources))
27
28 def fix_extension(self, ext, hpy_abi):
29 """
30 Modify an existing setuptools.Extension to generate an HPy module.
31 """
32 if hasattr(ext, 'hpy_abi'):
40 """ Extra sources needed only in the CPython ABI mode.
41 """
42 return list(map(str, self.src_dir.glob('ctx_*.c')))
43
44 def fix_distribution(self, dist):
45 """ Override build_ext to support hpy modules.
46
47 Used from both setup.py and hpy/test.
48 """
49 dist.hpydevel = self
50
51 base_build = dist.cmdclass.get("build", build)
52 base_build_ext = dist.cmdclass.get("build_ext", build_ext)
53 orig_bdist_egg_write_stub = bdist_egg_mod.write_stub
54
55 class build_hpy_ext(build_hpy_ext_mixin, base_build_ext, object):
56 _base_build_ext = base_build_ext
57
58 def dist_has_ext_modules(self):
59 if self.ext_modules or self.hpy_ext_modules:
60 return True
61 return False
62
63 def build_has_ext_modules(self):
64 return self.distribution.has_ext_modules()
65
66 def bdist_egg_write_stub(resource, pyfile):
67 if resource.endswith(".hpy.so"):
68 log.info("stub file already created for %s", resource)
69 return
70 orig_bdist_egg_write_stub(resource, pyfile)
71
72 # replace build_ext subcommand
73 dist.cmdclass['build_ext'] = build_hpy_ext
74 dist.__class__.has_ext_modules = dist_has_ext_modules
75 base_build.has_ext_modules = build_has_ext_modules
76 # setuptools / distutils store subcommands in .subcommands which
77 # is a list of tuples of (extension_name, extension_needs_to_run_func).
78 # The two lines below replace .subcommand entry for build_ext.
79 idx = [sub[0] for sub in base_build.sub_commands].index("build_ext")
80 base_build.sub_commands[idx] = ("build_ext", build_has_ext_modules)
81 bdist_egg_mod.write_stub = bdist_egg_write_stub
82
83
84 def handle_hpy_ext_modules(dist, attr, hpy_ext_modules):
85 """ Distuils hpy_ext_module setup(...) argument and --hpy-abi option.
86
87 See hpy's setup.py where this function is registered as an entry
88 point.
89 """
90 assert attr == 'hpy_ext_modules'
91
92 # add a global option --hpy-abi to setup.py
93 dist.__class__.hpy_abi = 'cpython'
94 dist.__class__.global_options += [
95 ('hpy-abi=', None, 'Specify the HPy ABI mode (default: cpython)')
96 ]
97 hpydevel = HPyDevel()
98 hpydevel.fix_distribution(dist)
99
100
101 _HPY_UNIVERSAL_MODULE_STUB_TEMPLATE = """
102 class Spec:
103 def __init__(self, name, origin):
104 self.name = name
105 self.origin = origin
106
107
108 def __bootstrap__():
109 import sys, pkg_resources
110 from hpy.universal import load_from_spec
111 ext_filepath = pkg_resources.resource_filename(__name__, {ext_file!r})
112 m = load_from_spec(Spec({module_name!r}, ext_filepath))
113 m.__file__ = ext_filepath
114 m.__loader__ = __loader__
115 m.__package__ = __package__
116 m.__spec__ = __spec__
117 sys.modules[__name__] = m
118
119 __bootstrap__()
120 """
121
122
123 class HPyExtensionName(str):
124 """ Wrapper around str to allow HPy extension modules to be identified.
125
126 The following build_ext command methods are passed only the *name*
127 of the extension and not the full extension object. The
128 build_hpy_ext_mixin class needs to detect when HPy are extensions
129 passed to these methods and override the default behaviour.
130
131 This str sub-class allows HPy extensions to be detected, while
132 still allowing the extension name to be used as an ordinary string.
133 """
134
135 def split(self, *args, **kw):
136 result = str.split(self, *args, **kw)
137 return [self.__class__(s) for s in result]
138
139 def translate(self, *args, **kw):
140 result = str.translate(self, *args, **kw)
141 return self.__class__(result)
142
143
144 def is_hpy_extension(ext_name):
145 """ Return True if the extension name is for an HPy extension. """
146 return isinstance(ext_name, HPyExtensionName)
147
148
149 def remember_hpy_extension(f):
150 """ Decorator for remembering whether an extension name belongs to an
151 HPy extension.
152 """
153 @functools.wraps(f)
154 def wrapper(self, ext_name):
155 if self._only_hpy_extensions:
156 assert is_hpy_extension(ext_name), (
157 "Extension name %r is not marked as an HPyExtensionName"
158 " but only HPy extensions are present. This is almost"
159 " certainly a bug in HPy's overriding of setuptools"
160 " build_ext. Please report this error the HPy maintainers."
161 % (ext_name,)
162 )
163 result = f(self, ext_name)
164 if is_hpy_extension(ext_name):
165 result = HPyExtensionName(result)
166 return result
167 return wrapper
168
169
170 class build_hpy_ext_mixin:
171 """ A mixin class for setuptools build_ext to add support for buidling
172 HPy extensions.
173 """
174
175 # Ideally we would have simply added the HPy extensions to .extensions
176 # at the end of .initialize_options() but the setuptools build_ext
177 # .finalize_options both iterate over and needless overwrite the
178 # .extensions attribute, so we hide the full extension list in
179 # ._extensions and expose it as a settable property that ignores attempts
180 # to overwrite it:
181
182 _extensions = None
183
184 @property
185 def extensions(self):
186 return self._extensions
187
188 @extensions.setter
189 def extensions(self, value):
190 pass # ignore any attempts to change the list of extensions directly
191
192 def initialize_options(self):
193 self._base_build_ext.initialize_options(self)
194 self.hpydevel = self.distribution.hpydevel
195
196 def _finalize_hpy_ext(self, ext):
197 if hasattr(ext, "hpy_abi"):
33198 return
34 ext.hpy_abi = hpy_abi
35 ext.include_dirs.append(str(self.include_dir))
36 ext.sources += self.get_extra_sources()
37 if hpy_abi == 'cpython':
38 ext.sources += self.get_ctx_sources()
39 if hpy_abi == 'universal':
199 ext.name = HPyExtensionName(ext.name)
200 ext.hpy_abi = self.distribution.hpy_abi
201 ext.include_dirs += self.hpydevel.get_extra_include_dirs()
202 ext.sources += self.hpydevel.get_extra_sources()
203 if ext.hpy_abi == 'cpython':
204 ext.sources += self.hpydevel.get_ctx_sources()
205 ext._hpy_needs_stub = False
206 if ext.hpy_abi == 'universal':
40207 ext.define_macros.append(('HPY_UNIVERSAL_ABI', None))
41
42 def collect_hpy_ext_names(self, dist, hpy_ext_modules):
43 """
44 This is sub-optimal but it should work in 99% of the cases, and complain
45 clearly in the others.
46
47 In order to implement build_hpy_ext, we need to know whether an
48 Extension was put inside hpy_ext_modules or ext_modules, and we need
49 to know it ONLY by looking at its name (because that's all we get when
50 distutils calls build_hpy_ext.get_ext_filename). So here we collect
51 and return all hpy_ext_names.
52
53 However, there is a problem: if the module is inside a package,
54 distutils' build_ext.get_ext_fullpath calls get_ext_filename with ONLY
55 the last part of the dotted name (see distutils/commands/build_ext.py).
56
57 This means that there is a risk of conflicts if we have two ext
58 modules with the same name in two different packages, of which one is
59 HPy and the other is legacy; e.g.::
60
61 setup(ext_modules = [Extension(name='foo.mymod', ...)],
62 hpy_ext_modules = [Extension(name='bar.mymod', ...)],)
63
64 In that case, we cannot know whether ``mymod`` is an HPy ext module or
65 not. If we detect such a problem, we exit early, and the only solution
66 is to rename one of them :(
67 """
68 def collect_ext_names(exts):
69 if exts is None:
70 return set()
71 names = set()
72 for ext in exts:
73 names.add(ext.name) # full name, e.g. 'foo.bar.baz'
74 names.add(ext.name.split('.')[-1]) # modname, e.g. 'baz'
75 return names
76
77 hpy_ext_names = collect_ext_names(hpy_ext_modules)
78 ext_names = collect_ext_names(dist.ext_modules)
79 conflicts = hpy_ext_names.intersection(ext_names)
80 if conflicts:
81 lines = ['\n']
82 lines.append('Name conflict between ext_modules and hpy_ext_modules:')
83 for name in conflicts:
84 lines.append(' - %s' % name)
85 lines.append('You can not have modules ending with the same name in both')
86 lines.append('ext_modules and hpy_ext_modules: this is a limitation of ')
87 lines.append('hpy.devel, please rename one of them.')
88 raise DistutilsSetupError('\n'.join(lines))
89 return hpy_ext_names
90
91 def fix_distribution(self, dist, hpy_ext_modules):
92 from setuptools.command.build_ext import build_ext
93 from setuptools.command.install import install
94
95 def is_hpy_extension(ext_name):
96 return ext_name in is_hpy_extension._ext_names
97 is_hpy_extension._ext_names = self.collect_hpy_ext_names(dist, hpy_ext_modules)
98
99 # add the hpy_extension modules to the normal ext_modules
100 if dist.ext_modules is None:
101 dist.ext_modules = []
102 dist.ext_modules += hpy_ext_modules
103
104 hpy_devel = self
105 base_build_ext = dist.cmdclass.get('build_ext', build_ext)
106 base_install = dist.cmdclass.get('install', install)
107
108 class build_hpy_ext(base_build_ext):
109 """
110 Custom distutils command which properly recognizes and handle hpy
111 extensions:
112
113 - modify 'include_dirs', 'sources' and 'define_macros' depending on
114 the selected hpy_abi
115
116 - modify the filename extension if we are targeting the universal
117 ABI.
118 """
119
120 def build_extension(self, ext):
121 if is_hpy_extension(ext.name):
122 # add the required include_dirs, sources and macros
123 hpy_devel.fix_extension(ext, hpy_abi=self.distribution.hpy_abi)
124 return base_build_ext.build_extension(self, ext)
125
126 def get_ext_filename(self, ext_name):
127 # this is needed to give the .hpy.so extension to universal extensions
128 if is_hpy_extension(ext_name) and self.distribution.hpy_abi == 'universal':
129 ext_path = ext_name.split('.')
130 ext_suffix = '.hpy.so' # XXX Windows?
131 return os.path.join(*ext_path) + ext_suffix
132 return base_build_ext.get_ext_filename(self, ext_name)
133
134 class install_hpy(base_install):
135
136 def run(self):
137 if self.distribution.hpy_abi == 'universal':
138 raise DistutilsError(
139 'setup.py install is not supported for HPy universal modules.\n'
140 ' At the moment, the only supported method is: \n'
141 ' setup.py --hpy-abi-universal build_ext --inplace')
142 return base_install.run(self)
143
144 dist.cmdclass['build_ext'] = build_hpy_ext
145 dist.cmdclass['install'] = install_hpy
146
147
148
149 def handle_hpy_ext_modules(dist, attr, hpy_ext_modules):
150 """
151 setuptools entry point, see setup.py
152 """
153 assert attr == 'hpy_ext_modules'
154
155 # Add a global option --hpy-abi to setup.py
156 if not hasattr(dist.__class__, 'hpy_abi'):
157 dist.__class__.hpy_abi = 'cpython'
158 dist.__class__.global_options += [
159 ('hpy-abi=', None, 'Specify the HPy ABI mode (default: cpython)')
160 ]
161
162 hpy_devel = HPyDevel()
163 hpy_devel.fix_distribution(dist, hpy_ext_modules)
208 ext._hpy_needs_stub = True
209
210 def finalize_options(self):
211 self._extensions = self.distribution.ext_modules or []
212 # _only_hpy_extensions is used only as a sanity check that no
213 # hpy extensions are misidentified as legacy C API extensions in the
214 # case where only hpy extensions are present.
215 self._only_hpy_extensions = not bool(self._extensions)
216 hpy_ext_modules = self.distribution.hpy_ext_modules or []
217 for ext in hpy_ext_modules:
218 self._finalize_hpy_ext(ext)
219 self._extensions.extend(hpy_ext_modules)
220 self._base_build_ext.finalize_options(self)
221 for ext in hpy_ext_modules:
222 ext._needs_stub = ext._hpy_needs_stub
223
224 @remember_hpy_extension
225 def get_ext_fullname(self, ext_name):
226 return self._base_build_ext.get_ext_fullname(self, ext_name)
227
228 @remember_hpy_extension
229 def get_ext_fullpath(self, ext_name):
230 return self._base_build_ext.get_ext_fullpath(self, ext_name)
231
232 @remember_hpy_extension
233 def get_ext_filename(self, ext_name):
234 if not is_hpy_extension(ext_name):
235 return self._base_build_ext.get_ext_filename(self, ext_name)
236 if self.distribution.hpy_abi == 'universal':
237 ext_path = ext_name.split('.')
238 ext_suffix = '.hpy.so' # XXX Windows?
239 ext_filename = os.path.join(*ext_path) + ext_suffix
240 else:
241 ext_filename = self._base_build_ext.get_ext_filename(
242 self, ext_name)
243 return ext_filename
244
245 def write_stub(self, output_dir, ext, compile=False):
246 if (not hasattr(ext, "hpy_abi") or
247 self.distribution.hpy_abi != 'universal'):
248 return self._base_build_ext.write_stub(
249 self, output_dir, ext, compile=compile)
250 pkgs = ext._full_name.split('.')
251 if compile:
252 # compile is true when .write_stub is called while copying
253 # extensions to the source folder as part of build_ext --inplace.
254 # In this situation, output_dir includes the folders that make up
255 # the packages containing the module. When compile is false,
256 # output_dir does not include those folders (and is just the
257 # build_lib folder).
258 pkgs = [pkgs[-1]]
259 stub_file = os.path.join(output_dir, *pkgs) + '.py'
260 log.info(
261 "writing hpy universal stub loader for %s to %s",
262 ext._full_name, stub_file)
263 if compile and os.path.exists(stub_file):
264 raise DistutilsError(stub_file + " already exists! Please delete.")
265 ext_file = os.path.basename(ext._file_name)
266 module_name = ext_file.split(".")[0]
267 if not self.dry_run:
268 with open(stub_file, 'w') as f:
269 f.write(_HPY_UNIVERSAL_MODULE_STUB_TEMPLATE.format(
270 ext_file=ext_file, module_name=module_name)
271 )
11 /*
22 DO NOT EDIT THIS FILE!
33
4 This file is automatically generated by tools/autogen.py from tools/public_api.h.
4 This file is automatically generated by hpy.tools.autogen.hpyfunc.autogen_hpyfunc_declare_h
5 See also hpy.tools.autogen and hpy/tools/public_api.h
6
57 Run this to regenerate:
68 make autogen
79
11 /*
22 DO NOT EDIT THIS FILE!
33
4 This file is automatically generated by tools/autogen.py from tools/public_api.h.
4 This file is automatically generated by hpy.tools.autogen.hpyslot.autogen_hpyslot_h
5 See also hpy.tools.autogen and hpy/tools/public_api.h
6
57 Run this to regenerate:
68 make autogen
79
11 /*
22 DO NOT EDIT THIS FILE!
33
4 This file is automatically generated by tools/autogen.py from tools/public_api.h.
4 This file is automatically generated by hpy.tools.autogen.trampolines.autogen_impl_h
5 See also hpy.tools.autogen and hpy/tools/public_api.h
6
57 Run this to regenerate:
68 make autogen
79
267269 return _py2h(PyNumber_InPlaceOr(_h2py(h1), _h2py(h2)));
268270 }
269271
272 HPyAPI_STORAGE int _HPy_IMPL_NAME(Callable_Check)(HPyContext ctx, HPy h)
273 {
274 return PyCallable_Check(_h2py(h));
275 }
276
270277 HPyAPI_STORAGE void _HPy_IMPL_NAME(Err_SetString)(HPyContext ctx, HPy h_type, const char *message)
271278 {
272279 PyErr_SetString(_h2py(h_type), message);
447454 return _py2h(PyDict_New());
448455 }
449456
457 HPyAPI_STORAGE int _HPy_IMPL_NAME(Tuple_Check)(HPyContext ctx, HPy h)
458 {
459 return PyTuple_Check(_h2py(h));
460 }
461
0 #ifndef HPY_COMMON_RUNTIME_CALL_H
1 #define HPY_COMMON_RUNTIME_CALL_H
2
3 #include <Python.h>
4 #include "hpy.h"
5
6 _HPy_HIDDEN HPy
7 ctx_CallTupleDict(HPyContext ctx, HPy callable, HPy args, HPy kw);
8
9 #endif /* HPY_COMMON_RUNTIME_CALL_H */
00
11 // automatically generated by setup.py:get_scm_config()
2 #define HPY_VERSION "0.1.dev875+g7c832a2"
3 #define HPY_GIT_REVISION "7c832a2"
2 #define HPY_VERSION "0.1.dev959+geb07982"
3 #define HPY_GIT_REVISION "eb07982"
11 /*
22 DO NOT EDIT THIS FILE!
33
4 This file is automatically generated by tools/autogen.py from tools/public_api.h.
4 This file is automatically generated by hpy.tools.autogen.hpyfunc.autogen_cpython_hpyfunc_trampoline_h
5 See also hpy.tools.autogen and hpy/tools/public_api.h
6
57 Run this to regenerate:
68 make autogen
79
271271 #include "../common/hpydef.h"
272272 #include "../common/hpytype.h"
273273 #include "../common/hpymodule.h"
274 #include "../common/runtime/ctx_call.h"
274275 #include "../common/runtime/ctx_module.h"
275276 #include "../common/runtime/ctx_type.h"
276277 #include "../common/runtime/ctx_listbuilder.h"
314315 return ctx_Cast(ctx, h);
315316 }
316317
318 HPyAPI_FUNC(HPy)
319 HPy_CallTupleDict(HPyContext ctx, HPy callable, HPy args, HPy kw)
320 {
321 return ctx_CallTupleDict(ctx, callable, args, kw);
322 }
323
317324 HPyAPI_FUNC(HPyListBuilder)
318325 HPyListBuilder_New(HPyContext ctx, HPy_ssize_t initial_size)
319326 {
11 /*
22 DO NOT EDIT THIS FILE!
33
4 This file is automatically generated by tools/autogen.py from tools/public_api.h.
4 This file is automatically generated by hpy.tools.autogen.ctx.autogen_ctx_h
5 See also hpy.tools.autogen and hpy/tools/public_api.h
6
57 Run this to regenerate:
68 make autogen
79
137139 HPy (*ctx_InPlaceAnd)(HPyContext ctx, HPy h1, HPy h2);
138140 HPy (*ctx_InPlaceXor)(HPyContext ctx, HPy h1, HPy h2);
139141 HPy (*ctx_InPlaceOr)(HPyContext ctx, HPy h1, HPy h2);
142 int (*ctx_Callable_Check)(HPyContext ctx, HPy h);
143 HPy (*ctx_CallTupleDict)(HPyContext ctx, HPy callable, HPy args, HPy kw);
144 void (*ctx_FatalError)(HPyContext ctx, const char *message);
140145 void (*ctx_Err_SetString)(HPyContext ctx, HPy h_type, const char *message);
141146 void (*ctx_Err_SetObject)(HPyContext ctx, HPy h_type, HPy h_value);
142147 int (*ctx_Err_Occurred)(HPyContext ctx);
182187 int (*ctx_List_Append)(HPyContext ctx, HPy h_list, HPy h_item);
183188 int (*ctx_Dict_Check)(HPyContext ctx, HPy h);
184189 HPy (*ctx_Dict_New)(HPyContext ctx);
185 void (*ctx_FatalError)(HPyContext ctx, const char *message);
190 int (*ctx_Tuple_Check)(HPyContext ctx, HPy h);
186191 HPy (*ctx_Tuple_FromArray)(HPyContext ctx, HPy items[], HPy_ssize_t n);
187192 HPy (*ctx_FromPyObject)(HPyContext ctx, cpy_PyObject *obj);
188193 cpy_PyObject *(*ctx_AsPyObject)(HPyContext ctx, HPy h);
11 /*
22 DO NOT EDIT THIS FILE!
33
4 This file is automatically generated by tools/autogen.py from tools/public_api.h.
4 This file is automatically generated by hpy.tools.autogen.hpyfunc.autogen_hpyfunc_trampoline_h
5 See also hpy.tools.autogen and hpy/tools/public_api.h
6
57 Run this to regenerate:
68 make autogen
79
11 /*
22 DO NOT EDIT THIS FILE!
33
4 This file is automatically generated by tools/autogen.py from tools/public_api.h.
4 This file is automatically generated by hpy.tools.autogen.trampolines.autogen_trampolines_h
5 See also hpy.tools.autogen and hpy/tools/public_api.h
6
57 Run this to regenerate:
68 make autogen
79
227229 return ctx->ctx_InPlaceOr ( ctx, h1, h2 );
228230 }
229231
232 static inline int HPyCallable_Check(HPyContext ctx, HPy h) {
233 return ctx->ctx_Callable_Check ( ctx, h );
234 }
235
236 static inline HPy HPy_CallTupleDict(HPyContext ctx, HPy callable, HPy args, HPy kw) {
237 return ctx->ctx_CallTupleDict ( ctx, callable, args, kw );
238 }
239
230240 static inline void HPyErr_SetString(HPyContext ctx, HPy h_type, const char *message) {
231241 ctx->ctx_Err_SetString ( ctx, h_type, message );
232242 }
403413 return ctx->ctx_Dict_New ( ctx );
404414 }
405415
416 static inline int HPyTuple_Check(HPyContext ctx, HPy h) {
417 return ctx->ctx_Tuple_Check ( ctx, h );
418 }
419
406420 static inline HPy HPyTuple_FromArray(HPyContext ctx, HPy items[], HPy_ssize_t n) {
407421 return ctx->ctx_Tuple_FromArray ( ctx, items, n );
408422 }
0 #include <Python.h>
1 #include "hpy.h"
2
3 #ifdef HPY_UNIVERSAL_ABI
4 // for _h2py and _py2h
5 # include "handles.h"
6 #endif
7
8 _HPy_HIDDEN HPy
9 ctx_CallTupleDict(HPyContext ctx, HPy callable, HPy args, HPy kw)
10 {
11 PyObject *obj;
12 if (!HPy_IsNull(args) && !HPyTuple_Check(ctx, args)) {
13 HPyErr_SetString(ctx, ctx->h_TypeError,
14 "HPy_CallTupleDict requires args to be a tuple or null handle");
15 return HPy_NULL;
16 }
17 if (!HPy_IsNull(kw) && !HPyDict_Check(ctx, kw)) {
18 HPyErr_SetString(ctx, ctx->h_TypeError,
19 "HPy_CallTupleDict requires kw to be a dict or null handle");
20 return HPy_NULL;
21 }
22 if (HPy_IsNull(kw)) {
23 obj = PyObject_CallObject(_h2py(callable), _h2py(args));
24 }
25 else if (!HPy_IsNull(args)){
26 obj = PyObject_Call(_h2py(callable), _h2py(args), _h2py(kw));
27 }
28 else {
29 // args is null, but kw is not, so we need to create an empty args tuple
30 // for CPython's PyObject_Call
31 HPy items[] = {};
32 HPy empty_tuple = HPyTuple_FromArray(ctx, items, 0);
33 obj = PyObject_Call(_h2py(callable), _h2py(empty_tuple), _h2py(kw));
34 HPy_Close(ctx, empty_tuple);
35 }
36 return _py2h(obj);
37 }
00
11 # automatically generated by setup.py:get_scm_config()
2 __version__ = "0.1.dev875+g7c832a2"
3 __git_revision__ = "7c832a2"
2 __version__ = "0.1.dev959+geb07982"
3 __git_revision__ = "eb07982"
0 from pypy.interpreter.error import oefmt
1 from .apiset import API
2 from . import handles
3
4 @API.func("HPy HPy_CallTupleDict(HPyContext ctx, HPy callable, HPy args, HPy kw)")
5 def HPy_CallTupleDict(space, ctx, h_callable, h_args, h_kw):
6 w_callable = handles.deref(space, h_callable)
7 w_args = handles.deref(space, h_args) if h_args else None
8 w_kw = handles.deref(space, h_kw) if h_kw else None
9
10 # Check the types here, as space.call would allow any iterable/mapping
11 if w_args and not space.isinstance_w(w_args, space.w_tuple):
12 raise oefmt(space.w_TypeError,
13 "HPy_CallTupleDict requires args to be a tuple or null handle")
14 if w_kw and not space.isinstance_w(w_kw, space.w_dict):
15 raise oefmt(space.w_TypeError,
16 "HPy_CallTupleDict requires kw to be a dict or null handle")
17
18 # Note: both w_args and w_kw are allowed to be None
19 w_result = space.call(w_callable, w_args, w_kw)
20 return handles.new(space, w_result)
1818 interp_unicode,
1919 interp_float,
2020 interp_bytes,
21 interp_call,
2122 interp_dict,
2223 interp_list,
2324 interp_tuple,
4243 state = space.fromcache(State)
4344 initfunc_ptr = rffi.cast(llapi.HPyInitFunc, initfunc_ptr)
4445 h_module = initfunc_ptr(state.ctx)
46 if not h_module:
47 raise oefmt(space.w_SystemError,
48 "initialization of %s failed without raising an exception",
49 name)
4550 return handles.consume(space, h_module)
4651
4752 def descr_load_from_spec(space, w_spec):
9797 def HPyLong_AsUnsignedLongLong(space, ctx, h):
9898 w_long = handles.deref(space, h)
9999 try:
100 return rffi.cast(rffi.ULONGLONG, space.r_ulonglong_w(w_long))
100 return rffi.cast(rffi.ULONGLONG, space.r_ulonglong_w(
101 w_long, allow_conversion=False))
101102 except OperationError as e:
102103 if e.match(space, space.w_ValueError):
103104 e.w_type = space.w_OverflowError
125126 error_value=API.cast("ssize_t", -1))
126127 def HPyLong_AsSsize_t(space, ctx, h):
127128 w_long = handles.deref(space, h)
128 return space.int_w(w_long)
129 return space.int_w(w_long, allow_conversion=False)
00 from rpython.rtyper.lltypesystem import lltype, rffi
1 from rpython.rlib.rarithmetic import widen
21 from pypy.interpreter.error import OperationError, oefmt
3 from pypy.interpreter.module import Module
2 from pypy.interpreter.module import Module, init_extra_module_attrs
43 from pypy.module._hpy_universal.apiset import API
54 from pypy.module._hpy_universal import llapi
65 from pypy.module._hpy_universal import handles
2019 attach_legacy_methods(space, pymethods, w_mod, modname)
2120 else:
2221 raise oefmt(space.w_RuntimeError,
23 "Module %s contains legacy methods, but _hpy_universal "
24 "was compiled without cpyext support", modname)
22 "Module %s contains legacy methods, but _hpy_universal "
23 "was compiled without cpyext support", modname)
2524 #
2625 # add the native HPy defines
2726 if hpydef.c_defines:
3736 space, name, sig, doc, hpymeth.c_impl, w_mod)
3837 space.setattr(w_mod, space.newtext(w_extfunc.name), w_extfunc)
3938 i += 1
39 if hpydef.c_m_doc:
40 w_doc = space.newtext(rffi.constcharp2str(hpydef.c_m_doc))
41 else:
42 w_doc = space.w_None
43 space.setattr(w_mod, space.newtext('__doc__'), w_doc)
44 init_extra_module_attrs(space, w_mod)
4045 return handles.new(space, w_mod)
4146
4247
6464 w_value = handles.deref(space, h_value)
6565 operation.setattr(space, w_obj, w_name, w_value)
6666 return API.int(0)
67
68
69 @API.func("int HPyCallable_Check(HPyContext ctx, HPy h)", error_value='CANNOT_FAIL')
70 def HPyCallable_Check(space, ctx, h_obj):
71 w_obj = handles.deref(space, h_obj)
72 return API.int(space.is_true(space.callable(w_obj)))
6773
6874
6975 @API.func("HPy HPy_GetItem(HPyContext ctx, HPy h_obj, HPy h_key)")
77 items_w[i] = handles.deref(space, items[i])
88 w_result = space.newtuple(items_w)
99 return handles.new(space, w_result)
10
11 @API.func("int HPyTuple_Check(HPyContext ctx, HPy h)", error_value='CANNOT_FAIL')
12 def HPyTuple_Check(space, ctx, h):
13 w_obj = handles.deref(space, h)
14 w_obj_type = space.type(w_obj)
15 res = (space.is_w(w_obj_type, space.w_tuple) or
16 space.issubtype_w(w_obj_type, space.w_tuple))
17 return API.int(res)
190190 void * ctx_InPlaceAnd;
191191 void * ctx_InPlaceXor;
192192 void * ctx_InPlaceOr;
193 void * ctx_Callable_Check;
194 void * ctx_CallTupleDict;
195 void * ctx_FatalError;
193196 void * ctx_Err_SetString;
194197 void * ctx_Err_SetObject;
195198 void * ctx_Err_Occurred;
235238 void * ctx_List_Append;
236239 void * ctx_Dict_Check;
237240 void * ctx_Dict_New;
238 void * ctx_FatalError;
241 void * ctx_Tuple_Check;
239242 void * ctx_Tuple_FromArray;
240243 void * ctx_FromPyObject;
241244 void * ctx_AsPyObject;
496499 SIZEOF_HPyObject_HEAD = rffi.sizeof(cts.gettype('struct _HPyObject_head_s'))
497500
498501 # HPy API functions which are implemented directly in C
502 pypy_HPy_FatalError = rffi.llexternal('pypy_HPy_FatalError',
503 [HPyContext, rffi.CCHARP],
504 lltype.Void,
505 compilation_info=eci, _nowrapper=True)
506
499507 pypy_HPyErr_Occurred = rffi.llexternal('pypy_HPyErr_Occurred', [HPyContext],
500508 rffi.INT_real,
501509 compilation_info=eci, _nowrapper=True)
55 # include "src/exception.h"
66 #endif
77
8 #include <stdio.h>
89 #include "universal/hpy.h"
910 #include "hpyerr.h"
1011 #include "bridge.h"
1112
1213
14 void pypy_HPy_FatalError(HPyContext ctx, const char *message)
15 {
16 fprintf(stderr, "Fatal Python error: %s\n", message);
17 abort();
18 }
1319
1420 int pypy_HPyErr_Occurred(HPyContext ctx)
1521 {
00 #include "src/precommondefs.h"
11 #include "universal/hpy.h"
22
3 RPY_EXTERN void pypy_HPy_FatalError(HPyContext ctx, const char *message);
34 RPY_EXTERN int pypy_HPyErr_Occurred(HPyContext ctx);
45 RPY_EXTERN void pypy_HPyErr_SetString(HPyContext ctx, HPy type, const char *message);
56 RPY_EXTERN void pypy_HPyErr_SetObject(HPyContext ctx, HPy type, HPy value);
6565 ctx_field = 'c_ctx_' + func.basename
6666 setattr(self.ctx, ctx_field, funcptr)
6767
68 self.ctx.c_ctx_FatalError = rffi.cast(rffi.VOIDP, llapi.pypy_HPy_FatalError)
6869 self.ctx.c_ctx_Err_Occurred = rffi.cast(rffi.VOIDP, llapi.pypy_HPyErr_Occurred)
6970 self.ctx.c_ctx_Err_SetString = rffi.cast(rffi.VOIDP, llapi.pypy_HPyErr_SetString)
7071 self.ctx.c_ctx_Err_SetObject = rffi.cast(rffi.VOIDP, llapi.pypy_HPyErr_SetObject)
00 import pytest
1 import sys
21 from .support import ExtensionCompiler
3
4 disable = False
5
6 if sys.platform == 'win32':
7 # skip all tests on windows, see issue hpyproject/hpy#61
8 disable = True
9
10 def pytest_ignore_collect(path, config):
11 if disable:
12 return True
13
14 def pytest_collect_file(path, parent):
15 if disable:
16 # We end up here when calling py.test .../test_foo.py directly
17 # It's OK to kill the whole session with the following line
18 pytest.skip("skipping on windows")
192
203 def pytest_addoption(parser):
214 parser.addoption(
197197
198198 def make_module(self, ExtensionTemplate, main_src, name, extra_sources):
199199 """
200 Compile&load a modulo into memory. This is NOT a proper import: e.g. the module
201 is not put into sys.modules
202 """
203 so_filename = self.compile_module(ExtensionTemplate, main_src, name,
204 extra_sources)
205 if self.hpy_abi == 'universal':
206 return self.load_universal_module(name, so_filename)
207 else:
208 return self.load_cython_module(name, so_filename)
209
210 def load_universal_module(self, name, so_filename):
211 assert self.hpy_abi == 'universal'
212 import hpy.universal
213 spec = Spec(name, so_filename)
214 return hpy.universal.load_from_spec(spec)
215
216 def load_cython_module(self, name, so_filename):
217 assert self.hpy_abi == 'cpython'
218 # we've got a normal CPython module compiled with the CPython API/ABI,
219 # let's load it normally. It is important to do the imports only here,
220 # because this file will be imported also by PyPy tests which runs on
221 # Python2
222 import importlib.util
223 from importlib.machinery import ExtensionFileLoader
224 spec = importlib.util.spec_from_file_location(name, so_filename)
225 module = importlib.util.module_from_spec(spec)
226 spec.loader.exec_module(module)
200 Compile & load a module. This is NOT a proper import: e.g.
201 the module is not put into sys.modules
202 """
203 mod_filename = self.compile_module(
204 ExtensionTemplate, main_src, name, extra_sources)
205 return self.load_module(name, mod_filename)
206
207 def load_module(self, name, mod_filename):
208 # It is important to do the imports only here, because this file will
209 # be imported also by PyPy tests which runs on Python2
210 import importlib
211 import sys
212 import os
213 if name in sys.modules:
214 raise ValueError(
215 "Test module {!r} already present in sys.modules".format(name))
216 importlib.invalidate_caches()
217 mod_dir = os.path.dirname(mod_filename)
218 sys.path.insert(0, mod_dir)
219 try:
220 module = importlib.import_module(name)
221 assert sys.modules[name] is module
222 finally:
223 # assert that the module import didn't change the sys.path entry
224 # that was added above, then remove the entry.
225 assert sys.path[0] == mod_dir
226 del sys.path[0]
227 if name in sys.modules:
228 del sys.modules[name]
227229 return module
228230
229231
241243 return self.compiler.make_module(ExtensionTemplate, main_src, name,
242244 extra_sources)
243245
244 def should_check_refcount(self):
245 # defaults to True on CPython, but is set to False by e.g. PyPy
246 return sys.implementation.name == 'cpython'
246 def supports_refcounts(self):
247 """ Returns True if the underlying Python implementation supports
248 reference counts.
249
250 By default returns True on CPython and False on other
251 implementations.
252 """
253 return sys.implementation.name == "cpython"
254
255 def supports_ordinary_make_module_imports(self):
256 """ Returns True if `.make_module(...)` loads modules using a
257 standard Python import mechanism (e.g. `importlib.import_module`).
258
259 By default returns True because the base implementation of
260 `.make_module(...)` uses an ordinary import. Sub-classes that
261 override `.make_module(...)` may also want to override this
262 method.
263 """
264 return True
265
266 def supports_sys_executable(self):
267 """ Returns True is `sys.executable` is set to a value that allows
268 a Python equivalent to the current Python to be launched via, e.g.,
269 `subprocess.run(...)`.
270
271 By default returns `True` if sys.executable is set to a true value.
272 """
273 return bool(getattr(sys, "executable", None))
247274
248275
249276 # the few functions below are copied and adapted from cffi/ffiplatform.py
262289 os.environ[key] = value
263290 return outputfilename
264291
292
265293 def _build(tmpdir, ext, hpy_devel, hpy_abi, compiler_verbose=0, debug=None):
266294 # XXX compact but horrible :-(
267295 from distutils.core import Distribution
268 import distutils.errors, distutils.log
296 import distutils.errors
297 import distutils.log
269298 #
270299 dist = Distribution()
271300 dist.parse_config_files()
272 options = dist.get_option_dict('build_ext')
273301 if debug is None:
274302 debug = sys.flags.debug
275 options['debug'] = ('ffiplatform', debug)
276 options['force'] = ('ffiplatform', True)
277 options['build_lib'] = ('ffiplatform', tmpdir)
278 options['build_temp'] = ('ffiplatform', tmpdir)
279 #
303 options_build_ext = dist.get_option_dict('build_ext')
304 options_build_ext['debug'] = ('ffiplatform', debug)
305 options_build_ext['force'] = ('ffiplatform', True)
306 options_build_ext['build_lib'] = ('ffiplatform', tmpdir)
307 options_build_ext['build_temp'] = ('ffiplatform', tmpdir)
308 options_build_py = dist.get_option_dict('build_py')
309 options_build_py['build_lib'] = ('ffiplatform', tmpdir)
310
280311 # this is the equivalent of passing --hpy-abi from setup.py's command line
281312 dist.hpy_abi = hpy_abi
282 hpy_devel.fix_distribution(dist, hpy_ext_modules=[ext])
283 #
313 dist.hpy_ext_modules = [ext]
314 hpy_devel.fix_distribution(dist)
315
284316 old_level = distutils.log.set_threshold(0) or 0
285317 try:
286318 distutils.log.set_verbosity(compiler_verbose)
287319 dist.run_command('build_ext')
288320 cmd_obj = dist.get_command_obj('build_ext')
289 [soname] = cmd_obj.get_outputs()
321 outputs = cmd_obj.get_outputs()
322 if hpy_abi == "cpython":
323 [mod_filename] = [x for x in outputs if not x.endswith(".py")]
324 else:
325 [mod_filename] = [x for x in outputs if x.endswith(".py")]
290326 finally:
291327 distutils.log.set_threshold(old_level)
292 #
293 return soname
328
329 return mod_filename
0 """
1 NOTE: this tests are also meant to be run as PyPy "applevel" tests.
2
3 This means that global imports will NOT be visible inside the test
4 functions. In particular, you have to "import pytest" inside the test in order
5 to be able to use e.g. pytest.raises (which on PyPy will be implemented by a
6 "fake pytest module")
7 """
8 from .support import HPyTest
9
10
11 class TestBasic(HPyTest):
12
13 def test_get_version(self):
14 if self.compiler.hpy_abi != 'universal':
15 return
16 import hpy.universal
17 version, gitrev = hpy.universal.get_version()
18 # it's a bit hard to test the CONTENT of these values. Let's just
19 # check that they are strings...
20 assert isinstance(version, str)
21 assert isinstance(gitrev, str)
22
23 def test_empty_module(self):
24 import sys
25 mod = self.make_module("""
26 @INIT
27 """)
28 assert type(mod) is type(sys)
29
30 def test_different_name(self):
31 mod = self.make_module("""
32 @INIT
33 """, name="foo")
34 assert mod.__name__ == "foo"
35
36 def test_noop_function(self):
37 mod = self.make_module("""
38 HPyDef_METH(f, "f", f_impl, HPyFunc_NOARGS, .doc="hello world")
39 static HPy f_impl(HPyContext ctx, HPy self)
40 {
41 return HPy_Dup(ctx, ctx->h_None);
42 }
43
44 @EXPORT(f)
45 @INIT
46 """)
47 assert mod.f() is None
48 assert mod.f.__doc__ == 'hello world'
49
50 def test_self_is_module(self):
51 mod = self.make_module("""
52 HPyDef_METH(f, "f", f_impl, HPyFunc_NOARGS)
53 static HPy f_impl(HPyContext ctx, HPy self)
54 {
55 return HPy_Dup(ctx, self);
56 }
57 @EXPORT(f)
58 @INIT
59 """)
60 assert mod.f() is mod
61
62 def test_identity_function(self):
63 mod = self.make_module("""
64 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
65 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
66 {
67 return HPy_Dup(ctx, arg);
68 }
69 @EXPORT(f)
70 @INIT
71 """)
72 x = object()
73 assert mod.f(x) is x
74
75 def test_float_asdouble(self):
76 mod = self.make_module("""
77 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
78 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
79 {
80 double a = HPyFloat_AsDouble(ctx, arg);
81 return HPyFloat_FromDouble(ctx, a * 2.);
82 }
83 @EXPORT(f)
84 @INIT
85 """)
86 assert mod.f(1.) == 2.
87
88 def test_wrong_number_of_arguments(self):
89 import pytest
90 mod = self.make_module("""
91 HPyDef_METH(f_noargs, "f_noargs", f_noargs_impl, HPyFunc_NOARGS)
92 static HPy f_noargs_impl(HPyContext ctx, HPy self)
93 {
94 return HPy_Dup(ctx, ctx->h_None);
95 }
96 HPyDef_METH(f_o, "f_o", f_o_impl, HPyFunc_O)
97 static HPy f_o_impl(HPyContext ctx, HPy self, HPy arg)
98 {
99 return HPy_Dup(ctx, ctx->h_None);
100 }
101 @EXPORT(f_noargs)
102 @EXPORT(f_o)
103 @INIT
104 """)
105 with pytest.raises(TypeError):
106 mod.f_noargs(1)
107 with pytest.raises(TypeError):
108 mod.f_o()
109 with pytest.raises(TypeError):
110 mod.f_o(1, 2)
111
112 def test_close(self):
113 mod = self.make_module("""
114 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
115 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
116 {
117 HPy one = HPyLong_FromLong(ctx, 1);
118 if (HPy_IsNull(one))
119 return HPy_NULL;
120 HPy res = HPy_Add(ctx, arg, one);
121 HPy_Close(ctx, one);
122 return res;
123 }
124 @EXPORT(f)
125 @INIT
126 """)
127 assert mod.f(41.5) == 42.5
128
129 def test_bool(self):
130 mod = self.make_module("""
131 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
132 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
133 {
134 int cond = HPyLong_AsLong(ctx, arg) > 5;
135 return HPy_Dup(ctx, cond ? ctx->h_True : ctx->h_False);
136 }
137 @EXPORT(f)
138 @INIT
139 """)
140 assert mod.f(4) is False
141 assert mod.f(6) is True
142
143 def test_exception(self):
144 import pytest
145 mod = self.make_module("""
146 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
147 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
148 {
149 long x = HPyLong_AsLong(ctx, arg);
150 if (x < 5) {
151 return HPyLong_FromLong(ctx, -x);
152 }
153 else {
154 HPyErr_SetString(ctx, ctx->h_ValueError, "hello world");
155 return HPy_NULL;
156 }
157 }
158 @EXPORT(f)
159 @INIT
160 """)
161 assert mod.f(-10) == 10
162 with pytest.raises(ValueError) as exc:
163 mod.f(20)
164 assert str(exc.value) == 'hello world'
165
166 def test_builtin_handles(self):
167 mod = self.make_module("""
168 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
169 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
170 {
171 long i = HPyLong_AsLong(ctx, arg);
172 HPy h;
173 switch(i) {
174 case 1: h = ctx->h_None; break;
175 case 2: h = ctx->h_False; break;
176 case 3: h = ctx->h_True; break;
177 case 4: h = ctx->h_ValueError; break;
178 case 5: h = ctx->h_TypeError; break;
179 case 6: h = ctx->h_IndexError; break;
180 case 7: h = ctx->h_SystemError; break;
181 case 8: h = ctx->h_BaseObjectType; break;
182 case 9: h = ctx->h_TypeType; break;
183 case 10: h = ctx->h_LongType; break;
184 case 11: h = ctx->h_UnicodeType; break;
185 case 12: h = ctx->h_TupleType; break;
186 case 13: h = ctx->h_ListType; break;
187 default:
188 HPyErr_SetString(ctx, ctx->h_ValueError, "invalid choice");
189 return HPy_NULL;
190 }
191 return HPy_Dup(ctx, h);
192 }
193 @EXPORT(f)
194 @INIT
195 """)
196 builtin_objs = (
197 '<NULL>', None, False, True, ValueError, TypeError, IndexError,
198 SystemError, object, type, int, str, tuple, list,
199 )
200 for i, obj in enumerate(builtin_objs):
201 if i == 0:
202 continue
203 assert mod.f(i) is obj
204
205 def test_extern_def(self):
206 import pytest
207 main = """
208 extern HPyDef f;
209 extern HPyDef g;
210 extern HPyDef h;
211 extern HPyDef i;
212
213 @EXPORT(f)
214 @EXPORT(g)
215 @EXPORT(h)
216 @EXPORT(i)
217 @INIT
218 """
219 extra = """
220 HPyDef_METH(f, "f", f_impl, HPyFunc_NOARGS)
221 static HPy f_impl(HPyContext ctx, HPy self)
222 {
223 return HPyLong_FromLong(ctx, 12345);
224 }
225 HPyDef_METH(g, "g", g_impl, HPyFunc_O)
226 static HPy g_impl(HPyContext ctx, HPy self, HPy arg)
227 {
228 return HPy_Dup(ctx, arg);
229 }
230 HPyDef_METH(h, "h", h_impl, HPyFunc_VARARGS)
231 static HPy h_impl(HPyContext ctx, HPy self, HPy *args, HPy_ssize_t nargs)
232 {
233 long a, b;
234 if (!HPyArg_Parse(ctx, NULL, args, nargs, "ll", &a, &b))
235 return HPy_NULL;
236 return HPyLong_FromLong(ctx, 10*a + b);
237 }
238 HPyDef_METH(i, "i", i_impl, HPyFunc_KEYWORDS)
239 static HPy i_impl(HPyContext ctx, HPy self, HPy *args, HPy_ssize_t nargs,
240 HPy kw)
241 {
242 long a, b;
243 static const char *kwlist[] = { "a", "b", NULL };
244 if (!HPyArg_ParseKeywords(ctx, NULL, args, nargs, kw, "ll", kwlist, &a, &b))
245 return HPy_NULL;
246 return HPyLong_FromLong(ctx, 10*a + b);
247 }
248 """
249 mod = self.make_module(main, extra_sources=[extra])
250 assert mod.f() == 12345
251 assert mod.g(42) == 42
252 assert mod.h(5, 6) == 56
253 assert mod.i(4, 3) == 43
254 assert mod.i(a=2, b=5) == 25
255 with pytest.raises(TypeError):
256 mod.h("not an integer", "not an integer either")
257
258 def test_Float_FromDouble(self):
259 mod = self.make_module("""
260 HPyDef_METH(f, "f", f_impl, HPyFunc_NOARGS)
261 static HPy f_impl(HPyContext ctx, HPy self)
262 {
263 return HPyFloat_FromDouble(ctx, 123.45);
264 }
265 @EXPORT(f)
266 @INIT
267 """)
268 assert mod.f() == 123.45
269
270 def test_unsupported_signature(self):
271 import pytest
272 with pytest.raises(ValueError) as exc:
273 self.make_module("""
274 HPyDef f = {
275 .kind = HPyDef_Kind_Meth,
276 .meth = {
277 .name = "f",
278 .signature = 1234,
279 }
280 };
281 @EXPORT(f)
282 @INIT
283 """)
284 assert str(exc.value) == 'Unsupported HPyMeth signature'
285
286 def test_repr_str_ascii_bytes(self):
287 mod = self.make_module("""
288 HPyDef_METH(f1, "f1", f1_impl, HPyFunc_O)
289 static HPy f1_impl(HPyContext ctx, HPy self, HPy arg)
290 {
291 return HPy_Repr(ctx, arg);
292 }
293 HPyDef_METH(f2, "f2", f2_impl, HPyFunc_O)
294 static HPy f2_impl(HPyContext ctx, HPy self, HPy arg)
295 {
296 return HPy_Str(ctx, arg);
297 }
298 HPyDef_METH(f3, "f3", f3_impl, HPyFunc_O)
299 static HPy f3_impl(HPyContext ctx, HPy self, HPy arg)
300 {
301 return HPy_ASCII(ctx, arg);
302 }
303 HPyDef_METH(f4, "f4", f4_impl, HPyFunc_O)
304 static HPy f4_impl(HPyContext ctx, HPy self, HPy arg)
305 {
306 return HPy_Bytes(ctx, arg);
307 }
308 @EXPORT(f1)
309 @EXPORT(f2)
310 @EXPORT(f3)
311 @EXPORT(f4)
312 @INIT
313 """)
314 assert mod.f1("\u1234") == "'\u1234'"
315 assert mod.f2(42) == "42"
316 assert mod.f3("\u1234") == "'\\u1234'"
317 assert mod.f4(bytearray(b"foo")) == b"foo"
318
319 def test_is_true(self):
320 mod = self.make_module("""
321 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
322 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
323 {
324 int cond = HPy_IsTrue(ctx, arg);
325 return HPy_Dup(ctx, cond ? ctx->h_True : ctx->h_False);
326 }
327 @EXPORT(f)
328 @INIT
329 """)
330 assert mod.f("1234") is True
331 assert mod.f("") is False
332
333 def test_richcompare(self):
334 mod = self.make_module("""
335 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
336 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
337 {
338 HPy arg2 = HPyLong_FromLong(ctx, 100);
339 HPy result = HPy_RichCompare(ctx, arg, arg2, HPy_GT);
340 HPy_Close(ctx, arg2);
341 return result;
342 }
343 @EXPORT(f)
344 @INIT
345 """)
346 assert mod.f(100) is False
347 assert mod.f(150) is True
348
349 def test_richcomparebool(self):
350 mod = self.make_module("""
351 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
352 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
353 {
354 HPy arg2 = HPyLong_FromLong(ctx, 100);
355 int result = HPy_RichCompareBool(ctx, arg, arg2, HPy_GE);
356 HPy_Close(ctx, arg2);
357 return HPyLong_FromLong(ctx, -result);
358 }
359 @EXPORT(f)
360 @INIT
361 """)
362 assert mod.f(50) == 0
363 assert mod.f(100) == -1
364
365 def test_hash(self):
366 mod = self.make_module("""
367 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
368 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
369 {
370 HPy_hash_t hash = HPy_Hash(ctx, arg);
371 return HPyLong_FromSsize_t(ctx, hash);
372 }
373 @EXPORT(f)
374 @INIT
375 """)
376 x = object()
377 assert mod.f(x) == hash(x)
+0
-378
pypy/module/_hpy_universal/test/_vendored/test_basic.py less more
0 """
1 NOTE: this tests are also meant to be run as PyPy "applevel" tests.
2
3 This means that global imports will NOT be visible inside the test
4 functions. In particular, you have to "import pytest" inside the test in order
5 to be able to use e.g. pytest.raises (which on PyPy will be implemented by a
6 "fake pytest module")
7 """
8 from .support import HPyTest
9
10
11 class TestBasic(HPyTest):
12
13 def test_get_version(self):
14 if self.compiler.hpy_abi != 'universal':
15 return
16 import hpy.universal
17 version, gitrev = hpy.universal.get_version()
18 # it's a bit hard to test the CONTENT of these values. Let's just
19 # check that they are strings...
20 assert isinstance(version, str)
21 assert isinstance(gitrev, str)
22
23 def test_empty_module(self):
24 import sys
25 mod = self.make_module("""
26 @INIT
27 """)
28 assert type(mod) is type(sys)
29
30 def test_different_name(self):
31 mod = self.make_module("""
32 @INIT
33 """, name="foo")
34 assert mod.__name__ == "foo"
35
36 def test_noop_function(self):
37 mod = self.make_module("""
38 HPyDef_METH(f, "f", f_impl, HPyFunc_NOARGS, .doc="hello world")
39 static HPy f_impl(HPyContext ctx, HPy self)
40 {
41 return HPy_Dup(ctx, ctx->h_None);
42 }
43
44 @EXPORT(f)
45 @INIT
46 """)
47 assert mod.f() is None
48 assert mod.f.__doc__ == 'hello world'
49
50 def test_self_is_module(self):
51 mod = self.make_module("""
52 HPyDef_METH(f, "f", f_impl, HPyFunc_NOARGS)
53 static HPy f_impl(HPyContext ctx, HPy self)
54 {
55 return HPy_Dup(ctx, self);
56 }
57 @EXPORT(f)
58 @INIT
59 """)
60 assert mod.f() is mod
61
62 def test_identity_function(self):
63 mod = self.make_module("""
64 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
65 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
66 {
67 return HPy_Dup(ctx, arg);
68 }
69 @EXPORT(f)
70 @INIT
71 """)
72 x = object()
73 assert mod.f(x) is x
74
75 def test_float_asdouble(self):
76 mod = self.make_module("""
77 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
78 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
79 {
80 double a = HPyFloat_AsDouble(ctx, arg);
81 return HPyFloat_FromDouble(ctx, a * 2.);
82 }
83 @EXPORT(f)
84 @INIT
85 """)
86 assert mod.f(1.) == 2.
87
88 def test_wrong_number_of_arguments(self):
89 import pytest
90 mod = self.make_module("""
91 HPyDef_METH(f_noargs, "f_noargs", f_noargs_impl, HPyFunc_NOARGS)
92 static HPy f_noargs_impl(HPyContext ctx, HPy self)
93 {
94 return HPy_Dup(ctx, ctx->h_None);
95 }
96 HPyDef_METH(f_o, "f_o", f_o_impl, HPyFunc_O)
97 static HPy f_o_impl(HPyContext ctx, HPy self, HPy arg)
98 {
99 return HPy_Dup(ctx, ctx->h_None);
100 }
101 @EXPORT(f_noargs)
102 @EXPORT(f_o)
103 @INIT
104 """)
105 with pytest.raises(TypeError):
106 mod.f_noargs(1)
107 with pytest.raises(TypeError):
108 mod.f_o()
109 with pytest.raises(TypeError):
110 mod.f_o(1, 2)
111
112 def test_close(self):
113 mod = self.make_module("""
114 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
115 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
116 {
117 HPy one = HPyLong_FromLong(ctx, 1);
118 if (HPy_IsNull(one))
119 return HPy_NULL;
120 HPy res = HPy_Add(ctx, arg, one);
121 HPy_Close(ctx, one);
122 return res;
123 }
124 @EXPORT(f)
125 @INIT
126 """)
127 assert mod.f(41.5) == 42.5
128
129 def test_bool(self):
130 mod = self.make_module("""
131 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
132 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
133 {
134 int cond = HPyLong_AsLong(ctx, arg) > 5;
135 return HPy_Dup(ctx, cond ? ctx->h_True : ctx->h_False);
136 }
137 @EXPORT(f)
138 @INIT
139 """)
140 assert mod.f(4) is False
141 assert mod.f(6) is True
142
143 def test_exception(self):
144 import pytest
145 mod = self.make_module("""
146 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
147 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
148 {
149 long x = HPyLong_AsLong(ctx, arg);
150 if (x < 5) {
151 return HPyLong_FromLong(ctx, -x);
152 }
153 else {
154 HPyErr_SetString(ctx, ctx->h_ValueError, "hello world");
155 return HPy_NULL;
156 }
157 }
158 @EXPORT(f)
159 @INIT
160 """)
161 assert mod.f(-10) == 10
162 with pytest.raises(ValueError) as exc:
163 mod.f(20)
164 assert str(exc.value) == 'hello world'
165
166 def test_builtin_handles(self):
167 mod = self.make_module("""
168 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
169 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
170 {
171 long i = HPyLong_AsLong(ctx, arg);
172 HPy h;
173 switch(i) {
174 case 1: h = ctx->h_None; break;
175 case 2: h = ctx->h_False; break;
176 case 3: h = ctx->h_True; break;
177 case 4: h = ctx->h_ValueError; break;
178 case 5: h = ctx->h_TypeError; break;
179 case 6: h = ctx->h_IndexError; break;
180 case 7: h = ctx->h_SystemError; break;
181 case 8: h = ctx->h_BaseObjectType; break;
182 case 9: h = ctx->h_TypeType; break;
183 case 10: h = ctx->h_LongType; break;
184 case 11: h = ctx->h_UnicodeType; break;
185 case 12: h = ctx->h_TupleType; break;
186 case 13: h = ctx->h_ListType; break;
187 default:
188 HPyErr_SetString(ctx, ctx->h_ValueError, "invalid choice");
189 return HPy_NULL;
190 }
191 return HPy_Dup(ctx, h);
192 }
193 @EXPORT(f)
194 @INIT
195 """)
196 builtin_objs = (
197 '<NULL>', None, False, True, ValueError, TypeError, IndexError,
198 SystemError, object, type, int, str, tuple, list,
199 )
200 for i, obj in enumerate(builtin_objs):
201 if i == 0:
202 continue
203 assert mod.f(i) is obj
204
205 def test_extern_def(self):
206 import pytest
207 main = """
208 extern HPyDef f;
209 extern HPyDef g;
210 extern HPyDef h;
211 extern HPyDef i;
212
213 @EXPORT(f)
214 @EXPORT(g)
215 @EXPORT(h)
216 @EXPORT(i)
217 @INIT
218 """
219 extra = """
220 HPyDef_METH(f, "f", f_impl, HPyFunc_NOARGS)
221 static HPy f_impl(HPyContext ctx, HPy self)
222 {
223 return HPyLong_FromLong(ctx, 12345);
224 }
225 HPyDef_METH(g, "g", g_impl, HPyFunc_O)
226 static HPy g_impl(HPyContext ctx, HPy self, HPy arg)
227 {
228 return HPy_Dup(ctx, arg);
229 }
230 HPyDef_METH(h, "h", h_impl, HPyFunc_VARARGS)
231 static HPy h_impl(HPyContext ctx, HPy self, HPy *args, HPy_ssize_t nargs)
232 {
233 long a, b;
234 if (!HPyArg_Parse(ctx, NULL, args, nargs, "ll", &a, &b))
235 return HPy_NULL;
236 return HPyLong_FromLong(ctx, 10*a + b);
237 }
238 HPyDef_METH(i, "i", i_impl, HPyFunc_KEYWORDS)
239 static HPy i_impl(HPyContext ctx, HPy self, HPy *args, HPy_ssize_t nargs,
240 HPy kw)
241 {
242 long a, b;
243 static const char *kwlist[] = { "a", "b", NULL };
244 if (!HPyArg_ParseKeywords(ctx, NULL, args, nargs, kw, "ll", kwlist, &a, &b))
245 return HPy_NULL;
246 return HPyLong_FromLong(ctx, 10*a + b);
247 }
248 """
249 mod = self.make_module(main, extra_sources=[extra])
250 assert mod.f() == 12345
251 assert mod.g(42) == 42
252 assert mod.h(5, 6) == 56
253 assert mod.i(4, 3) == 43
254 assert mod.i(a=2, b=5) == 25
255 with pytest.raises(TypeError):
256 mod.h("not an integer", "not an integer either")
257
258 def test_Float_FromDouble(self):
259 mod = self.make_module("""
260 HPyDef_METH(f, "f", f_impl, HPyFunc_NOARGS)
261 static HPy f_impl(HPyContext ctx, HPy self)
262 {
263 return HPyFloat_FromDouble(ctx, 123.45);
264 }
265 @EXPORT(f)
266 @INIT
267 """)
268 assert mod.f() == 123.45
269
270 def test_unsupported_signature(self):
271 import pytest
272 with pytest.raises(ValueError) as exc:
273 self.make_module("""
274 HPyDef f = {
275 .kind = HPyDef_Kind_Meth,
276 .meth = {
277 .name = "f",
278 .signature = 1234,
279 }
280 };
281 @EXPORT(f)
282 @INIT
283 """)
284 assert str(exc.value) == 'Unsupported HPyMeth signature'
285
286 def test_repr_str_ascii_bytes(self):
287 mod = self.make_module("""
288 HPyDef_METH(f1, "f1", f1_impl, HPyFunc_O)
289 static HPy f1_impl(HPyContext ctx, HPy self, HPy arg)
290 {
291 return HPy_Repr(ctx, arg);
292 }
293 HPyDef_METH(f2, "f2", f2_impl, HPyFunc_O)
294 static HPy f2_impl(HPyContext ctx, HPy self, HPy arg)
295 {
296 return HPy_Str(ctx, arg);
297 }
298 HPyDef_METH(f3, "f3", f3_impl, HPyFunc_O)
299 static HPy f3_impl(HPyContext ctx, HPy self, HPy arg)
300 {
301 return HPy_ASCII(ctx, arg);
302 }
303 HPyDef_METH(f4, "f4", f4_impl, HPyFunc_O)
304 static HPy f4_impl(HPyContext ctx, HPy self, HPy arg)
305 {
306 return HPy_Bytes(ctx, arg);
307 }
308 @EXPORT(f1)
309 @EXPORT(f2)
310 @EXPORT(f3)
311 @EXPORT(f4)
312 @INIT
313 """)
314 assert mod.f1("\u1234") == "'\u1234'"
315 assert mod.f2(42) == "42"
316 assert mod.f3("\u1234") == "'\\u1234'"
317 assert mod.f4(bytearray(b"foo")) == b"foo"
318
319 def test_is_true(self):
320 mod = self.make_module("""
321 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
322 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
323 {
324 int cond = HPy_IsTrue(ctx, arg);
325 return HPy_Dup(ctx, cond ? ctx->h_True : ctx->h_False);
326 }
327 @EXPORT(f)
328 @INIT
329 """)
330 assert mod.f("1234") is True
331 assert mod.f("") is False
332
333 def test_richcompare(self):
334 mod = self.make_module("""
335 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
336 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
337 {
338 HPy arg2 = HPyLong_FromLong(ctx, 100);
339 HPy result = HPy_RichCompare(ctx, arg, arg2, HPy_GT);
340 HPy_Close(ctx, arg2);
341 return result;
342 }
343 @EXPORT(f)
344 @INIT
345 """)
346 assert mod.f(100) is False
347 assert mod.f(150) is True
348
349 def test_richcomparebool(self):
350 mod = self.make_module("""
351 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
352 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
353 {
354 HPy arg2 = HPyLong_FromLong(ctx, 100);
355 int result = HPy_RichCompareBool(ctx, arg, arg2, HPy_GE);
356 HPy_Close(ctx, arg2);
357 return HPyLong_FromLong(ctx, -result);
358 }
359 @EXPORT(f)
360 @INIT
361 """)
362 assert mod.f(50) == 0
363 assert mod.f(100) == -1
364
365 def test_hash(self):
366 mod = self.make_module("""
367 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
368 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
369 {
370 HPy_hash_t hash = HPy_Hash(ctx, arg);
371 return HPyLong_FromSsize_t(ctx, hash);
372 }
373 @EXPORT(f)
374 @INIT
375 """)
376 x = object()
377 assert mod.f(x) == hash(x)
0 from .support import HPyTest
1
2
3 class TestCall(HPyTest):
4 def argument_combinations(self, **items):
5 """ Returns all possible ways of expressing the given items as
6 arguments to a function.
7 """
8 items = list(items.items())
9 for i in range(len(items) + 1):
10 args = tuple(item[1] for item in items[:i])
11 kw = dict(items[i:])
12 yield {"args": args, "kw": kw}
13 if not args:
14 yield {"kw": kw}
15 if not kw:
16 yield {"args": args}
17 if not args and not kw:
18 yield {}
19
20 def test_hpy_calltupledict(self):
21 import pytest
22 mod = self.make_module("""
23 HPyDef_METH(call, "call", call_impl, HPyFunc_KEYWORDS)
24 static HPy call_impl(HPyContext ctx, HPy self,
25 HPy *args, HPy_ssize_t nargs, HPy kw)
26 {
27
28 HPy f, result;
29 HPy f_args = HPy_NULL;
30 HPy f_kw = HPy_NULL;
31 HPyTracker ht;
32 static const char *kwlist[] = { "f", "args", "kw", NULL };
33 if (!HPyArg_ParseKeywords(ctx, &ht, args, nargs, kw, "O|OO",
34 kwlist, &f, &f_args, &f_kw)) {
35 return HPy_NULL;
36 }
37 result = HPy_CallTupleDict(ctx, f, f_args, f_kw);
38 HPyTracker_Close(ctx, ht);
39 return result;
40 }
41 @EXPORT(call)
42 @INIT
43 """)
44
45 def f(a, b):
46 return a + b
47
48 def g():
49 return "this is g"
50
51 # test passing arguments with handles of the correct type --
52 # i.e. args is a tuple or a null handle, kw is a dict or a null handle.
53 for d in self.argument_combinations(a=1, b=2):
54 assert mod.call(f, **d) == 3
55 for d in self.argument_combinations(a=1):
56 with pytest.raises(TypeError):
57 mod.call(f, **d)
58 for d in self.argument_combinations():
59 with pytest.raises(TypeError):
60 mod.call(f, **d)
61 for d in self.argument_combinations():
62 assert mod.call(g, **d) == "this is g"
63 for d in self.argument_combinations(object=2):
64 assert mod.call(str, **d) == "2"
65 for d in self.argument_combinations():
66 with pytest.raises(TypeError):
67 mod.call("not callable", **d)
68 for d in self.argument_combinations(unknown=2):
69 with pytest.raises(TypeError):
70 mod.call("not callable", **d)
71
72 # test passing handles of the incorrect type as arguments
73 with pytest.raises(TypeError):
74 mod.call(f, args=[1, 2])
75 with pytest.raises(TypeError):
76 mod.call(f, args="string")
77 with pytest.raises(TypeError):
78 mod.call(f, args=1)
79 with pytest.raises(TypeError):
80 mod.call(f, args=None)
81 with pytest.raises(TypeError):
82 mod.call(f, kw=[1, 2])
83 with pytest.raises(TypeError):
84 mod.call(f, kw="string")
85 with pytest.raises(TypeError):
86 mod.call(f, kw=1)
87 with pytest.raises(TypeError):
88 mod.call(f, kw=None)
89
90 def test_hpycallable_check(self):
91 mod = self.make_module("""
92 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
93 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
94 {
95 if (HPyCallable_Check(ctx, arg))
96 return HPy_Dup(ctx, ctx->h_True);
97 return HPy_Dup(ctx, ctx->h_False);
98 }
99 @EXPORT(f)
100 @INIT
101 """)
102
103 def f():
104 return "this is f"
105
106 assert mod.f(f) is True
107 assert mod.f(str) is True
108 assert mod.f("a") is False
109 assert mod.f(3) is False
22
33 class TestCPythonCompatibility(HPyTest):
44
5 # One note about the should_check_refcount() in the tests below: on
5 # One note about the supports_refcounts() in the tests below: on
66 # CPython, handles are actually implemented as INCREF/DECREF, so we can
77 # check e.g. after an HPy_Dup the refcnt is += 1. However, on PyPy they
88 # are implemented in a completely different way which is unrelated to the
3434 x = mod.f()
3535 assert x[0] == 1234
3636 assert len(x) == 2
37 if self.should_check_refcount():
37 if self.supports_refcounts():
3838 assert x == [1234, +1]
3939
4040 def test_aspyobject(self):
9696 @INIT
9797 """)
9898 x = mod.f()
99 if self.should_check_refcount():
99 if self.supports_refcounts():
100100 assert x == -1
101101
102102 def test_hpy_dup(self):
122122 @INIT
123123 """)
124124 x = mod.f()
125 if self.should_check_refcount():
125 if self.supports_refcounts():
126126 assert x == +1
127127
128128 def test_many_handles(self):
1919 mod.f()
2020
2121 def test_FatalError(self):
22 import os
23 import sys
2224 mod = self.make_module("""
2325 HPyDef_METH(f, "f", f_impl, HPyFunc_NOARGS)
2426 static HPy f_impl(HPyContext ctx, HPy self)
3234 @EXPORT(f)
3335 @INIT
3436 """)
35 # Calling mod.f() gives a fatal error, ending in abort().
36 # How to check that? For now we just check that the above compiles
37 if not self.supports_sys_executable():
38 # if sys.executable is not available (e.g. inside pypy app-level)
39 # tests, then skip the rest of this test
40 return
41 # subprocess is not importable in pypy app-level tests
42 import subprocess
43 env = os.environ.copy()
44 env["PYTHONPATH"] = os.path.dirname(mod.__file__)
45 result = subprocess.run([
46 sys.executable,
47 "-c", "import {} as mod; mod.f()".format(mod.__name__)
48 ], env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
49 assert result.returncode == -6
50 assert result.stdout == b""
51 assert result.stderr.startswith(b"Fatal Python error: boom!\n")
3752
3853 def test_HPyErr_Occurred(self):
3954 import pytest
232247 check_exception(EnvironmentError)
233248 check_exception(IOError)
234249
235 @pytest_collecting.mark.xfail(True, reason=(
236 "Creating the unicode exceptions requires something like HPyCall"
237 " and that isn't implemented yet."
238 ))
239250 def test_h_unicode_exceptions(self):
240251 import pytest
241252 mod = self.make_module("""
263274 HPy_Close(ctx, h_dict);
264275 return HPy_NULL;
265276 }
266 h_err_value = HPy_Call(ctx, h_err, h_args, h_kw);
277 h_err_value = HPy_CallTupleDict(ctx, h_err, h_args, h_kw);
267278 if (HPy_IsNull(h_err_value)) {
268279 HPy_Close(ctx, h_dict);
269280 HPy_Close(ctx, h_err);
11
22
33 class TestLong(HPyTest):
4
5 def magic_int(self, v):
6 """ Return an instance of a class that implements __int__
7 and returns value v.
8 """
9 class MagicInt(object):
10 def __int__(self):
11 return v
12 return MagicInt()
13
14 def magic_index(self, v):
15 """ Return an instance of a class that implements __index__
16 and returns value v.
17 """
18 class MagicIndex(object):
19 def __index__(self):
20 return v
21 return MagicIndex()
22
23 def python_supports_magic_index(self):
24 """ Return True if the Python version is 3.8 or later and thus
25 should support calling __index__ in the various HPyLong_As...
26 methods.
27 """
28 import sys
29 vi = sys.version_info
30 return (vi.major > 3 or (vi.major == 3 and vi.minor >= 8))
431
532 def test_Long_FromLong(self):
633 mod = self.make_module("""
3259 assert mod.f(45) == 90
3360 with pytest.raises(TypeError):
3461 mod.f("this is not a number")
62 assert mod.f(self.magic_int(2)) == 4
63 if self.python_supports_magic_index():
64 assert mod.f(self.magic_index(2)) == 4
3565
3666 def test_Long_FromUnsignedLong(self):
3767 mod = self.make_module("""
6595 mod.f(-91)
6696 with pytest.raises(TypeError):
6797 mod.f("this is not a number")
98 with pytest.raises(TypeError):
99 mod.f(self.magic_int(2))
100 with pytest.raises(TypeError):
101 mod.f(self.magic_index(2))
68102
69103 def test_Long_AsUnsignedLongMask(self):
70104 import pytest
84118 assert mod.f(-1) == 2**64 - 1
85119 with pytest.raises(TypeError):
86120 mod.f("this is not a number")
121 assert mod.f(self.magic_int(2)) == 2
122 if self.python_supports_magic_index():
123 assert mod.f(self.magic_index(2)) == 2
87124
88125 def test_Long_FromLongLong(self):
89126 mod = self.make_module("""
117154 assert mod.f(-2147483648) == -2147483648
118155 with pytest.raises(TypeError):
119156 mod.f("this is not a number")
157 assert mod.f(self.magic_int(2)) == 2
158 if self.python_supports_magic_index():
159 assert mod.f(self.magic_index(2)) == 2
120160
121161 def test_Long_FromUnsignedLongLong(self):
122162 mod = self.make_module("""
151191 mod.f(-4294967296)
152192 with pytest.raises(TypeError):
153193 mod.f("this is not a number")
194 with pytest.raises(TypeError):
195 mod.f(self.magic_int(2))
196 with pytest.raises(TypeError):
197 mod.f(self.magic_index(2))
154198
155199 def test_Long_AsUnsignedLongLongMask(self):
156200 import pytest
170214 assert mod.f(-1) == 2**64 - 1
171215 with pytest.raises(TypeError):
172216 mod.f("this is not a number")
217 assert mod.f(self.magic_int(2)) == 2
218 if self.python_supports_magic_index():
219 assert mod.f(self.magic_index(2)) == 2
173220
174221 def test_Long_FromSize_t(self):
175222 mod = self.make_module("""
204251 mod.f(-2147483648)
205252 with pytest.raises(TypeError):
206253 mod.f("this is not a number")
254 with pytest.raises(TypeError):
255 mod.f(self.magic_int(2))
256 with pytest.raises(TypeError):
257 mod.f(self.magic_index(2))
207258
208259 def test_Long_FromSsize_t(self):
209260 mod = self.make_module("""
240291 assert mod.f(-41) == -41
241292 with pytest.raises(TypeError):
242293 mod.f("this is not a number")
294 with pytest.raises(TypeError):
295 mod.f(self.magic_int(2))
296 with pytest.raises(TypeError):
297 mod.f(self.magic_index(2))
00 from .support import HPyTest
11
22 class TestTuple(HPyTest):
3
4 def test_Check(self):
5 mod = self.make_module("""
6 HPyDef_METH(f, "f", f_impl, HPyFunc_O)
7 static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
8 {
9 if (HPyTuple_Check(ctx, arg))
10 return HPy_Dup(ctx, ctx->h_True);
11 return HPy_Dup(ctx, ctx->h_False);
12 }
13 @EXPORT(f)
14 @INIT
15 """)
16 class MyTuple(tuple):
17 pass
18
19 assert mod.f(()) is True
20 assert mod.f([]) is False
21 assert mod.f(MyTuple()) is True
322
423 def test_FromArray(self):
524 mod = self.make_module("""
191191 def test_refcount(self):
192192 import pytest
193193 import sys
194 if not self.should_check_refcount():
194 if not self.supports_refcounts():
195195 pytest.skip()
196196 mod = self.make_module("""
197197 @DEFINE_PointObject
0 import pytest as pytest_collecting
1
20 from .support import HPyTest
3
4 # this function should probably goes somewhere into hpy.universal and/or and
5 # hpy package and/or an import hook, or whatever. I do not want to think about
6 # this now.
7 def import_module_properly(mod):
8 raise NotImplementedError("fix me eventually")
9
10 # this was moved from support.py, where it did not belong
11 ## class HPyLoader(ExtensionFileLoader):
12 ## def create_module(self, spec):
13 ## import hpy.universal
14 ## return hpy.universal.load_from_spec(spec)
151
162
173 class TestImporting(HPyTest):
184
19 @pytest_collecting.mark.xfail
205 def test_importing_attributes(self):
21 import sys
22 modname = 'mytest'
23 so_filename = self.compile_module("""
6 import pytest
7 if not self.supports_ordinary_make_module_imports():
8 pytest.skip()
9 mod = self.make_module("""
2410 @INIT
25 """, name=modname)
26 mod = import_module_properly(so_filename, modname)
27 assert mod in sys.modules
11 """, name='mytest')
12 assert mod.__name__ == 'mytest'
13 assert mod.__package__ == ''
14 assert mod.__doc__ == 'some test for hpy'
2815 assert mod.__loader__.name == 'mytest'
2916 assert mod.__spec__.loader is mod.__loader__
17 assert mod.__spec__.name == 'mytest'
3018 assert mod.__file__
77 from pypy.module._hpy_universal._vendored.hpy.devel import HPyDevel
88
99 COMPILER_VERBOSE = False
10
1110
1211
1312 class HPyAppTest(object):
5453 else:
5554 items_w = space.unpackiterable(w_extra_sources)
5655 extra_sources = [space.text_w(item) for item in items_w]
57 so_filename = compiler.compile_module(ExtensionTemplate,
56 py_filename = compiler.compile_module(ExtensionTemplate,
5857 source_template, name, extra_sources)
58 so_filename = py_filename.replace(".py", ".hpy.so")
5959 w_mod = space.appexec([space.newtext(so_filename), space.newtext(name)],
6060 """(path, modname):
6161 import _hpy_universal
6565 return w_mod
6666 self.w_make_module = self.space.wrap(interp2app(descr_make_module))
6767
68 def should_check_refcount(space):
68 def supports_refcounts(space):
6969 return space.w_False
70 self.w_should_check_refcount = self.space.wrap(interp2app(should_check_refcount))
70 self.w_supports_refcounts = self.space.wrap(interp2app(supports_refcounts))
71
72 def supports_ordinary_make_module_imports(space):
73 return space.w_False
74 self.w_supports_ordinary_make_module_imports = self.space.wrap(
75 interp2app(supports_ordinary_make_module_imports))
76
77 def supports_sys_executable(space):
78 return space.w_False
79 self.w_supports_sys_executable = self.space.wrap(
80 interp2app(supports_sys_executable))
7181
7282 self.w_compiler = self.space.appexec([], """():
7383 class compiler:
2929 - ListBuilder_Cancel is not tested
3030
3131 """
32 def test_import_failure(self):
33 import pytest
34 with pytest.raises(RuntimeError):
35 self.make_module("""
36 HPy_MODINIT(test)
37 static HPy init_test_impl(HPyContext ctx)
38 {
39 HPyErr_SetString(ctx, ctx->h_RuntimeError, "foo");
40 return HPyLong_FromLong(ctx, 42);
41 }
42 """, name='test')
43
44 def test_import_bad_module(self):
45 import pytest
46 with pytest.raises(SystemError):
47 self.make_module("""
48 HPy_MODINIT(test)
49 static HPy init_test_impl(HPyContext ctx)
50 {
51 return HPy_NULL;
52 }
53 """, name='test')
54
55 def test_HPyModule_Create(self):
56 mod = self.make_module("""
57 HPyDef_METH(f, "f", f_impl, HPyFunc_NOARGS)
58 static HPy f_impl(HPyContext ctx, HPy self)
59 {
60 HPyModuleDef def = {
61 .m_name = "foo",
62 .m_doc = "Some doc",
63 .m_size = -1,
64 };
65 return HPyModule_Create(ctx, &def);
66 }
67 @EXPORT(f)
68 @INIT
69 """)
70 m = mod.f()
71 assert m.__name__ == "foo"
72 assert m.__doc__ == "Some doc"
73 assert m.__package__ is None
74 assert m.__loader__ is None
75 assert m.__spec__ is None
76 assert set(vars(m).keys()) == {
77 '__name__', '__doc__', '__package__', '__loader__', '__spec__'}
3278
3379
3480 class TestExtraCPythonCompatibility(HPyTest):
00 """ The ffi for rpython
11 """
22
3 from rpython.rtyper.lltypesystem import rffi
3 from rpython.rtyper.lltypesystem import rffi, lltype
44 from rpython.rtyper.tool import rffi_platform
55 from rpython.translator.tool.cbuild import ExternalCompilationInfo
66
7474
7575 eci = eci.merge(ExternalCompilationInfo(
7676 post_include_bits=[
77 "RPY_EXTERN char *rpy_curses_setupterm(char *, int);\n"
77 "RPY_EXTERN int rpy_curses_setupterm(char *, int, int *);\n"
7878 "RPY_EXTERN char *rpy_curses_tigetstr(char *);\n"
7979 "RPY_EXTERN char *rpy_curses_tparm(char *, int, int, int, int,"
8080 " int, int, int, int, int);"
8484 %(include_lines)s
8585
8686 RPY_EXTERN
87 char *rpy_curses_setupterm(char *term, int fd)
88 {
89 int errret = -42;
90 if (setupterm(term, fd, &errret) == ERR) {
91 switch (errret) {
92 case 0:
93 return "setupterm: could not find terminal";
94 case -1:
95 return "setupterm: could not find terminfo database";
96 default:
97 return "setupterm: unknown error";
98 }
99 }
100 return NULL;
87 int rpy_curses_setupterm(char *t, int fd, int *errret) {
88 return setupterm(t, fd, errret);
10189 }
10290
10391 RPY_EXTERN
119107 """ % globals()]))
120108
121109
122 rpy_curses_setupterm = rffi.llexternal(
123 "rpy_curses_setupterm", [rffi.CCHARP, rffi.INT], rffi.CCHARP,
124 compilation_info=eci)
110 setupterm = rffi.llexternal(
111 "rpy_curses_setupterm", [rffi.CCHARP, rffi.INT, rffi.INTP],
112 rffi.INT, compilation_info=eci)
125113
126114 rpy_curses_tigetstr = rffi.llexternal(
127115 "rpy_curses_tigetstr", [rffi.CCHARP], rffi.CCHARP,
11 from pypy.interpreter.error import OperationError
22 from pypy.module._minimal_curses import fficurses
33 from rpython.rtyper.lltypesystem import lltype, rffi
4 from rpython.rlib.rarithmetic import r_uint, intmask, widen
45
56
67 class ModuleInfo:
2122
2223 @unwrap_spec(fd=int)
2324 def setupterm(space, w_termname=None, fd=-1):
25 _fd = fd
2426 if fd == -1:
2527 w_stdout = space.getattr(space.getbuiltinmodule('sys'),
2628 space.newtext('stdout'))
27 fd = space.int_w(space.call_function(space.getattr(w_stdout,
29 _fd = space.int_w(space.call_function(space.getattr(w_stdout,
2830 space.newtext('fileno'))))
2931 if space.is_none(w_termname):
3032 termname = None
33 termname_err = 'None'
3134 else:
3235 termname = space.text_w(w_termname)
36 termname_err = "'%s'" % termname
3337
34 with rffi.scoped_str2charp(termname) as ll_term:
35 fd = rffi.cast(rffi.INT, fd)
36 ll_errmsg = fficurses.rpy_curses_setupterm(ll_term, fd)
37 if ll_errmsg:
38 raise curses_error(space, rffi.charp2str(ll_errmsg))
39
38 p_errret = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
39 try:
40 with rffi.scoped_str2charp(termname) as ll_term:
41 _fd = rffi.cast(rffi.INT, _fd)
42 errval = fficurses.setupterm(ll_term, _fd, p_errret)
43
44 if errval == -1:
45 errret = widen(p_errret[0])
46 if errret == 0:
47 msg_ext = 'could not find terminal'
48 elif errret == -1:
49 msg_ext = 'could not find termininfo database'
50 else:
51 msg_ext = 'unknown error'
52 msg = ("setupterm(%s, %d) failed (err=%d): %s" %
53 (termname_err, fd, errret, msg_ext))
54 raise curses_error(space, msg)
55 finally:
56 lltype.free(p_errret, flavor='raw')
4057 space.fromcache(ModuleInfo).setupterm_called = True
4158
4259 @unwrap_spec(capname='text')
8080
8181 def runs_setupterm():
8282 null = lltype.nullptr(rffi.CCHARP.TO)
83 fficurses.rpy_curses_setupterm(null, 1)
83 p_errret = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
84 errval = fficurses.setupterm(null, 1, p_errret)
8485
8586 fn = compile(runs_setupterm, [])
8687 fn()
9192 from pypy.module._minimal_curses import fficurses
9293
9394 def runs_ctgetstr():
95 p_errret = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
9496 with rffi.scoped_str2charp("xterm") as ll_term:
95 fficurses.rpy_curses_setupterm(ll_term, 1)
97 errval = fficurses.setupterm(ll_term, 1, p_errret)
9698 with rffi.scoped_str2charp("cup") as ll_capname:
9799 ll = fficurses.rpy_curses_tigetstr(ll_capname)
98100 return rffi.charp2str(ll)
107109 from pypy.module._minimal_curses import fficurses
108110
109111 def runs_tparm():
112 p_errret = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
110113 with rffi.scoped_str2charp("xterm") as ll_term:
111 fficurses.rpy_curses_setupterm(ll_term, 1)
114 errval = fficurses.setupterm(ll_term, 1, p_errret)
112115 with rffi.scoped_str2charp("cup") as ll_capname:
113116 cup = fficurses.rpy_curses_tigetstr(ll_capname)
114117 res = fficurses.rpy_curses_tparm(cup, 5, 3, 0, 0, 0, 0, 0, 0, 0)
533533 return w_item, n
534534
535535 def sub_get_printable_location(filter_is_callable, use_builder, filter_type, pattern):
536 s = str(pattern)
536 s = str(pattern.pattern)
537537 if len(s) > 120:
538538 s = s[:110] + '...'
539539 if use_builder == '\x00':
551551
552552
553553 def split_get_printable_location(num_groups, ctx_type, pattern):
554 s = str(pattern)
554 s = str(pattern.pattern)
555555 if len(s) > 120:
556556 s = s[:110] + '...'
557557
14331433
14341434
14351435 def mangle_name(prefix, name):
1436 if name.startswith('Py'):
1436 if name.startswith('PyPyUnicode'):
1437 # for PyPyUnicode_Check, PyPyUnicode_CheckExact
1438 return name
1439 elif name.startswith('Py'):
14371440 return prefix + name[2:]
14381441 elif name.startswith('_Py'):
14391442 return '_' + prefix + name[3:]
1010 utf8_encode_utf_32_helper, str_decode_latin_1, utf8_encode_latin_1)
1111 from pypy.objspace.std.unicodeobject import unicodedb
1212 from pypy.module.cpyext.api import (
13 CANNOT_FAIL, Py_ssize_t, Py_TPFLAGS_UNICODE_SUBCLASS, cpython_api,
14 bootstrap_function, CONST_STRING, INTP_real,
13 CANNOT_FAIL, Py_ssize_t, cpython_api,
14 bootstrap_function, CONST_STRING, INTP_real, Py_TPFLAGS_UNICODE_SUBCLASS,
1515 CONST_WSTRING, Py_CLEANUP_SUPPORTED, slot_function, cts, parse_dir,
1616 PyTypeObjectPtr)
1717 from pypy.module.cpyext.pyerrors import PyErr_BadArgument
4646 default_encoding = lltype.malloc(rffi.CCHARP.TO, DEFAULT_ENCODING_SIZE,
4747 flavor='raw', zero=True)
4848
49
5049 WCHAR_KIND = 0
5150 _1BYTE_KIND = 1
5251 _2BYTE_KIND = 2
5958 4: '_4BYTE_KIND',
6059 }
6160
62 def PyUnicode_Check(ref):
61 # Backward compatibility: in PyPy7.3.4 this function became a C macro. But
62 # since we do not change the API, we need to export this function from the
63 # dll/so. This requires giving the mangled name here and special casing it in
64 # mangle_name from api.py
65 @cts.decl("int PyPyUnicode_Check(void * obj)", error=CANNOT_FAIL)
66 def PyUnicode_Check(space, ref):
6367 if not ref:
6468 return False
69 ref = rffi.cast(PyObject, ref)
6570 return (widen(ref.c_ob_type.c_tp_flags) & Py_TPFLAGS_UNICODE_SUBCLASS) != 0
71
72 # Backward compatibility: in PyPy7.3.4 this function became a C macro. But
73 # since we do not change the API, we need to also export this function from the
74 # dll/so. This requires giving the mangled name here and special casing it in
75 # mangle_name from api.py
76 @cts.decl("int PyPyUnicode_CheckExact(void * obj)", error=CANNOT_FAIL)
77 def PyUnicode_CheckExact(space, ref):
78 if not ref:
79 return False
80 w_obj = from_ref(space, rffi.cast(PyObject, ref))
81 w_obj_type = space.type(w_obj)
82 return space.is_w(w_obj_type, space.w_unicode)
83
6684
6785 def new_empty_unicode(space, length):
6886 """
446464 def PyUnicode_AsUnicodeAndSize(space, ref, psize):
447465 """Return a read-only pointer to the Unicode object's internal Py_UNICODE
448466 buffer, NULL if unicode is not a Unicode object."""
449 if not PyUnicode_Check(ref):
467 if not PyUnicode_Check(space, ref):
450468 raise oefmt(space.w_TypeError, "expected unicode object")
451469 if not get_wbuffer(ref):
452470 w_unicode = from_ref(space, rffi.cast(PyObject, ref))
497515
498516 @cts.decl("char * PyUnicode_AsUTF8AndSize(PyObject *unicode, Py_ssize_t *psize)")
499517 def PyUnicode_AsUTF8AndSize(space, ref, psize):
500 if not PyUnicode_Check(ref):
518 if not PyUnicode_Check(space, ref):
501519 PyErr_BadArgument(space)
502520 if not get_ready(ref):
503521 res = _PyUnicode_Ready(space, ref)
556574 return default_encoding
557575
558576 def _unicode_as_encoded_object(space, pyobj, llencoding, llerrors):
559 if not PyUnicode_Check(pyobj):
577 if not PyUnicode_Check(space, pyobj):
560578 PyErr_BadArgument(space)
561579
562580 encoding = errors = None
594612 """Encode a Unicode object using Unicode-Escape and return the result as Python
595613 string object. Error handling is "strict". Return NULL if an exception was
596614 raised by the codec."""
597 if not PyUnicode_Check(pyobj):
615 if not PyUnicode_Check(space, pyobj):
598616 PyErr_BadArgument(space)
599617
600618 w_unicode = from_ref(space, pyobj)
885903 """Encode a Unicode object and return the result as Python
886904 string object. Error handling is "strict". Return NULL if an
887905 exception was raised by the codec."""
888 if not PyUnicode_Check(pyobj):
906 if not PyUnicode_Check(space, pyobj):
889907 PyErr_BadArgument(space)
890908 w_unicode = from_ref(space, pyobj)
891909 return unicodeobject.encode_object(space, w_unicode, encoding, "strict")
13341352 @cts.decl("""Py_ssize_t PyUnicode_FindChar(PyObject *str, Py_UCS4 ch,
13351353 Py_ssize_t start, Py_ssize_t end, int direction)""", error=-1)
13361354 def PyUnicode_FindChar(space, ref, ch, start, end, direction):
1337 if not PyUnicode_Check(ref):
1355 if not PyUnicode_Check(space, ref):
13381356 PyErr_BadArgument(space)
13391357 w_str = from_ref(space, ref)
13401358 ch = widen(ch)
13511369
13521370 @cts.decl("Py_UCS4 PyUnicode_ReadChar(PyObject *unicode, Py_ssize_t index)", error=-1)
13531371 def PyUnicode_ReadChar(space, ref, index):
1354 if not PyUnicode_Check(ref):
1372 if not PyUnicode_Check(space, ref):
13551373 PyErr_BadArgument(space)
13561374 if not get_ready(ref):
13571375 PyErr_BadArgument(space)
13691387 - ref must not have a RPython object
13701388 - ref must not have been processed by _PyUnicode_Ready
13711389 """
1372 if not PyUnicode_Check(ref):
1390 if not PyUnicode_Check(space, ref):
13731391 PyErr_BadArgument(space)
13741392 if index < 0 or index > get_len(ref):
13751393 raise oefmt(space.w_IndexError, "string index out of range")
2727 '_fix_co_filename': 'interp_imp.fix_co_filename',
2828
2929 'source_hash': 'interp_imp.source_hash',
30 'check_hash_based_pycs': 'space.newtext("default")'
30 'check_hash_based_pycs': 'space.newtext("default")',
3131 }
3232
3333 appleveldefs = {
644644 return res
645645 """, [])
646646 assert len([l for l in log.loops if l.chunks[1].bytecode_name.startswith("DescrOperation.contains")]) == 2
647
648 def test_methodcall_kwargs_regression(self):
649 log = self.run("""
650 class A:
651 def f(self, x, y, z):
652 return x + y + z
653 def main():
654 a = A()
655 res = 0
656 for i in range(10000):
657 a.f(x=i, y=i+1, z=i*2) # ID: meth
658 res += i
659 """, [])
660
661 loop, = log.loops_by_id('meth')
662
663 assert loop.match_by_id("meth", """
664 setfield_gc(p15, i65, descr=...)
665 guard_not_invalidated(descr=...)
666 i68 = int_mul_ovf(i62, 2)
667 guard_no_overflow(descr=...)
668 p69 = force_token()
669 """)
670
195195 exc = raises(TypeError, 'sys.flags.optimize = 3')
196196 assert 'readonly' in str(exc.value)
197197 raises(AttributeError, 'sys.flags.not_a_sys_flag = 2')
198
198
199199 def test_sys_exit(self):
200200 import sys
201201 exc = raises(SystemExit, sys.exit)
220220 def test_sys_flags_dev_mode_is_bool(self):
221221 import sys
222222 assert type(sys.flags.dev_mode) is bool
223
224223
225224 class AppTestSysModulePortedFromCPython:
226225 spaceconfig = {
402402
403403 assert (d1 + from_copy) == (d1 + from_compressor)
404404
405 @py.test.mark.skipif(rzlib.ZLIB_VERSION in ('1.2.8', '1.2.3'), reason='does not error check')
405 @py.test.mark.skipif(rzlib.ZLIB_VERSION in ('1.2.7', '1.2.8', '1.2.3'), reason='does not error check')
406406 def test_cannot_copy_compressor_with_stream_in_inconsistent_state(self):
407407 if self.runappdirect: skip("can't run with -A")
408408 compressor = self.zlib.compressobj()
9898
9999 @jit.unroll_safe
100100 def CALL_METHOD_KW(f, n_arguments, *ignored):
101 from pypy.objspace.std.tupleobject import W_AbstractTupleObject
101102 # opargs contains the arg + kwarg count, excluding the implicit 'self'
102103 w_self = f.peekvalue_maybe_none(n_arguments + 1)
103 w_tup_varnames = f.popvalue()
104 keywords_w = f.space.fixedview(w_tup_varnames)
105 n_keywords = len(keywords_w)
104
105 space = f.space
106 # like in BUILD_CONST_KEY_MAP we can't use space.fixedview because then
107 # the immutability of the tuple is lost
108 w_tup_varnames = space.interp_w(W_AbstractTupleObject, f.popvalue())
109 n_keywords = space.len_w(w_tup_varnames)
110 keywords = [None] * n_keywords
111 keywords_w = [None] * n_keywords
112 for i in range(n_keywords):
113 keywords[i] = space.text_w(w_tup_varnames.getitem(space, i))
114 w_value = f.peekvalue(n_keywords - 1 - i)
115 keywords_w[i] = w_value
116 f.dropvalues(n_keywords)
106117 n_arguments -= n_keywords
107118 n = n_arguments + (w_self is not None)
108 keywords = [f.space.text_w(w_keyword) for w_keyword in keywords_w]
109 keywords_w = [None] * n_keywords
110 while True:
111 n_keywords -= 1
112 if n_keywords < 0:
113 break
114 w_value = f.popvalue()
115 keywords_w[n_keywords] = w_value
116
117119 arguments = f.popvalues(n) # includes w_self if it is not None
118120 if w_self is None:
119121 f.popvalue_maybe_none() # removes w_self, which is None
404404 argument reverse. Argument must be unwrapped."""
405405 self.strategy.sort(self, reverse)
406406
407 def physical_size(self):
408 """ return the physical (ie overallocated size) of the underlying list.
409 """
410 # exposed in __pypy__
411 return self.strategy.physical_size(self)
412
407413 # exposed to app-level
408414
409415 @staticmethod
551557
552558 def descr_setitem(self, space, w_index, w_any):
553559 if isinstance(w_index, W_SliceObject):
560 # special case for l[:] = l2
561 if (space.is_w(w_index.w_start, space.w_None) and
562 space.is_w(w_index.w_stop, space.w_None) and
563 space.is_w(w_index.w_step, space.w_None)):
564 if space.is_w(self, w_any):
565 return
566 # use the extend logic
567 self.clear(space)
568 self.extend(w_any)
569 return
570
554571 oldsize = self.length()
555572 start, stop, step, slicelength = w_index.indices4(space, oldsize)
556573 if isinstance(w_any, W_ListObject):
557 self.setslice(start, step, slicelength, w_any)
574 w_other = w_any
558575 else:
559576 sequence_w = space.listview(w_any)
560577 w_other = W_ListObject(space, sequence_w)
561 self.setslice(start, step, slicelength, w_other)
578 self.setslice(start, step, slicelength, w_other)
562579 return
563580
564581 idx = space.getindex_w(w_index, space.w_IndexError, "list")
860877 def is_empty_strategy(self):
861878 return False
862879
880 def physical_size(self, w_list):
881 raise oefmt(self.space.w_ValueError, "can't get physical size of list")
882
863883
864884 class EmptyListStrategy(ListStrategy):
865885 """EmptyListStrategy is used when a W_List withouth elements is created.
10191039
10201040 def is_empty_strategy(self):
10211041 return True
1042
1043 def physical_size(self, w_list):
1044 return 0
10221045
10231046
10241047 class SizeListStrategy(EmptyListStrategy):
15161539 i -= 1
15171540 return
15181541 else:
1519 # Make a shallow copy to more easily handle the reversal case
1520 w_list.reverse()
1542 # other_items is items and step is < 0, therefore:
1543 assert step == -1
1544 items.reverse()
15211545 return
15221546 #other_items = list(other_items)
15231547 for i in range(len2):
15851609
15861610 def reverse(self, w_list):
15871611 self.unerase(w_list.lstorage).reverse()
1612
1613 def physical_size(self, w_list):
1614 from rpython.rlib.objectmodel import list_get_physical_size
1615 l = self.unerase(w_list.lstorage)
1616 return list_get_physical_size(l)
15881617
15891618
15901619 class ObjectListStrategy(ListStrategy):
11721172 logger_copy = set(logger[:]) # prevent re-evaluation during pytest error print
11731173 assert (foo2, foo2_bis) in logger_copy
11741174 assert logger_copy.issubset({(foo1, foo2_bis), (foo2, foo2_bis), (foo3, foo2_bis)})
1175
1176 def test_pickle(self):
1177 d = {1: 1, 2: 2, 3: 3}
1178 it = iter(d)
1179 first = next(it)
1180 reduced = it.__reduce__()
1181 rebuild, args = reduced
1182 new = rebuild(*args)
1183 items = set(new)
1184 assert len(items) == 2
1185 items.add(first)
1186 assert items == set(d)
11751187
11761188
11771189 class AppTestStrategies(object):
11281128 for i in range(count):
11291129 b[i:i+1] = ['y']
11301130 assert b == ['y'] * count
1131
1132 def test_setslice_full(self):
1133 l = [1, 2, 3]
1134 l[::] = "abc"
1135 assert l == ['a', 'b', 'c']
1136
1137 l = [1, 2, 3]
1138 l[::] = []
1139 assert l == []
1140
1141 l = [1, 2, 3]
1142 l[::] = l
1143 assert l == [1, 2, 3]
11311144
11321145 def test_recursive_repr(self):
11331146 l = []
304304
305305 def descr_hash(self, space):
306306 if _unroll_condition(self):
307 return self._descr_hash_unroll(space)
307 res = self._descr_hash_unroll(space)
308308 else:
309 return self._descr_hash_jitdriver(space)
309 res = self._descr_hash_jitdriver(space)
310 return space.newint(res)
310311
311312 @jit.unroll_safe
312313 def _descr_hash_unroll(self, space):
319320 z -= 1
320321 mult += 82520 + z + z
321322 x += 97531
322 return space.newint(intmask(x))
323 return intmask(x)
323324
324325 def _descr_hash_jitdriver(self, space):
325326 mult = 1000003
337338 mult += 82520 + z + z
338339 i += 1
339340 x += 97531
340 return space.newint(intmask(x))
341 return intmask(x)
341342
342343 def descr_eq(self, space, w_other):
343344 if not isinstance(w_other, W_AbstractTupleObject):
3030 raise ValueError(f"'{a}' not in '{b}'")
3131
3232
33
34
35 pypy_versions = {'7.3.3': {'python_version': ['3.7.9', '3.6.12', '2.7.18'],
33 pypy_versions = {
34 '7.3.4rc1': {'python_version': ['3.7.10', '2.7.18'],
35 'date': '2021-03-19',
36 },
37 '7.3.3': {'python_version': ['3.7.9', '3.6.12', '2.7.18'],
3638 'date': '2020-11-21',
3739 },
3840 '7.3.3rc1': {'python_version': ['3.6.12'],
5052 pypy version for that cpython"""
5153 ret = {}
5254 for pypy_ver, vv in v.items():
55 if 'rc' in pypy_ver:
56 # skip release candidates
57 continue
5358 for pv in vv['python_version']:
5459 # for nightlies, we rely on python_version being major.minor while
5560 # for releases python_version is major.minor.patch
6267 latest_pypys = create_latest_versions(pypy_versions)
6368
6469 arches = ['aarch64', 'i686', 'x64', 'x86', 'darwin', 's390x']
65 platforms = ['linux', 'win32', 'darwin']
70 platforms = ['linux', 'win32', 'win64', 'darwin']
6671 arch_map={('aarch64', 'linux'): 'aarch64',
6772 ('i686', 'linux'): 'linux32',
6873 ('x64', 'linux'): 'linux64',
6974 ('s390x', 'linux'): 's390x',
7075 ('x86', 'win32'): 'win32',
76 ('x64', 'win64'): 'win64',
7177 ('x64', 'darwin'): 'osx64',
7278 }
7379
8692 elif d['latest_pypy'] is True:
8793 assert_equal(latest_pypys[d['python_version']], d['pypy_version'])
8894 else:
89 assert_different(latest_pypys[d['python_version']], d['pypy_version'])
95 try:
96 assert_different(latest_pypys[d['python_version']], d['pypy_version'])
97 except KeyError:
98 assert 'rc' in d['pypy_version']
9099 if 'date' in d:
91100 assert_equal(d['date'], v['date'])
92101 for f in d['files']:
4545 RPYTHON_BUILDERS = [
4646 'rpython-linux-x86-32',
4747 'rpython-linux-x86-64',
48 'rpython-win-x86-32'
49 # 'rpython-win-x86-64'
48 # 'rpython-win-x86-32'
49 'rpython-win-x86-64'
5050 ]
5151
5252 def get_user():
252252 os.symlink(POSIX_EXE, 'pypy{}'.format(python_ver))
253253 os.symlink(POSIX_EXE, 'python')
254254 os.symlink(POSIX_EXE, 'python{}'.format(python_ver))
255 os.symlink(POSIX_EXE, 'python{}'.format(python_ver[1]))
255 os.symlink(POSIX_EXE, 'python{}'.format(python_ver[0]))
256256 finally:
257257 os.chdir(old_dir)
258258 fix_permissions(pypydir)
354354 parser.add_argument('--embedded-dependencies', '--no-embedded-dependencies',
355355 dest='embed_dependencies',
356356 action=NegateAction,
357 default=(ARCH in ('darwin', 'aarch64')),
357 default=(ARCH in ('darwin', 'aarch64', 'x86_64')),
358358 help='whether to embed dependencies in CFFI modules '
359359 '(default on OS X)')
360360 parser.add_argument('--make-portable',
11
22 # Edit these appropriately before running this script
33 pmaj=3 # python main version: 2 or 3
4 pmin=6 # python minor version
4 pmin=7 # python minor version
55 maj=7
66 min=3
7 rev=3
8 #rc=rc2 # set to blank for actual release
7 rev=4
8 rc=rc1 # comment this line for actual release
99
1010 function maybe_exit {
1111 if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
4747 function repackage_builds {
4848 # Download latest builds from the buildmaster, rename the top
4949 # level directory, and repackage ready to be uploaded
50 actual_ver=xxxxxxxxxxxxxxx
5150 for plat in linux linux64 osx64 aarch64 s390x # linux-armhf-raspbian linux-armel
5251 do
5352 echo downloading package for $plat
6968 fi
7069 tar -xf pypy-c-jit-latest-$plat.tar.bz2
7170 rm pypy-c-jit-latest-$plat.tar.bz2
71
72 # Check that this is the correct version
73 actual_ver=$(grep PYPY_VERSION pypy-c-jit-*-$plat/include/patchlevel.h |cut -f3 -d' ')
74 if [ $actual_ver != "\"$maj.$min.$rev\"" ]
75 then
76 echo xxxxxxxxxxxxxxxxxxxxxx
77 echo version mismatch, expected "\"$maj.$min.$rev\"", got $actual_ver for $plat
78 echo xxxxxxxxxxxxxxxxxxxxxx
79 exit -1
80 rm -rf pypy-c-jit-*-$plat
81 continue
82 fi
83
84 # Move the files into the correct directory and create the tarball
7285 plat_final=$plat
7386 if [ $plat = linux ]; then
7487 plat_final=linux32
7588 fi
7689 mv pypy-c-jit-*-$plat $rel-$plat_final
77 # TODO: automate the platform choice or move it to the head of the file
78 if [ $plat_final == linux64 ]
79 then
80 actual_ver=`$rel-$plat_final/bin/$exe -c "import sys; print('.'.join([str(x) for x in sys.pypy_version_info[:2]]))"`
81 fi
8290 echo packaging $plat_final
8391 tar --owner=root --group=root --numeric-owner -cjf $rel-$plat_final.tar.bz2 $rel-$plat_final
8492 rm -rf $rel-$plat_final
8593 done
86 if [ "$actual_ver" != "$maj.$min" ]
87 then
88 echo xxxxxxxxxxxxxxxxxxxxxx
89 echo version mismatch, expected $maj.$min, got $actual_ver
90 echo xxxxxxxxxxxxxxxxxxxxxx
91 exit -1
92 rm -rf $rel-$plat_final
93 continue
94 fi
95 plat=win32
96 if wget http://buildbot.pypy.org/nightly/$branchname/pypy-c-jit-latest-$plat.zip
97 then
94 # end of "for" loop
95 for plat in win64 win32
96 do
97 if wget -q --show-progress http://buildbot.pypy.org/nightly/$branchname/pypy-c-jit-latest-$plat.zip
98 then
99 echo $plat downloaded
100 else
101 echo $plat no download available
102 continue
103 fi
98104 unzip -q pypy-c-jit-latest-$plat.zip
99105 rm pypy-c-jit-latest-$plat.zip
106 actual_ver=$(grep PYPY_VERSION pypy-c-jit-*-$plat/include/patchlevel.h |cut -f3 -d' ')
107 if [ $actual_ver != "\"$maj.$min.$rev\"" ]
108 then
109 echo xxxxxxxxxxxxxxxxxxxxxx
110 echo version mismatch, expected "\"$maj.$min.$rev\"", got $actual_ver for $plat
111 echo xxxxxxxxxxxxxxxxxxxxxx
112 rm -rf pypy-c-jit-*-$plat
113 continue
114 fi
100115 mv pypy-c-jit-*-$plat $rel-$plat
101116 zip -rq $rel-$plat.zip $rel-$plat
102117 rm -rf $rel-$plat
103 else
104 echo no download for $plat
105 fi
118 done
119 # end of "for" loop
106120 }
107121
108122 function repackage_source {
00 [
1 {
2 "pypy_version": "7.3.4rc1",
3 "python_version": "3.7.10",
4 "stable": false,
5 "latest_pypy": false,
6 "date": "2021-03-19",
7 "files": [
8 {
9 "filename": "pypy3.7-v7.3.4rc1-aarch64.tar.bz2",
10 "arch": "aarch64",
11 "platform": "linux",
12 "download_url": "https://downloads.python.org/pypy/pypy3.7-v7.3.4rc1-aarch64.tar.bz2"
13 },
14 {
15 "filename": "pypy3.7-v7.3.4rc1-linux32.tar.bz2",
16 "arch": "i686",
17 "platform": "linux",
18 "download_url": "https://downloads.python.org/pypy/pypy3.7-v7.3.4rc1-linux32.tar.bz2"
19 },
20 {
21 "filename": "pypy3.7-v7.3.4rc1-linux64.tar.bz2",
22 "arch": "x64",
23 "platform": "linux",
24 "download_url": "https://downloads.python.org/pypy/pypy3.7-v7.3.4rc1-linux64.tar.bz2"
25 },
26 {
27 "filename": "pypy3.7-v7.3.4rc1-osx64.tar.bz2",
28 "arch": "x64",
29 "platform": "darwin",
30 "download_url": "https://downloads.python.org/pypy/pypy3.7-v7.3.4rc1-osx64.tar.bz2"
31 },
32 {
33 "filename": "pypy3.7-v7.3.4rc1-win64.zip",
34 "arch": "x64",
35 "platform": "win64",
36 "download_url": "https://downloads.python.org/pypy/pypy3.7-v7.3.4rc1-win64.zip"
37 }
38 ]
39 },
40 {
41 "pypy_version": "7.3.4rc1",
42 "python_version": "2.7.18",
43 "stable": false,
44 "latest_pypy": false,
45 "date": "2021-03-19",
46 "files": [
47 {
48 "filename": "pypy2.7-v7.3.4rc1-aarch64.tar.bz2",
49 "arch": "aarch64",
50 "platform": "linux",
51 "download_url": "https://downloads.python.org/pypy/pypy2.7-v7.3.4rc1-aarch64.tar.bz2"
52 },
53 {
54 "filename": "pypy2.7-v7.3.4rc1-linux32.tar.bz2",
55 "arch": "i686",
56 "platform": "linux",
57 "download_url": "https://downloads.python.org/pypy/pypy2.7-v7.3.4rc1-linux32.tar.bz2"
58 },
59 {
60 "filename": "pypy2.7-v7.3.4rc1-linux64.tar.bz2",
61 "arch": "x64",
62 "platform": "linux",
63 "download_url": "https://downloads.python.org/pypy/pypy2.7-v7.3.4rc1-linux64.tar.bz2"
64 },
65 {
66 "filename": "pypy2.7-v7.3.4rc1-osx64.tar.bz2",
67 "arch": "x64",
68 "platform": "darwin",
69 "download_url": "https://downloads.python.org/pypy/pypy2.7-v7.3.4rc1-osx64.tar.bz2"
70 },
71 {
72 "filename": "pypy2.7-v7.3.4rc1-win64.zip",
73 "arch": "x64",
74 "platform": "win64",
75 "download_url": "https://downloads.python.org/pypy/pypy2.7-v7.3.4rc1-win64.zip"
76 }
77 ]
78 },
179 {
280 "pypy_version": "7.3.3",
381 "python_version": "3.6.12",
703703 return self._optimize_oois_ooisnot(op, True, False)
704704
705705 def optimize_INSTANCE_PTR_EQ(self, op):
706 arg0 = get_box_replacement(op.getarg(0))
707 arg1 = get_box_replacement(op.getarg(1))
708 self.pure_from_args(rop.INSTANCE_PTR_EQ, [arg1, arg0], op)
706709 return self._optimize_oois_ooisnot(op, False, True)
707710
708711 def optimize_INSTANCE_PTR_NE(self, op):
712 arg0 = get_box_replacement(op.getarg(0))
713 arg1 = get_box_replacement(op.getarg(1))
714 self.pure_from_args(rop.INSTANCE_PTR_NE, [arg1, arg0], op)
709715 return self._optimize_oois_ooisnot(op, True, True)
710716
711717 def optimize_CALL_N(self, op):
404404 [p0]
405405 guard_class(p0, ConstClass(node_vtable)) []
406406 jump(p0)
407 """
408 self.optimize_loop(ops, expected)
409
410 def test_instance_ptr_eq_is_symmetric(self):
411 ops = """
412 [p0, p1]
413 i0 = instance_ptr_eq(p0, p1)
414 guard_false(i0) []
415 i1 = instance_ptr_eq(p1, p0)
416 guard_false(i1) []
417 jump(p0, p1)
418 """
419 expected = """
420 [p0, p1]
421 i0 = instance_ptr_eq(p0, p1)
422 guard_false(i0) []
423 jump(p0, p1)
424 """
425 self.optimize_loop(ops, expected)
426
427 ops = """
428 [p0, p1]
429 i0 = instance_ptr_ne(p0, p1)
430 guard_true(i0) []
431 i1 = instance_ptr_ne(p1, p0)
432 guard_true(i1) []
433 jump(p0, p1)
434 """
435 expected = """
436 [p0, p1]
437 i0 = instance_ptr_ne(p0, p1)
438 guard_true(i0) []
439 jump(p0, p1)
407440 """
408441 self.optimize_loop(ops, expected)
409442
488488 hop.exception_is_here()
489489 hop.gendirectcall(r_list.LIST._ll_resize_hint, v_list, v_sizehint)
490490
491 def list_get_physical_size(l):
492 """ try to get the physical size of an overallocated RPython list. will
493 return the regular length untranslated. """
494 return len(l)
495
496 def ll_physical_size(l):
497 return len(l.items)
498
499 class Entry(ExtRegistryEntry):
500 _about_ = list_get_physical_size
501
502 def compute_result_annotation(self, s_l):
503 from rpython.annotator import model as annmodel
504 if annmodel.s_None.contains(s_l):
505 pass # first argument is only None so far, but we
506 # expect a generalization later
507 elif not isinstance(s_l, annmodel.SomeList):
508 raise annmodel.AnnotatorError("First argument must be a list")
509 return annmodel.SomeInteger(nonneg=True)
510
511 def specialize_call(self, hop):
512 from rpython.rtyper.lltypesystem.rlist import FixedSizeListRepr, ListRepr
513 v_list, = hop.inputargs(*hop.args_r)
514 if isinstance(hop.args_r[0], ListRepr):
515 ll_func = ll_physical_size
516 else:
517 ll_func = v_list.concretetype.TO.ll_length
518 hop.exception_cannot_occur()
519 return hop.gendirectcall(ll_func, v_list)
520
521
491522 # ____________________________________________________________
492523 #
493524 # id-like functions. The idea is that calling hash() or id() is not
1010 # we print based on indices in 'args'. We first print
1111 # 'ctx.pattern' from the arg number debugprint[0].
1212 pattern = args[debugprint[0]]
13 s = str(pattern)
13 s = str(pattern.pattern)
1414 if len(s) > 120:
1515 s = s[:110] + '...'
1616 if len(debugprint) > 1:
77 iterkeys_with_hash, iteritems_with_hash, contains_with_hash,
88 setitem_with_hash, getitem_with_hash, delitem_with_hash, import_from_mixin,
99 fetch_translated_config, try_inline, delitem_if_value_is, move_to_end,
10 never_allocate, dont_inline)
10 never_allocate, dont_inline, list_get_physical_size)
1111 from rpython.translator.translator import TranslationContext, graphof
1212 from rpython.rtyper.test.tool import BaseRtypingTest
1313 from rpython.rtyper.test.test_llinterp import interpret
589589 r = interpret(f, [29])
590590 assert r == 1
591591
592 def test_list_get_physical_size():
593 def f(z):
594 l = [z, z + 1]
595 if z:
596 l.append(z)
597 return list_get_physical_size(l)
598
599 r = interpret(f, [29])
600 assert r == 6
601
602 # now with fixed-sized list
603 def f(z):
604 l = [z, z + 1]
605 return list_get_physical_size(l)
606
607 r = interpret(f, [29])
608 assert r == 2
609
592610 def test_iterkeys_with_hash():
593611 def f(i):
594612 d = {i + .0: 5, i + .5: 6}