Author: Richard Plangger <[email protected]>
Branch: py3.5-memoryview
Changeset: r86390:cb2cf459a284
Date: 2016-08-22 09:27 +0200
http://bitbucket.org/pypy/pypy/changeset/cb2cf459a284/
Log: merge py3.5
diff too long, truncating to 2000 out of 3687 lines
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -99,14 +99,16 @@
RegrTest('test___all__.py', core=True),
RegrTest('test___future__.py', core=True),
RegrTest('test__locale.py', usemodules='_locale'),
+ RegrTest('test__opcode.py'),
RegrTest('test__osx_support.py'),
RegrTest('test_abc.py'),
RegrTest('test_abstract_numbers.py'),
RegrTest('test_aifc.py'),
RegrTest('test_argparse.py', usemodules='binascii'),
RegrTest('test_array.py', core=True, usemodules='struct array binascii'),
+ RegrTest('test_asdl_parser.py'),
RegrTest('test_ast.py', core=True, usemodules='struct'),
- RegrTest('test_asynchat.py', usemodules='select fcntl'),
+ RegrTest('test_asynchat.py', usemodules='select fcntl', skip="XXX:
deadlocks or takes forever"),
RegrTest('test_asyncore.py', usemodules='select fcntl'),
RegrTest('test_atexit.py', core=True),
RegrTest('test_audioop.py'),
@@ -123,7 +125,7 @@
RegrTest('test_bufio.py', core=True),
RegrTest('test_builtin.py', core=True, usemodules='binascii'),
RegrTest('test_bytes.py', usemodules='struct binascii'),
- RegrTest('test_bz2.py', usemodules='bz2'),
+ RegrTest('test_bz2.py', usemodules='bz2', skip="XXX: deadlocks?"),
RegrTest('test_calendar.py'),
RegrTest('test_call.py', core=True),
RegrTest('test_capi.py', usemodules='cpyext'),
@@ -134,7 +136,7 @@
RegrTest('test_cmath.py', core=True),
RegrTest('test_cmd.py'),
RegrTest('test_cmd_line.py'),
- RegrTest('test_cmd_line_script.py'),
+ RegrTest('test_cmd_line_script.py', skip="XXX: deadlocks?"),
RegrTest('test_code.py', core=True),
RegrTest('test_code_module.py'),
RegrTest('test_codeccallbacks.py', core=True),
@@ -151,20 +153,19 @@
RegrTest('test_codecmaps_tw.py', usemodules='_multibytecodec'),
RegrTest('test_codecs.py', core=True, usemodules='_multibytecodec struct
unicodedata array'),
RegrTest('test_codeop.py', core=True),
- RegrTest('test_coding.py', core=True),
RegrTest('test_collections.py', usemodules='binascii struct'),
RegrTest('test_colorsys.py'),
RegrTest('test_compare.py', core=True),
RegrTest('test_compile.py', core=True),
RegrTest('test_compileall.py'),
RegrTest('test_complex.py', core=True),
- RegrTest('test_concurrent_futures.py',
- skip="XXX: deadlocks" if sys.platform == 'win32' else False),
+ RegrTest('test_concurrent_futures.py', skip="XXX: deadlocks" if
sys.platform == 'win32' else False),
RegrTest('test_configparser.py'),
RegrTest('test_contains.py', core=True),
RegrTest('test_contextlib.py', usemodules="thread"),
RegrTest('test_copy.py', core=True),
RegrTest('test_copyreg.py', core=True),
+ RegrTest('test_coroutines.py'),
RegrTest('test_cprofile.py'),
RegrTest('test_crashers.py'),
RegrTest('test_crypt.py', usemodules='crypt'),
@@ -176,7 +177,7 @@
RegrTest('test_dbm_dumb.py'),
RegrTest('test_dbm_gnu.py'),
RegrTest('test_dbm_ndbm.py'),
- RegrTest('test_decimal.py'),
+ RegrTest('test_decimal.py', skip="XXX: deadlocks?"),
RegrTest('test_decorators.py', core=True),
RegrTest('test_defaultdict.py', usemodules='_collections'),
RegrTest('test_deque.py', core=True, usemodules='_collections struct'),
@@ -195,8 +196,11 @@
RegrTest('test_dummy_thread.py', core=True),
RegrTest('test_dummy_threading.py', core=True),
RegrTest('test_dynamic.py'),
+ RegrTest('test_dynamicclassattribute.py'),
+ RegrTest('test_eintr.py'),
RegrTest('test_email', skip="XXX is a directory"),
RegrTest('test_ensurepip.py'),
+ RegrTest('test_enum.py'),
RegrTest('test_enumerate.py', core=True),
RegrTest('test_eof.py', core=True),
RegrTest('test_epoll.py'),
@@ -204,23 +208,24 @@
RegrTest('test_exception_variations.py'),
RegrTest('test_exceptions.py', core=True),
RegrTest('test_extcall.py', core=True),
- RegrTest('test_faulthandler.py'),
+ RegrTest('test_faulthandler.py', skip="XXX: deadlocks?"),
RegrTest('test_fcntl.py', usemodules='fcntl'),
RegrTest('test_file.py', usemodules="posix", core=True),
RegrTest('test_file_eintr.py'),
RegrTest('test_filecmp.py', core=True),
RegrTest('test_fileinput.py', core=True),
RegrTest('test_fileio.py'),
+ RegrTest('test_finalization.py'),
RegrTest('test_float.py', core=True),
RegrTest('test_flufl.py'),
RegrTest('test_fnmatch.py', core=True),
- RegrTest('test_fork1.py', usemodules="thread"),
+ RegrTest('test_fork1.py', usemodules="thread", skip="XXX: deadlocks?"),
RegrTest('test_format.py', core=True),
RegrTest('test_fractions.py'),
- RegrTest('test_frozen.py', skip="unsupported extension module"),
- RegrTest('test_ftplib.py'),
+ RegrTest('test_frame.py'),
+ RegrTest('test_ftplib.py', skip="XXX: deadlocks?"),
RegrTest('test_funcattrs.py', core=True),
- RegrTest('test_functools.py'),
+ RegrTest('test_functools.py', skip="XXX: deadlocks?"),
RegrTest('test_future.py', core=True),
RegrTest('test_future3.py', core=True),
RegrTest('test_future4.py', core=True),
@@ -250,11 +255,9 @@
RegrTest('test_httplib.py'),
RegrTest('test_httpservers.py'),
RegrTest('test_idle.py'),
- RegrTest('test_imaplib.py'),
+ RegrTest('test_imaplib.py', skip="XXX: deadlocks?"),
RegrTest('test_imghdr.py'),
RegrTest('test_imp.py', core=True, usemodules='thread'),
- RegrTest('test_import.py', core=True),
- RegrTest('test_importhooks.py', core=True),
RegrTest('test_importlib', 'XXX is a directory'),
RegrTest('test_index.py'),
RegrTest('test_inspect.py', usemodules="struct unicodedata"),
@@ -268,6 +271,7 @@
RegrTest('test_iterlen.py', core=True, usemodules="_collections
itertools"),
RegrTest('test_itertools.py', core=True, usemodules="itertools struct"),
RegrTest('test_json', skip="XXX is a directory"),
+ RegrTest('test_keyword.py'),
RegrTest('test_keywordonlyarg.py'),
RegrTest('test_kqueue.py'),
RegrTest('test_largefile.py'),
@@ -296,8 +300,10 @@
RegrTest('test_modulefinder.py'),
RegrTest('test_msilib.py'),
RegrTest('test_multibytecodec.py', usemodules='_multibytecodec'),
- RegrTest('test_multiprocessing.py', skip="XXX: deadlocks the buildbots"),
- RegrTest('test_namespace_pkgs.py'),
+ RegrTest('test_multiprocessing_fork.py', skip="XXX: deadlocks?"),
+ RegrTest('test_multiprocessing_forkserver.py', skip="XXX: deadlocks?"),
+ RegrTest('test_multiprocessing_main_handling.py', skip="XXX: deadlocks?"),
+ RegrTest('test_multiprocessing_spawn.py', skip="XXX: deadlocks?"),
RegrTest('test_netrc.py'),
RegrTest('test_nis.py'),
RegrTest('test_nntplib.py'),
@@ -312,10 +318,10 @@
RegrTest('test_ossaudiodev.py'),
RegrTest('test_osx_env.py'),
RegrTest('test_parser.py', skip="slowly deprecating compiler"),
- RegrTest('test_pdb.py'),
+ RegrTest('test_pathlib.py'),
+ RegrTest('test_pdb.py', skip="XXX: deadlocks?"),
RegrTest('test_peepholer.py'),
RegrTest('test_pep247.py'),
- RegrTest('test_pep263.py'),
RegrTest('test_pep277.py'),
RegrTest('test_pep292.py'),
RegrTest('test_pep3120.py'),
@@ -323,6 +329,7 @@
RegrTest('test_pep3151.py'),
RegrTest('test_pep352.py'),
RegrTest('test_pep380.py'),
+ RegrTest('test_pep479.py'),
RegrTest('test_pickle.py', core=True),
RegrTest('test_pickletools.py', core=False),
RegrTest('test_pipes.py'),
@@ -331,9 +338,9 @@
RegrTest('test_pkgutil.py'),
RegrTest('test_platform.py'),
RegrTest('test_plistlib.py'),
- RegrTest('test_poll.py'),
+ RegrTest('test_poll.py', skip="XXX: deadlocks?"),
RegrTest('test_popen.py'),
- RegrTest('test_poplib.py'),
+ RegrTest('test_poplib.py', skip="XXX: deadlocks?"),
RegrTest('test_posix.py', usemodules="_rawffi"),
RegrTest('test_posixpath.py'),
RegrTest('test_pow.py', core=True),
@@ -356,6 +363,7 @@
RegrTest('test_range.py', core=True),
RegrTest('test_re.py', core=True),
RegrTest('test_readline.py'),
+ RegrTest('test_regrtest.py'),
RegrTest('test_reprlib.py', core=True),
RegrTest('test_resource.py'),
RegrTest('test_richcmp.py', core=True),
@@ -365,7 +373,9 @@
RegrTest('test_sax.py'),
RegrTest('test_sched.py'),
RegrTest('test_scope.py', core=True),
+ RegrTest('test_script_helper.py'),
RegrTest('test_select.py'),
+ RegrTest('test_selectors.py'),
RegrTest('test_set.py', core=True),
RegrTest('test_setcomps.py', core=True),
RegrTest('test_shelve.py'),
@@ -381,10 +391,13 @@
RegrTest('test_socket.py', usemodules='thread _weakref'),
RegrTest('test_socketserver.py', usemodules='thread'),
RegrTest('test_sort.py', core=True),
- RegrTest('test_sqlite.py', usemodules="thread _rawffi zlib"),
+ RegrTest('test_source_encoding.py'),
+ RegrTest('test_spwd.py'),
+ RegrTest('test_sqlite.py', usemodules="thread _rawffi zlib", skip="XXX:
deadlocks?"),
RegrTest('test_ssl.py', usemodules='_ssl _socket select'),
RegrTest('test_startfile.py'),
RegrTest('test_stat.py'),
+ RegrTest('test_statistics.py'),
RegrTest('test_strftime.py'),
RegrTest('test_string.py', core=True),
RegrTest('test_stringprep.py'),
@@ -394,13 +407,13 @@
RegrTest('test_struct.py', usemodules='struct'),
RegrTest('test_structmembers.py', skip="CPython specific"),
RegrTest('test_structseq.py'),
- RegrTest('test_subprocess.py', usemodules='signal'),
+ RegrTest('test_subprocess.py', usemodules='signal', skip="XXX:
deadlocks?"),
RegrTest('test_sunau.py'),
RegrTest('test_sundry.py'),
RegrTest('test_super.py', core=True),
RegrTest('test_support.py'),
RegrTest('test_symtable.py', skip="implementation detail"),
- RegrTest('test_syntax.py', core=True),
+ RegrTest('test_syntax.py', core=True, skip="XXX: infinite loop?"),
RegrTest('test_sys.py', core=True, usemodules='struct'),
RegrTest('test_sys_setprofile.py', core=True),
RegrTest('test_sys_settrace.py', core=True),
@@ -408,29 +421,30 @@
RegrTest('test_syslog.py'),
RegrTest('test_tarfile.py'),
RegrTest('test_tcl.py'),
- RegrTest('test_telnetlib.py'),
+ RegrTest('test_telnetlib.py', skip="XXX: deadlocks?"),
RegrTest('test_tempfile.py'),
RegrTest('test_textwrap.py'),
RegrTest('test_thread.py', usemodules="thread", core=True),
- RegrTest('test_threaded_import.py', usemodules="thread", core=True),
- RegrTest('test_threadedtempfile.py',
- usemodules="thread", core=False),
- RegrTest('test_threading.py', usemodules="thread", core=True),
- RegrTest('test_threading_local.py', usemodules="thread", core=True),
+ RegrTest('test_threaded_import.py', usemodules="thread", core=True,
skip="XXX: deadlocks?"),
+ RegrTest('test_threadedtempfile.py', usemodules="thread", core=False,
skip="XXX: deadlocks?"),
+ RegrTest('test_threading.py', usemodules="thread", core=True, skip="XXX:
deadlocks?"),
+ RegrTest('test_threading_local.py', usemodules="thread", core=True,
skip="XXX: deadlocks?"),
RegrTest('test_threadsignals.py', usemodules="thread"),
RegrTest('test_time.py', core=True, usemodules="struct thread _rawffi"),
RegrTest('test_timeit.py'),
RegrTest('test_timeout.py'),
+ RegrTest('test_tix.py'),
RegrTest('test_tk.py'),
RegrTest('test_tokenize.py'),
- RegrTest('test_tools.py'),
RegrTest('test_trace.py'),
RegrTest('test_traceback.py', core=True),
+ RegrTest('test_tracemalloc.py'),
RegrTest('test_ttk_guionly.py'),
RegrTest('test_ttk_textonly.py'),
RegrTest('test_tuple.py', core=True),
RegrTest('test_typechecks.py'),
RegrTest('test_types.py', core=True),
+ RegrTest('test_typing.py'),
RegrTest('test_ucn.py'),
RegrTest('test_unary.py', core=True),
RegrTest('test_unicode.py', core=True),
@@ -455,7 +469,6 @@
RegrTest('test_venv.py', usemodules="struct"),
RegrTest('test_wait3.py', usemodules="thread"),
RegrTest('test_wait4.py', usemodules="thread"),
- RegrTest('test_warnings.py', core=True),
RegrTest('test_wave.py'),
RegrTest('test_weakref.py', core=True, usemodules='_weakref'),
RegrTest('test_weakset.py'),
@@ -470,8 +483,9 @@
RegrTest('test_xml_etree_c.py'),
RegrTest('test_xmlrpc.py'),
RegrTest('test_xmlrpc_net.py'),
+ RegrTest('test_zipapp.py'),
RegrTest('test_zipfile.py'),
- RegrTest('test_zipfile64.py'),
+ RegrTest('test_zipfile64.py', skip="XXX: infinite loop or just long
time?"),
RegrTest('test_zipimport.py', usemodules='zlib zipimport'),
RegrTest('test_zipimport_support.py', usemodules='zlib zipimport'),
RegrTest('test_zlib.py', usemodules='zlib'),
diff --git a/lib_pypy/resource.py b/lib_pypy/resource.py
--- a/lib_pypy/resource.py
+++ b/lib_pypy/resource.py
@@ -86,7 +86,11 @@
if len(limits) != 2:
raise ValueError("expected a tuple of 2 integers")
- if lib.my_setrlimit(resource, limits[0], limits[1]) == -1:
+ # accept and round down floats, like CPython does
+ limit0 = int(limits[0])
+ limit1 = int(limits[1])
+
+ if lib.my_setrlimit(resource, limit0, limit1) == -1:
if ffi.errno == EINVAL:
raise ValueError("current limit exceeds maximum limit")
elif ffi.errno == EPERM:
diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst
--- a/pypy/doc/faq.rst
+++ b/pypy/doc/faq.rst
@@ -356,6 +356,11 @@
that a C-level traceback is usually of no help at all in PyPy.
Debugging PyPy can be annoying.
+`This is a clear and useful bug report.`__ (Admittedly, sometimes
+the problem is really hard to reproduce, but please try to.)
+
+.. __:
https://bitbucket.org/pypy/pypy/issues/2363/segfault-in-gc-pinned-object-in
+
In more details:
* First, please give the exact PyPy version, and the OS.
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
@@ -128,3 +128,19 @@
.. branch: cpyext-realloc
Implement PyObject_Realloc
+
+.. branch: inline-blocks
+
+Improve a little bit the readability of the generated C code
+
+.. branch: improve-vmprof-testing
+
+Improved vmprof support: now tries hard to not miss any Python-level
+frame in the captured stacks, even if there is the metainterp or
+blackhole interp involved. Also fix the stacklet (greenlet) support.
+
+.. branch: py2-mappingproxy
+
+``type.__dict__`` now returns a ``dict_proxy`` object, like on CPython.
+Previously it returned what looked like a regular dict object (but it
+was already read-only).
diff --git a/pypy/interpreter/astcompiler/assemble.py
b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -389,7 +389,8 @@
def _stacksize(self, blocks):
"""Compute co_stacksize."""
for block in blocks:
- block.initial_depth = 0
+ block.initial_depth = -99
+ blocks[0].initial_depth = 0
# Assumes that it is sufficient to walk the blocks in 'post-order'.
# This means we ignore all back-edges, but apart from that, we only
# look into a block when all the previous blocks have been done.
@@ -397,9 +398,17 @@
for block in blocks:
depth = self._do_stack_depth_walk(block)
if block.auto_inserted_return and depth != 0:
- os.write(2, "StackDepthComputationError in %s at %s:%s\n" % (
- self.compile_info.filename, self.name, self.first_lineno))
- raise StackDepthComputationError # fatal error
+ # This case occurs if this code object uses some
+ # construction for which the stack depth computation
+ # is wrong (too high). If you get here while working
+ # on the astcompiler, then you should at first ignore
+ # the error, and comment out the 'raise' below. Such
+ # an error is not really bad: it is just a bit
+ # wasteful. For release-ready versions, though, we'd
+ # like not to be wasteful. :-)
+ os.write(2, "StackDepthComputationError(POS) in %s at %s:%s\n"
+ % (self.compile_info.filename, self.name, self.first_lineno))
+ raise StackDepthComputationError # would-be-nice-not-to-have
return self._max_depth
def _next_stack_depth_walk(self, nextblock, depth):
@@ -408,8 +417,20 @@
def _do_stack_depth_walk(self, block):
depth = block.initial_depth
+ if depth == -99: # this block is never reached, skip
+ return 0
for instr in block.instructions:
depth += _opcode_stack_effect(instr.opcode, instr.arg)
+ if depth < 0:
+ # This is really a fatal error, don't comment out this
+ # 'raise'. It means that the stack depth computation
+ # thinks there is a path that yields a negative stack
+ # depth, which means that it underestimates the space
+ # needed and it would crash when interpreting this
+ # code.
+ os.write(2, "StackDepthComputationError(NEG) in %s at %s:%s\n"
+ % (self.compile_info.filename, self.name, self.first_lineno))
+ raise StackDepthComputationError # really fatal error
if depth >= self._max_depth:
self._max_depth = depth
jump_op = instr.opcode
@@ -560,7 +581,6 @@
ops.LIST_APPEND: -1,
ops.SET_ADD: -1,
ops.MAP_ADD: -2,
- # XXX
ops.BINARY_POWER: -1,
ops.BINARY_MULTIPLY: -1,
@@ -602,8 +622,8 @@
ops.PRINT_EXPR: -1,
- ops.WITH_CLEANUP_START: -1,
- ops.WITH_CLEANUP_FINISH: -1, # XXX Sometimes more
+ ops.WITH_CLEANUP_START: 1,
+ ops.WITH_CLEANUP_FINISH: -2,
ops.LOAD_BUILD_CLASS: 1,
ops.POP_BLOCK: 0,
ops.POP_EXCEPT: -1,
@@ -619,7 +639,6 @@
ops.YIELD_FROM: -1,
ops.COMPARE_OP: -1,
- # TODO
ops.LOOKUP_METHOD: 1,
ops.LOAD_NAME: 1,
diff --git a/pypy/interpreter/astcompiler/codegen.py
b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -599,17 +599,21 @@
b_try_cleanup = self.new_block()
b_after_loop = self.new_block()
b_after_loop_else = self.new_block()
+
self.emit_jump(ops.SETUP_LOOP, b_after_loop)
self.push_frame_block(F_BLOCK_LOOP, b_try)
+
fr.iter.walkabout(self)
self.emit_op(ops.GET_AITER)
self.load_const(self.space.w_None)
self.emit_op(ops.YIELD_FROM)
+
self.use_next_block(b_try)
# This adds another line, so each for iteration can be traced.
self.lineno_set = False
self.emit_jump(ops.SETUP_EXCEPT, b_except)
self.push_frame_block(F_BLOCK_EXCEPT, b_try)
+
self.emit_op(ops.GET_ANEXT)
self.load_const(self.space.w_None)
self.emit_op(ops.YIELD_FROM)
@@ -617,9 +621,10 @@
self.emit_op(ops.POP_BLOCK)
self.pop_frame_block(F_BLOCK_EXCEPT, b_try)
self.emit_jump(ops.JUMP_FORWARD, b_after_try)
+
self.use_next_block(b_except)
- self.emit_op(ops.POP_TOP)
- self.emit_op_name(ops.LOAD_GLOBAL, self.names, "StopIterError")
+ self.emit_op(ops.DUP_TOP)
+ self.emit_op_name(ops.LOAD_GLOBAL, self.names, "StopAsyncIteration")
self.emit_op_arg(ops.COMPARE_OP, 10)
self.emit_jump(ops.POP_JUMP_IF_FALSE, b_try_cleanup, True)
@@ -627,18 +632,29 @@
self.emit_op(ops.POP_TOP)
self.emit_op(ops.POP_TOP)
self.emit_op(ops.POP_EXCEPT) # for SETUP_EXCEPT
+ # Manually remove the 'aiter' object from the valuestack.
+ # This POP_TOP is not needed from the point of view of
+ # pyopcode.py, which will pop anything to match the stack
+ # depth of the SETUP_LOOP, but it is needed to make
+ # PythonCodeMaker._stacksize() compute an exact result and not
+ # crash with StackDepthComputationError.
+ self.emit_op(ops.POP_TOP)
self.emit_op(ops.POP_BLOCK) # for SETUP_LOOP
self.emit_jump(ops.JUMP_ABSOLUTE, b_after_loop_else, True)
self.use_next_block(b_try_cleanup)
self.emit_op(ops.END_FINALLY)
+
self.use_next_block(b_after_try)
self.visit_sequence(fr.body)
self.emit_jump(ops.JUMP_ABSOLUTE, b_try, True)
+
self.emit_op(ops.POP_BLOCK) # for SETUP_LOOP
self.pop_frame_block(F_BLOCK_LOOP, b_try)
+
self.use_next_block(b_after_loop)
self.emit_jump(ops.JUMP_ABSOLUTE, b_end, True)
+
self.use_next_block(b_after_loop_else)
self.visit_sequence(fr.orelse)
diff --git a/pypy/interpreter/astcompiler/optimize.py
b/pypy/interpreter/astcompiler/optimize.py
--- a/pypy/interpreter/astcompiler/optimize.py
+++ b/pypy/interpreter/astcompiler/optimize.py
@@ -118,7 +118,7 @@
# don't constant-fold if "w_left" and "w_right" are integers and
# the estimated bit length of the power is unreasonably large
space.appexec([w_left, w_right], """(left, right):
- if isinstance(left, (int, long)) and isinstance(right, (int, long)):
+ if isinstance(left, int) and isinstance(right, int):
if left.bit_length() * right > 5000:
raise OverflowError
""")
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py
b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -511,6 +511,9 @@
x *= 7
""", 'x', 42
+ def test_with_stacksize_bug(self):
+ compile_with_astcompiler("with a:\n pass", 'exec', self.space)
+
def test_with_bug(self):
yield self.simple_test, """
class ContextManager:
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1749,6 +1749,23 @@
"Python int too large for C unsigned short")
return value
+ def c_uid_t_w(self, w_obj):
+ # xxx assumes that uid_t and gid_t are a C unsigned int.
+ # Equivalent to space.c_uint_w(), with the exception that
+ # it also accepts -1 and converts that to UINT_MAX, which
+ # is (uid_t)-1. And values smaller than -1 raise
+ # OverflowError, not ValueError.
+ try:
+ return self.c_uint_w(w_obj)
+ except OperationError as e:
+ if e.match(self, self.w_ValueError):
+ # ValueError: cannot convert negative integer to unsigned
+ if self.int_w(w_obj) == -1:
+ return UINT_MAX
+ raise oefmt(self.w_OverflowError,
+ "user/group id smaller than minimum (-1)")
+ raise
+
def truncatedint_w(self, w_obj, allow_conversion=True):
# Like space.gateway_int_w(), but return the integer truncated
# instead of raising OverflowError. For obscure cases only.
@@ -1937,6 +1954,7 @@
'PendingDeprecationWarning',
'ReferenceError',
'ResourceWarning',
+ 'RecursionError',
'RuntimeError',
'RuntimeWarning',
'StopIteration',
diff --git a/pypy/interpreter/eval.py b/pypy/interpreter/eval.py
--- a/pypy/interpreter/eval.py
+++ b/pypy/interpreter/eval.py
@@ -40,9 +40,6 @@
and possibly more locals."""
return self.signature().getallvarnames()
- def getformalargcount(self):
- return self.signature().scope_length()
-
def getdocstring(self, space):
return space.w_None
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -38,7 +38,9 @@
'name?',
'w_kw_defs?']
- def __init__(self, space, code, w_globals=None, defs_w=[], w_kw_defs=None,
+ w_kw_defs = None
+
+ def __init__(self, space, code, w_globals=None, defs_w=[], kw_defs_w=None,
closure=None, w_ann=None, forcename=None, qualname=None):
self.space = space
self.name = forcename or code.co_name
@@ -48,10 +50,12 @@
self.w_func_globals = w_globals # the globals dictionary
self.closure = closure # normally, list of Cell instances or None
self.defs_w = defs_w
- self.w_kw_defs = w_kw_defs
self.w_func_dict = None # filled out below if needed
self.w_module = None
self.w_ann = w_ann
+ #
+ if kw_defs_w is not None:
+ self.init_kwdefaults_dict(kw_defs_w)
def __repr__(self):
# return "function %s.%s" % (self.space, self.name)
@@ -379,14 +383,23 @@
def fset_func_kwdefaults(self, space, w_new):
if space.is_w(w_new, space.w_None):
- w_new = None
- elif not space.isinstance_w(w_new, space.w_dict):
- raise oefmt(space.w_TypeError, "__kwdefaults__ must be a dict")
- self.w_kw_defs = w_new
+ self.w_kw_defs = None
+ else:
+ if not space.isinstance_w(w_new, space.w_dict):
+ raise oefmt(space.w_TypeError, "__kwdefaults__ must be a dict")
+ self.w_kw_defs = w_new
def fdel_func_kwdefaults(self, space):
self.w_kw_defs = None
+ def init_kwdefaults_dict(self, kw_defs_w):
+ # use the moduledict logic to get normally-constant entries
+ space = self.space
+ w_dict = space.newdict(module=True)
+ for w_name, w_value in kw_defs_w:
+ space.setitem(w_dict, w_name, w_value)
+ self.w_kw_defs = w_dict
+
def fget_func_doc(self, space):
if self.w_doc is None:
self.w_doc = self.code.getdocstring(space)
@@ -663,10 +676,12 @@
def __init__(self, func):
assert isinstance(func, Function)
Function.__init__(self, func.space, func.code, func.w_func_globals,
- func.defs_w, None, func.closure, None, func.name)
+ func.defs_w, None, func.closure,
+ None, func.name)
self.w_doc = func.w_doc
self.w_func_dict = func.w_func_dict
self.w_module = func.w_module
+ self.w_kw_defs = func.w_kw_defs
def descr_builtinfunction__new__(space, w_subtype):
raise oefmt(space.w_TypeError,
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -28,6 +28,8 @@
from rpython.rlib.rarithmetic import r_longlong, r_int, r_ulonglong, r_uint
from rpython.tool.sourcetools import func_with_new_name, compile2
+NO_DEFAULT = object()
+
# internal non-translatable parts:
class SignatureBuilder(object):
@@ -44,12 +46,21 @@
self.argnames = argnames
self.varargname = varargname
self.kwargname = kwargname
+ self.kwonlyargnames = None
def append(self, argname):
- self.argnames.append(argname)
+ if self.kwonlyargnames is None:
+ self.argnames.append(argname)
+ else:
+ self.kwonlyargnames.append(argname)
+
+ def marker_kwonly(self):
+ assert self.kwonlyargnames is None
+ self.kwonlyargnames = []
def signature(self):
- return Signature(self.argnames, self.varargname, self.kwargname)
+ return Signature(self.argnames, self.varargname, self.kwargname,
+ self.kwonlyargnames)
#________________________________________________________________
@@ -66,13 +77,6 @@
"""NOT_RPYTHON"""
raise NotImplementedError
-def kwonly(arg_unwrapper):
- """Mark argument as keyword-only.
-
- XXX: has no actual effect for now.
- """
- return arg_unwrapper
-
class UnwrapSpecRecipe(object):
"NOT_RPYTHON"
@@ -177,6 +181,9 @@
def visit_c_ushort(self, el, app_sig):
self.checked_space_method(el, app_sig)
+ def visit_c_uid_t(self, el, app_sig):
+ self.checked_space_method(el, app_sig)
+
def visit_truncatedint_w(self, el, app_sig):
self.checked_space_method(el, app_sig)
@@ -226,6 +233,11 @@
name = int_unwrapping_space_method(typ)
self.checked_space_method(name, app_sig)
+ def visit_kwonly(self, _, app_sig):
+ argname = self.orig_arg()
+ assert argname == '__kwonly__'
+ app_sig.marker_kwonly()
+
class UnwrapSpec_EmitRun(UnwrapSpecEmit):
@@ -307,9 +319,15 @@
def visit_c_ushort(self, typ):
self.run_args.append("space.c_ushort_w(%s)" % (self.scopenext(),))
+ def visit_c_uid_t(self, typ):
+ self.run_args.append("space.c_uid_t_w(%s)" % (self.scopenext(),))
+
def visit_truncatedint_w(self, typ):
self.run_args.append("space.truncatedint_w(%s)" % (self.scopenext(),))
+ def visit_kwonly(self, typ):
+ self.run_args.append("None")
+
def _make_unwrap_activation_class(self, unwrap_spec, cache={}):
try:
key = tuple(unwrap_spec)
@@ -456,9 +474,15 @@
def visit_c_ushort(self, typ):
self.unwrap.append("space.c_ushort_w(%s)" % (self.nextarg(),))
+ def visit_c_uid_t(self, typ):
+ self.unwrap.append("space.c_uid_t_w(%s)" % (self.nextarg(),))
+
def visit_truncatedint_w(self, typ):
self.unwrap.append("space.truncatedint_w(%s)" % (self.nextarg(),))
+ def visit_kwonly(self, typ):
+ raise FastFuncNotSupported
+
def make_fastfunc(unwrap_spec, func):
unwrap_info = UnwrapSpec_FastFunc_Unwrap()
unwrap_info.apply_over(unwrap_spec)
@@ -554,6 +578,8 @@
unwrap_spec.append('args_w')
elif argname.startswith('w_'):
unwrap_spec.append(W_Root)
+ elif argname == '__kwonly__':
+ unwrap_spec.append('kwonly')
else:
unwrap_spec.append(None)
@@ -603,7 +629,12 @@
# First extract the signature from the (CPython-level) code object
from pypy.interpreter import pycode
- argnames, varargname, kwargname =
pycode.cpython_code_signature(func.func_code)
+ sig = pycode.cpython_code_signature(func.func_code)
+ argnames = sig.argnames
+ varargname = sig.varargname
+ kwargname = sig.kwargname
+ if sig.kwonlyargnames:
+ import pdb; pdb.set_trace()
self._argnames = argnames
if unwrap_spec is None:
@@ -627,7 +658,9 @@
app_sig = SignatureBuilder(func)
UnwrapSpec_Check(orig_sig).apply_over(unwrap_spec, app_sig)
- self.sig = argnames, varargname, kwargname = app_sig.signature()
+ self.sig = app_sig.signature()
+ argnames = self.sig.argnames
+ varargname = self.sig.varargname
self.minargs = len(argnames)
if varargname:
@@ -720,7 +753,7 @@
raise OperationError(space.w_MemoryError, space.w_None)
except rstackovf.StackOverflow as e:
rstackovf.check_stack_overflow()
- raise oefmt(space.w_RuntimeError,
+ raise oefmt(space.w_RecursionError,
"maximum recursion depth exceeded")
except RuntimeError: # not on top of py.py
raise OperationError(space.w_RuntimeError, space.w_None)
@@ -936,64 +969,71 @@
self.name = app_name
self.as_classmethod = as_classmethod
- if not f.func_defaults:
- self._staticdefs = []
- else:
- argnames = self._code._argnames
- defaults = f.func_defaults
- self._staticdefs = zip(argnames[-len(defaults):], defaults)
+ argnames = self._code._argnames
+ defaults = f.func_defaults or ()
+ self._staticdefs = dict(zip(
+ argnames[len(argnames) - len(defaults):], defaults))
+
return self
def _getdefaults(self, space):
"NOT_RPYTHON"
- defs_w = []
- unwrap_spec = self._code._unwrap_spec[-len(self._staticdefs):]
- for i, (name, defaultval) in enumerate(self._staticdefs):
+ alldefs_w = {}
+ assert len(self._code._argnames) == len(self._code._unwrap_spec)
+ for name, spec in zip(self._code._argnames, self._code._unwrap_spec):
+ if name == '__kwonly__':
+ continue
+
+ defaultval = self._staticdefs.get(name, NO_DEFAULT)
+ w_def = Ellipsis
if name.startswith('w_'):
- assert defaultval is None, (
+ assert defaultval in (NO_DEFAULT, None), (
"%s: default value for '%s' can only be None, got %r; "
"use unwrap_spec(...=WrappedDefault(default))" % (
self._code.identifier, name, defaultval))
- defs_w.append(None)
- elif name != '__args__' and name != 'args_w':
- spec = unwrap_spec[i]
- if isinstance(defaultval, str) and spec not in [str]:
- defs_w.append(space.newbytes(defaultval))
- else:
- defs_w.append(space.wrap(defaultval))
- if self._code._unwrap_spec:
- UNDEFINED = object()
- alldefs_w = [UNDEFINED] * len(self._code.sig[0])
- if defs_w:
- alldefs_w[-len(defs_w):] = defs_w
- code = self._code
- assert isinstance(code._unwrap_spec, (list, tuple))
- assert isinstance(code._argnames, list)
- assert len(code._unwrap_spec) == len(code._argnames)
- for i in range(len(code._unwrap_spec)-1, -1, -1):
- spec = code._unwrap_spec[i]
- argname = code._argnames[i]
- if isinstance(spec, tuple) and spec[0] is W_Root:
- assert False, "use WrappedDefault"
- if isinstance(spec, WrappedDefault):
- default_value = spec.default_value
- if isinstance(default_value, str):
- w_default = space.newbytes(default_value)
- else:
- w_default = space.wrap(default_value)
- assert isinstance(w_default, W_Root)
- assert argname.startswith('w_')
- argname = argname[2:]
- j = self._code.sig[0].index(argname)
- assert alldefs_w[j] in (UNDEFINED, None)
- alldefs_w[j] = w_default
- first_defined = 0
- while (first_defined < len(alldefs_w) and
- alldefs_w[first_defined] is UNDEFINED):
- first_defined += 1
- defs_w = alldefs_w[first_defined:]
- assert UNDEFINED not in defs_w
- return defs_w
+ if defaultval is None:
+ w_def = None
+
+ if isinstance(spec, tuple) and spec[0] is W_Root:
+ assert False, "use WrappedDefault"
+ elif isinstance(spec, WrappedDefault):
+ assert name.startswith('w_')
+ defaultval = spec.default_value
+ w_def = Ellipsis
+
+ if defaultval is not NO_DEFAULT:
+ if name != '__args__' and name != 'args_w':
+ if w_def is Ellipsis:
+ if isinstance(defaultval, str) and spec not in [str]:
+ w_def = space.newbytes(defaultval)
+ else:
+ w_def = space.wrap(defaultval)
+ if name.startswith('w_'):
+ name = name[2:]
+ alldefs_w[name] = w_def
+ #
+ # Here, 'alldefs_w' maps some argnames to their wrapped default
+ # value. We return two lists:
+ # - a list of defaults for positional arguments, which covers
+ # some suffix of the sig.argnames list
+ # - a list of pairs (w_name, w_def) for kwonly arguments
+ #
+ sig = self._code.sig
+ first_defined = 0
+ while (first_defined < len(sig.argnames) and
+ sig.argnames[first_defined] not in alldefs_w):
+ first_defined += 1
+ defs_w = [alldefs_w.pop(name) for name in sig.argnames[first_defined:]]
+
+ kw_defs_w = None
+ if alldefs_w:
+ kw_defs_w = []
+ for name, w_def in sorted(alldefs_w.items()):
+ assert name in sig.kwonlyargnames
+ w_name = space.newunicode(name.decode('utf-8'))
+ kw_defs_w.append((w_name, w_def))
+
+ return defs_w, kw_defs_w
# lazy binding to space
@@ -1013,9 +1053,10 @@
def build(cache, gateway):
"NOT_RPYTHON"
space = cache.space
- defs = gateway._getdefaults(space) # needs to be implemented by
subclass
+ defs_w, kw_defs_w = gateway._getdefaults(space)
code = gateway._code
- fn = FunctionWithFixedCode(space, code, None, defs,
forcename=gateway.name)
+ fn = FunctionWithFixedCode(space, code, None, defs_w, kw_defs_w,
+ forcename=gateway.name)
if not space.config.translating:
fn.add_to_table()
if gateway.as_classmethod:
@@ -1153,15 +1194,15 @@
source = source[source.find('\n') + 1:].lstrip()
assert source.startswith("def "), "can only transform functions"
source = source[4:]
- import __future__
- if flags & __future__.CO_FUTURE_DIVISION:
- prefix += "from __future__ import division\n"
- if flags & __future__.CO_FUTURE_ABSOLUTE_IMPORT:
- prefix += "from __future__ import absolute_import\n"
- if flags & __future__.CO_FUTURE_PRINT_FUNCTION:
- prefix += "from __future__ import print_function\n"
- if flags & __future__.CO_FUTURE_UNICODE_LITERALS:
- prefix += "from __future__ import unicode_literals\n"
+ # The following flags have no effect any more in app-level code
+ # (i.e. they are always on anyway), and have been removed:
+ # CO_FUTURE_DIVISION
+ # CO_FUTURE_ABSOLUTE_IMPORT
+ # CO_FUTURE_PRINT_FUNCTION
+ # CO_FUTURE_UNICODE_LITERALS
+ # Original code was, for each of these flags:
+ # if flags & __future__.CO_xxx:
+ # prefix += "from __future__ import yyy\n"
p = source.find('(')
assert p >= 0
funcname = source[:p].strip()
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -6,7 +6,14 @@
from rpython.rlib import jit
-class GeneratorIterator(W_Root):
+class GeneratorOrCoroutine(W_Root):
+ """XXX: move the common functionality here!"""
+
+ def descr_close(self):
+ raise NotImplementedError
+
+
+class GeneratorIterator(GeneratorOrCoroutine):
"An iterator created by a generator."
_immutable_fields_ = ['pycode']
@@ -333,7 +340,7 @@
get_printable_location =
get_printable_coroutine_location_genentry,
name='coroutineentry')
-class Coroutine(W_Root):
+class Coroutine(GeneratorOrCoroutine):
"A coroutine object."
_immutable_fields_ = ['pycode']
diff --git a/pypy/interpreter/mixedmodule.py b/pypy/interpreter/mixedmodule.py
--- a/pypy/interpreter/mixedmodule.py
+++ b/pypy/interpreter/mixedmodule.py
@@ -19,6 +19,7 @@
""" NOT_RPYTHON """
Module.__init__(self, space, w_name)
self.lazy = True
+ self.lazy_initial_values_w = {}
self.__class__.buildloaders()
self.loaders = self.loaders.copy() # copy from the class to the inst
self.submodules_w = []
@@ -57,22 +58,11 @@
if not self.lazy and self.w_initialdict is None:
self.save_module_content_for_future_reload()
- def save_module_content_for_future_reload(self, save_all=False):
- # Because setdictvalue is unable to immediately load all attributes
- # (due to an importlib bootstrapping problem), this method needs to be
- # able to support saving the content of a module's dict without
- # requiring that the entire dict already be loaded. To support that
- # properly, when updating the dict, we must be careful to never
- # overwrite the value of a key already in w_initialdict. (So as to
avoid
- # overriding the builtin value with a user-provided value)
- if self.space.is_none(self.w_initialdict) or save_all:
- self.w_initialdict = self.space.call_method(self.w_dict, 'copy')
- else:
- w_items = self.space.call_method(self.w_dict, 'items')
- for w_item in self.space.iteriterable(w_items):
- w_key, w_value = self.space.fixedview(w_item,
expected_length=2)
- if not self.space.contains_w(self.w_initialdict, w_key):
- self.space.setitem(self.w_initialdict, w_key, w_value)
+ def save_module_content_for_future_reload(self):
+ # Save the current dictionary in w_initialdict, for future
+ # reloads. This forces the dictionary if needed.
+ w_dict = self.getdict(self.space)
+ self.w_initialdict = self.space.call_method(w_dict, 'copy')
@classmethod
def get_applevel_name(cls):
@@ -101,9 +91,13 @@
return w_value
def setdictvalue(self, space, attr, w_value):
- if self.lazy:
- self._load_lazily(space, attr)
- self.save_module_content_for_future_reload()
+ if self.lazy and attr not in self.lazy_initial_values_w:
+ # in lazy mode, the first time an attribute changes,
+ # we save away the old (initial) value. This allows
+ # a future getdict() call to build the correct
+ # self.w_initialdict, containing the initial value.
+ w_initial_value = self._load_lazily(space, attr)
+ self.lazy_initial_values_w[attr] = w_initial_value
space.setitem_str(self.w_dict, attr, w_value)
return True
@@ -137,13 +131,29 @@
def getdict(self, space):
if self.lazy:
- for name in self.loaders:
- w_value = self.get(name)
- space.setitem(self.w_dict, space.new_interned_str(name),
w_value)
- self.lazy = False
- self.save_module_content_for_future_reload()
+ self._force_lazy_dict_now()
return self.w_dict
+ def _force_lazy_dict_now(self):
+ # Force the dictionary by calling all lazy loaders now.
+ # This also saves in self.w_initialdict a copy of all the
+ # initial values, including if they have already been
+ # modified by setdictvalue().
+ space = self.space
+ for name in self.loaders:
+ w_value = self.get(name)
+ space.setitem(self.w_dict, space.new_interned_str(name), w_value)
+ self.lazy = False
+ self.save_module_content_for_future_reload()
+ for key, w_initial_value in self.lazy_initial_values_w.items():
+ w_key = space.new_interned_str(key)
+ if w_initial_value is not None:
+ space.setitem(self.w_initialdict, w_key, w_initial_value)
+ else:
+ if space.finditem(self.w_initialdict, w_key) is not None:
+ space.delitem(self.w_initialdict, w_key)
+ del self.lazy_initial_values_w
+
def _cleanup_(self):
self.getdict(self.space)
self.w_initialdict = None
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -45,7 +45,7 @@
# cpython_code_signature helper
def cpython_code_signature(code):
- "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)."
+ """Return a Signature instance."""
argcount = code.co_argcount
varnames = code.co_varnames
if we_are_translated():
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -1,7 +1,7 @@
""" PyFrame class implementation with the interpreter main loop.
"""
-from rpython.rlib import jit
+from rpython.rlib import jit, rweakref
from rpython.rlib.debug import make_sure_not_resized, check_nonneg
from rpython.rlib.jit import hint
from rpython.rlib.objectmodel import instantiate, specialize, we_are_translated
@@ -62,6 +62,8 @@
__metaclass__ = extendabletype
frame_finished_execution = False
+ f_generator_wref = rweakref.dead_ref # for generators/coroutines
+ f_generator_nowref = None # (only one of the two attrs)
last_instr = -1
last_exception = None
f_backref = jit.vref_None
@@ -238,14 +240,24 @@
self.locals_cells_stack_w[index] = outer_func.closure[i]
index += 1
+ def _is_generator_or_coroutine(self):
+ return (self.getcode().co_flags & (pycode.CO_COROUTINE |
+ pycode.CO_GENERATOR)) != 0
+
def run(self):
"""Start this frame's execution."""
- if self.getcode().co_flags & pycode.CO_COROUTINE:
- from pypy.interpreter.generator import Coroutine
- return self.space.wrap(Coroutine(self))
- elif self.getcode().co_flags & pycode.CO_GENERATOR:
- from pypy.interpreter.generator import GeneratorIterator
- return self.space.wrap(GeneratorIterator(self))
+ if self._is_generator_or_coroutine():
+ if self.getcode().co_flags & pycode.CO_COROUTINE:
+ from pypy.interpreter.generator import Coroutine
+ gen = Coroutine(self)
+ else:
+ from pypy.interpreter.generator import GeneratorIterator
+ gen = GeneratorIterator(self)
+ if self.space.config.translation.rweakref:
+ self.f_generator_wref = rweakref.ref(gen)
+ else:
+ self.f_generator_nowref = gen
+ return self.space.wrap(gen)
else:
return self.execute_frame()
@@ -886,6 +898,37 @@
frame = frame.f_backref()
return None
+ def descr_clear(self, space):
+ # Clears a random subset of the attributes (e.g. some the fast
+ # locals, but not f_locals). Also clears last_exception, which
+ # is not quite like CPython when it clears f_exc_* (however
+ # there might not be an observable difference).
+ if not self.frame_finished_execution:
+ if not self._is_generator_or_coroutine():
+ raise oefmt(space.w_RuntimeError,
+ "cannot clear an executing frame")
+ if space.config.translation.rweakref:
+ gen = self.f_generator_wref()
+ else:
+ gen = self.f_generator_nowref
+ if gen is not None:
+ if gen.running:
+ raise oefmt(space.w_RuntimeError,
+ "cannot clear an executing frame")
+ # xxx CPython raises the RuntimeWarning "coroutine was never
+ # awaited" in this case too. Does it make any sense?
+ gen.descr_close()
+
+ self.last_exception = None
+ debug = self.getdebug()
+ if debug is not None:
+ debug.w_f_trace = None
+
+ # clear the locals, including the cell/free vars, and the stack
+ for i in range(len(self.locals_cells_stack_w)):
+ self.locals_cells_stack_w[i] = None
+ self.valuestackdepth = 0
+
# ____________________________________________________________
def get_block_class(opname):
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -96,7 +96,7 @@
# Note that this case catches AttributeError!
rstackovf.check_stack_overflow()
next_instr = self.handle_asynchronous_error(ec,
- self.space.w_RuntimeError,
+ self.space.w_RecursionError,
self.space.wrap("maximum recursion depth exceeded"))
return next_instr
@@ -1288,15 +1288,15 @@
for i in range(len(names_w) - 1, -1, -1):
space.setitem(w_ann, names_w[i], self.popvalue())
defaultarguments = self.popvalues(posdefaults)
- w_kw_defs = None
+ kw_defs_w = None
if kwdefaults:
- w_kw_defs = space.newdict(strdict=True)
- for i in range(kwdefaults - 1, -1, -1):
- w_name = self.popvalue()
- w_def = self.popvalue()
- space.setitem(w_kw_defs, w_def, w_name)
+ kw_defs_w = []
+ for i in range(kwdefaults):
+ w_defvalue = self.popvalue()
+ w_defname = self.popvalue()
+ kw_defs_w.append((w_defname, w_defvalue))
fn = function.Function(space, codeobj, self.get_w_globals(),
defaultarguments,
- w_kw_defs, freevars, w_ann, qualname=qualname)
+ kw_defs_w, freevars, w_ann, qualname=qualname)
self.pushvalue(space.wrap(fn))
def MAKE_FUNCTION(self, oparg, next_instr):
diff --git a/pypy/interpreter/signature.py b/pypy/interpreter/signature.py
--- a/pypy/interpreter/signature.py
+++ b/pypy/interpreter/signature.py
@@ -39,6 +39,7 @@
def scope_length(self):
scopelen = len(self.argnames)
+ scopelen += len(self.kwonlyargnames)
scopelen += self.has_vararg()
scopelen += self.has_kwarg()
return scopelen
@@ -68,18 +69,3 @@
if not isinstance(other, Signature):
return NotImplemented
return not self == other
-
-
- # make it look tuply for its use in the annotator
-
- def __len__(self):
- return 3
-
- def __getitem__(self, i):
- if i == 0:
- return self.argnames
- if i == 1:
- return self.varargname
- if i == 2:
- return self.kwargname
- raise IndexError
diff --git a/pypy/interpreter/test/test_argument.py
b/pypy/interpreter/test/test_argument.py
--- a/pypy/interpreter/test/test_argument.py
+++ b/pypy/interpreter/test/test_argument.py
@@ -30,7 +30,7 @@
assert sig.num_argnames() == 3
assert sig.has_vararg()
assert sig.has_kwarg()
- assert sig.scope_length() == 5
+ assert sig.scope_length() == 6
assert sig.getallvarnames() == ["a", "b", "c", "d", "kwonly", "c"]
def test_eq(self):
@@ -47,13 +47,6 @@
assert sig.find_argname("d") == -1
assert sig.find_argname("kwonly") == 3
- def test_tuply(self):
- sig = Signature(["a", "b", "c"], "d", "e")
- x, y, z = sig
- assert x == ["a", "b", "c"]
- assert y == "d"
- assert z == "e"
-
class dummy_wrapped_dict(dict):
def __nonzero__(self):
raise NotImplementedError
diff --git a/pypy/interpreter/test/test_gateway.py
b/pypy/interpreter/test/test_gateway.py
--- a/pypy/interpreter/test/test_gateway.py
+++ b/pypy/interpreter/test/test_gateway.py
@@ -47,6 +47,12 @@
code = gateway.BuiltinCode(f, unwrap_spec=[gateway.ObjSpace, "index"])
assert code.signature() == Signature(["index"], None, None)
+ def f(space, __kwonly__, w_x):
+ pass
+ code = gateway.BuiltinCode(f, unwrap_spec=[gateway.ObjSpace,
+ "kwonly", W_Root])
+ assert code.signature() == Signature([], kwonlyargnames=['x'])
+
def test_call(self):
def c(space, w_x, w_y, hello_w):
@@ -753,7 +759,7 @@
@gateway.unwrap_spec(w_x = WrappedDefault(42), y=int)
def g(space, w_x, y):
never_called
- py.test.raises(AssertionError, space.wrap, gateway.interp2app_temp(g))
+ py.test.raises(KeyError, space.wrap, gateway.interp2app_temp(g))
def test_unwrap_spec_default_applevel_bug2(self):
space = self.space
@@ -803,6 +809,80 @@
w_res = space.call_args(w_g, args)
assert space.eq_w(w_res, space.newbytes('foo'))
+ def test_unwrap_spec_kwonly(self):
+ space = self.space
+ def g(space, w_x, __kwonly__, w_y):
+ return space.sub(w_x, w_y)
+ w_g = space.wrap(gateway.interp2app_temp(g))
+ w = space.wrap
+ w1 = w(1)
+
+ for i in range(4):
+ a = argument.Arguments(space, [w1, w1, w1])
+ py.test.raises(gateway.OperationError, space.call_args, w_g, a)
+ py.test.raises(gateway.OperationError, space.call_function, w_g,
+ *(i * (w1,)))
+
+ args = argument.Arguments(space, [w(1)],
+ w_starstararg = w({'y': 10}))
+ assert space.eq_w(space.call_args(w_g, args), w(-9))
+ args = argument.Arguments(space, [],
+ w_starstararg = w({'x': 2, 'y': 10}))
+ assert space.eq_w(space.call_args(w_g, args), w(-8))
+
+ def test_unwrap_spec_kwonly_default(self):
+ space = self.space
+ @gateway.unwrap_spec(w_x2=WrappedDefault(50), y2=int)
+ def g(space, w_x1, w_x2, __kwonly__, w_y1, y2=200):
+ return space.sub(space.sub(w_x1, w_x2),
+ space.sub(w_y1, w(y2)))
+ w_g = space.wrap(gateway.interp2app_temp(g))
+ w = space.wrap
+ w1 = w(1)
+
+ for i in range(6):
+ py.test.raises(gateway.OperationError, space.call_function, w_g,
+ *(i * (w1,)))
+
+ def expected(x1, x2=50, y1="missing", y2=200):
+ return (x1 - x2) - (y1 - y2)
+
+ def check(*args, **kwds):
+ a = argument.Arguments(space, [], w_stararg = w(args),
+ w_starstararg = w(kwds))
+ w_res = space.call_args(w_g, a)
+ assert space.eq_w(w_res, w(expected(*args, **kwds)))
+
+ del kwds['y1']
+ a = argument.Arguments(space, [], w_stararg = w(args),
+ w_starstararg = w(kwds))
+ py.test.raises(gateway.OperationError, space.call_args, w_g, a)
+
+ args += (1234,)
+ a = argument.Arguments(space, [], w_stararg = w(args),
+ w_starstararg = w(kwds))
+ py.test.raises(gateway.OperationError, space.call_args, w_g, a)
+
+ check(5, y1=1234)
+ check(5, 1, y1=1234)
+ check(5, x2=1, y1=1234)
+ check(5, y1=1234, y2=343)
+ check(5, 1, y1=1234, y2=343)
+ check(5, x2=1, y1=1234, y2=343)
+ check(x1=5, y1=1234, )
+ check(x1=5, x2=1, y1=1234, )
+ check(x1=5, y1=1234, y2=343)
+ check(x1=5, x2=1, y1=1234, y2=343)
+
+ def test_unwrap_spec_kwonly_default_2(self):
+ space = self.space
+ @gateway.unwrap_spec(w_x2=WrappedDefault(50))
+ def g(space, w_x2=None):
+ return w_x2
+ w_g = space.wrap(gateway.interp2app_temp(g))
+ w_res = space.call_function(w_g)
+ assert space.eq_w(w_res, space.wrap(50))
+
class AppTestPyTestMark:
@py.test.mark.unlikely_to_exist
diff --git a/pypy/interpreter/test/test_generator.py
b/pypy/interpreter/test/test_generator.py
--- a/pypy/interpreter/test/test_generator.py
+++ b/pypy/interpreter/test/test_generator.py
@@ -220,22 +220,17 @@
raises(RuntimeError, g.close)
def test_close_on_collect(self):
- ## we need to exec it, else it won't run on python2.4
- d = {}
- exec("""
def f():
try:
yield
finally:
f.x = 42
- """.strip(), d, d)
-
- g = d['f']()
+ g = f()
next(g)
del g
import gc
gc.collect()
- assert d['f'].x == 42
+ assert f.x == 42
def test_generator_raises_typeerror(self):
def f():
diff --git a/pypy/interpreter/test/test_interpreter.py
b/pypy/interpreter/test/test_interpreter.py
--- a/pypy/interpreter/test/test_interpreter.py
+++ b/pypy/interpreter/test/test_interpreter.py
@@ -407,7 +407,7 @@
def f(): f()
try:
f()
- except RuntimeError as e:
+ except RecursionError as e:
assert str(e) == "maximum recursion depth exceeded"
else:
assert 0, "should have raised!"
@@ -435,6 +435,20 @@
assert X().f() == 42
"""
+ def test_kwonlyarg_required(self):
+ """
+ def f(*, a=5, b):
+ return (a, b)
+ assert f(b=10) == (5, 10)
+ assert f(a=7, b=12) == (7, 12)
+ raises(TypeError, f)
+ raises(TypeError, f, 1)
+ raises(TypeError, f, 1, 1)
+ raises(TypeError, f, a=1)
+ raises(TypeError, f, 1, a=1)
+ raises(TypeError, f, 1, b=1)
+ """
+
def test_extended_unpacking_short(self):
"""
class Seq:
diff --git a/pypy/interpreter/test/test_module.py
b/pypy/interpreter/test/test_module.py
--- a/pypy/interpreter/test/test_module.py
+++ b/pypy/interpreter/test/test_module.py
@@ -165,7 +165,7 @@
import sys
import os
- assert sys.__package__ is None
+ assert sys.__package__ == ''
assert os.__package__ == ''
assert not hasattr(type(sys)('foo'), '__package__')
diff --git a/pypy/interpreter/test/test_pyframe.py
b/pypy/interpreter/test/test_pyframe.py
--- a/pypy/interpreter/test/test_pyframe.py
+++ b/pypy/interpreter/test/test_pyframe.py
@@ -545,3 +545,41 @@
it = yield_raise()
assert next(it) is KeyError
assert next(it) is KeyError
+
+ def test_frame_clear(self):
+ import sys, gc, weakref
+ #
+ raises(RuntimeError, sys._getframe().clear)
+ def g():
+ yield 5
+ raises(RuntimeError, sys._getframe().clear)
+ yield 6
+ assert list(g()) == [5, 6]
+ #
+ class A:
+ pass
+ a1 = A(); a1ref = weakref.ref(a1)
+ a2 = A(); a2ref = weakref.ref(a2)
+ seen = []
+ def f():
+ local_a1 = a1
+ for loc in [5, 6, a2]:
+ try:
+ yield sys._getframe()
+ finally:
+ seen.append(42)
+ seen.append(43)
+ gen = f()
+ frame = next(gen)
+ a1 = a2 = None
+ gc.collect(); gc.collect()
+ assert a1ref() is not None
+ assert a2ref() is not None
+ assert seen == []
+ frame.clear()
+ assert seen == [42]
+ gc.collect(); gc.collect()
+ assert a1ref() is None, "locals not cleared"
+ assert a2ref() is None, "stack not cleared"
+ #
+ raises(StopIteration, next, gen)
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -202,7 +202,8 @@
name = func.__name__
extra = ', '.join(extraargs)
from pypy.interpreter import pycode
- argnames, _, _ = pycode.cpython_code_signature(func.func_code)
+ sig = pycode.cpython_code_signature(func.func_code)
+ argnames = sig.argnames
if use_closure:
if argnames[1] == 'space':
args = "closure, space, obj"
@@ -605,6 +606,7 @@
PyFrame.typedef = TypeDef('frame',
__reduce__ = interp2app(PyFrame.descr__reduce__),
__setstate__ = interp2app(PyFrame.descr__setstate__),
+ clear = interp2app(PyFrame.descr_clear),
f_builtins = GetSetProperty(PyFrame.fget_f_builtins),
f_lineno = GetSetProperty(PyFrame.fget_f_lineno, PyFrame.fset_f_lineno),
f_back = GetSetProperty(PyFrame.fget_f_back),
@@ -797,10 +799,15 @@
)
assert not GeneratorIterator.typedef.acceptable_as_base_class # no __new__
+# TODO: to have the same distinction (Coroutine | Iterator) as in cpython 3.5,
+# a wrapper typedef with __anext__ has to be created, and __anext__ has to be
+# removed in coroutine
Coroutine.typedef = TypeDef("coroutine",
__repr__ = interp2app(Coroutine.descr__repr__),
__reduce__ = interp2app(Coroutine.descr__reduce__),
__setstate__ = interp2app(Coroutine.descr__setstate__),
+ __anext__ = interp2app(Coroutine.descr_next,
+ descrmismatch='__anext__'),
send = interp2app(Coroutine.descr_send,
descrmismatch='send'),
throw = interp2app(Coroutine.descr_throw,
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
@@ -131,7 +131,7 @@
@unwrap_spec(w_module=MixedModule)
def save_module_content_for_future_reload(space, w_module):
- w_module.save_module_content_for_future_reload(save_all=True)
+ w_module.save_module_content_for_future_reload()
def set_code_callback(space, w_callable):
cache = space.fromcache(CodeHookCache)
diff --git a/pypy/module/_ast/test/test_ast.py
b/pypy/module/_ast/test/test_ast.py
--- a/pypy/module/_ast/test/test_ast.py
+++ b/pypy/module/_ast/test/test_ast.py
@@ -118,9 +118,9 @@
def test_object(self):
ast = self.ast
const = ast.Const(4)
- assert const.value == 4
- const.value = 5
- assert const.value == 5
+ assert const.obj == 4
+ const.obj = 5
+ assert const.obj == 5
def test_optional(self):
mod = self.get_ast("x(32)", "eval")
diff --git a/pypy/module/_asyncio/test/test_asyncio.py
b/pypy/module/_asyncio/test/test_asyncio.py
--- a/pypy/module/_asyncio/test/test_asyncio.py
+++ b/pypy/module/_asyncio/test/test_asyncio.py
@@ -1,4 +1,5 @@
class AppTestAsyncIO(object):
+ """These tests are based on the async-await syntax of Python 3.5."""
spaceconfig = dict(usemodules=["select","_socket","thread","signal",
"struct","_multiprocessing","array",
@@ -9,17 +10,71 @@
# the problem occured at await asyncio.open_connection
# after calling run_until_complete
"""
- import encodings.idna
- import asyncio
- async def f():
- reader, writer = await asyncio.open_connection('example.com', 80)
-
- loop = asyncio.get_event_loop()
- loop.run_until_complete(f())
- print("done with async loop")
+import encodings.idna
+import asyncio
+
+async def f():
+ reader, writer = await asyncio.open_connection('example.com', 80)
+ writer.close()
+
+loop = asyncio.get_event_loop()
+loop.run_until_complete(f())
+ """
+
+ def test_async_for(self):
+ # tests if async for receives all stores values in the right order
+ # and if the correct methods __aiter__ and __anext__ get called
+ # and if the end results of run_until_complete are None (in a tuple)
+ """
+import asyncio
+
+class AsyncIter:
+ def __init__(self):
+ self._data = list(range(5))
+ self._index = 0
+
+ async def __aiter__(self):
+ return self
+
+ async def __anext__(self):
+ while self._index < 5:
+ await asyncio.sleep(1)
+ self._index += 1
+ return self._data[self._index-1]
+ raise StopAsyncIteration
+
+class Corotest(object):
+ def __init__(self):
+ self.res = "-"
+
+ async def do_loop(self):
+ async for x in AsyncIter():
+ self.res += str(x)
+ self.res += "-"
+
+cor = Corotest()
+loop = asyncio.get_event_loop()
+futures = [asyncio.ensure_future(cor.do_loop()),
asyncio.ensure_future(cor.do_loop())]
+taskres = loop.run_until_complete(asyncio.wait(futures))
+assert cor.res.count('0') == 2
+assert cor.res.count('1') == 2
+assert cor.res.count('2') == 2
+assert cor.res.count('3') == 2
+assert cor.res.count('4') == 2
+assert cor.res.find("0") < cor.res.find("1")
+assert cor.res.find("1") < cor.res.find("2")
+assert cor.res.find("2") < cor.res.find("3")
+assert cor.res.find("3") < cor.res.find("4")
+assert isinstance(taskres, tuple)
+assert len(taskres) == 2
+assert "result=None" in repr(taskres[0].pop())
+assert "result=None" in repr(taskres[0].pop())
"""
def test_asynchronous_context_managers(self):
+ # it is important that "releasing lock A" happens before "holding lock
B"
+ # or the other way around, but it is not allowed that both coroutines
+ # hold the lock at the same time
"""
import encodings.idna
import asyncio
@@ -44,5 +99,12 @@
finally:
loop.close()
-assert cor.res == "- coro 1: waiting for lock - coro 1: holding the lock -
coro 2: waiting for lock - coro 1: releasing the lock - coro 2: holding the
lock - coro 2: releasing the lock -"
+assert "coro 1: waiting for lock" in cor.res
+assert "coro 1: holding the lock" in cor.res
+assert "coro 1: releasing the lock" in cor.res
+assert "coro 2: waiting for lock" in cor.res
+assert "coro 2: holding the lock" in cor.res
+assert "coro 2: releasing the lock" in cor.res
+assert cor.res.find("coro 1: releasing the lock") < cor.res.find("coro 2:
holding the lock") or \
+cor.res.find("coro 2: releasing the lock") < cor.res.find("coro 1: holding the
lock")
"""
diff --git a/pypy/module/_cffi_backend/cdataobj.py
b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -310,11 +310,15 @@
self.ctype.name, ct.name)
#
itemsize = ct.ctitem.size
- if itemsize <= 0:
- itemsize = 1
with self as ptr1, w_other as ptr2:
diff = (rffi.cast(lltype.Signed, ptr1) -
- rffi.cast(lltype.Signed, ptr2)) // itemsize
+ rffi.cast(lltype.Signed, ptr2))
+ if itemsize > 1:
+ if diff % itemsize:
+ raise oefmt(space.w_ValueError,
+ "pointer subtraction: the distance between the two "
+ "pointers is not a multiple of the item size")
+ diff //= itemsize
return space.wrap(diff)
#
return self._add_or_sub(w_other, -1)
diff --git a/pypy/module/_cffi_backend/misc.py
b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -257,6 +257,7 @@
sandboxsafe=True)
# split here for JIT backends that don't support floats/longlongs/etc.
[email protected]_look_inside
def is_nonnull_longdouble(cdata):
return _is_nonnull_longdouble(read_raw_longdouble_data(cdata))
def is_nonnull_float(cdata, size):
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py
b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -576,6 +576,19 @@
e = py.test.raises(TypeError, "q - a")
assert str(e.value) == "cannot subtract cdata 'short *' and cdata 'int *'"
+def test_ptr_sub_unaligned():
+ BInt = new_primitive_type("int")
+ BIntPtr = new_pointer_type(BInt)
+ a = cast(BIntPtr, 1240)
+ for bi in range(1430, 1438):
+ b = cast(BIntPtr, bi)
+ if ((bi - 1240) % size_of_int()) == 0:
+ assert b - a == (bi - 1240) // size_of_int()
+ assert a - b == (1240 - bi) // size_of_int()
+ else:
+ py.test.raises(ValueError, "b - a")
+ py.test.raises(ValueError, "a - b")
+
def test_cast_primitive_from_cdata():
p = new_primitive_type("int")
n = cast(p, cast(p, -42))
diff --git a/pypy/module/_cffi_backend/test/test_re_python.py
b/pypy/module/_cffi_backend/test/test_re_python.py
--- a/pypy/module/_cffi_backend/test/test_re_python.py
+++ b/pypy/module/_cffi_backend/test/test_re_python.py
@@ -69,10 +69,13 @@
sub_ffi.set_source('re_py_subsrc', None)
sub_ffi.emit_python_code(str(tmpdir.join('re_py_subsrc.py')))
#
- space.appexec([space.wrap(str(tmpdir))], """(path):
- import _cffi_backend # force it to be initialized
- import sys
- sys.path.insert(0, path)
+ cls.w_fix_path = space.appexec([space.wrap(str(tmpdir))], """(path):
+ def fix_path(ignored=None):
+ import _cffi_backend # force it to be initialized
+ import sys
+ if path not in sys.path:
+ sys.path.insert(0, path)
+ return fix_path
""")
def teardown_method(self, meth):
@@ -86,17 +89,20 @@
def test_constant_1(self):
+ self.fix_path()
from re_python_pysrc import ffi
assert ffi.integer_const('FOOBAR') == -42
assert ffi.integer_const('FOOBAZ') == -43
def test_large_constant(self):
+ self.fix_path()
from re_python_pysrc import ffi
assert ffi.integer_const('BIGPOS') == 420000000000
assert ffi.integer_const('BIGNEG') == -420000000000
def test_function(self):
import _cffi_backend
+ self.fix_path()
from re_python_pysrc import ffi
lib = ffi.dlopen(self.extmod)
assert lib.add42(-10) == 32
@@ -104,6 +110,7 @@
def test_dlclose(self):
import _cffi_backend
+ self.fix_path()
from re_python_pysrc import ffi
lib = ffi.dlopen(self.extmod)
ffi.dlclose(lib)
@@ -115,17 +122,20 @@
"library '%s' has been closed" % (self.extmod,))
def test_constant_via_lib(self):
+ self.fix_path()
from re_python_pysrc import ffi
lib = ffi.dlopen(self.extmod)
assert lib.FOOBAR == -42
assert lib.FOOBAZ == -43
def test_opaque_struct(self):
+ self.fix_path()
from re_python_pysrc import ffi
ffi.cast("struct foo_s *", 0)
raises(TypeError, ffi.new, "struct foo_s *")
def test_nonopaque_struct(self):
+ self.fix_path()
from re_python_pysrc import ffi
for p in [ffi.new("struct bar_s *", [5, b"foobar"]),
ffi.new("bar_t *", [5, b"foobar"])]:
@@ -134,12 +144,14 @@
assert p.a[5] == ord('r')
def test_enum(self):
+ self.fix_path()
from re_python_pysrc import ffi
assert ffi.integer_const("BB") == 1
e = ffi.cast("enum foo_e", 2)
assert ffi.string(e) == "CC"
def test_include_1(self):
+ self.fix_path()
from re_py_subsrc import ffi
assert ffi.integer_const('FOOBAR') == -42
assert ffi.integer_const('FOOBAZ') == -43
@@ -153,6 +165,7 @@
assert p.a[4] == ord('a')
def test_global_var(self):
+ self.fix_path()
from re_python_pysrc import ffi
lib = ffi.dlopen(self.extmod)
assert lib.globalvar42 == 1234
@@ -163,24 +176,28 @@
assert lib.globalvar42 == 1238
def test_global_const_int(self):
+ self.fix_path()
from re_python_pysrc import ffi
lib = ffi.dlopen(self.extmod)
assert lib.globalconst42 == 4321
raises(AttributeError, ffi.addressof, lib, 'globalconst42')
def test_global_const_nonint(self):
+ self.fix_path()
from re_python_pysrc import ffi
lib = ffi.dlopen(self.extmod)
assert ffi.string(lib.globalconsthello, 8) == b"hello"
raises(AttributeError, ffi.addressof, lib, 'globalconsthello')
def test_rtld_constants(self):
+ self.fix_path()
from re_python_pysrc import ffi
ffi.RTLD_NOW # check that we have the attributes
ffi.RTLD_LAZY
ffi.RTLD_GLOBAL
def test_no_such_function_or_global_var(self):
+ self.fix_path()
from re_python_pysrc import ffi
lib = ffi.dlopen(self.extmod)
e = raises(ffi.error, getattr, lib, 'no_such_function')
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
@@ -79,7 +79,7 @@
class AppTestRecompiler:
- spaceconfig = dict(usemodules=['_cffi_backend', 'imp'])
+ spaceconfig = dict(usemodules=['_cffi_backend', 'imp', 'cpyext', 'struct'])
def setup_class(cls):
if cls.runappdirect:
diff --git a/pypy/module/_frozen_importlib/__init__.py
b/pypy/module/_frozen_importlib/__init__.py
--- a/pypy/module/_frozen_importlib/__init__.py
+++ b/pypy/module/_frozen_importlib/__init__.py
@@ -16,11 +16,10 @@
@staticmethod
def _compile_bootstrap_module(space, name, w_name, w_dict):
"""NOT_RPYTHON"""
- ec = space.getexecutioncontext()
with open(os.path.join(lib_python, 'importlib', name + '.py')) as fp:
source = fp.read()
pathname = "<frozen importlib.%s>" % name
- code_w = ec.compiler.compile(source, pathname, 'exec', 0)
+ code_w = Module._cached_compile(space, source, pathname, 'exec', 0)
space.setitem(w_dict, space.wrap('__name__'), w_name)
space.setitem(w_dict, space.wrap('__builtins__'),
space.wrap(space.builtin))
@@ -43,6 +42,31 @@
self.w_import = space.wrap(interp_import.import_with_frames_removed)
+ @staticmethod
+ def _cached_compile(space, source, *args):
+ from rpython.config.translationoption import CACHE_DIR
+ from pypy.module.marshal import interp_marshal
+
+ cachename = os.path.join(CACHE_DIR, 'frozen_importlib_bootstrap')
+ try:
+ if space.config.translating:
+ raise IOError("don't use the cache when translating pypy")
+ with open(cachename, 'rb') as f:
+ previous = f.read(len(source) + 1)
+ if previous != source + '\x00':
+ raise IOError("source changed")
+ w_bin = space.newbytes(f.read())
+ code_w = interp_marshal.loads(space, w_bin)
+ except IOError:
+ # must (re)compile the source
+ ec = space.getexecutioncontext()
+ code_w = ec.compiler.compile(source, *args)
+ w_bin = interp_marshal.dumps(space, code_w, space.wrap(2))
+ content = source + '\x00' + space.bytes_w(w_bin)
+ with open(cachename, 'wb') as f:
+ f.write(content)
+ return code_w
+
def startup(self, space):
"""Copy our __import__ to builtins."""
w_install = self.getdictvalue(space, '_install')
diff --git a/pypy/module/_jitlog/test/test__jitlog.py
b/pypy/module/_jitlog/test/test__jitlog.py
--- a/pypy/module/_jitlog/test/test__jitlog.py
+++ b/pypy/module/_jitlog/test/test__jitlog.py
@@ -10,10 +10,10 @@
def setup_class(cls):
cls.w_tmpfilename = cls.space.wrap(str(udir.join('test__jitlog.1')))
- cls.w_mark_header = cls.space.wrap(jl.MARK_JITLOG_HEADER)
- cls.w_version = cls.space.wrap(jl.JITLOG_VERSION_16BIT_LE)
+ cls.w_mark_header = cls.space.newbytes(jl.MARK_JITLOG_HEADER)
+ cls.w_version = cls.space.newbytes(jl.JITLOG_VERSION_16BIT_LE)
cls.w_is_32bit = cls.space.wrap(sys.maxint == 2**31-1)
- cls.w_machine = cls.space.wrap(platform.machine())
+ cls.w_machine = cls.space.newbytes(platform.machine())
cls.w_resops = cls.space.newdict()
space = cls.space
for key, value in opname.items():
@@ -48,5 +48,3 @@
assert opnum in self.resops
# the name must equal
assert self.resops[opnum] == opname
-
-
diff --git a/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h
b/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h
--- a/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h
+++ b/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h
@@ -268,22 +268,26 @@
min = 0;
max = haystacksize;
- for (pos = haystacksize >> 1; min != max; pos = (min + max) >> 1)
+ for (pos = haystacksize >> 1; min != max; pos = (min + max) >> 1) {
if (value < haystack[pos].uniseq) {
- if (max == pos) break;
- else max = pos;
+ if (max != pos) {
+ max = pos;
+ continue;
+ }
}
else if (value > haystack[pos].uniseq) {
- if (min == pos) break;
- else min = pos;
+ if (min != pos) {
+ min = pos;
+ continue;
+ }
}
- else
- break;
+ break;
+ }
- if (value == haystack[pos].uniseq)
- return haystack[pos].code;
- else
- return DBCINV;
+ if (value == haystack[pos].uniseq) {
+ return haystack[pos].code;
+ }
+ return DBCINV;
}
#endif
diff --git a/pypy/module/_pypyjson/interp_decoder.py
b/pypy/module/_pypyjson/interp_decoder.py
--- a/pypy/module/_pypyjson/interp_decoder.py
+++ b/pypy/module/_pypyjson/interp_decoder.py
@@ -327,7 +327,8 @@
i += 1
if ch == '"':
content_utf8 = builder.build()
- content_unicode = unicodehelper.decode_utf8(self.space,
content_utf8)
+ content_unicode = unicodehelper.decode_utf8(
+ self.space, content_utf8, allow_surrogates=True)
self.last_type = TYPE_STRING
self.pos = i
return self.space.wrap(content_unicode)
@@ -374,7 +375,8 @@
# this point
#
uchr = runicode.code_to_unichr(val) # may be a surrogate pair again
- utf8_ch = unicodehelper.encode_utf8(self.space, uchr)
+ utf8_ch = unicodehelper.encode_utf8(
+ self.space, uchr, allow_surrogates=True)
builder.append(utf8_ch)
return i
diff --git a/pypy/module/_pypyjson/test/test__pypyjson.py
b/pypy/module/_pypyjson/test/test__pypyjson.py
--- a/pypy/module/_pypyjson/test/test__pypyjson.py
+++ b/pypy/module/_pypyjson/test/test__pypyjson.py
@@ -10,10 +10,10 @@
assert dec.skip_whitespace(8) == len(s)
dec.close()
-
+
class AppTest(object):
- spaceconfig = {"objspace.usemodules._pypyjson": True}
+ spaceconfig = {"usemodules": ['_pypyjson']}
def test_raise_on_bytes(self):
import _pypyjson
@@ -40,7 +40,7 @@
raises(ValueError, _pypyjson.loads, 'fa')
raises(ValueError, _pypyjson.loads, 'f')
raises(ValueError, _pypyjson.loads, 'falXX')
-
+
def test_decode_string(self):
import _pypyjson
@@ -69,7 +69,7 @@
import _pypyjson
assert _pypyjson.loads(r'"\\"') == '\\'
assert _pypyjson.loads(r'"\""') == '"'
- assert _pypyjson.loads(r'"\/"') == '/'
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit