Author: Matti Picus <[email protected]>
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
[email protected]_look_inside
+def _int_floordiv(n, m):
+ return llop.int_floordiv(lltype.Signed, n, m)
+
[email protected]_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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit