Author: Matti Picus <matti.pi...@gmail.com> Branch: cpyext-ext Changeset: r84851:8e9668880107 Date: 2016-05-31 23:31 +0300 http://bitbucket.org/pypy/pypy/changeset/8e9668880107/
Log: merge default into branch diff too long, truncating to 2000 out of 9846 lines diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -22,3 +22,6 @@ bbd45126bc691f669c4ebdfbd74456cd274c6b92 release-5.0.1 3260adbeba4a8b6659d1cc0d0b41f266769b74da release-5.1 b0a649e90b6642251fb4a765fe5b27a97b1319a9 release-5.1.1 +80ef432a32d9baa4b3c5a54c215e8ebe499f6374 release-5.1.2 +40497617ae91caa1a394d8be6f9cd2de31cb0628 release-pypy3.3-v5.2 +40497617ae91caa1a394d8be6f9cd2de31cb0628 release-pypy3.3-v5.2 diff --git a/lib-python/2.7/subprocess.py b/lib-python/2.7/subprocess.py --- a/lib-python/2.7/subprocess.py +++ b/lib-python/2.7/subprocess.py @@ -834,54 +834,63 @@ c2pread, c2pwrite = None, None errread, errwrite = None, None + ispread = False if stdin is None: p2cread = _subprocess.GetStdHandle(_subprocess.STD_INPUT_HANDLE) if p2cread is None: p2cread, _ = _subprocess.CreatePipe(None, 0) + ispread = True elif stdin == PIPE: p2cread, p2cwrite = _subprocess.CreatePipe(None, 0) + ispread = True elif isinstance(stdin, int): p2cread = msvcrt.get_osfhandle(stdin) else: # Assuming file-like object p2cread = msvcrt.get_osfhandle(stdin.fileno()) - p2cread = self._make_inheritable(p2cread) + p2cread = self._make_inheritable(p2cread, ispread) # We just duplicated the handle, it has to be closed at the end to_close.add(p2cread) if stdin == PIPE: to_close.add(p2cwrite) + ispwrite = False if stdout is None: c2pwrite = _subprocess.GetStdHandle(_subprocess.STD_OUTPUT_HANDLE) if c2pwrite is None: _, c2pwrite = _subprocess.CreatePipe(None, 0) + ispwrite = True elif stdout == PIPE: c2pread, c2pwrite = _subprocess.CreatePipe(None, 0) + ispwrite = True elif isinstance(stdout, int): c2pwrite = msvcrt.get_osfhandle(stdout) else: # Assuming file-like object c2pwrite = msvcrt.get_osfhandle(stdout.fileno()) - c2pwrite = self._make_inheritable(c2pwrite) + c2pwrite = self._make_inheritable(c2pwrite, ispwrite) # We just duplicated the handle, it has to be closed at the end to_close.add(c2pwrite) if stdout == PIPE: to_close.add(c2pread) + ispwrite = False if stderr is None: errwrite = _subprocess.GetStdHandle(_subprocess.STD_ERROR_HANDLE) if errwrite is None: _, errwrite = _subprocess.CreatePipe(None, 0) + ispwrite = True elif stderr == PIPE: errread, errwrite = _subprocess.CreatePipe(None, 0) + ispwrite = True elif stderr == STDOUT: - errwrite = c2pwrite.handle # pass id to not close it + errwrite = c2pwrite elif isinstance(stderr, int): errwrite = msvcrt.get_osfhandle(stderr) else: # Assuming file-like object errwrite = msvcrt.get_osfhandle(stderr.fileno()) - errwrite = self._make_inheritable(errwrite) + errwrite = self._make_inheritable(errwrite, ispwrite) # We just duplicated the handle, it has to be closed at the end to_close.add(errwrite) if stderr == PIPE: @@ -892,13 +901,14 @@ errread, errwrite), to_close - def _make_inheritable(self, handle): + def _make_inheritable(self, handle, close=False): """Return a duplicate of handle, which is inheritable""" dupl = _subprocess.DuplicateHandle(_subprocess.GetCurrentProcess(), handle, _subprocess.GetCurrentProcess(), 0, 1, _subprocess.DUPLICATE_SAME_ACCESS) - # If the initial handle was obtained with CreatePipe, close it. - if not isinstance(handle, int): + # PyPy: If the initial handle was obtained with CreatePipe, + # close it. + if close: handle.Close() return dupl diff --git a/lib-python/2.7/test/test_sys_settrace.py b/lib-python/2.7/test/test_sys_settrace.py --- a/lib-python/2.7/test/test_sys_settrace.py +++ b/lib-python/2.7/test/test_sys_settrace.py @@ -328,8 +328,8 @@ def test_13_genexp(self): if self.using_gc: + gc.enable() test_support.gc_collect() - gc.enable() try: self.run_test(generator_example) # issue1265: if the trace function contains a generator, diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py --- a/lib_pypy/_pypy_interact.py +++ b/lib_pypy/_pypy_interact.py @@ -6,7 +6,7 @@ irc_header = "And now for something completely different" -def interactive_console(mainmodule=None, quiet=False): +def interactive_console(mainmodule=None, quiet=False, future_flags=0): # set sys.{ps1,ps2} just before invoking the interactive interpreter. This # mimics what CPython does in pythonrun.c if not hasattr(sys, 'ps1'): @@ -37,15 +37,17 @@ raise ImportError from pyrepl.simple_interact import run_multiline_interactive_console except ImportError: - run_simple_interactive_console(mainmodule) + run_simple_interactive_console(mainmodule, future_flags=future_flags) else: - run_multiline_interactive_console(mainmodule) + run_multiline_interactive_console(mainmodule, future_flags=future_flags) -def run_simple_interactive_console(mainmodule): +def run_simple_interactive_console(mainmodule, future_flags=0): import code if mainmodule is None: import __main__ as mainmodule console = code.InteractiveConsole(mainmodule.__dict__, filename='<stdin>') + if future_flags: + console.compile.compiler.flags |= future_flags # some parts of code.py are copied here because it seems to be impossible # to start an interactive console without printing at least one line # of banner diff --git a/lib_pypy/_pypy_irc_topic.py b/lib_pypy/_pypy_irc_topic.py --- a/lib_pypy/_pypy_irc_topic.py +++ b/lib_pypy/_pypy_irc_topic.py @@ -224,23 +224,9 @@ va ClCl orvat bayl zbqrengryl zntvp vf n tbbq guvat <psobym> """ -from string import ascii_uppercase, ascii_lowercase - def rot13(data): - """ A simple rot-13 encoder since `str.encode('rot13')` was removed from - Python as of version 3.0. It rotates both uppercase and lowercase letters individually. - """ - total = [] - for char in data: - if char in ascii_uppercase: - index = (ascii_uppercase.find(char) + 13) % 26 - total.append(ascii_uppercase[index]) - elif char in ascii_lowercase: - index = (ascii_lowercase.find(char) + 13) % 26 - total.append(ascii_lowercase[index]) - else: - total.append(char) - return "".join(total) + return ''.join(chr(ord(c)+(13 if 'A'<=c.upper()<='M' else + -13 if 'N'<=c.upper()<='Z' else 0)) for c in data) def some_topic(): import time diff --git a/lib_pypy/_subprocess.py b/lib_pypy/_subprocess.py --- a/lib_pypy/_subprocess.py +++ b/lib_pypy/_subprocess.py @@ -4,6 +4,9 @@ subprocess module on Windows. """ +import sys +if sys.platform != 'win32': + raise ImportError("The '_subprocess' module is only available on Windows") # Declare external Win32 functions diff --git a/lib_pypy/cffi/commontypes.py b/lib_pypy/cffi/commontypes.py --- a/lib_pypy/cffi/commontypes.py +++ b/lib_pypy/cffi/commontypes.py @@ -35,8 +35,11 @@ "you call ffi.set_unicode()" % (commontype,)) else: if commontype == cdecl: - raise api.FFIError("Unsupported type: %r. Please file a bug " - "if you think it should be." % (commontype,)) + raise api.FFIError( + "Unsupported type: %r. Please look at " + "http://cffi.readthedocs.io/en/latest/cdef.html#ffi-cdef-limitations " + "and file an issue if you think this type should really " + "be supported." % (commontype,)) result, quals = parser.parse_type_and_quals(cdecl) # recursive assert isinstance(result, model.BaseTypeByIdentity) diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py --- a/lib_pypy/pyrepl/simple_interact.py +++ b/lib_pypy/pyrepl/simple_interact.py @@ -43,11 +43,13 @@ return short return text -def run_multiline_interactive_console(mainmodule=None): +def run_multiline_interactive_console(mainmodule=None, future_flags=0): import code if mainmodule is None: import __main__ as mainmodule console = code.InteractiveConsole(mainmodule.__dict__, filename='<stdin>') + if future_flags: + console.compile.compiler.flags |= future_flags def more_lines(unicodetext): # ooh, look at the hack: diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst --- a/pypy/doc/build.rst +++ b/pypy/doc/build.rst @@ -70,9 +70,6 @@ bz2 libbz2 -lzma (PyPy3 only) - liblzma - pyexpat libexpat1 @@ -98,11 +95,16 @@ tk tk-dev +lzma (PyPy3 only) + liblzma + +To run untranslated tests, you need the Boehm garbage collector libgc. + On Debian, this is the command to install all build-time dependencies:: apt-get install gcc make libffi-dev pkg-config libz-dev libbz2-dev \ libsqlite3-dev libncurses-dev libexpat1-dev libssl-dev libgdbm-dev \ - tk-dev libgc-dev + tk-dev libgc-dev liblzma-dev For the optional lzma module on PyPy3 you will also need ``liblzma-dev``. diff --git a/pypy/doc/index-of-release-notes.rst b/pypy/doc/index-of-release-notes.rst --- a/pypy/doc/index-of-release-notes.rst +++ b/pypy/doc/index-of-release-notes.rst @@ -49,6 +49,13 @@ release-0.6 +CPython 3.3 compatible versions +------------------------------- + +.. toctree:: + + release-pypy3.3-v5.2-alpha1.rst + CPython 3.2 compatible versions ------------------------------- diff --git a/pypy/doc/release-pypy3.3-v5.2-alpha1.rst b/pypy/doc/release-pypy3.3-v5.2-alpha1.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/release-pypy3.3-v5.2-alpha1.rst @@ -0,0 +1,69 @@ +=================== +PyPy3 v5.2 alpha 1 +=================== + +We're pleased to announce the first alpha release of PyPy3.3 v5.2. This is the +first release of PyPy which targets Python 3.3 (3.3.5) compatibility. + +We would like to thank all of the people who donated_ to the `py3k proposal`_ +for supporting the work that went into this and future releases. + +You can download the PyPy3.3 v5.2 alpha 1 release here: + + http://pypy.org/download.html#python-3-3-5-compatible-pypy3-3-v5-2 + +Highlights +========== + +* Python 3.3.5 support! + + - Being an early alpha release, there are some `missing features`_ such as a + `PEP 393-like space efficient string representation`_ and `known issues`_ + including performance regressions (e.g. issue `#2305`_). The focus for this + release has been updating to 3.3 compatibility. Windows is also not yet + supported. + +* `ensurepip`_ is also included (it's only included in CPython 3 >= 3.4). + +What is PyPy? +============== + +PyPy is a very compliant Python interpreter, almost a drop-in replacement for +CPython 2.7.10 and one day 3.3.5. It's fast due to its integrated tracing JIT +compiler. + +We also welcome developers of other `dynamic languages`_ to see what RPython +can do for them. + +This release supports: + + * **x86** machines on most common operating systems except Windows + (Linux 32/64, Mac OS X 64, OpenBSD, FreeBSD), + + * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux, + + * big- and little-endian variants of **PPC64** running Linux, + + * **s390x** running Linux + +Please try it out and let us know what you think. We welcome feedback, we know +you are using PyPy, please tell us about it! + +We'd especially like to thank these people for their contributions to this +release: + +Manuel Jacob, Ronan Lamy, Mark Young, Amaury Forgeot d'Arc, Philip Jenvey, +Martin Matusiak, Vasily Kuznetsov, Matti Picus, Armin Rigo and many others. + +Cheers + +The PyPy Team + +.. _donated: http://morepypy.blogspot.com/2012/01/py3k-and-numpy-first-stage-thanks-to.html +.. _`py3k proposal`: http://pypy.org/py3donate.html +.. _`PEP 393-like space efficient string representation`: https://bitbucket.org/pypy/pypy/issues/2309/optimized-unicode-representation +.. _`missing features`: https://bitbucket.org/pypy/pypy/issues?status=new&status=open&component=PyPy3+%28running+Python+3.x%29&kind=enhancement +.. _`known issues`: https://bitbucket.org/pypy/pypy/issues?status=new&status=open&component=PyPy3%20%28running%20Python%203.x%29 +.. _`#2305`: https://bitbucket.org/pypy/pypy/issues/2305 +.. _`ensurepip`: https://docs.python.org/3/library/ensurepip.html#module-ensurepip +.. _`dynamic languages`: http://pypyjs.org diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -89,3 +89,40 @@ Use the new rgc.FinalizerQueue mechanism to clean up the handling of ``__del__`` methods. Fixes notably issue #2287. (All RPython subclasses of W_Root need to use FinalizerQueue now.) + +.. branch: ufunc-outer + +Implement ufunc.outer on numpypy + +.. branch: verbose-imports + +Support ``pypy -v``: verbose imports. It does not log as much as +cpython, but it should be enough to help when debugging package layout +problems. + +.. branch: cpyext-macros-cast + +Fix some warnings when compiling CPython C extension modules + +.. branch: syntax_fix + +.. branch: remove-raisingops + +Remove most of the _ovf, _zer and _val operations from RPython. Kills +quite some code internally, and allows the JIT to do better +optimizations: for example, app-level code like ``x / 2`` or ``x % 2`` +can now be turned into ``x >> 1`` or ``x & 1``, even if x is possibly +negative. + +.. branch: cpyext-old-buffers + +Generalize cpyext old-style buffers to more than just str/buffer, add support for mmap + +.. branch: numpy-includes + +Move _numpypy headers into a directory so they are not picked up by upstream numpy, scipy +This allows building upstream numpy and scipy in pypy via cpyext + +.. branch: traceviewer-common-merge-point-formats + +Teach RPython JIT's off-line traceviewer the most common ``debug_merge_point`` formats. \ No newline at end of file diff --git a/pypy/doc/whatsnew-pypy3-5.1.1-alpha1.rst b/pypy/doc/whatsnew-pypy3-5.1.1-alpha1.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/whatsnew-pypy3-5.1.1-alpha1.rst @@ -0,0 +1,10 @@ +================================= +What's new in PyPy3 5.1.1 alpha 1 +================================= + +.. A recent revision, ignoring all other branches for this release +.. startrev: 29d14733e007 + +.. branch: py3.3 + +Python 3.3 compatibility diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst --- a/pypy/doc/windows.rst +++ b/pypy/doc/windows.rst @@ -238,6 +238,15 @@ for use. The release packaging script will pick up the tcltk runtime in the lib directory and put it in the archive. +The lzma compression library +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Python 3.3 ship with CFFI wrappers for the lzma library, which can be +downloaded from this site http://tukaani.org/xz. Python 3.3-3.5 use version +5.0.5, a prebuilt version can be downloaded from +http://tukaani.org/xz/xz-5.0.5-windows.zip, check the signature +http://tukaani.org/xz/xz-5.0.5-windows.zip.sig + Using the mingw compiler ------------------------ diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py --- a/pypy/interpreter/app_main.py +++ b/pypy/interpreter/app_main.py @@ -2,7 +2,7 @@ # This is pure Python code that handles the main entry point into "pypy". # See test/test_app_main. -# Missing vs CPython: -d, -t, -v, -x, -3 +# Missing vs CPython: -d, -t, -x, -3 USAGE1 = __doc__ = """\ Options and arguments (and corresponding environment variables): -B : don't write .py[co] files on import; also PYTHONDONTWRITEBYTECODE=x @@ -19,6 +19,8 @@ -s : don't add user site directory to sys.path; also PYTHONNOUSERSITE -S : don't imply 'import site' on initialization -u : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x +-v : verbose (trace import statements); also PYTHONVERBOSE=x + can be supplied multiple times to increase verbosity -V : print the Python version number and exit (also --version) -W arg : warning control; arg is action:message:category:module:lineno also PYTHONWARNINGS=arg @@ -529,6 +531,7 @@ warnoptions, unbuffered, ignore_environment, + verbose, **ignored): # with PyPy in top of CPython we can only have around 100 # but we need more in the translated PyPy for the compiler package @@ -580,6 +583,12 @@ if hasattr(signal, 'SIGXFSZ'): signal.signal(signal.SIGXFSZ, signal.SIG_IGN) + # Pre-load the default encoder (controlled by PYTHONIOENCODING) now. + # This is needed before someone mucks up with sys.path (or even adds + # a unicode string to it, leading to infinite recursion when we try + # to encode it during importing). Note: very obscure. Issue #2314. + str(u'') + def inspect_requested(): # We get an interactive prompt in one of the following three cases: # @@ -600,6 +609,11 @@ ((inspect or (readenv and real_getenv('PYTHONINSPECT'))) and sys.stdin.isatty())) + try: + from _ast import PyCF_ACCEPT_NULL_BYTES + except ImportError: + PyCF_ACCEPT_NULL_BYTES = 0 + future_flags = [0] success = True try: @@ -610,7 +624,9 @@ @hidden_applevel def run_it(): - exec run_command in mainmodule.__dict__ + co_cmd = compile(run_command, '<module>', 'exec') + exec co_cmd in mainmodule.__dict__ + future_flags[0] = co_cmd.co_flags success = run_toplevel(run_it) elif run_module: # handle the "-m" command @@ -622,11 +638,6 @@ # handle the case where no command/filename/module is specified # on the command-line. - try: - from _ast import PyCF_ACCEPT_NULL_BYTES - except ImportError: - PyCF_ACCEPT_NULL_BYTES = 0 - # update sys.path *after* loading site.py, in case there is a # "site.py" file in the script's directory. Only run this if we're # executing the interactive prompt, if we're running a script we @@ -653,6 +664,7 @@ 'exec', PyCF_ACCEPT_NULL_BYTES) exec co_python_startup in mainmodule.__dict__ + future_flags[0] = co_python_startup.co_flags mainmodule.__file__ = python_startup run_toplevel(run_it) try: @@ -663,11 +675,14 @@ inspect = True else: # If not interactive, just read and execute stdin normally. + if verbose: + print_banner(not no_site) @hidden_applevel def run_it(): co_stdin = compile(sys.stdin.read(), '<stdin>', 'exec', PyCF_ACCEPT_NULL_BYTES) exec co_stdin in mainmodule.__dict__ + future_flags[0] = co_stdin.co_flags mainmodule.__file__ = '<stdin>' success = run_toplevel(run_it) else: @@ -697,7 +712,20 @@ args = (runpy._run_module_as_main, '__main__', False) else: # no. That's the normal path, "pypy stuff.py". - args = (execfile, filename, mainmodule.__dict__) + # This includes the logic from execfile(), tweaked + # to grab the future_flags at the end. + @hidden_applevel + def run_it(): + f = file(filename, 'rU') + try: + source = f.read() + finally: + f.close() + co_main = compile(source.rstrip()+"\n", filename, + 'exec', PyCF_ACCEPT_NULL_BYTES) + exec co_main in mainmodule.__dict__ + future_flags[0] = co_main.co_flags + args = (run_it,) success = run_toplevel(*args) except SystemExit as e: @@ -710,12 +738,21 @@ # start a prompt if requested if inspect_requested(): try: + import __future__ from _pypy_interact import interactive_console pypy_version_info = getattr(sys, 'pypy_version_info', sys.version_info) irc_topic = pypy_version_info[3] != 'final' or ( readenv and os.getenv('PYPY_IRC_TOPIC')) + flags = 0 + for fname in __future__.all_feature_names: + feature = getattr(__future__, fname) + if future_flags[0] & feature.compiler_flag: + flags |= feature.compiler_flag + kwds = {} + if flags: + kwds['future_flags'] = flags success = run_toplevel(interactive_console, mainmodule, - quiet=not irc_topic) + quiet=not irc_topic, **kwds) except SystemExit as e: status = e.code else: @@ -724,10 +761,10 @@ return status def print_banner(copyright): - print 'Python %s on %s' % (sys.version, sys.platform) + print >> sys.stderr, 'Python %s on %s' % (sys.version, sys.platform) if copyright: - print ('Type "help", "copyright", "credits" or ' - '"license" for more information.') + print >> sys.stderr, ('Type "help", "copyright", "credits" or ' + '"license" for more information.') STDLIB_WARNING = """\ debug: WARNING: Library path not found, using compiled-in sys.path. diff --git a/pypy/interpreter/astcompiler/test/test_ast.py b/pypy/interpreter/astcompiler/test/test_ast.py --- a/pypy/interpreter/astcompiler/test/test_ast.py +++ b/pypy/interpreter/astcompiler/test/test_ast.py @@ -1,8 +1,8 @@ from pypy.interpreter.astcompiler import ast class TestAstToObject: def test_types(self, space): - assert space.is_true(space.issubtype( - ast.get(space).w_Module, ast.get(space).w_mod)) + assert space.issubtype_w( + ast.get(space).w_Module, ast.get(space).w_mod) def test_num(self, space): value = space.wrap(42) diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -1215,7 +1215,7 @@ def abstract_issubclass_w(self, w_cls1, w_cls2): # Equivalent to 'issubclass(cls1, cls2)'. - return self.is_true(self.issubtype(w_cls1, w_cls2)) + return self.issubtype_w(w_cls1, w_cls2) def abstract_isinstance_w(self, w_obj, w_cls): # Equivalent to 'isinstance(obj, cls)'. @@ -1237,16 +1237,16 @@ def exception_is_valid_obj_as_class_w(self, w_obj): if not self.isinstance_w(w_obj, self.w_type): return False - return self.is_true(self.issubtype(w_obj, self.w_BaseException)) + return self.issubtype_w(w_obj, self.w_BaseException) def exception_is_valid_class_w(self, w_cls): - return self.is_true(self.issubtype(w_cls, self.w_BaseException)) + return self.issubtype_w(w_cls, self.w_BaseException) def exception_getclass(self, w_obj): return self.type(w_obj) def exception_issubclass_w(self, w_cls1, w_cls2): - return self.is_true(self.issubtype(w_cls1, w_cls2)) + return self.issubtype_w(w_cls1, w_cls2) def new_exception_class(self, *args, **kwargs): "NOT_RPYTHON; convenience method to create excceptions in modules" diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py --- a/pypy/interpreter/executioncontext.py +++ b/pypy/interpreter/executioncontext.py @@ -466,6 +466,13 @@ list = self.fired_actions if list is not None: self.fired_actions = None + # NB. in case there are several actions, we reset each + # 'action._fired' to false only when we're about to call + # 'action.perform()'. This means that if + # 'action.fire()' happens to be called any time before + # the corresponding perform(), the fire() has no + # effect---which is the effect we want, because + # perform() will be called anyway. for action in list: action._fired = False action.perform(ec, frame) diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py --- a/pypy/interpreter/test/test_app_main.py +++ b/pypy/interpreter/test/test_app_main.py @@ -76,6 +76,11 @@ print 'Goodbye2' # should not be reached """) +script_with_future = getscript(""" + from __future__ import division + from __future__ import print_function + """) + class TestParseCommandLine: def check_options(self, options, sys_argv, **expected): @@ -445,6 +450,31 @@ finally: os.environ['PYTHONSTARTUP'] = old + def test_future_in_executed_script(self): + child = self.spawn(['-i', script_with_future]) + child.expect('>>> ') + child.sendline('x=1; print(x/2, 3/4)') + child.expect('0.5 0.75') + + def test_future_in_python_startup(self, monkeypatch): + monkeypatch.setenv('PYTHONSTARTUP', script_with_future) + child = self.spawn([]) + child.expect('>>> ') + child.sendline('x=1; print(x/2, 3/4)') + child.expect('0.5 0.75') + + def test_future_in_cmd(self): + child = self.spawn(['-i', '-c', 'from __future__ import division']) + child.expect('>>> ') + child.sendline('x=1; x/2; 3/4') + child.expect('0.5') + child.expect('0.75') + + def test_cmd_co_name(self): + child = self.spawn(['-c', + 'import sys; print sys._getframe(0).f_code.co_name']) + child.expect('<module>') + def test_ignore_python_inspect(self): os.environ['PYTHONINSPECT_'] = '1' try: diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py --- a/pypy/interpreter/typedef.py +++ b/pypy/interpreter/typedef.py @@ -12,7 +12,8 @@ class TypeDef(object): - def __init__(self, __name, __base=None, __total_ordering__=None, **rawdict): + def __init__(self, __name, __base=None, __total_ordering__=None, + __buffer=None, **rawdict): "NOT_RPYTHON: initialization-time only" self.name = __name if __base is None: @@ -22,6 +23,8 @@ else: bases = [__base] self.bases = bases + assert __buffer in {None, 'read-write', 'read'}, "Unknown value for __buffer" + self.buffer = __buffer self.heaptype = False self.hasdict = '__dict__' in rawdict # no __del__: use an RPython _finalize_() method and register_finalizer diff --git a/pypy/module/__builtin__/__init__.py b/pypy/module/__builtin__/__init__.py --- a/pypy/module/__builtin__/__init__.py +++ b/pypy/module/__builtin__/__init__.py @@ -86,8 +86,8 @@ 'max' : 'functional.max', 'reversed' : 'functional.reversed', 'super' : 'descriptor.W_Super', - 'staticmethod' : 'descriptor.StaticMethod', - 'classmethod' : 'descriptor.ClassMethod', + 'staticmethod' : 'pypy.interpreter.function.StaticMethod', + 'classmethod' : 'pypy.interpreter.function.ClassMethod', 'property' : 'descriptor.W_Property', 'globals' : 'interp_inspect.globals', diff --git a/pypy/module/__builtin__/abstractinst.py b/pypy/module/__builtin__/abstractinst.py --- a/pypy/module/__builtin__/abstractinst.py +++ b/pypy/module/__builtin__/abstractinst.py @@ -76,11 +76,10 @@ w_pretendtype = space.getattr(w_obj, space.wrap('__class__')) if space.is_w(w_pretendtype, space.type(w_obj)): return False # common case: obj.__class__ is type(obj) - if allow_override: - w_result = space.issubtype_allow_override(w_pretendtype, - w_klass_or_tuple) - else: - w_result = space.issubtype(w_pretendtype, w_klass_or_tuple) + if not allow_override: + return space.issubtype_w(w_pretendtype, w_klass_or_tuple) + w_result = space.issubtype_allow_override(w_pretendtype, + w_klass_or_tuple) except OperationError as e: if e.async(space): raise @@ -137,11 +136,9 @@ # -- case (type, type) try: - if allow_override: - w_result = space.issubtype_allow_override(w_derived, - w_klass_or_tuple) - else: - w_result = space.issubtype(w_derived, w_klass_or_tuple) + if not allow_override: + return space.issubtype_w(w_derived, w_klass_or_tuple) + w_result = space.issubtype_allow_override(w_derived, w_klass_or_tuple) except OperationError as e: # if one of the args was not a type, ignore it if not e.match(space, space.w_TypeError): raise # propagate other errors diff --git a/pypy/module/__builtin__/descriptor.py b/pypy/module/__builtin__/descriptor.py --- a/pypy/module/__builtin__/descriptor.py +++ b/pypy/module/__builtin__/descriptor.py @@ -1,31 +1,39 @@ from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter.error import OperationError, oefmt -from pypy.interpreter.function import StaticMethod, ClassMethod -from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault -from pypy.interpreter.typedef import (TypeDef, interp_attrproperty_w, - generic_new_descr) +from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec +from pypy.interpreter.typedef import ( + TypeDef, generic_new_descr, interp_attrproperty_w) from pypy.objspace.descroperation import object_getattribute class W_Super(W_Root): - def __init__(self, space, w_starttype, w_objtype, w_self): + + def __init__(self, space): + self.w_starttype = None + self.w_objtype = None + self.w_self = None + + def descr_init(self, space, w_starttype, w_obj_or_type=None): + if space.is_none(w_obj_or_type): + w_type = None # unbound super object + w_obj_or_type = space.w_None + else: + w_type = _super_check(space, w_starttype, w_obj_or_type) self.w_starttype = w_starttype - self.w_objtype = w_objtype - self.w_self = w_self + self.w_objtype = w_type + self.w_self = w_obj_or_type def get(self, space, w_obj, w_type=None): - w = space.wrap if self.w_self is None or space.is_w(w_obj, space.w_None): - return w(self) + return self else: # if type(self) is W_Super: # XXX write a fast path for this common case - w_selftype = space.type(w(self)) + w_selftype = space.type(self) return space.call_function(w_selftype, self.w_starttype, w_obj) - @unwrap_spec(name=str) - def getattribute(self, space, name): - w = space.wrap + def getattribute(self, space, w_name): + name = space.str_w(w_name) # only use a special logic for bound super objects and not for # getting the __class__ of the super object itself. if self.w_objtype is not None and name != '__class__': @@ -45,44 +53,42 @@ return space.get_and_call_function(w_get, w_value, w_obj, self.w_objtype) # fallback to object.__getattribute__() - return space.call_function(object_getattribute(space), - w(self), w(name)) + return space.call_function(object_getattribute(space), self, w_name) -def descr_new_super(space, w_subtype, w_starttype, w_obj_or_type=None): - if space.is_none(w_obj_or_type): - w_type = None # unbound super object - w_obj_or_type = space.w_None - else: - w_objtype = space.type(w_obj_or_type) - if space.is_true(space.issubtype(w_objtype, space.w_type)) and \ - space.is_true(space.issubtype(w_obj_or_type, w_starttype)): - w_type = w_obj_or_type # special case for class methods - elif space.is_true(space.issubtype(w_objtype, w_starttype)): - w_type = w_objtype # normal case - else: - try: - w_type = space.getattr(w_obj_or_type, space.wrap('__class__')) - except OperationError as o: - if not o.match(space, space.w_AttributeError): - raise - w_type = w_objtype - if not space.is_true(space.issubtype(w_type, w_starttype)): - raise oefmt(space.w_TypeError, - "super(type, obj): obj must be an instance or " - "subtype of type") - # XXX the details of how allocate_instance() should be used are not - # really well defined - w_result = space.allocate_instance(W_Super, w_subtype) - W_Super.__init__(w_result, space, w_starttype, w_type, w_obj_or_type) - return w_result +def _super_check(space, w_starttype, w_obj_or_type): + """Check that the super() call makes sense. Returns a type""" + w_objtype = space.type(w_obj_or_type) + + if (space.issubtype_w(w_objtype, space.w_type) and + space.issubtype_w(w_obj_or_type, w_starttype)): + # special case for class methods + return w_obj_or_type + + if space.issubtype_w(w_objtype, w_starttype): + # normal case + return w_objtype + + try: + w_type = space.getattr(w_obj_or_type, space.wrap('__class__')) + except OperationError as e: + if not e.match(space, space.w_AttributeError): + raise + w_type = w_objtype + + if space.issubtype_w(w_type, w_starttype): + return w_type + raise oefmt(space.w_TypeError, + "super(type, obj): obj must be an instance or subtype of type") W_Super.typedef = TypeDef( 'super', - __new__ = interp2app(descr_new_super), + __new__ = generic_new_descr(W_Super), + __init__ = interp2app(W_Super.descr_init), __thisclass__ = interp_attrproperty_w("w_starttype", W_Super), __getattribute__ = interp2app(W_Super.getattribute), __get__ = interp2app(W_Super.get), - __doc__ = """super(type) -> unbound super object + __doc__ = """\ +super(type) -> unbound super object super(type, obj) -> bound super object; requires isinstance(obj, type) super(type, type2) -> bound super object; requires issubclass(type2, type) @@ -100,10 +106,10 @@ def __init__(self, space): pass - @unwrap_spec(w_fget = WrappedDefault(None), - w_fset = WrappedDefault(None), - w_fdel = WrappedDefault(None), - w_doc = WrappedDefault(None)) + @unwrap_spec(w_fget=WrappedDefault(None), + w_fset=WrappedDefault(None), + w_fdel=WrappedDefault(None), + w_doc=WrappedDefault(None)) def init(self, space, w_fget=None, w_fset=None, w_fdel=None, w_doc=None): self.w_fget = w_fget self.w_fset = w_fset @@ -113,18 +119,17 @@ # our __doc__ comes from the getter if we don't have an explicit one if (space.is_w(self.w_doc, space.w_None) and not space.is_w(self.w_fget, space.w_None)): - w_getter_doc = space.findattr(self.w_fget, space.wrap("__doc__")) + w_getter_doc = space.findattr(self.w_fget, space.wrap('__doc__')) if w_getter_doc is not None: if type(self) is W_Property: self.w_doc = w_getter_doc else: - space.setattr(space.wrap(self), space.wrap("__doc__"), - w_getter_doc) + space.setattr(self, space.wrap('__doc__'), w_getter_doc) self.getter_doc = True def get(self, space, w_obj, w_objtype=None): if space.is_w(w_obj, space.w_None): - return space.wrap(self) + return self if space.is_w(self.w_fget, space.w_None): raise oefmt(space.w_AttributeError, "unreadable attribute") return space.call_function(self.w_fget, w_obj) @@ -162,11 +167,13 @@ else: w_doc = self.w_doc w_type = self.getclass(space) - return space.call_function(w_type, w_getter, w_setter, w_deleter, w_doc) + return space.call_function(w_type, w_getter, w_setter, w_deleter, + w_doc) W_Property.typedef = TypeDef( 'property', - __doc__ = '''property(fget=None, fset=None, fdel=None, doc=None) -> property attribute + __doc__ = '''\ +property(fget=None, fset=None, fdel=None, doc=None) -> property attribute fget is a function to be used for getting an attribute value, and likewise fset is a function for setting, and fdel a function for deleting, an diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py --- a/pypy/module/__builtin__/functional.py +++ b/pypy/module/__builtin__/functional.py @@ -145,8 +145,17 @@ else: compare = space.lt jitdriver = min_jitdriver + any_kwds = bool(args.keywords) args_w = args.arguments_w if len(args_w) > 1: + if unroll and len(args_w) == 2 and not any_kwds: + # a fast path for the common case, useful for interpreted + # mode and to reduce the length of the jit trace + w0, w1 = args_w + if space.is_true(compare(w1, w0)): + return w1 + else: + return w0 w_sequence = space.newtuple(args_w) elif len(args_w): w_sequence = args_w[0] @@ -155,8 +164,8 @@ "%s() expects at least one argument", implementation_of) w_key = None - kwds = args.keywords - if kwds: + if any_kwds: + kwds = args.keywords if kwds[0] == "key" and len(kwds) == 1: w_key = args.keywords_w[0] else: diff --git a/pypy/module/__builtin__/test/test_functional.py b/pypy/module/__builtin__/test/test_functional.py --- a/pypy/module/__builtin__/test/test_functional.py +++ b/pypy/module/__builtin__/test/test_functional.py @@ -296,6 +296,11 @@ assert min([1, 2, 3]) == 1 raises(TypeError, min, 1, 2, bar=2) raises(TypeError, min, 1, 2, key=lambda x: x, bar=2) + assert type(min(1, 1.0)) is int + assert type(min(1.0, 1)) is float + assert type(min(1, 1.0, 1L)) is int + assert type(min(1.0, 1L, 1)) is float + assert type(min(1L, 1, 1.0)) is long def test_max(self): assert max(1, 2) == 2 @@ -303,3 +308,8 @@ assert max([1, 2, 3]) == 3 raises(TypeError, max, 1, 2, bar=2) raises(TypeError, max, 1, 2, key=lambda x: x, bar=2) + assert type(max(1, 1.0)) is int + assert type(max(1.0, 1)) is float + assert type(max(1, 1.0, 1L)) is int + assert type(max(1.0, 1L, 1)) is float + assert type(max(1L, 1, 1.0)) is long diff --git a/pypy/module/__pypy__/interp_intop.py b/pypy/module/__pypy__/interp_intop.py --- a/pypy/module/__pypy__/interp_intop.py +++ b/pypy/module/__pypy__/interp_intop.py @@ -2,6 +2,19 @@ from rpython.rtyper.lltypesystem import lltype from rpython.rtyper.lltypesystem.lloperation import llop from rpython.rlib.rarithmetic import r_uint, intmask +from rpython.rlib import jit + + +# XXX maybe temporary: hide llop.int_{floordiv,mod} from the JIT, +# because now it expects only Python-style divisions, not the +# C-style divisions of these two ll operations +@jit.dont_look_inside +def _int_floordiv(n, m): + return llop.int_floordiv(lltype.Signed, n, m) + +@jit.dont_look_inside +def _int_mod(n, m): + return llop.int_mod(lltype.Signed, n, m) @unwrap_spec(n=int, m=int) @@ -18,11 +31,11 @@ @unwrap_spec(n=int, m=int) def int_floordiv(space, n, m): - return space.wrap(llop.int_floordiv(lltype.Signed, n, m)) + return space.wrap(_int_floordiv(n, m)) @unwrap_spec(n=int, m=int) def int_mod(space, n, m): - return space.wrap(llop.int_mod(lltype.Signed, n, m)) + return space.wrap(_int_mod(n, m)) @unwrap_spec(n=int, m=int) def int_lshift(space, n, m): diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py --- a/pypy/module/__pypy__/interp_magic.py +++ b/pypy/module/__pypy__/interp_magic.py @@ -51,6 +51,11 @@ space.newint(cache.misses.get(name, 0))]) def builtinify(space, w_func): + """To implement at app-level modules that are, in CPython, + implemented in C: this decorator protects a function from being ever + bound like a method. Useful because some tests do things like put + a "built-in" function on a class and access it via the instance. + """ from pypy.interpreter.function import Function, BuiltinFunction func = space.interp_w(Function, w_func) bltn = BuiltinFunction(func) diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py --- a/pypy/module/_cffi_backend/ctypeobj.py +++ b/pypy/module/_cffi_backend/ctypeobj.py @@ -233,10 +233,9 @@ # __________ app-level attributes __________ def dir(self): space = self.space - w_self = space.wrap(self) lst = [space.wrap(name) for name in _name_of_attributes - if space.findattr(w_self, space.wrap(name)) is not None] + if space.findattr(self, space.wrap(name)) is not None] return space.newlist(lst) def _fget(self, attrchar): diff --git a/pypy/module/_cffi_backend/lib_obj.py b/pypy/module/_cffi_backend/lib_obj.py --- a/pypy/module/_cffi_backend/lib_obj.py +++ b/pypy/module/_cffi_backend/lib_obj.py @@ -196,9 +196,13 @@ if is_getattr and attr == '__dict__': return self.full_dict_copy() if is_getattr and attr == '__class__': - return self.space.type(self) + # used to be space.type(self). But HAAAAAACK! + # That makes help() behave correctly. I couldn't + # find a more reasonable way. Urgh. + from pypy.interpreter.module import Module + return self.space.gettypeobject(Module.typedef) if is_getattr and attr == '__name__': - return self.descr_repr() + return self.space.wrap("%s.lib" % self.libname) raise oefmt(self.space.w_AttributeError, "cffi library '%s' has no function, constant " "or global variable named '%s'", diff --git a/pypy/module/_cffi_backend/test/test_recompiler.py b/pypy/module/_cffi_backend/test/test_recompiler.py --- a/pypy/module/_cffi_backend/test/test_recompiler.py +++ b/pypy/module/_cffi_backend/test/test_recompiler.py @@ -1039,8 +1039,8 @@ assert MYFOO == 42 assert hasattr(lib, '__dict__') assert lib.__all__ == ['MYFOO', 'mybar'] # but not 'myvar' - assert lib.__name__ == repr(lib) - assert lib.__class__ is type(lib) + assert lib.__name__ == '_CFFI_test_import_from_lib.lib' + assert lib.__class__ is type(sys) # !! hack for help() def test_macro_var_callback(self): ffi, lib = self.prepare( diff --git a/pypy/module/_collections/interp_deque.py b/pypy/module/_collections/interp_deque.py --- a/pypy/module/_collections/interp_deque.py +++ b/pypy/module/_collections/interp_deque.py @@ -389,20 +389,18 @@ def copy(self): "Return a shallow copy of a deque." space = self.space - w_self = space.wrap(self) if self.maxlen == sys.maxint: - return space.call_function(space.type(w_self), w_self) + return space.call_function(space.type(self), self) else: - return space.call_function(space.type(w_self), w_self, + return space.call_function(space.type(self), self, space.wrap(self.maxlen)) def reduce(self): "Return state information for pickling." space = self.space - w_self = space.wrap(self) - w_type = space.type(w_self) - w_dict = space.findattr(w_self, space.wrap('__dict__')) - w_list = space.call_function(space.w_list, w_self) + w_type = space.type(self) + w_dict = space.findattr(self, space.wrap('__dict__')) + w_list = space.call_function(space.w_list, self) if w_dict is None: if self.maxlen == sys.maxint: result = [ diff --git a/pypy/module/_weakref/interp__weakref.py b/pypy/module/_weakref/interp__weakref.py --- a/pypy/module/_weakref/interp__weakref.py +++ b/pypy/module/_weakref/interp__weakref.py @@ -156,12 +156,12 @@ class W_WeakrefBase(W_Root): - def __init__(w_self, space, w_obj, w_callable): + def __init__(self, space, w_obj, w_callable): assert w_callable is not space.w_None # should be really None - w_self.space = space + self.space = space assert w_obj is not None - w_self.w_obj_weak = weakref.ref(w_obj) - w_self.w_callable = w_callable + self.w_obj_weak = weakref.ref(w_obj) + self.w_callable = w_callable @jit.dont_look_inside def dereference(self): @@ -171,8 +171,8 @@ def clear(self): self.w_obj_weak = dead_ref - def activate_callback(w_self): - w_self.space.call_function(w_self.w_callable, w_self) + def activate_callback(self): + self.space.call_function(self.w_callable, self) def descr__repr__(self, space): w_obj = self.dereference() @@ -189,9 +189,9 @@ class W_Weakref(W_WeakrefBase): - def __init__(w_self, space, w_obj, w_callable): - W_WeakrefBase.__init__(w_self, space, w_obj, w_callable) - w_self.w_hash = None + def __init__(self, space, w_obj, w_callable): + W_WeakrefBase.__init__(self, space, w_obj, w_callable) + self.w_hash = None def descr__init__weakref(self, space, w_obj, w_callable=None, __args__=None): diff --git a/pypy/module/_winreg/interp_winreg.py b/pypy/module/_winreg/interp_winreg.py --- a/pypy/module/_winreg/interp_winreg.py +++ b/pypy/module/_winreg/interp_winreg.py @@ -14,11 +14,13 @@ space.wrap(message)])) class W_HKEY(W_Root): - def __init__(self, hkey): + def __init__(self, space, hkey): self.hkey = hkey + self.space = space + self.register_finalizer(space) - def descr_del(self, space): - self.Close(space) + def _finalize_(self): + self.Close(self.space) def as_int(self): return rffi.cast(rffi.SIZE_T, self.hkey) @@ -64,7 +66,7 @@ @unwrap_spec(key=int) def new_HKEY(space, w_subtype, key): hkey = rffi.cast(rwinreg.HKEY, key) - return space.wrap(W_HKEY(hkey)) + return space.wrap(W_HKEY(space, hkey)) descr_HKEY_new = interp2app(new_HKEY) W_HKEY.typedef = TypeDef( @@ -91,7 +93,6 @@ __int__ - Converting a handle to an integer returns the Win32 handle. __cmp__ - Handle objects are compared using the handle value.""", __new__ = descr_HKEY_new, - __del__ = interp2app(W_HKEY.descr_del), __repr__ = interp2app(W_HKEY.descr_repr), __int__ = interp2app(W_HKEY.descr_int), __nonzero__ = interp2app(W_HKEY.descr_nonzero), @@ -480,7 +481,7 @@ ret = rwinreg.RegCreateKey(hkey, subkey, rethkey) if ret != 0: raiseWindowsError(space, ret, 'CreateKey') - return space.wrap(W_HKEY(rethkey[0])) + return space.wrap(W_HKEY(space, rethkey[0])) @unwrap_spec(subkey=str, res=int, sam=rffi.r_uint) def CreateKeyEx(space, w_hkey, subkey, res=0, sam=rwinreg.KEY_WRITE): @@ -502,7 +503,7 @@ lltype.nullptr(rwin32.LPDWORD.TO)) if ret != 0: raiseWindowsError(space, ret, 'CreateKeyEx') - return space.wrap(W_HKEY(rethkey[0])) + return space.wrap(W_HKEY(space, rethkey[0])) @unwrap_spec(subkey=str) def DeleteKey(space, w_hkey, subkey): @@ -549,7 +550,7 @@ ret = rwinreg.RegOpenKeyEx(hkey, subkey, res, sam, rethkey) if ret != 0: raiseWindowsError(space, ret, 'RegOpenKeyEx') - return space.wrap(W_HKEY(rethkey[0])) + return space.wrap(W_HKEY(space, rethkey[0])) @unwrap_spec(index=int) def EnumValue(space, w_hkey, index): @@ -688,7 +689,7 @@ ret = rwinreg.RegConnectRegistry(machine, hkey, rethkey) if ret != 0: raiseWindowsError(space, ret, 'RegConnectRegistry') - return space.wrap(W_HKEY(rethkey[0])) + return space.wrap(W_HKEY(space, rethkey[0])) @unwrap_spec(source=unicode) def ExpandEnvironmentStrings(space, source): diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -161,12 +161,13 @@ if copy_numpy_headers: try: - dstdir.mkdir('numpy') + dstdir.mkdir('_numpypy') + dstdir.mkdir('_numpypy/numpy') except py.error.EEXIST: pass - numpy_dstdir = dstdir / 'numpy' + numpy_dstdir = dstdir / '_numpypy' / 'numpy' - numpy_include_dir = include_dir / 'numpy' + numpy_include_dir = include_dir / '_numpypy' / 'numpy' numpy_headers = numpy_include_dir.listdir('*.h') + numpy_include_dir.listdir('*.inl') _copy_header_files(numpy_headers, numpy_dstdir) @@ -203,46 +204,46 @@ # id. Invariant: this variable always contain 0 when the PyPy GIL is # released. It should also contain 0 when regular RPython code # executes. In non-cpyext-related code, it will thus always be 0. -# +# # **make_generic_cpy_call():** RPython to C, with the GIL held. Before # the call, must assert that the global variable is 0 and set the # current thread identifier into the global variable. After the call, # assert that the global variable still contains the current thread id, # and reset it to 0. -# +# # **make_wrapper():** C to RPython; by default assume that the GIL is # held, but accepts gil="acquire", "release", "around", # "pygilstate_ensure", "pygilstate_release". -# +# # When a wrapper() is called: -# +# # * "acquire": assert that the GIL is not currently held, i.e. the # global variable does not contain the current thread id (otherwise, # deadlock!). Acquire the PyPy GIL. After we acquired it, assert # that the global variable is 0 (it must be 0 according to the # invariant that it was 0 immediately before we acquired the GIL, # because the GIL was released at that point). -# +# # * gil=None: we hold the GIL already. Assert that the current thread # identifier is in the global variable, and replace it with 0. -# +# # * "pygilstate_ensure": if the global variable contains the current # thread id, replace it with 0 and set the extra arg to 0. Otherwise, # do the "acquire" and set the extra arg to 1. Then we'll call # pystate.py:PyGILState_Ensure() with this extra arg, which will do # the rest of the logic. -# +# # When a wrapper() returns, first assert that the global variable is # still 0, and then: -# +# # * "release": release the PyPy GIL. The global variable was 0 up to # and including at the point where we released the GIL, but afterwards # it is possible that the GIL is acquired by a different thread very # quickly. -# +# # * gil=None: we keep holding the GIL. Set the current thread # identifier into the global variable. -# +# # * "pygilstate_release": if the argument is PyGILState_UNLOCKED, # release the PyPy GIL; otherwise, set the current thread identifier # into the global variable. The rest of the logic of @@ -254,7 +255,7 @@ cpyext_namespace = NameManager('cpyext_') -class ApiFunction: +class ApiFunction(object): def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED, c_name=None, gil=None, result_borrowed=False, result_is_ll=False): self.argtypes = argtypes @@ -292,11 +293,48 @@ def get_wrapper(self, space): wrapper = getattr(self, '_wrapper', None) if wrapper is None: - wrapper = make_wrapper(space, self.callable, self.gil) - self._wrapper = wrapper - wrapper.relax_sig_check = True - if self.c_name is not None: - wrapper.c_name = cpyext_namespace.uniquename(self.c_name) + wrapper = self._wrapper = self._make_wrapper(space) + return wrapper + + # Make the wrapper for the cases (1) and (2) + def _make_wrapper(self, space): + "NOT_RPYTHON" + # This logic is obscure, because we try to avoid creating one + # big wrapper() function for every callable. Instead we create + # only one per "signature". + + argtypesw = zip(self.argtypes, + [_name.startswith("w_") for _name in self.argnames]) + error_value = getattr(self, "error_value", CANNOT_FAIL) + if (isinstance(self.restype, lltype.Ptr) + and error_value is not CANNOT_FAIL): + assert lltype.typeOf(error_value) == self.restype + assert not error_value # only support error=NULL + error_value = 0 # because NULL is not hashable + + if self.result_is_ll: + result_kind = "L" + elif self.result_borrowed: + result_kind = "B" # note: 'result_borrowed' is ignored if we also + else: # say 'result_is_ll=True' (in this case it's + result_kind = "." # up to you to handle refcounting anyway) + + signature = (tuple(argtypesw), + self.restype, + result_kind, + error_value, + self.gil) + + cache = space.fromcache(WrapperCache) + try: + wrapper_gen = cache.wrapper_gens[signature] + except KeyError: + wrapper_gen = WrapperGen(space, signature) + cache.wrapper_gens[signature] = wrapper_gen + wrapper = wrapper_gen.make_wrapper(self.callable) + wrapper.relax_sig_check = True + if self.c_name is not None: + wrapper.c_name = cpyext_namespace.uniquename(self.c_name) return wrapper DEFAULT_HEADER = 'pypy_decl.h' @@ -373,7 +411,16 @@ arg = rffi.cast(ARG, as_pyobj(space, input_arg)) else: arg = rffi.cast(ARG, input_arg) - elif is_PyObject(ARG) and is_wrapped: + elif ARG == rffi.VOIDP and not is_wrapped: + # unlike is_PyObject case above, we allow any kind of + # argument -- just, if it's an object, we assume the + # caller meant for it to become a PyObject*. + if input_arg is None or isinstance(input_arg, W_Root): + keepalives += (input_arg,) + arg = rffi.cast(ARG, as_pyobj(space, input_arg)) + else: + arg = rffi.cast(ARG, input_arg) + elif (is_PyObject(ARG) or ARG == rffi.VOIDP) and is_wrapped: # build a W_Root, possibly from a 'PyObject *' if is_pyobj(input_arg): arg = from_ref(space, input_arg) @@ -660,7 +707,7 @@ w_obj_type = space.type(w_obj) w_type = get_w_type(space) return (space.is_w(w_obj_type, w_type) or - space.is_true(space.issubtype(w_obj_type, w_type))) + space.issubtype_w(w_obj_type, w_type)) def check_exact(space, w_obj): "Implements the Py_Xxx_CheckExact function" w_obj_type = space.type(w_obj) @@ -683,92 +730,61 @@ def __init__(self, space): self.space = space self.wrapper_gens = {} # {signature: WrapperGen()} - self.stats = [0, 0] class WrapperGen(object): wrapper_second_level = None + A = lltype.Array(lltype.Char) def __init__(self, space, signature): self.space = space self.signature = signature - self.callable2name = [] def make_wrapper(self, callable): - self.callable2name.append((callable, callable.__name__)) if self.wrapper_second_level is None: self.wrapper_second_level = make_wrapper_second_level( - self.space, self.callable2name, *self.signature) + self.space, *self.signature) wrapper_second_level = self.wrapper_second_level + name = callable.__name__ + pname = lltype.malloc(self.A, len(name), flavor='raw', immortal=True) + for i in range(len(name)): + pname[i] = name[i] + def wrapper(*args): # no GC here, not even any GC object - args += (callable,) - return wrapper_second_level(*args) + return wrapper_second_level(callable, pname, *args) wrapper.__name__ = "wrapper for %r" % (callable, ) return wrapper -# Make the wrapper for the cases (1) and (2) -def make_wrapper(space, callable, gil=None): - "NOT_RPYTHON" - # This logic is obscure, because we try to avoid creating one - # big wrapper() function for every callable. Instead we create - # only one per "signature". - argnames = callable.api_func.argnames - argtypesw = zip(callable.api_func.argtypes, - [_name.startswith("w_") for _name in argnames]) - error_value = getattr(callable.api_func, "error_value", CANNOT_FAIL) - if (isinstance(callable.api_func.restype, lltype.Ptr) - and error_value is not CANNOT_FAIL): - assert lltype.typeOf(error_value) == callable.api_func.restype - assert not error_value # only support error=NULL - error_value = 0 # because NULL is not hashable - - if callable.api_func.result_is_ll: - result_kind = "L" - elif callable.api_func.result_borrowed: - result_kind = "B" # note: 'result_borrowed' is ignored if we also - else: # say 'result_is_ll=True' (in this case it's - result_kind = "." # up to you to handle refcounting anyway) - - signature = (tuple(argtypesw), - callable.api_func.restype, - result_kind, - error_value, - gil) - - cache = space.fromcache(WrapperCache) - cache.stats[1] += 1 - try: - wrapper_gen = cache.wrapper_gens[signature] - except KeyError: - #print signature - wrapper_gen = cache.wrapper_gens[signature] = WrapperGen(space, - signature) - cache.stats[0] += 1 - #print 'Wrapper cache [wrappers/total]:', cache.stats - return wrapper_gen.make_wrapper(callable) - +@dont_inline +def _unpack_name(pname): + return ''.join([pname[i] for i in range(len(pname))]) @dont_inline def deadlock_error(funcname): + funcname = _unpack_name(funcname) fatalerror_notb("GIL deadlock detected when a CPython C extension " "module calls '%s'" % (funcname,)) @dont_inline def no_gil_error(funcname): + funcname = _unpack_name(funcname) fatalerror_notb("GIL not held when a CPython C extension " "module calls '%s'" % (funcname,)) @dont_inline def not_supposed_to_fail(funcname): - raise SystemError("The function '%s' was not supposed to fail" - % (funcname,)) + funcname = _unpack_name(funcname) + print "Error in cpyext, CPython compatibility layer:" + print "The function", funcname, "was not supposed to fail" + raise SystemError @dont_inline def unexpected_exception(funcname, e, tb): + funcname = _unpack_name(funcname) print 'Fatal error in cpyext, CPython compatibility layer, calling',funcname print 'Either report a bug or consider not using this particular extension' if not we_are_translated(): @@ -784,7 +800,7 @@ pypy_debug_catch_fatal_exception() assert False -def make_wrapper_second_level(space, callable2name, argtypesw, restype, +def make_wrapper_second_level(space, argtypesw, restype, result_kind, error_value, gil): from rpython.rlib import rgil argtypes_enum_ui = unrolling_iterable(enumerate(argtypesw)) @@ -807,29 +823,19 @@ def invalid(err): "NOT_RPYTHON: translation-time crash if this ends up being called" raise ValueError(err) - invalid.__name__ = 'invalid_%s' % (callable2name[0][1],) - def nameof(callable): - for c, n in callable2name: - if c is callable: - return n - return '<unknown function>' - nameof._dont_inline_ = True - - def wrapper_second_level(*args): + def wrapper_second_level(callable, pname, *args): from pypy.module.cpyext.pyobject import make_ref, from_ref, is_pyobj from pypy.module.cpyext.pyobject import as_pyobj # we hope that malloc removal removes the newtuple() that is # inserted exactly here by the varargs specializer - callable = args[-1] - args = args[:-1] # see "Handling of the GIL" above (careful, we don't have the GIL here) tid = rthread.get_or_make_ident() _gil_auto = (gil_auto_workaround and cpyext_glob_tid_ptr[0] != tid) if gil_acquire or _gil_auto: if cpyext_glob_tid_ptr[0] == tid: - deadlock_error(nameof(callable)) + deadlock_error(pname) rgil.acquire() assert cpyext_glob_tid_ptr[0] == 0 elif pygilstate_ensure: @@ -842,7 +848,7 @@ args += (pystate.PyGILState_UNLOCKED,) else: if cpyext_glob_tid_ptr[0] != tid: - no_gil_error(nameof(callable)) + no_gil_error(pname) cpyext_glob_tid_ptr[0] = 0 rffi.stackcounter.stacks_counter += 1 @@ -859,6 +865,10 @@ if is_PyObject(typ) and is_wrapped: assert is_pyobj(arg) arg_conv = from_ref(space, rffi.cast(PyObject, arg)) + elif typ == rffi.VOIDP and is_wrapped: + # Many macros accept a void* so that one can pass a + # PyObject* or a PySomeSubtype*. + arg_conv = from_ref(space, rffi.cast(PyObject, arg)) else: arg_conv = arg boxed_args += (arg_conv, ) @@ -888,7 +898,7 @@ if failed: if error_value is CANNOT_FAIL: - raise not_supposed_to_fail(nameof(callable)) + raise not_supposed_to_fail(pname) retval = error_value elif is_PyObject(restype): @@ -908,7 +918,7 @@ retval = rffi.cast(restype, result) except Exception as e: - unexpected_exception(nameof(callable), e, tb) + unexpected_exception(pname, e, tb) return fatal_value assert lltype.typeOf(retval) == restype @@ -1019,7 +1029,7 @@ structindex = {} for header, header_functions in FUNCTIONS_BY_HEADER.iteritems(): for name, func in header_functions.iteritems(): - if not func: + if not func: # added only for the macro, not the decl continue restype, args = c_function_signature(db, func) @@ -1033,7 +1043,7 @@ RPY_EXTERN struct PyPyAPI* pypyAPI = &_pypyAPI; """ % dict(members=structmembers) - functions = generate_decls_and_callbacks(db, export_symbols, + functions = generate_decls_and_callbacks(db, export_symbols, prefix='cpyexttest') global_objects = [] @@ -1415,7 +1425,7 @@ generate_macros(export_symbols, prefix=prefix) - functions = generate_decls_and_callbacks(db, [], api_struct=False, + functions = generate_decls_and_callbacks(db, [], api_struct=False, prefix=prefix) code = "#include <Python.h>\n" if use_micronumpy: @@ -1471,7 +1481,7 @@ if not func: continue newname = mangle_name('PyPy', name) or name - deco = entrypoint_lowlevel("cpyext", func.argtypes, newname, + deco = entrypoint_lowlevel("cpyext", func.argtypes, newname, relax=True) deco(func.get_wrapper(space)) diff --git a/pypy/module/cpyext/cdatetime.py b/pypy/module/cpyext/cdatetime.py --- a/pypy/module/cpyext/cdatetime.py +++ b/pypy/module/cpyext/cdatetime.py @@ -1,4 +1,5 @@ from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rtyper.annlowlevel import llhelper from pypy.module.cpyext.pyobject import PyObject, make_ref from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, cpython_struct, PyObjectFields) @@ -16,6 +17,23 @@ ('TimeType', PyTypeObjectPtr), ('DeltaType', PyTypeObjectPtr), ('TZInfoType', PyTypeObjectPtr), + + ('Date_FromDate', lltype.Ptr(lltype.FuncType( + [rffi.INT_real, rffi.INT_real, rffi.INT_real, PyTypeObjectPtr], + PyObject))), + ('Time_FromTime', lltype.Ptr(lltype.FuncType( + [rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, + PyObject, PyTypeObjectPtr], + PyObject))), + ('DateTime_FromDateAndTime', lltype.Ptr(lltype.FuncType( + [rffi.INT_real, rffi.INT_real, rffi.INT_real, + rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, + PyObject, PyTypeObjectPtr], + PyObject))), + ('Delta_FromDelta', lltype.Ptr(lltype.FuncType( + [rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, + PyTypeObjectPtr], + PyObject))), )) @cpython_api([], lltype.Ptr(PyDateTime_CAPI)) @@ -45,6 +63,19 @@ datetimeAPI.c_TZInfoType = rffi.cast( PyTypeObjectPtr, make_ref(space, w_type)) + datetimeAPI.c_Date_FromDate = llhelper( + _PyDate_FromDate.api_func.functype, + _PyDate_FromDate.api_func.get_wrapper(space)) + datetimeAPI.c_Time_FromTime = llhelper( + _PyTime_FromTime.api_func.functype, + _PyTime_FromTime.api_func.get_wrapper(space)) + datetimeAPI.c_DateTime_FromDateAndTime = llhelper( + _PyDateTime_FromDateAndTime.api_func.functype, + _PyDateTime_FromDateAndTime.api_func.get_wrapper(space)) + datetimeAPI.c_Delta_FromDelta = llhelper( + _PyDelta_FromDelta.api_func.functype, + _PyDelta_FromDelta.api_func.get_wrapper(space)) + return datetimeAPI PyDateTime_DateStruct = lltype.ForwardReference() @@ -94,36 +125,40 @@ make_check_function("PyDelta_Check", "timedelta") make_check_function("PyTZInfo_Check", "tzinfo") -# Constructors +# Constructors. They are better used as macros. -@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDate_FromDate(space, year, month, day): +@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, PyTypeObjectPtr], + PyObject) +def _PyDate_FromDate(space, year, month, day, w_type): """Return a datetime.date object with the specified year, month and day. """ year = rffi.cast(lltype.Signed, year) month = rffi.cast(lltype.Signed, month) day = rffi.cast(lltype.Signed, day) - w_datetime = PyImport_Import(space, space.wrap("datetime")) - return space.call_method( - w_datetime, "date", + return space.call_function( + w_type, space.wrap(year), space.wrap(month), space.wrap(day)) -@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyTime_FromTime(space, hour, minute, second, usecond): +@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, + PyObject, PyTypeObjectPtr], PyObject) +def _PyTime_FromTime(space, hour, minute, second, usecond, w_tzinfo, w_type): """Return a ``datetime.time`` object with the specified hour, minute, second and microsecond.""" hour = rffi.cast(lltype.Signed, hour) minute = rffi.cast(lltype.Signed, minute) second = rffi.cast(lltype.Signed, second) usecond = rffi.cast(lltype.Signed, usecond) - w_datetime = PyImport_Import(space, space.wrap("datetime")) - return space.call_method( - w_datetime, "time", + return space.call_function( + w_type, space.wrap(hour), space.wrap(minute), space.wrap(second), - space.wrap(usecond)) + space.wrap(usecond), w_tzinfo) -@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDateTime_FromDateAndTime(space, year, month, day, hour, minute, second, usecond): +@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, + rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, + PyObject, PyTypeObjectPtr], PyObject) +def _PyDateTime_FromDateAndTime(space, year, month, day, + hour, minute, second, usecond, + w_tzinfo, w_type): """Return a datetime.datetime object with the specified year, month, day, hour, minute, second and microsecond. """ @@ -134,12 +169,11 @@ minute = rffi.cast(lltype.Signed, minute) second = rffi.cast(lltype.Signed, second) usecond = rffi.cast(lltype.Signed, usecond) - w_datetime = PyImport_Import(space, space.wrap("datetime")) - return space.call_method( - w_datetime, "datetime", + return space.call_function( + w_type, space.wrap(year), space.wrap(month), space.wrap(day), space.wrap(hour), space.wrap(minute), space.wrap(second), - space.wrap(usecond)) + space.wrap(usecond), w_tzinfo) @cpython_api([PyObject], PyObject) def PyDateTime_FromTimestamp(space, w_args): @@ -161,8 +195,10 @@ w_method = space.getattr(w_type, space.wrap("fromtimestamp")) return space.call(w_method, w_args) -@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject) -def PyDelta_FromDSU(space, days, seconds, useconds): +@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, + PyTypeObjectPtr], + PyObject) +def _PyDelta_FromDelta(space, days, seconds, useconds, normalize, w_type): """Return a datetime.timedelta object representing the given number of days, seconds and microseconds. Normalization is performed so that the resulting number of microseconds and seconds lie in the ranges documented for @@ -171,74 +207,73 @@ days = rffi.cast(lltype.Signed, days) seconds = rffi.cast(lltype.Signed, seconds) useconds = rffi.cast(lltype.Signed, useconds) - w_datetime = PyImport_Import(space, space.wrap("datetime")) - return space.call_method( - w_datetime, "timedelta", + return space.call_function( + w_type, space.wrap(days), space.wrap(seconds), space.wrap(useconds)) # Accessors -@cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) +@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL) def PyDateTime_GET_YEAR(space, w_obj): """Return the year, as a positive int. """ return space.int_w(space.getattr(w_obj, space.wrap("year"))) -@cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) +@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL) def PyDateTime_GET_MONTH(space, w_obj): """Return the month, as an int from 1 through 12. """ return space.int_w(space.getattr(w_obj, space.wrap("month"))) -@cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL) +@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL) def PyDateTime_GET_DAY(space, w_obj): """Return the day, as an int from 1 through 31. """ return space.int_w(space.getattr(w_obj, space.wrap("day"))) -@cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL) def PyDateTime_DATE_GET_HOUR(space, w_obj): """Return the hour, as an int from 0 through 23. """ return space.int_w(space.getattr(w_obj, space.wrap("hour"))) -@cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL) def PyDateTime_DATE_GET_MINUTE(space, w_obj): """Return the minute, as an int from 0 through 59. """ return space.int_w(space.getattr(w_obj, space.wrap("minute"))) -@cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL) def PyDateTime_DATE_GET_SECOND(space, w_obj): """Return the second, as an int from 0 through 59. """ return space.int_w(space.getattr(w_obj, space.wrap("second"))) -@cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL) +@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL) def PyDateTime_DATE_GET_MICROSECOND(space, w_obj): """Return the microsecond, as an int from 0 through 999999. """ return space.int_w(space.getattr(w_obj, space.wrap("microsecond"))) -@cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL) def PyDateTime_TIME_GET_HOUR(space, w_obj): """Return the hour, as an int from 0 through 23. """ return space.int_w(space.getattr(w_obj, space.wrap("hour"))) -@cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL) def PyDateTime_TIME_GET_MINUTE(space, w_obj): """Return the minute, as an int from 0 through 59. """ return space.int_w(space.getattr(w_obj, space.wrap("minute"))) -@cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL) def PyDateTime_TIME_GET_SECOND(space, w_obj): """Return the second, as an int from 0 through 59. """ return space.int_w(space.getattr(w_obj, space.wrap("second"))) -@cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL) +@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL) def PyDateTime_TIME_GET_MICROSECOND(space, w_obj): """Return the microsecond, as an int from 0 through 999999. """ @@ -248,14 +283,14 @@ # But it does not seem possible to expose a different structure # for types defined in a python module like lib/datetime.py. -@cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL) +@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL) def PyDateTime_DELTA_GET_DAYS(space, w_obj): return space.int_w(space.getattr(w_obj, space.wrap("days"))) -@cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL) +@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL) def PyDateTime_DELTA_GET_SECONDS(space, w_obj): return space.int_w(space.getattr(w_obj, space.wrap("seconds"))) -@cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL) +@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL) def PyDateTime_DELTA_GET_MICROSECONDS(space, w_obj): return space.int_w(space.getattr(w_obj, space.wrap("microseconds"))) diff --git a/pypy/module/cpyext/floatobject.py b/pypy/module/cpyext/floatobject.py --- a/pypy/module/cpyext/floatobject.py +++ b/pypy/module/cpyext/floatobject.py @@ -48,7 +48,7 @@ def PyFloat_AsDouble(space, w_obj): return space.float_w(space.float(w_obj)) -@cpython_api([PyObject], lltype.Float, error=CANNOT_FAIL) +@cpython_api([rffi.VOIDP], lltype.Float, error=CANNOT_FAIL) def PyFloat_AS_DOUBLE(space, w_float): """Return a C double representation of the contents of w_float, but without error checking.""" diff --git a/pypy/module/cpyext/include/numpy/README b/pypy/module/cpyext/include/_numpypy/numpy/README rename from pypy/module/cpyext/include/numpy/README rename to pypy/module/cpyext/include/_numpypy/numpy/README diff --git a/pypy/module/cpyext/include/numpy/__multiarray_api.h b/pypy/module/cpyext/include/_numpypy/numpy/__multiarray_api.h rename from pypy/module/cpyext/include/numpy/__multiarray_api.h rename to pypy/module/cpyext/include/_numpypy/numpy/__multiarray_api.h diff --git a/pypy/module/cpyext/include/numpy/arrayobject.h b/pypy/module/cpyext/include/_numpypy/numpy/arrayobject.h rename from pypy/module/cpyext/include/numpy/arrayobject.h rename to pypy/module/cpyext/include/_numpypy/numpy/arrayobject.h diff --git a/pypy/module/cpyext/include/numpy/ndarraytypes.h b/pypy/module/cpyext/include/_numpypy/numpy/ndarraytypes.h rename from pypy/module/cpyext/include/numpy/ndarraytypes.h rename to pypy/module/cpyext/include/_numpypy/numpy/ndarraytypes.h diff --git a/pypy/module/cpyext/include/numpy/npy_3kcompat.h b/pypy/module/cpyext/include/_numpypy/numpy/npy_3kcompat.h rename from pypy/module/cpyext/include/numpy/npy_3kcompat.h rename to pypy/module/cpyext/include/_numpypy/numpy/npy_3kcompat.h diff --git a/pypy/module/cpyext/include/numpy/npy_common.h b/pypy/module/cpyext/include/_numpypy/numpy/npy_common.h rename from pypy/module/cpyext/include/numpy/npy_common.h rename to pypy/module/cpyext/include/_numpypy/numpy/npy_common.h diff --git a/pypy/module/cpyext/include/numpy/old_defines.h b/pypy/module/cpyext/include/_numpypy/numpy/old_defines.h rename from pypy/module/cpyext/include/numpy/old_defines.h rename to pypy/module/cpyext/include/_numpypy/numpy/old_defines.h diff --git a/pypy/module/cpyext/include/cStringIO.h b/pypy/module/cpyext/include/cStringIO.h new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/include/cStringIO.h @@ -0,0 +1,73 @@ +#ifndef Py_CSTRINGIO_H +#define Py_CSTRINGIO_H +#ifdef __cplusplus +extern "C" { +#endif +/* + + This header provides access to cStringIO objects from C. + Functions are provided for calling cStringIO objects and + macros are provided for testing whether you have cStringIO + objects. + + Before calling any of the functions or macros, you must initialize + the routines with: + + PycString_IMPORT + + This would typically be done in your init function. + +*/ + +#define PycStringIO_CAPSULE_NAME "cStringIO.cStringIO_CAPI" + +#define PycString_IMPORT \ + PycStringIO = ((struct PycStringIO_CAPI*)PyCapsule_Import(\ + PycStringIO_CAPSULE_NAME, 0)) + +/* Basic functions to manipulate cStringIO objects from C */ + +static struct PycStringIO_CAPI { + + /* Read a string from an input object. If the last argument + is -1, the remainder will be read. + */ + int(*cread)(PyObject *, char **, Py_ssize_t); + + /* Read a line from an input object. Returns the length of the read + line as an int and a pointer inside the object buffer as char** (so + the caller doesn't have to provide its own buffer as destination). + */ + int(*creadline)(PyObject *, char **); + + /* Write a string to an output object*/ + int(*cwrite)(PyObject *, const char *, Py_ssize_t); + + /* Get the output object as a Python string (returns new reference). */ + PyObject *(*cgetvalue)(PyObject *); + + /* Create a new output object */ + PyObject *(*NewOutput)(int); + + /* Create an input object from a Python string + (copies the Python string reference). + */ + PyObject *(*NewInput)(PyObject *); + + /* The Python types for cStringIO input and output objects. + Note that you can do input on an output object. + */ + PyTypeObject *InputType, *OutputType; + +} *PycStringIO; + +/* These can be used to test if you have one */ +#define PycStringIO_InputCheck(O) \ + (0) /* Py_TYPE(O)==PycStringIO->InputType) */ +#define PycStringIO_OutputCheck(O) \ + (0) /* Py_TYPE(O)==PycStringIO->OutputType) */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_CSTRINGIO_H */ diff --git a/pypy/module/cpyext/include/datetime.h b/pypy/module/cpyext/include/datetime.h --- a/pypy/module/cpyext/include/datetime.h +++ b/pypy/module/cpyext/include/datetime.h @@ -12,6 +12,13 @@ PyTypeObject *TimeType; PyTypeObject *DeltaType; _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit