From pypy.commits at gmail.com Sat Apr 1 04:43:27 2017 From: pypy.commits at gmail.com (arigo) Date: Sat, 01 Apr 2017 01:43:27 -0700 (PDT) Subject: [pypy-commit] pypy default: The exact message we get depends on the underlying (host) cffi version Message-ID: <58df682f.ebafdf0a.a4ea2.a209@mx.google.com> Author: Armin Rigo Branch: Changeset: r90887:efad75426201 Date: 2017-04-01 10:43 +0200 http://bitbucket.org/pypy/pypy/changeset/efad75426201/ Log: The exact message we get depends on the underlying (host) cffi version 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 @@ -1471,8 +1471,13 @@ with self.StdErrCapture(fd=True) as f: res = lib.bar(4, 5) assert res == 0 - assert f.getvalue() == ( + assert f.getvalue() in ( + # If the underlying cffi is <= 1.9 "extern \"Python\": function bar() called, but no code was attached " + "to it yet with @ffi.def_extern(). Returning 0.\n", + # If the underlying cffi is >= 1.10 + "extern \"Python\": function _CFFI_test_extern_python_1.bar() " + "called, but no code was attached " "to it yet with @ffi.def_extern(). Returning 0.\n") @ffi.def_extern("bar") From pypy.commits at gmail.com Sat Apr 1 04:45:59 2017 From: pypy.commits at gmail.com (arigo) Date: Sat, 01 Apr 2017 01:45:59 -0700 (PDT) Subject: [pypy-commit] pypy default: Fix test (expecting AssertionError now for out-of-bounds unsafe access) Message-ID: <58df68c7.2ea0df0a.6bdd4.a650@mx.google.com> Author: Armin Rigo Branch: Changeset: r90888:e21e09d948c3 Date: 2017-04-01 10:45 +0200 http://bitbucket.org/pypy/pypy/changeset/e21e09d948c3/ Log: Fix test (expecting AssertionError now for out-of-bounds unsafe access) diff --git a/rpython/rlib/rstrategies/test/test_rstrategies.py b/rpython/rlib/rstrategies/test/test_rstrategies.py --- a/rpython/rlib/rstrategies/test/test_rstrategies.py +++ b/rpython/rlib/rstrategies/test/test_rstrategies.py @@ -204,7 +204,7 @@ if is_safe: py.test.raises(IndexError, s.fetch, l, -1) else: - assert s.fetch(l, -1) == s.fetch(l, size - 1) + py.test.raises(AssertionError, s.fetch, l, -1) def test_init_Empty(): l = W_List(EmptyStrategy, 0) @@ -249,7 +249,7 @@ if is_safe: py.test.raises(IndexError, s.store, l, -1, stored_value) else: - store_test(-1) + py.test.raises(AssertionError, s.store, l, -1, stored_value) def test_store_Nil(): do_test_store(NilStrategy, stored_value=w_nil) From pypy.commits at gmail.com Sat Apr 1 04:48:40 2017 From: pypy.commits at gmail.com (arigo) Date: Sat, 01 Apr 2017 01:48:40 -0700 (PDT) Subject: [pypy-commit] pypy default: fix on 32-bit Message-ID: <58df6968.9d711c0a.b95d7.31ee@mx.google.com> Author: Armin Rigo Branch: Changeset: r90889:5907000d9e3d Date: 2017-04-01 10:48 +0200 http://bitbucket.org/pypy/pypy/changeset/5907000d9e3d/ Log: fix on 32-bit diff --git a/rpython/rlib/rvmprof/src/rvmprof.h b/rpython/rlib/rvmprof/src/rvmprof.h --- a/rpython/rlib/rvmprof/src/rvmprof.h +++ b/rpython/rlib/rvmprof/src/rvmprof.h @@ -28,7 +28,7 @@ RPY_EXTERN void vmprof_ignore_signals(int); RPY_EXTERN int vmprof_enable(int memory, int native); RPY_EXTERN int vmprof_disable(void); -RPY_EXTERN int vmprof_register_virtual_function(char *, long, int); +RPY_EXTERN int vmprof_register_virtual_function(char *, intptr_t, int); RPY_EXTERN void* vmprof_stack_new(void); RPY_EXTERN int vmprof_stack_append(void*, long); RPY_EXTERN long vmprof_stack_pop(void*); From pypy.commits at gmail.com Sat Apr 1 04:01:18 2017 From: pypy.commits at gmail.com (arigo) Date: Sat, 01 Apr 2017 01:01:18 -0700 (PDT) Subject: [pypy-commit] pypy default: Issue #2526: fix for a corner case of __future__ imports Message-ID: <58df5e4e.8bd11c0a.3a02e.2574@mx.google.com> Author: Armin Rigo Branch: Changeset: r90886:49dcf5e4c5a1 Date: 2017-04-01 10:00 +0200 http://bitbucket.org/pypy/pypy/changeset/49dcf5e4c5a1/ Log: Issue #2526: fix for a corner case of __future__ imports diff --git a/pypy/interpreter/pyparser/future.py b/pypy/interpreter/pyparser/future.py --- a/pypy/interpreter/pyparser/future.py +++ b/pypy/interpreter/pyparser/future.py @@ -78,6 +78,7 @@ from pypy.interpreter.pyparser import pygram it = TokenIterator(tokens) result = 0 + last_position = (0, 0) # # The only things that can precede a future statement are another # future statement and a doc string (only one). This is a very @@ -92,6 +93,11 @@ it.skip_name("__future__") and it.skip_name("import")): it.skip(pygram.tokens.LPAR) # optionally + # return in 'last_position' any line-column pair that points + # somewhere inside the last __future__ import statement + # (at the start would be fine too, but it's easier to grab a + # random position inside) + last_position = (it.tok[2], it.tok[3]) result |= future_flags.get_compiler_feature(it.next_feature_name()) while it.skip(pygram.tokens.COMMA): result |= future_flags.get_compiler_feature(it.next_feature_name()) @@ -99,5 +105,4 @@ it.skip(pygram.tokens.SEMI) # optionally it.skip_newlines() - position = (it.tok[2], it.tok[3]) - return result, position + return result, last_position diff --git a/pypy/interpreter/pyparser/test/test_future.py b/pypy/interpreter/pyparser/test/test_future.py --- a/pypy/interpreter/pyparser/test/test_future.py +++ b/pypy/interpreter/pyparser/test/test_future.py @@ -2,10 +2,9 @@ from pypy.interpreter.pyparser import future, pytokenizer from pypy.tool import stdlib___future__ as fut -def run(s, expected_last_future=None): +def run(s, expected_last_future=(0, 0)): source_lines = s.splitlines(True) tokens = pytokenizer.generate_tokens(source_lines, 0) - expected_last_future = expected_last_future or tokens[-1][2:4] # flags, last_future_import = future.add_future_flags( future.futureFlags_2_7, tokens) @@ -14,7 +13,7 @@ def test_docstring(): s = '"Docstring\\" "\nfrom __future__ import division\n' - f = run(s) + f = run(s, (2, 24)) assert f == fut.CO_FUTURE_DIVISION def test_comment(): @@ -45,167 +44,167 @@ def test_from(): s = 'from __future__ import division\n' - f = run(s) + f = run(s, (1, 24)) assert f == fut.CO_FUTURE_DIVISION def test_froms(): s = 'from __future__ import division, generators, with_statement\n' - f = run(s) + f = run(s, (1, 24)) assert f == (fut.CO_FUTURE_DIVISION | fut.CO_GENERATOR_ALLOWED | fut.CO_FUTURE_WITH_STATEMENT) def test_from_as(): s = 'from __future__ import division as b\n' - f = run(s) + f = run(s, (1, 24)) assert f == fut.CO_FUTURE_DIVISION def test_froms_as(): s = 'from __future__ import division as b, generators as c\n' - f = run(s) + f = run(s, (1, 24)) assert f == (fut.CO_FUTURE_DIVISION | fut.CO_GENERATOR_ALLOWED) def test_from_paren(): s = 'from __future__ import (division)\n' - f = run(s) + f = run(s, (1, 25)) assert f == fut.CO_FUTURE_DIVISION def test_froms_paren(): s = 'from __future__ import (division, generators)\n' - f = run(s) + f = run(s, (1, 25)) assert f == (fut.CO_FUTURE_DIVISION | fut.CO_GENERATOR_ALLOWED) def test_froms_paren_as(): s = 'from __future__ import (division as b, generators,)\n' - f = run(s) + f = run(s, (1, 25)) assert f == (fut.CO_FUTURE_DIVISION | fut.CO_GENERATOR_ALLOWED) def test_paren_with_newline(): s = 'from __future__ import (division,\nabsolute_import)\n' - f = run(s) + f = run(s, (1, 24)) assert f == (fut.CO_FUTURE_DIVISION | fut.CO_FUTURE_ABSOLUTE_IMPORT) def test_paren_with_newline_2(): s = 'from __future__ import (\ndivision,\nabsolute_import)\n' - f = run(s) + f = run(s, (2, 0)) assert f == (fut.CO_FUTURE_DIVISION | fut.CO_FUTURE_ABSOLUTE_IMPORT) def test_multiline(): s = '"abc" #def\n #ghi\nfrom __future__ import (division as b, generators,)\nfrom __future__ import with_statement\n' - f = run(s) + f = run(s, (4, 23)) assert f == (fut.CO_FUTURE_DIVISION | fut.CO_GENERATOR_ALLOWED | fut.CO_FUTURE_WITH_STATEMENT) def test_windows_style_lineendings(): s = '"abc" #def\r\n #ghi\r\nfrom __future__ import (division as b, generators,)\r\nfrom __future__ import with_statement\r\n' - f = run(s) + f = run(s, (4, 23)) assert f == (fut.CO_FUTURE_DIVISION | fut.CO_GENERATOR_ALLOWED | fut.CO_FUTURE_WITH_STATEMENT) def test_mac_style_lineendings(): s = '"abc" #def\r #ghi\rfrom __future__ import (division as b, generators,)\rfrom __future__ import with_statement\r' - f = run(s) + f = run(s, (4, 23)) assert f == (fut.CO_FUTURE_DIVISION | fut.CO_GENERATOR_ALLOWED | fut.CO_FUTURE_WITH_STATEMENT) def test_semicolon(): s = '"abc" #def\n #ghi\nfrom __future__ import (division as b, generators,); from __future__ import with_statement\n' - f = run(s) + f = run(s, (3, 78)) assert f == (fut.CO_FUTURE_DIVISION | fut.CO_GENERATOR_ALLOWED | fut.CO_FUTURE_WITH_STATEMENT) def test_semicolon_2(): s = 'from __future__ import division; from foo import bar' - f = run(s, expected_last_future=(1, 39)) + f = run(s, expected_last_future=(1, 24)) assert f == fut.CO_FUTURE_DIVISION def test_full_chain(): s = '"abc" #def\n #ghi\nfrom __future__ import (division as b, generators,); from __future__ import with_statement\n' - f = run(s) + f = run(s, (3, 78)) assert f == (fut.CO_FUTURE_DIVISION | fut.CO_GENERATOR_ALLOWED | fut.CO_FUTURE_WITH_STATEMENT) def test_intervening_code(): s = 'from __future__ import (division as b, generators,)\nfrom sys import modules\nfrom __future__ import with_statement\n' - f = run(s, expected_last_future=(2, 5)) + f = run(s, expected_last_future=(1, 25)) assert f == (fut.CO_FUTURE_DIVISION | fut.CO_GENERATOR_ALLOWED) def test_nonexisting(): s = 'from __future__ import non_existing_feature\n' - f = run(s) + f = run(s, (1, 24)) assert f == 0 def test_nonexisting_2(): s = 'from __future__ import non_existing_feature, with_statement\n' - f = run(s) + f = run(s, (1, 24)) assert f == fut.CO_FUTURE_WITH_STATEMENT def test_from_import_abs_import(): s = 'from __future__ import absolute_import\n' - f = run(s) + f = run(s, (1, 24)) assert f == fut.CO_FUTURE_ABSOLUTE_IMPORT def test_raw_doc(): s = 'r"Doc"\nfrom __future__ import with_statement\n' - f = run(s) + f = run(s, (2, 23)) assert f == fut.CO_FUTURE_WITH_STATEMENT def test_unicode_doc(): s = 'u"Doc"\nfrom __future__ import with_statement\n' - f = run(s) + f = run(s, (2, 23)) assert f == fut.CO_FUTURE_WITH_STATEMENT def test_raw_unicode_doc(): s = 'ru"Doc"\nfrom __future__ import with_statement\n' - f = run(s) + f = run(s, (2, 23)) assert f == fut.CO_FUTURE_WITH_STATEMENT def test_continuation_line(): s = "\\\nfrom __future__ import with_statement\n" - f = run(s) + f = run(s, (2, 23)) assert f == fut.CO_FUTURE_WITH_STATEMENT def test_continuation_lines(): s = "\\\n \t\\\nfrom __future__ import with_statement\n" - f = run(s) + f = run(s, (3, 23)) assert f == fut.CO_FUTURE_WITH_STATEMENT def test_lots_of_continuation_lines(): s = "\\\n\\\n\\\n\\\n\\\n\\\n\nfrom __future__ import with_statement\n" - f = run(s) + f = run(s, (8, 23)) assert f == fut.CO_FUTURE_WITH_STATEMENT def test_continuation_lines_raise(): s = " \\\n \t\\\nfrom __future__ import with_statement\n" - f = run(s, expected_last_future=(1, 0)) + f = run(s) assert f == 0 # because of the INDENT def test_continuation_lines_in_docstring_single_quoted(): s = '"\\\n\\\n\\\n\\\n\\\n\\\n"\nfrom __future__ import division\n' - f = run(s) + f = run(s, (8, 24)) assert f == fut.CO_FUTURE_DIVISION def test_continuation_lines_in_docstring_triple_quoted(): s = '"""\\\n\\\n\\\n\\\n\\\n\\\n"""\nfrom __future__ import division\n' - f = run(s) + f = run(s, (8, 24)) assert f == fut.CO_FUTURE_DIVISION def test_blank_lines(): s = ('\n\t\n\nfrom __future__ import with_statement' ' \n \n \nfrom __future__ import division') - f = run(s) + f = run(s, (7, 23)) assert f == fut.CO_FUTURE_WITH_STATEMENT | fut.CO_FUTURE_DIVISION def test_dummy_semicolons(): s = ('from __future__ import division;\n' 'from __future__ import with_statement;') - f = run(s) + f = run(s, (2, 23)) assert f == fut.CO_FUTURE_DIVISION | fut.CO_FUTURE_WITH_STATEMENT diff --git a/pypy/interpreter/test/test_syntax.py b/pypy/interpreter/test/test_syntax.py --- a/pypy/interpreter/test/test_syntax.py +++ b/pypy/interpreter/test/test_syntax.py @@ -366,6 +366,15 @@ assert isinstance(ns["b"], str) assert isinstance(ns["c"], str) + def test_both_futures_with_semicolon(self): + # Issue #2526: a corner case which crashes only if the file + # contains *nothing more* than two __future__ imports separated + # by a semicolon. + s = """ +from __future__ import unicode_literals; from __future__ import print_function +""" + exec s in {} + class AppTestComprehensions: From pypy.commits at gmail.com Sat Apr 1 05:19:16 2017 From: pypy.commits at gmail.com (arigo) Date: Sat, 01 Apr 2017 02:19:16 -0700 (PDT) Subject: [pypy-commit] pypy default: Trying to fix the vmprof platform-conditionals Message-ID: <58df7094.4ca8df0a.cbf22.ad49@mx.google.com> Author: Armin Rigo Branch: Changeset: r90890:2846cda12de2 Date: 2017-04-01 11:11 +0200 http://bitbucket.org/pypy/pypy/changeset/2846cda12de2/ Log: Trying to fix the vmprof platform-conditionals diff --git a/rpython/rlib/rvmprof/cintf.py b/rpython/rlib/rvmprof/cintf.py --- a/rpython/rlib/rvmprof/cintf.py +++ b/rpython/rlib/rvmprof/cintf.py @@ -22,29 +22,31 @@ SHARED.join('symboltable.c') ] if sys.platform.startswith('linux'): - separate_module_files += [ - BACKTRACE.join('backtrace.c'), - BACKTRACE.join('state.c'), - BACKTRACE.join('elf.c'), - BACKTRACE.join('dwarf.c'), - BACKTRACE.join('fileline.c'), - BACKTRACE.join('mmap.c'), - BACKTRACE.join('mmapio.c'), - BACKTRACE.join('posix.c'), - BACKTRACE.join('sort.c'), - ] + if sys.maxint > 2**32: # doesn't seem to compile on 32-bit Linux + separate_module_files += [ + BACKTRACE.join('backtrace.c'), + BACKTRACE.join('state.c'), + BACKTRACE.join('elf.c'), + BACKTRACE.join('dwarf.c'), + BACKTRACE.join('fileline.c'), + BACKTRACE.join('mmap.c'), + BACKTRACE.join('mmapio.c'), + BACKTRACE.join('posix.c'), + BACKTRACE.join('sort.c'), + ] + compile_extra += ['-DVMPROF_BACKTRACE'] _libs = ['dl'] compile_extra += ['-DVMPROF_UNIX'] compile_extra += ['-DVMPROF_LINUX'] -elif sys.platform == 'darwin': +elif sys.platform == 'win32': + compile_extra = ['-DRPYTHON_VMPROF', '-DVMPROF_WINDOWS'] + separate_module_files = [SHARED.join('vmprof_main_win32.c')] + _libs = [] +else: + # Guessing a BSD-like Unix platform compile_extra += ['-DVMPROF_UNIX'] compile_extra += ['-DVMPROF_MAC'] _libs = [] -else: - # windows - compile_extra = ['-DRPYTHON_VMPROF', '-DVMPROF_WINDOWS'] - separate_module_files = [SHARED.join('vmprof_main_win32.c')] - _libs = [] eci_kwds = dict( diff --git a/rpython/rlib/rvmprof/src/shared/symboltable.c b/rpython/rlib/rvmprof/src/shared/symboltable.c --- a/rpython/rlib/rvmprof/src/shared/symboltable.c +++ b/rpython/rlib/rvmprof/src/shared/symboltable.c @@ -8,7 +8,7 @@ #include #include -#ifdef VMPROF_LINUX +#ifdef VMPROF_BACKTRACE #include #endif @@ -215,7 +215,7 @@ name[name_len-1] = 0; } lookup_vmprof_debug_info(name, info.dli_fbase, srcfile, srcfile_len, lineno); -#elif defined(__unix__) +#elif defined(RVMPROF_BACKTRACE) if (bstate == NULL) { bstate = backtrace_create_state (NULL, 1, backtrace_error_cb, NULL); } From pypy.commits at gmail.com Sat Apr 1 08:54:40 2017 From: pypy.commits at gmail.com (plan_rich) Date: Sat, 01 Apr 2017 05:54:40 -0700 (PDT) Subject: [pypy-commit] extradoc extradoc: add blog post entry Message-ID: <58dfa310.d5161c0a.9e3bf.7d51@mx.google.com> Author: Richard Plangger Branch: extradoc Changeset: r5793:3ed56edfa7ab Date: 2017-04-01 08:54 -0400 http://bitbucket.org/pypy/extradoc/changeset/3ed56edfa7ab/ Log: add blog post entry diff --git a/blog/draft/vmprof-native.rst b/blog/draft/vmprof-native.rst new file mode 100644 --- /dev/null +++ b/blog/draft/vmprof-native.rst @@ -0,0 +1,149 @@ +We are happy to announce a new release for the PyPI package vmprof. + +It is now able to capture native stack frames on Linux and Mac OS X to show you bottle necks in compiled code (such as CFFI modules, Cython or C Python extensions). It supports PyPy, CPython versions 2.7, 3.4, 3.5 and 3.6. Special thanks to Jetbrains for funding the native profiling support. + +What is vmprof? +=============== + +If you have already worked with vmprof you can skip the next two section. If not, here is a short introduction: + + +The goal of vmprof package is to give you more insight into your program. It is a statistical profiler. Another prominent profiler you might already have worked with is cProfile. It is bundled with the Python standard library. + + +vmprof's distinct feature (from most other profilers) is that it does not significantly slow down your program execution. The employed strategy is statistical, rather than deterministic. Not every function call is intercepted, but it samples stack traces and memory usage at a configured sample rate (usually around 100hz). You can imagine that this creates a lot less contention than doing work before and after each function call. + + +As mentioned earlier cProfile gives you a complete profile, but it needs to intercept every function call (it is a deterministic profiler). Usually this means that you have to capture and record every function call, but this takes an significant amount time. + + +The overhead vmprof consumes is roughly 3-4% of your total program runtime or even less if you reduce the sampling frequency. Indeed it lets you sample and inspect much larger programs. If you failed to profile a large application with cProfile, please give vmprof a shot. + + +vmprof.com or PyCharm +====================== + + +There are two major alternative to the command line tools shipped with vmprof. + + A web service on vmprof.com + A commercial version of PyCharm + +Since the PyPy Team runs and maintains the service on vmprof.com I'll explain some more details here. Still PyCharm is a great IDE and uses vmprof to display the statistical profiles. We highly recommend to use either of those, the command line tool is only good for quick inspection. + + +On vmprof.com you can inspect the generated profile interactively instead of looking at console output. What is sent to vmprof.com? You can find details here. + + +There are currently three visualizations we'll quickly explain: + + +Flamegraph: Accumulates and displays the most frequent codepaths. It allows you to quickly and accurately identify hot spots in your code. The flame graph below is a very short run of richards.py (less. Thus it shows a lot of time spent in PyPy's JIT compiler. + + + +List all functions (optionally sorted): the equivalent of the vmprof command line output in the web. + + + +Memory curve: A line plot that shows how how many MBytes have been consumed over the lifetime of your program (see more info in the section below). + + + +Native programs +=============== + +The new feature introduced in vmprof 0.4.0 allows you to look beyond the Python level. As you might know, Python maintains a stack of frames to save the execution. Up to now the vmprof profiles only contained that level of information. But what if you program jumps to native code (such as calling gzip compression on a large file)? Up to now you would not see that information. + + +Many packages make use of the CPython C API (which we discurage, please lookup cffi for a better way to call C). Have you ever had the issue that you know that your performance problems reach down to, but you could not profile it properly? Now you can! + + +Let's inspect a very simple Python program to find out why a program is significantly slower on Linux than on Mac: + + +import numpy as np +n = 1000 +a = np.random.random((n, n)) +b = np.random.random((n, n)) +c = np.dot(np.abs(a), b) + + +Take two NxN random matrix objects and create a dot product. The first argument to the dot product provides the absolute value of the random matrix. + + +Run, Python, NumPy, OS, n=..., Took +[1] CPython 3.5.2, NumPy 1.12.1, Mac OS X, 10.12.3, n=5000, ~9 sec +[2] CPython 3.6.0, NumPy 1.12.1, Linux 64, Kernel 4.9.14, n=1000, ~26 sec + +Note that the Linux machine operates on a 5 times smaller matrix, still it takes much longer. What is wrong? Is Linux slow? CPython 3.6.0? Well no, lets inspect and [1] and [2] (shown below in that order). + +[2] runs on Linux, spends nearly all of the time in PyArray_MatrixProduct2, if you compare to [1] on Mac OS X, you'll see that a lot of time is spent in generating the random numbers and the rest in cblas_matrixproduct. + +Blas has a very efficient implementation so you can achieve the same on Linux if you install a blas implementation (such as openblas). + +Usually you can spot potential program source locations that take a lot of time and might be the first starting point to resolve performance issues. + +Beyond Python programs +====================== + + +It is not unthinkable that the strategy can be reused for native programs. Indeed this can already be done by creating a small cffi wrapper around an entry point of a compiled C program. It would even work for programs compiled from other languages (e.g. C++ or Fortran). The resulting function names are the full symbol name embedded into either the executable symboltable or extracted from the dwarf debugging information. Most of those will be compiler specific and contain some cryptic information. + +Memory profiling +================ + +We thankfully received a code contribution from the company Blue Yonder. They have built a memory profiler (for Linux and Mac OS X) on top of vmprof.com that displays the memory consumption for the runtime of your process. + +You can run it the following way: + + +$ python -m vmprof --mem --web script.py + + +By adding --mem, vmprof will capture memory information and display it in the dedicated view on vmprof.com. You can tha view by by clicking the 'Memory' switch in the flamegraph view. + + +There is more + + +Some more minor highlights contained in 0.4.x: + + VMProf support for Windows 64 bit (python only) + VMProf can read profiles generated by another host system + VMProf is now bundled in several binary wheel for fast and easy installation (Mac OS X, Linux 32/64 for CPython 2.7, 3.4, 3.5, 3.6) + +Future plans - Profile Streaming +================================ + + +vmprof has not reached the end of development. There are many features we could implement. But there is one feature that could be a great asset to many Python developers. + + +Continuous delivery of your statistical profile, or in short, profile streaming. One of the great strengths of vmprof is that is consumes very little overhead. It is not a crazy idea to run this in production. + + +It would require a smart way to stream the profile in the background to vmprof.com and new visualizations to look at much more data your Python service produces. + + +If that sounds like a solid vmprof improvement, don't hesitate to get in touch with us (e.g. IRC #pypy, mailing list pypy-dev, or comment below) + + +You can help! +============= + + +There are some immediate things other people could help with. Either by donating time or money (yes we have occasional contributors which is great)! + + We gladly received code contribution for the memory profiler. But it was not enough time to finish the migration completely. Sadly it is a bit brittle right now. + We would like to spend more time on other visualizations. This should include to give a much better user experience on vmprof.com (like a tutorial that explains the visualization that we already have). + Build Windows 32/64 bit wheels (for all CPython versions we currently support) + +We are also happy to accept google summer of code projects on vmprof for new visualizations and other improvements. If you qualify and are interested, don't hesitate to ask! + + +Richard Plangger (plan_rich) and the PyPy Team + + +[1] Mac OS X http://vmprof.com/#/567aa150-5927-4867-b22d-dbb67ac824ac +[2] Linux64 http://vmprof.com/#/097fded2-b350-4d68-ae93-7956cd10150c From pypy.commits at gmail.com Sat Apr 1 11:22:55 2017 From: pypy.commits at gmail.com (rlamy) Date: Sat, 01 Apr 2017 08:22:55 -0700 (PDT) Subject: [pypy-commit] pypy PyBuffer: Remove BinaryBuffer API from Buffer: getitem(), setitem(), getslice(), setslice() Message-ID: <58dfc5cf.4ca8df0a.cbf22.1496@mx.google.com> Author: Ronan Lamy Branch: PyBuffer Changeset: r90893:d7d49f4a1803 Date: 2017-04-01 16:22 +0100 http://bitbucket.org/pypy/pypy/changeset/d7d49f4a1803/ Log: Remove BinaryBuffer API from Buffer: getitem(), setitem(), getslice(), setslice() diff --git a/pypy/interpreter/buffer.py b/pypy/interpreter/buffer.py --- a/pypy/interpreter/buffer.py +++ b/pypy/interpreter/buffer.py @@ -15,23 +15,6 @@ "Returns an interp-level string with the whole content of the buffer." return ''.join(self._copy_buffer()) - def getitem(self, index): - "Returns the index'th character in the buffer." - raise NotImplementedError # Must be overriden. No bounds checks. - - def getslice(self, start, stop, step, size): - # May be overridden. No bounds checks. - return ''.join([self.getitem(i) for i in range(start, stop, step)]) - - def setitem(self, index, char): - "Write a character into the buffer." - raise NotImplementedError # Must be overriden. No bounds checks. - - def setslice(self, start, string): - # May be overridden. No bounds checks. - for i in range(len(string)): - self.setitem(start + i, string[i]) - def get_raw_address(self): raise ValueError("no raw buffer") @@ -109,12 +92,6 @@ def as_str(self): return self.data.as_str() - def getitem(self, index): - return self.data.getitem(index) - - def setitem(self, index, value): - return self.data.setitem(index, value) - def get_raw_address(self): return self.data.get_raw_address() @@ -237,7 +214,7 @@ if start == 0 and stop == len(self.value): return self.value return self.value[start:stop] - return Buffer.getslice(self, start, stop, step, size) + return BinaryBuffer.getslice(self, start, stop, step, size) def get_raw_address(self): from rpython.rtyper.lltypesystem import rffi diff --git a/pypy/objspace/std/memoryobject.py b/pypy/objspace/std/memoryobject.py --- a/pypy/objspace/std/memoryobject.py +++ b/pypy/objspace/std/memoryobject.py @@ -695,25 +695,6 @@ def getlength(self): return self.shape[0] * self.getitemsize() - def getitem(self, index): - return self.buf.getitem(self.offset + index) - - def setitem(self, index, char): - self.buf.setitem(self.offset + index, char) - - def getslice(self, start, stop, step, size): - if start == stop: - return '' # otherwise, adding self.offset might make them - # out of bounds - return self.buf.getslice(self.offset + start, self.offset + stop, - step, size) - - def setslice(self, start, string): - if len(string) == 0: - return # otherwise, adding self.offset might make 'start' - # out of bounds - self.buf.setslice(self.offset + start, string) - def get_raw_address(self): from rpython.rtyper.lltypesystem import rffi ptr = self.buf.get_raw_address() @@ -748,18 +729,6 @@ def as_str_and_offset_maybe(self): return self.parent.as_str_and_offset_maybe() - def getitem(self, index): - return self.parent.getitem(index) - - def setitem(self, index, value): - return self.parent.setitem(index, value) - - def getslice(self, start, stop, step, size): - return self.parent.getslice(start, stop, step, size) - - def setslice(self, start, string): - self.parent.setslice(start, string) - def get_raw_address(self): return self.parent.get_raw_address() From pypy.commits at gmail.com Sat Apr 1 11:22:52 2017 From: pypy.commits at gmail.com (rlamy) Date: Sat, 01 Apr 2017 08:22:52 -0700 (PDT) Subject: [pypy-commit] pypy PyBuffer: Fix PyBuffer/BinaryBuffer confusion in _cffi_backend Message-ID: <58dfc5cc.d4b2df0a.b60ec.1638@mx.google.com> Author: Ronan Lamy Branch: PyBuffer Changeset: r90891:d8147a9479bc Date: 2017-04-01 02:13 +0100 http://bitbucket.org/pypy/pypy/changeset/d8147a9479bc/ Log: Fix PyBuffer/BinaryBuffer confusion in _cffi_backend diff --git a/pypy/module/_cffi_backend/cbuffer.py b/pypy/module/_cffi_backend/cbuffer.py --- a/pypy/module/_cffi_backend/cbuffer.py +++ b/pypy/module/_cffi_backend/cbuffer.py @@ -79,20 +79,20 @@ if space.isinstance_w(w_other, space.w_unicode): return space.w_NotImplemented try: - other_buf = space.buffer_w(w_other, space.BUF_SIMPLE) + other_pybuf = space.buffer_w(w_other, space.BUF_SIMPLE) except OperationError as e: if e.async(space): raise return space.w_NotImplemented my_buf = self.buffer my_len = len(my_buf) - other_len = len(other_buf) + other_len = other_pybuf.getlength() if other_len != my_len: if mode == 'E': return space.w_False if mode == 'N': return space.w_True - cmp = _memcmp(my_buf, other_buf, min(my_len, other_len)) + cmp = _memcmp(my_buf, other_pybuf.as_binary(), min(my_len, other_len)) if cmp == 0: if my_len < other_len: cmp = -1 From pypy.commits at gmail.com Sat Apr 1 11:22:54 2017 From: pypy.commits at gmail.com (rlamy) Date: Sat, 01 Apr 2017 08:22:54 -0700 (PDT) Subject: [pypy-commit] pypy PyBuffer: Remove __len__ and __getitem__ from Buffer API Message-ID: <58dfc5ce.97e61c0a.626da.e5df@mx.google.com> Author: Ronan Lamy Branch: PyBuffer Changeset: r90892:a4ec60792800 Date: 2017-04-01 02:26 +0100 http://bitbucket.org/pypy/pypy/changeset/a4ec60792800/ Log: Remove __len__ and __getitem__ from Buffer API diff --git a/pypy/interpreter/buffer.py b/pypy/interpreter/buffer.py --- a/pypy/interpreter/buffer.py +++ b/pypy/interpreter/buffer.py @@ -11,11 +11,6 @@ """Returns the size in bytes (even if getitemsize() > 1).""" raise NotImplementedError - def __len__(self): - res = self.getlength() - assert res >= 0 - return res - def as_str(self): "Returns an interp-level string with the whole content of the buffer." return ''.join(self._copy_buffer()) @@ -24,9 +19,6 @@ "Returns the index'th character in the buffer." raise NotImplementedError # Must be overriden. No bounds checks. - def __getitem__(self, i): - return self.getitem(i) - def getslice(self, start, stop, step, size): # May be overridden. No bounds checks. return ''.join([self.getitem(i) for i in range(start, stop, step)]) From pypy.commits at gmail.com Sat Apr 1 12:02:44 2017 From: pypy.commits at gmail.com (arigo) Date: Sat, 01 Apr 2017 09:02:44 -0700 (PDT) Subject: [pypy-commit] pypy default: Be explicit about not-implemented slot wrappers, rather than defaulting Message-ID: <58dfcf24.16a1df0a.3ba5d.22ba@mx.google.com> Author: Armin Rigo Branch: Changeset: r90894:20b913db347d Date: 2017-04-01 18:02 +0200 http://bitbucket.org/pypy/pypy/changeset/20b913db347d/ Log: Be explicit about not-implemented slot wrappers, rather than defaulting to that if we don't find any global function with the correct name diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -810,6 +810,9 @@ wrapper = None else: wrapper = globals().get(WRAPPER, Ellipsis) + if wrapper is Ellipsis: + assert WRAPPER.endswith('_XXX'), ( + "no wrapper function called %r in slotdefs.py" % WRAPPER) # irregular interface, because of tp_getattr/tp_getattro confusion if NAME == "__getattr__": @@ -826,6 +829,7 @@ if wrapper is Ellipsis: @func_renamer(WRAPPER) def wrapper(space, w_self, w_args, func, w_kwds): + print "cpyext missing wrapper", WRAPPER, "for", NAME raise NotImplementedError("Wrapper for slot " + NAME) wrapper1 = None wrapper2 = wrapper @@ -833,6 +837,7 @@ if wrapper is Ellipsis: @func_renamer(WRAPPER) def wrapper(space, w_self, w_args, func): + print "cpyext missing wrapper", WRAPPER, "for", NAME raise NotImplementedError("Wrapper for slot " + NAME) wrapper1 = wrapper wrapper2 = None @@ -879,15 +884,18 @@ # Copy new slotdefs from typeobject.c # Remove comments and tabs # Done. +# XXX NOTE that we already tweaked that string manually! +# Also, a few wrapper functions have a name ending in "_XXX" to mean +# that we know it is not implemented so far. slotdefs_str = r""" static slotdef slotdefs[] = { SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc, "x.__len__() <==> len(x)"), SQSLOT("__add__", sq_concat, slot_sq_concat, wrap_binaryfunc, "x.__add__(y) <==> x+y"), - SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc, + SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc_XXX, "x.__mul__(n) <==> x*n"), - SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc, + SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc_XXX, "x.__rmul__(n) <==> n*x"), SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item, "x.__getitem__(y) <==> x[y]"), @@ -904,7 +912,7 @@ "x.__setslice__(i, j, y) <==> x[i:j]=y\n\ \n\ Use of negative indices is not supported."), - SQSLOT("__delslice__", sq_ass_slice, slot_sq_ass_slice, wrap_delslice, + SQSLOT("__delslice__", sq_ass_slice, slot_sq_ass_slice, wrap_delslice_XXX, "x.__delslice__(i, j) <==> del x[i:j]\n\ \n\ Use of negative indices is not supported."), @@ -913,7 +921,7 @@ SQSLOT("__iadd__", sq_inplace_concat, NULL, wrap_binaryfunc, "x.__iadd__(y) <==> x+=y"), SQSLOT("__imul__", sq_inplace_repeat, NULL, - wrap_indexargfunc, "x.__imul__(y) <==> x*=y"), + wrap_indexargfunc_XXX, "x.__imul__(y) <==> x*=y"), MPSLOT("__len__", mp_length, slot_mp_length, wrap_lenfunc, "x.__len__() <==> len(x)"), @@ -972,7 +980,7 @@ RBINSLOT("__rxor__", nb_xor, slot_nb_xor, "^"), BINSLOT("__or__", nb_or, slot_nb_or, "|"), RBINSLOT("__ror__", nb_or, slot_nb_or, "|"), - NBSLOT("__coerce__", nb_coerce, slot_nb_coerce, wrap_coercefunc, + NBSLOT("__coerce__", nb_coerce, slot_nb_coerce, wrap_coercefunc_XXX, "x.__coerce__(y) <==> coerce(x, y)"), UNSLOT("__int__", nb_int, slot_nb_int, wrap_unaryfunc, "int(x)"), From pypy.commits at gmail.com Sat Apr 1 12:12:29 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sat, 01 Apr 2017 09:12:29 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: CPython makes a difference between OSError(None, None) and OSError(), Message-ID: <58dfd16d.c791df0a.48e0c.237c@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90895:259a16de4c00 Date: 2017-04-01 14:35 +0200 http://bitbucket.org/pypy/pypy/changeset/259a16de4c00/ Log: CPython makes a difference between OSError(None,None) and OSError(), do the same in PyPy diff --git a/pypy/module/exceptions/interp_exceptions.py b/pypy/module/exceptions/interp_exceptions.py --- a/pypy/module/exceptions/interp_exceptions.py +++ b/pypy/module/exceptions/interp_exceptions.py @@ -443,10 +443,10 @@ """OS system call failed.""" def __init__(self, space): - self.w_errno = space.w_None - self.w_strerror = space.w_None - self.w_filename = space.w_None - self.w_filename2 = space.w_None + self.w_errno = None + self.w_strerror = None + self.w_filename = None + self.w_filename2 = None self.written = -1 # only for BlockingIOError. W_BaseException.__init__(self, space) @@ -556,9 +556,9 @@ # since we rebind args_w, we need special reduce, grump def descr_reduce(self, space): extra = [] - if not space.is_w(self.w_filename, space.w_None): + if self.w_filename: extra.append(self.w_filename) - if not space.is_w(self.w_filename2, space.w_None): + if self.w_filename2: extra.append(space.w_None) extra.append(self.w_filename2) lst = [self.getclass(space), space.newtuple(self.args_w + extra)] @@ -567,25 +567,26 @@ return space.newtuple(lst) def descr_str(self, space): - if (not space.is_w(self.w_errno, space.w_None) and - not space.is_w(self.w_strerror, space.w_None)): + if self.w_errno: errno = space.unicode_w(space.str(self.w_errno)) + else: + errno = u"" + if self.w_strerror: strerror = space.unicode_w(space.str(self.w_strerror)) - if not space.is_w(self.w_filename, space.w_None): - if not space.is_w(self.w_filename2, space.w_None): - return space.newunicode(u"[Errno %s] %s: %s -> %s" % ( - errno, - strerror, - space.unicode_w(space.repr(self.w_filename)), - space.unicode_w(space.repr(self.w_filename2)))) - return space.newunicode(u"[Errno %s] %s: %s" % ( - errno, - strerror, - space.unicode_w(space.repr(self.w_filename)))) + else: + strerror = u"" + if self.w_filename: + if self.w_filename2: + return space.newunicode(u"[Errno %s] %s: %s -> %s" % ( + errno, strerror, + space.unicode_w(space.repr(self.w_filename)), + space.unicode_w(space.repr(self.w_filename2)))) + return space.newunicode(u"[Errno %s] %s: %s" % ( + errno, strerror, + space.unicode_w(space.repr(self.w_filename)))) + if self.w_errno and self.w_strerror: return space.newunicode(u"[Errno %s] %s" % ( - errno, - strerror, - )) + errno, strerror)) return W_BaseException.descr_str(self, space) def descr_get_written(self, space): @@ -637,7 +638,7 @@ not space.is_w(self.w_strerror, space.w_None)): winerror = space.int_w(self.w_winerror) strerror = space.unicode_w(self.w_strerror) - if not space.is_w(self.w_filename, space.w_None): + if self.w_filename: return space.newunicode(u"[Error %d] %s: %s" % ( winerror, strerror, diff --git a/pypy/module/exceptions/test/test_exc.py b/pypy/module/exceptions/test/test_exc.py --- a/pypy/module/exceptions/test/test_exc.py +++ b/pypy/module/exceptions/test/test_exc.py @@ -2,8 +2,6 @@ class AppTestExc(object): - spaceconfig = dict(usemodules=('exceptions',)) - def setup_class(cls): cls.w_file = cls.space.wrap(__file__) @@ -392,6 +390,12 @@ assert e.filename2 == "bok" assert str(e) == "[Errno 42] bar: 'baz' -> 'bok'" + def test_oserror_None(self): + assert str(OSError()) == "" + assert str(OSError(None)) == "None" + assert str(OSError(None, None)) == "[Errno None] None" + assert str(OSError(None, None, None, None)) == "[Errno None] None" + # Check the heuristic for print & exec covers significant cases # As well as placing some limits on false positives def test_former_statements_refer_to_builtins(self): From pypy.commits at gmail.com Sat Apr 1 12:12:31 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sat, 01 Apr 2017 09:12:31 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: Remove WindowsError, and add support for the "winerror" parameter in OSError. Message-ID: <58dfd16f.92061c0a.eba0.af88@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90896:1b8d1cb66a57 Date: 2017-04-01 18:11 +0200 http://bitbucket.org/pypy/pypy/changeset/1b8d1cb66a57/ Log: Remove WindowsError, and add support for the "winerror" parameter in OSError. Also maybe fix wrap_oserror on Windows. This is a shoot in the dark: I don't have Windows. But most of interp_exceptions can be tested on Linux. diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py --- a/pypy/interpreter/error.py +++ b/pypy/interpreter/error.py @@ -9,6 +9,7 @@ from rpython.rlib.objectmodel import we_are_translated, specialize from rpython.rlib.objectmodel import dont_inline from rpython.rlib import rstack, rstackovf +from rpython.rlib import rwin32 from pypy.interpreter import debug @@ -568,33 +569,6 @@ # 31: ANSI color code "red" ansi_print(text, esc="31", file=file, newline=newline) -try: - WindowsError -except NameError: - _WINDOWS = False -else: - _WINDOWS = True - - def wrap_windowserror(space, e, w_filename=None): - XXX # WindowsError no longer exists in Py3.5 - # instead, OSError has a kwarg winerror that overrides - # any errno supplied - from rpython.rlib import rwin32 - - winerror = e.winerror - try: - msg = rwin32.FormatError(winerror) - except ValueError: - msg = 'Windows Error %d' % winerror - exc = space.w_WindowsError - if w_filename is not None: - w_error = space.call_function(exc, space.newint(winerror), - space.newtext(msg), w_filename) - else: - w_error = space.call_function(exc, space.newint(winerror), - space.newtext(msg)) - return OperationError(exc, w_error) - @specialize.arg(3, 6) def wrap_oserror2(space, e, w_filename=None, exception_name='w_OSError', w_exception_class=None, w_filename2=None, eintr_retry=False): @@ -612,9 +586,6 @@ """ assert isinstance(e, OSError) - if _WINDOWS and isinstance(e, WindowsError): - return wrap_windowserror(space, e, w_filename) - if w_exception_class is None: w_exc = getattr(space, exception_name) else: @@ -631,28 +602,37 @@ def _wrap_oserror2_impl(space, e, w_filename, w_filename2, w_exc, eintr_retry): # move the common logic in its own function, instead of having it # duplicated 4 times in all 4 specialized versions of wrap_oserror2() - errno = e.errno - if errno == EINTR: - space.getexecutioncontext().checksignals() - if eintr_retry: - return None + if rwin32.WIN32 and isinstance(e, WindowsError): + winerror = e.winerror + try: + msg = rwin32.FormatError(winerror) + except ValueError: + msg = 'Windows Error %d' % winerror + w_errno = space.w_None + w_winerror = space.newint(winerror) + w_msg = space.newtext(msg) + else: + errno = e.errno + if errno == EINTR: + space.getexecutioncontext().checksignals() + if eintr_retry: + return None - try: - msg = strerror(errno) - except ValueError: - msg = u'error %d' % errno - if w_filename is not None: - if w_filename2 is not None: - w_error = space.call_function(w_exc, space.newint(errno), - space.newunicode(msg), w_filename, - space.w_None, w_filename2) - else: - w_error = space.call_function(w_exc, space.newint(errno), - space.newunicode(msg), w_filename) - else: - w_error = space.call_function(w_exc, space.newint(errno), - space.newunicode(msg)) + try: + msg = strerror(errno) + except ValueError: + msg = u'error %d' % errno + w_errno = space.newint(errno) + w_winerror = space.w_None + w_msg = space.newunicode(msg) + + if w_filename is None: + w_filename = space.w_None + if w_filename2 is None: + w_filename2 = space.w_None + w_error = space.call_function(w_exc, w_errno, w_msg, w_filename, + w_winerror, w_filename2) operror = OperationError(w_exc, w_error) if eintr_retry: raise operror diff --git a/pypy/module/exceptions/__init__.py b/pypy/module/exceptions/__init__.py --- a/pypy/module/exceptions/__init__.py +++ b/pypy/module/exceptions/__init__.py @@ -1,4 +1,4 @@ -import sys +from rpython.rlib import rwin32 from pypy.interpreter.mixedmodule import MixedModule class Module(MixedModule): @@ -73,8 +73,8 @@ 'ZeroDivisionError' : 'interp_exceptions.W_ZeroDivisionError', } - if sys.platform.startswith("win"): - interpleveldefs['WindowsError'] = 'interp_exceptions.W_WindowsError' + if rwin32.WIN32: + interpleveldefs['WindowsError'] = 'interp_exceptions.W_OSError' def setup_after_space_initialization(self): from pypy.objspace.std.transparent import register_proxyable diff --git a/pypy/module/exceptions/interp_exceptions.py b/pypy/module/exceptions/interp_exceptions.py --- a/pypy/module/exceptions/interp_exceptions.py +++ b/pypy/module/exceptions/interp_exceptions.py @@ -444,6 +444,7 @@ def __init__(self, space): self.w_errno = None + self.w_winerror = None self.w_strerror = None self.w_filename = None self.w_filename2 = None @@ -476,18 +477,36 @@ w_errno = args_w[0] w_strerror = args_w[1] w_filename = None + w_winerror = None w_filename2 = None if len(args_w) > 2: w_filename = args_w[2] - if len(args_w) > 4: - w_filename2 = args_w[4] - return w_errno, w_strerror, w_filename, w_filename2 - return None, None, None, None + if len(args_w) > 3: + w_winerror = args_w[3] + if len(args_w) > 4: + w_filename2 = args_w[4] + if rwin32.WIN32 and w_winerror: + # Under Windows, if the winerror constructor argument is + # an integer, the errno attribute is determined from the + # Windows error code, and the errno argument is + # ignored. + # On other platforms, the winerror argument is + # ignored, and the winerror attribute does not exist. + try: + winerror = space.int_w(w_winerror) + except OperationError: + w_winerror = None + else: + w_errno = space.newint( + WINERROR_TO_ERRNO.get(winerror, DEFAULT_WIN32_ERRNO)) + return w_errno, w_winerror, w_strerror, w_filename, w_filename2 + return None, None, None, None, None @staticmethod def descr_new(space, w_subtype, __args__): args_w, kwds_w = __args__.unpack() w_errno = None + w_winerror = None w_strerror = None w_filename = None w_filename2 = None @@ -495,7 +514,7 @@ if kwds_w: raise oefmt(space.w_TypeError, "OSError does not take keyword arguments") - (w_errno, w_strerror, w_filename, w_filename2 + (w_errno, w_winerror, w_strerror, w_filename, w_filename2 ) = W_OSError._parse_init_args(space, args_w) if (not space.is_none(w_errno) and space.is_w(w_subtype, space.gettypeobject(W_OSError.typedef))): @@ -513,8 +532,8 @@ exc = space.allocate_instance(W_OSError, w_subtype) W_OSError.__init__(exc, space) if not W_OSError._use_init(space, w_subtype): - exc._init_error(space, args_w, w_errno, w_strerror, w_filename, - w_filename2) + exc._init_error(space, args_w, w_errno, w_winerror, w_strerror, + w_filename, w_filename2) return exc def descr_init(self, space, __args__): @@ -525,18 +544,17 @@ if kwds_w: raise oefmt(space.w_TypeError, "OSError does not take keyword arguments") - (w_errno, w_strerror, w_filename, w_filename2 + (w_errno, w_winerror, w_strerror, w_filename, w_filename2 ) = W_OSError._parse_init_args(space, args_w) - self._init_error(space, args_w, w_errno, w_strerror, w_filename, - w_filename2) + self._init_error(space, args_w, w_errno, w_winerror, w_strerror, + w_filename, w_filename2) - def _init_error(self, space, args_w, w_errno, w_strerror, w_filename, - w_filename2): + def _init_error(self, space, args_w, w_errno, w_winerror, w_strerror, + w_filename, w_filename2): W_BaseException.descr_init(self, space, args_w) - if w_errno: - self.w_errno = w_errno - if w_strerror: - self.w_strerror = w_strerror + self.w_errno = w_errno + self.w_winerror = w_winerror + self.w_strerror = w_strerror if not space.is_none(w_filename): if space.isinstance_w( @@ -546,7 +564,8 @@ except OperationError: self.w_filename = w_filename else: - self.w_filename = w_filename + if not space.is_none(w_filename): + self.w_filename = w_filename if not space.is_none(w_filename2): self.w_filename2 = w_filename2 # filename is removed from the args tuple (for compatibility @@ -575,6 +594,20 @@ strerror = space.unicode_w(space.str(self.w_strerror)) else: strerror = u"" + if rwin32.WIN32 and self.w_winerror: + winerror = space.unicode_w(space.str(self.w_winerror)) + # If available, winerror has the priority over errno + if self.w_filename: + if self.w_filename2: + return space.newunicode(u"[WinError %s] %s: %s -> %s" % ( + winerror, strerror, + space.unicode_w(space.repr(self.w_filename)), + space.unicode_w(space.repr(self.w_filename2)))) + return space.newunicode(u"[WinError %s] %s: %s" % ( + winerror, strerror, + space.unicode_w(space.repr(self.w_filename)))) + return space.newunicode(u"[WinError %s] %s" % ( + winerror, strerror)) if self.w_filename: if self.w_filename2: return space.newunicode(u"[Errno %s] %s: %s -> %s" % ( @@ -597,6 +630,12 @@ def descr_set_written(self, space, w_written): self.written = space.int_w(w_written) + +if hasattr(rwin32, 'build_winerror_to_errno'): + WINERROR_TO_ERRNO, DEFAULT_WIN32_ERRNO = rwin32.build_winerror_to_errno() +else: + WINERROR_TO_ERRNO, DEFAULT_WIN32_ERRNO = {}, 22 # EINVAL + W_OSError.typedef = TypeDef( 'OSError', W_Exception.typedef, @@ -609,62 +648,11 @@ strerror = readwrite_attrproperty_w('w_strerror', W_OSError), filename = readwrite_attrproperty_w('w_filename', W_OSError), filename2= readwrite_attrproperty_w('w_filename2',W_OSError), + winerror = readwrite_attrproperty_w('w_winerror', W_OSError), characters_written = GetSetProperty(W_OSError.descr_get_written, W_OSError.descr_set_written), ) -class W_WindowsError(W_OSError): - """MS-Windows OS system call failed.""" - - def __init__(self, space): - self.w_winerror = space.w_None - W_OSError.__init__(self, space) - - def descr_init(self, space, __args__): - # Set errno to the POSIX errno, and winerror to the Win32 - # error code. - W_OSError.descr_init(self, space, __args__) - try: - errno = space.int_w(self.w_errno) - except OperationError: - errno = self._default_errno - else: - errno = self._winerror_to_errno.get(errno, self._default_errno) - self.w_winerror = self.w_errno - self.w_errno = space.newint(errno) - - def descr_str(self, space): - if (not space.is_w(self.w_winerror, space.w_None) and - not space.is_w(self.w_strerror, space.w_None)): - winerror = space.int_w(self.w_winerror) - strerror = space.unicode_w(self.w_strerror) - if self.w_filename: - return space.newunicode(u"[Error %d] %s: %s" % ( - winerror, - strerror, - space.unicode_w(self.w_filename))) - return space.newunicode(u"[Error %d] %s" % (winerror, - strerror)) - return W_BaseException.descr_str(self, space) - - if hasattr(rwin32, 'build_winerror_to_errno'): - _winerror_to_errno, _default_errno = rwin32.build_winerror_to_errno() - # Python 2 doesn't map ERROR_DIRECTORY (267) to ENOTDIR but - # Python 3 (CPython issue #12802) and build_winerror_to_errno do - del _winerror_to_errno[267] - else: - _winerror_to_errno, _default_errno = {}, 22 # EINVAL - -W_WindowsError.typedef = TypeDef( - "WindowsError", - W_OSError.typedef, - __doc__ = W_WindowsError.__doc__, - __new__ = _new(W_WindowsError), - __init__ = interp2app(W_WindowsError.descr_init), - __str__ = interp2app(W_WindowsError.descr_str), - winerror = readwrite_attrproperty_w('w_winerror', W_WindowsError), - ) - W_BlockingIOError = _new_exception( "BlockingIOError", W_OSError, "I/O operation would block") W_ConnectionError = _new_exception( diff --git a/pypy/module/exceptions/test/test_exc.py b/pypy/module/exceptions/test/test_exc.py --- a/pypy/module/exceptions/test/test_exc.py +++ b/pypy/module/exceptions/test/test_exc.py @@ -101,12 +101,13 @@ WindowsError except NameError: skip('WindowsError not present') - ee = WindowsError(3, "x", "y") - assert str(ee) == "[Error 3] x: y" + ee = WindowsError(None, "x", "y", 3) + assert type(ee) is FileNotFoundError + assert str(ee) == "[WinError 3] x: 'y'" # winerror=3 (ERROR_PATH_NOT_FOUND) maps to errno=2 (ENOENT) assert ee.winerror == 3 assert ee.errno == 2 - assert str(WindowsError(3, "x")) == "[Error 3] x" + assert str(WindowsError(3, "x")) == "[Errno 3] x" def test_syntax_error(self): s = SyntaxError() From pypy.commits at gmail.com Sat Apr 1 12:19:41 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sat, 01 Apr 2017 09:19:41 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: wrap_windowserror can be replaced by wrap_oserror, everywhere. Message-ID: <58dfd31d.9d711c0a.b95d7.b007@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90897:3a59893aaaba Date: 2017-04-01 18:19 +0200 http://bitbucket.org/pypy/pypy/changeset/3a59893aaaba/ Log: wrap_windowserror can be replaced by wrap_oserror, everywhere. diff --git a/pypy/module/_multiprocessing/interp_win32.py b/pypy/module/_multiprocessing/interp_win32.py --- a/pypy/module/_multiprocessing/interp_win32.py +++ b/pypy/module/_multiprocessing/interp_win32.py @@ -4,7 +4,7 @@ from rpython.rtyper.tool import rffi_platform from rpython.translator.tool.cbuild import ExternalCompilationInfo -from pypy.interpreter.error import oefmt, wrap_windowserror +from pypy.interpreter.error import oefmt, wrap_oserror from pypy.interpreter.function import StaticMethod from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.module._multiprocessing.interp_connection import w_handle @@ -106,7 +106,7 @@ def CloseHandle(space, w_handle): handle = handle_w(space, w_handle) if not rwin32.CloseHandle(handle): - raise wrap_windowserror(space, rwin32.lastSavedWindowsError()) + raise wrap_oserror(space, rwin32.lastSavedWindowsError()) def GetLastError(space): return space.newint(rwin32.GetLastError_saved()) @@ -126,7 +126,7 @@ outputsize, inputsize, timeout, rffi.NULL) if handle == rwin32.INVALID_HANDLE_VALUE: - raise wrap_windowserror(space, rwin32.lastSavedWindowsError()) + raise wrap_oserror(space, rwin32.lastSavedWindowsError()) return w_handle(space, handle) @@ -136,7 +136,7 @@ if overlapped: raise oefmt(space.w_NotImplementedError, "expected a NULL pointer") if not _ConnectNamedPipe(handle, rffi.NULL): - raise wrap_windowserror(space, rwin32.lastSavedWindowsError()) + raise wrap_oserror(space, rwin32.lastSavedWindowsError()) def SetNamedPipeHandleState(space, w_handle, w_pipemode, w_maxinstances, w_timeout): @@ -156,7 +156,7 @@ statep[2] = rffi.ptradd(state, 2) if not _SetNamedPipeHandleState(handle, statep[0], statep[1], statep[2]): - raise wrap_windowserror(space, rwin32.lastSavedWindowsError()) + raise wrap_oserror(space, rwin32.lastSavedWindowsError()) finally: lltype.free(state, flavor='raw') lltype.free(statep, flavor='raw') @@ -165,7 +165,7 @@ def WaitNamedPipe(space, name, timeout): # Careful: zero means "default value specified by CreateNamedPipe()" if not _WaitNamedPipe(name, timeout): - raise wrap_windowserror(space, rwin32.lastSavedWindowsError()) + raise wrap_oserror(space, rwin32.lastSavedWindowsError()) @unwrap_spec(filename='fsencode', access=r_uint, share=r_uint, disposition=r_uint, flags=r_uint) @@ -180,7 +180,7 @@ disposition, flags, rwin32.NULL_HANDLE) if handle == rwin32.INVALID_HANDLE_VALUE: - raise wrap_windowserror(space, rwin32.lastSavedWindowsError()) + raise wrap_oserror(space, rwin32.lastSavedWindowsError()) return w_handle(space, handle) 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 @@ -2,7 +2,7 @@ from pypy.interpreter.baseobjspace import W_Root, BufferInterfaceNotFound from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.interpreter.typedef import TypeDef, GetSetProperty -from pypy.interpreter.error import OperationError, oefmt, wrap_windowserror +from pypy.interpreter.error import OperationError, oefmt, wrap_oserror from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rlib import rwinreg, rwin32 from rpython.rlib.rarithmetic import r_uint, intmask @@ -702,7 +702,7 @@ try: return space.newunicode(rwinreg.ExpandEnvironmentStrings(source)) except WindowsError as e: - raise wrap_windowserror(space, e) + raise wrap_oserror(space, e) def DisableReflectionKey(space, w_key): """Disables registry reflection for 32-bit processes running on a 64-bit diff --git a/pypy/module/time/interp_time.py b/pypy/module/time/interp_time.py --- a/pypy/module/time/interp_time.py +++ b/pypy/module/time/interp_time.py @@ -39,7 +39,7 @@ # timeout. On Ctrl-C, the signal handler is called, the event is set, # and the wait function exits. from rpython.rlib import rwin32 - from pypy.interpreter.error import wrap_windowserror, wrap_oserror + from pypy.interpreter.error import wrap_oserror from rpython.rlib import rthread as thread eci = ExternalCompilationInfo( @@ -101,9 +101,9 @@ globalState.interrupt_event = rwin32.CreateEvent( rffi.NULL, True, False, rffi.NULL) except WindowsError as e: - raise wrap_windowserror(space, e) + raise wrap_oserror(space, e) if not _setCtrlHandlerRoutine(globalState.interrupt_event): - raise wrap_windowserror(space, + raise wrap_oserror(space, rwin32.lastSavedWindowsError("SetConsoleCtrlHandler")) globalState = GlobalState() @@ -911,7 +911,7 @@ is_time_adjustment_disabled) if not ok: # Is this right? Cargo culting... - raise wrap_windowserror(space, + raise wrap_oserror(space, rwin32.lastSavedWindowsError("GetSystemTimeAdjustment")) resolution = resolution * time_increment[0] _setinfo(space, w_info, implementation, resolution, True, False) @@ -1020,7 +1020,7 @@ worked = GetProcessTimes(current_process, creation_time, exit_time, kernel_time, user_time) if not worked: - raise wrap_windowserror(space, + raise wrap_oserror(space, rwin32.lastSavedWindowsError("GetProcessTimes")) kernel_time2 = (kernel_time.c_dwLowDateTime | r_ulonglong(kernel_time.c_dwHighDateTime) << 32) From pypy.commits at gmail.com Sat Apr 1 12:25:34 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sat, 01 Apr 2017 09:25:34 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: In cpyext, skip WindowsError when reading symbols from the exception modules. Message-ID: <58dfd47e.ebafdf0a.a4ea2.2200@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90898:bf7f4f9cb1f4 Date: 2017-04-01 18:24 +0200 http://bitbucket.org/pypy/pypy/changeset/bf7f4f9cb1f4/ Log: In cpyext, skip WindowsError when reading symbols from the exception modules. 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 @@ -651,7 +651,7 @@ global all_exceptions all_exceptions = list(exceptions.Module.interpleveldefs) for exc_name in all_exceptions: - if exc_name in ('EnvironmentError', 'IOError'): + if exc_name in ('EnvironmentError', 'IOError', 'WindowsError'): # FIXME: aliases of OSError cause a clash of names via # export_struct continue From pypy.commits at gmail.com Sat Apr 1 12:42:43 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sat, 01 Apr 2017 09:42:43 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: Attempt to import interp_scandir on Windows Message-ID: <58dfd883.16a1df0a.3ba5d.2d63@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90899:ba2d0d7ea48e Date: 2017-04-01 18:42 +0200 http://bitbucket.org/pypy/pypy/changeset/ba2d0d7ea48e/ Log: Attempt to import interp_scandir on Windows diff --git a/rpython/rlib/rposix_scandir.py b/rpython/rlib/rposix_scandir.py --- a/rpython/rlib/rposix_scandir.py +++ b/rpython/rlib/rposix_scandir.py @@ -1,4 +1,4 @@ -from rpython.rlib import rposix +from rpython.rlib import rposix, rwin32 from rpython.rlib.objectmodel import specialize from rpython.rtyper.lltypesystem import lltype, rffi @@ -17,7 +17,8 @@ def closedir(dirp): rposix.c_closedir(dirp) -NULL_DIRP = lltype.nullptr(rposix.DIRP.TO) +if not rwin32.WIN32: + NULL_DIRP = lltype.nullptr(rposix.DIRP.TO) def nextentry(dirp): """Read the next entry and returns an opaque object. From pypy.commits at gmail.com Sat Apr 1 12:51:02 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sat, 01 Apr 2017 09:51:02 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: Convert one remaining space.wrap() in _winreg Message-ID: <58dfda76.0eb7df0a.8f5d2.e3da@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90900:ed2af05e6735 Date: 2017-04-01 18:50 +0200 http://bitbucket.org/pypy/pypy/changeset/ed2af05e6735/ Log: Convert one remaining space.wrap() in _winreg 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 @@ -110,7 +110,7 @@ elif isinstance(w_hkey, W_HKEY): return w_hkey.hkey elif space.isinstance_w(w_hkey, space.w_int): - if space.is_true(space.lt(w_hkey, space.wrap(0))): + if space.is_true(space.lt(w_hkey, space.newint(0))): return rffi.cast(rwinreg.HKEY, space.int_w(w_hkey)) return rffi.cast(rwinreg.HKEY, space.uint_w(w_hkey)) else: From pypy.commits at gmail.com Sat Apr 1 13:01:43 2017 From: pypy.commits at gmail.com (rlamy) Date: Sat, 01 Apr 2017 10:01:43 -0700 (PDT) Subject: [pypy-commit] pypy default: kill _XXX and Ellipsis hacks Message-ID: <58dfdcf7.9d711c0a.b95d7.bab4@mx.google.com> Author: Ronan Lamy Branch: Changeset: r90901:a09ae92a91a0 Date: 2017-04-01 18:01 +0100 http://bitbucket.org/pypy/pypy/changeset/a09ae92a91a0/ Log: kill _XXX and Ellipsis hacks diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -4,10 +4,10 @@ from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rlib.rarithmetic import widen -from rpython.rlib import rgc # Force registration of gc.collect +from rpython.rlib import rgc # Force registration of gc.collect from pypy.module.cpyext.api import ( - slot_function, generic_cpy_call, PyObject, Py_ssize_t, Py_TPFLAGS_CHECKTYPES, - pypy_decl, Py_buffer, Py_bufferP, PyTypeObjectPtr, cts) + slot_function, generic_cpy_call, PyObject, Py_ssize_t, + Py_TPFLAGS_CHECKTYPES, Py_buffer, Py_bufferP, PyTypeObjectPtr, cts) from pypy.module.cpyext.typeobjectdefs import ( unaryfunc, ternaryfunc, binaryfunc, getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc, inquiry, @@ -792,6 +792,16 @@ return 0 return buff_w +missing_wrappers = ['wrap_indexargfunc', 'wrap_delslice', 'wrap_coercefunc'] +for name in missing_wrappers: + assert name not in globals() + def missing_wrapper(space, w_self, w_args, func, w_kwds): + print "cpyext: missing slot wrapper " + name + raise NotImplementedError("Slot wrapper " + name) + missing_wrapper.__name__ = name + globals()[name] = missing_wrapper + + PyWrapperFlag_KEYWORDS = 1 class TypeSlot: @@ -809,10 +819,7 @@ if WRAPPER is None: wrapper = None else: - wrapper = globals().get(WRAPPER, Ellipsis) - if wrapper is Ellipsis: - assert WRAPPER.endswith('_XXX'), ( - "no wrapper function called %r in slotdefs.py" % WRAPPER) + wrapper = globals()[WRAPPER] # irregular interface, because of tp_getattr/tp_getattro confusion if NAME == "__getattr__": @@ -826,19 +833,9 @@ function = getattr(userslot, FUNCTION or '!missing', None) assert FLAGS == 0 or FLAGS == PyWrapperFlag_KEYWORDS if FLAGS: - if wrapper is Ellipsis: - @func_renamer(WRAPPER) - def wrapper(space, w_self, w_args, func, w_kwds): - print "cpyext missing wrapper", WRAPPER, "for", NAME - raise NotImplementedError("Wrapper for slot " + NAME) wrapper1 = None wrapper2 = wrapper else: - if wrapper is Ellipsis: - @func_renamer(WRAPPER) - def wrapper(space, w_self, w_args, func): - print "cpyext missing wrapper", WRAPPER, "for", NAME - raise NotImplementedError("Wrapper for slot " + NAME) wrapper1 = wrapper wrapper2 = None return TypeSlot(NAME, SLOT, function, wrapper1, wrapper2, DOC) @@ -885,17 +882,15 @@ # Remove comments and tabs # Done. # XXX NOTE that we already tweaked that string manually! -# Also, a few wrapper functions have a name ending in "_XXX" to mean -# that we know it is not implemented so far. slotdefs_str = r""" static slotdef slotdefs[] = { SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc, "x.__len__() <==> len(x)"), SQSLOT("__add__", sq_concat, slot_sq_concat, wrap_binaryfunc, "x.__add__(y) <==> x+y"), - SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc_XXX, + SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc, "x.__mul__(n) <==> x*n"), - SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc_XXX, + SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc, "x.__rmul__(n) <==> n*x"), SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item, "x.__getitem__(y) <==> x[y]"), @@ -912,7 +907,7 @@ "x.__setslice__(i, j, y) <==> x[i:j]=y\n\ \n\ Use of negative indices is not supported."), - SQSLOT("__delslice__", sq_ass_slice, slot_sq_ass_slice, wrap_delslice_XXX, + SQSLOT("__delslice__", sq_ass_slice, slot_sq_ass_slice, wrap_delslice, "x.__delslice__(i, j) <==> del x[i:j]\n\ \n\ Use of negative indices is not supported."), @@ -921,7 +916,7 @@ SQSLOT("__iadd__", sq_inplace_concat, NULL, wrap_binaryfunc, "x.__iadd__(y) <==> x+=y"), SQSLOT("__imul__", sq_inplace_repeat, NULL, - wrap_indexargfunc_XXX, "x.__imul__(y) <==> x*=y"), + wrap_indexargfunc, "x.__imul__(y) <==> x*=y"), MPSLOT("__len__", mp_length, slot_mp_length, wrap_lenfunc, "x.__len__() <==> len(x)"), @@ -980,7 +975,7 @@ RBINSLOT("__rxor__", nb_xor, slot_nb_xor, "^"), BINSLOT("__or__", nb_or, slot_nb_or, "|"), RBINSLOT("__ror__", nb_or, slot_nb_or, "|"), - NBSLOT("__coerce__", nb_coerce, slot_nb_coerce, wrap_coercefunc_XXX, + NBSLOT("__coerce__", nb_coerce, slot_nb_coerce, wrap_coercefunc, "x.__coerce__(y) <==> coerce(x, y)"), UNSLOT("__int__", nb_int, slot_nb_int, wrap_unaryfunc, "int(x)"), From pypy.commits at gmail.com Sat Apr 1 13:02:05 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sat, 01 Apr 2017 10:02:05 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: win32 multiprocessing: restore the w_handle function from a deleted module. Message-ID: <58dfdd0d.55061c0a.4b93.c785@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90902:cedc709e41d2 Date: 2017-04-01 19:01 +0200 http://bitbucket.org/pypy/pypy/changeset/cedc709e41d2/ Log: win32 multiprocessing: restore the w_handle function from a deleted module. diff --git a/pypy/module/_multiprocessing/interp_win32.py b/pypy/module/_multiprocessing/interp_win32.py --- a/pypy/module/_multiprocessing/interp_win32.py +++ b/pypy/module/_multiprocessing/interp_win32.py @@ -7,7 +7,6 @@ from pypy.interpreter.error import oefmt, wrap_oserror from pypy.interpreter.function import StaticMethod from pypy.interpreter.gateway import interp2app, unwrap_spec -from pypy.module._multiprocessing.interp_connection import w_handle CONSTANTS = """ PIPE_ACCESS_INBOUND PIPE_ACCESS_DUPLEX @@ -35,6 +34,9 @@ def handle_w(space, w_handle): return rffi.cast(rwin32.HANDLE, space.int_w(w_handle)) +def w_handle(space, handle): + return space.wrap(rffi.cast(rffi.INTPTR_T, handle)) + _CreateNamedPipe = rwin32.winexternal( 'CreateNamedPipeA', [ rwin32.LPCSTR, From pypy.commits at gmail.com Sat Apr 1 13:48:28 2017 From: pypy.commits at gmail.com (rlamy) Date: Sat, 01 Apr 2017 10:48:28 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: hg merge default Message-ID: <58dfe7ec.c30b1c0a.d564c.cdae@mx.google.com> Author: Ronan Lamy Branch: py3.5 Changeset: r90903:49c746636960 Date: 2017-04-01 18:47 +0100 http://bitbucket.org/pypy/pypy/changeset/49c746636960/ Log: hg merge default diff too long, truncating to 2000 out of 49367 lines diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -32,10 +32,11 @@ import threading try: - from __pypy__ import newlist_hint + from __pypy__ import newlist_hint, add_memory_pressure except ImportError: assert '__pypy__' not in sys.builtin_module_names newlist_hint = lambda sizehint: [] + add_memory_pressure = lambda size: None if sys.version_info[0] >= 3: StandardError = Exception @@ -152,6 +153,9 @@ check_same_thread=True, factory=None, cached_statements=100, uri=0): factory = Connection if not factory else factory + # an sqlite3 db seems to be around 100 KiB at least (doesn't matter if + # backed by :memory: or a file) + add_memory_pressure(100 * 1024) return factory(database, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri) diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst --- a/pypy/doc/build.rst +++ b/pypy/doc/build.rst @@ -79,6 +79,9 @@ _ssl libssl +_vmprof + libunwind (optional, loaded dynamically at runtime) + Make sure to have these libraries (with development headers) installed before building PyPy, otherwise the resulting binary will not contain these modules. Furthermore, the following libraries should be present @@ -185,7 +188,7 @@ :: cd pypy/tool/release - ./package.py pypy-VER-PLATFORM + ./package.py --archive-name=pypy-VER-PLATFORM This creates a clean and prepared hierarchy, as well as a ``.tar.bz2`` with the same content; both are found by default in diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst --- a/pypy/doc/cpython_differences.rst +++ b/pypy/doc/cpython_differences.rst @@ -364,6 +364,24 @@ .. __: https://bitbucket.org/pypy/pypy/issue/1974/different-behaviour-for-collections-of +Performance Differences +------------------------- + +CPython has an optimization that can make repeated string concatenation not +quadratic. For example, this kind of code runs in O(n) time:: + + s = '' + for string in mylist: + s += string + +In PyPy, this code will always have quadratic complexity. Note also, that the +CPython optimization is brittle and can break by having slight variations in +your code anyway. So you should anyway replace the code with:: + + parts = [] + for string in mylist: + parts.append(string) + s = "".join(parts) Miscellaneous ------------- diff --git a/pypy/doc/install.rst b/pypy/doc/install.rst --- a/pypy/doc/install.rst +++ b/pypy/doc/install.rst @@ -57,6 +57,7 @@ .. code-block:: console $ ./pypy-xxx/bin/pypy -m ensurepip + $ ./pypy-xxx/bin/pip install -U pip wheel # to upgrade to the latest versions $ ./pypy-xxx/bin/pip install pygments # for example Third party libraries will be installed in ``pypy-xxx/site-packages``, and @@ -77,7 +78,17 @@ # from the mercurial checkout $ virtualenv -p /path/to/pypy/pypy/translator/goal/pypy-c my-pypy-env -Note that bin/python is now a symlink to bin/pypy. + # in any case activate it + $ source my-pypy-env/bin/activate + +Note that my-pypy-env/bin/python is now a symlink to my-pypy-env/bin/pypy +so you should be able to run pypy simply by typing:: + + $ python + +You should still upgrade pip and wheel to the latest versions via:: + + $ my-pypy-env/bin/pip install -U pip wheel .. _pip: http://pypi.python.org/pypi/pip .. _ensurepip: https://docs.python.org/2.7/library/ensurepip.html 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 @@ -2,7 +2,22 @@ What's new in PyPy2.7 5.8+ ========================== -.. this is a revision shortly after release-pypy2.7-v5.7 +.. this is a revision shortly after release-pypy2.7-v5.7.0 .. startrev: 44f31f6dd39f +Add cpyext interfaces for ``PyModule_New`` +Correctly handle `dict.pop`` where the ``pop`` +key is not the same type as the ``dict``'s and ``pop`` +is called with a default (will be part of release 5.7.1) + +.. branch: issue2522 + +Fix missing tp_new on w_object called through multiple inheritance +(will be part of release 5.7.1) + +.. branch: lstrip_to_empty_string + +.. branch: vmprof-native + +PyPy support to profile native frames in vmprof. diff --git a/pypy/interpreter/pyparser/future.py b/pypy/interpreter/pyparser/future.py --- a/pypy/interpreter/pyparser/future.py +++ b/pypy/interpreter/pyparser/future.py @@ -80,6 +80,7 @@ from pypy.interpreter.pyparser import pygram it = TokenIterator(tokens) result = 0 + last_position = (0, 0) # # The only things that can precede a future statement are another # future statement and a doc string (only one). This is a very @@ -94,6 +95,11 @@ it.skip_name("__future__") and it.skip_name("import")): it.skip(pygram.tokens.LPAR) # optionally + # return in 'last_position' any line-column pair that points + # somewhere inside the last __future__ import statement + # (at the start would be fine too, but it's easier to grab a + # random position inside) + last_position = (it.tok[2], it.tok[3]) result |= future_flags.get_compiler_feature(it.next_feature_name()) while it.skip(pygram.tokens.COMMA): result |= future_flags.get_compiler_feature(it.next_feature_name()) @@ -104,5 +110,4 @@ # remove the flags that were specified but are anyway mandatory result &= ~future_flags.mandatory_flags - position = (it.tok[2], it.tok[3]) - return result, position + return result, last_position diff --git a/pypy/interpreter/pyparser/test/test_future.py b/pypy/interpreter/pyparser/test/test_future.py --- a/pypy/interpreter/pyparser/test/test_future.py +++ b/pypy/interpreter/pyparser/test/test_future.py @@ -2,10 +2,9 @@ from pypy.interpreter.pyparser import future, pytokenizer from pypy.tool import stdlib___future__ as fut -def run(s, expected_last_future=None): +def run(s, expected_last_future=(0, 0)): source_lines = s.splitlines(True) tokens = pytokenizer.generate_tokens(source_lines, 0) - expected_last_future = expected_last_future or tokens[-1][2:4] # flags, last_future_import = future.add_future_flags( future.futureFlags_3_5, tokens) @@ -14,7 +13,7 @@ def test_docstring(): s = '"Docstring\\" "\nfrom __future__ import division\n' - f = run(s) + f = run(s, (2, 24)) assert f == 0 def test_comment(): @@ -45,152 +44,152 @@ def test_from(): s = 'from __future__ import division\n' - f = run(s) + f = run(s, (1, 24)) assert f == 0 def test_froms(): s = 'from __future__ import division, generators, with_statement\n' - f = run(s) + f = run(s, (1, 24)) assert f == 0 def test_from_as(): s = 'from __future__ import division as b\n' - f = run(s) + f = run(s, (1, 24)) assert f == 0 def test_froms_as(): s = 'from __future__ import division as b, generators as c\n' - f = run(s) + f = run(s, (1, 24)) assert f == 0 def test_from_paren(): s = 'from __future__ import (division)\n' - f = run(s) + f = run(s, (1, 25)) assert f == 0 def test_froms_paren(): s = 'from __future__ import (division, generators)\n' - f = run(s) + f = run(s, (1, 25)) assert f == 0 def test_froms_paren_as(): s = 'from __future__ import (division as b, generators,)\n' - f = run(s) + f = run(s, (1, 25)) assert f == 0 def test_paren_with_newline(): s = 'from __future__ import (division,\nabsolute_import)\n' - f = run(s) + f = run(s, (1, 24)) assert f == 0 def test_paren_with_newline_2(): s = 'from __future__ import (\ndivision,\nabsolute_import)\n' - f = run(s) + f = run(s, (2, 0)) assert f == 0 def test_multiline(): s = '"abc" #def\n #ghi\nfrom __future__ import (division as b, generators,)\nfrom __future__ import with_statement\n' - f = run(s) + f = run(s, (4, 23)) assert f == 0 def test_windows_style_lineendings(): s = '"abc" #def\r\n #ghi\r\nfrom __future__ import (division as b, generators,)\r\nfrom __future__ import with_statement\r\n' - f = run(s) + f = run(s, (4, 23)) assert f == 0 def test_mac_style_lineendings(): s = '"abc" #def\r #ghi\rfrom __future__ import (division as b, generators,)\rfrom __future__ import with_statement\r' - f = run(s) + f = run(s, (4, 23)) assert f == 0 def test_semicolon(): s = '"abc" #def\n #ghi\nfrom __future__ import (division as b, generators,); from __future__ import with_statement\n' - f = run(s) + f = run(s, (3, 78)) assert f == 0 def test_semicolon_2(): s = 'from __future__ import division; from foo import bar' - f = run(s, expected_last_future=(1, 39)) + f = run(s, expected_last_future=(1, 24)) assert f == 0 def test_full_chain(): s = '"abc" #def\n #ghi\nfrom __future__ import (division as b, generators,); from __future__ import with_statement\n' - f = run(s) + f = run(s, (3, 78)) assert f == 0 def test_intervening_code(): s = 'from __future__ import (division as b, generators,)\nfrom sys import modules\nfrom __future__ import with_statement\n' - f = run(s, expected_last_future=(2, 5)) + f = run(s, expected_last_future=(1, 25)) assert f == 0 def test_nonexisting(): s = 'from __future__ import non_existing_feature\n' - f = run(s) + f = run(s, (1, 24)) assert f == 0 def test_nonexisting_2(): s = 'from __future__ import non_existing_feature, with_statement\n' - f = run(s) + f = run(s, (1, 24)) assert f == 0 def test_from_import_abs_import(): s = 'from __future__ import absolute_import\n' - f = run(s) + f = run(s, (1, 24)) assert f == 0 def test_raw_doc(): s = 'r"Doc"\nfrom __future__ import with_statement\n' - f = run(s) + f = run(s, (2, 23)) assert f == 0 def test_unicode_doc(): s = 'u"Doc"\nfrom __future__ import with_statement\n' - f = run(s) + f = run(s, (2, 23)) assert f == 0 def test_raw_unicode_doc(): s = 'ru"Doc"\nfrom __future__ import with_statement\n' - f = run(s) + f = run(s, (2, 23)) assert f == 0 def test_continuation_line(): s = "\\\nfrom __future__ import with_statement\n" - f = run(s) + f = run(s, (2, 23)) assert f == 0 def test_continuation_lines(): s = "\\\n \t\\\nfrom __future__ import with_statement\n" - f = run(s) + f = run(s, (3, 23)) assert f == 0 def test_lots_of_continuation_lines(): s = "\\\n\\\n\\\n\\\n\\\n\\\n\nfrom __future__ import with_statement\n" - f = run(s) + f = run(s, (8, 23)) assert f == 0 def test_continuation_lines_raise(): s = " \\\n \t\\\nfrom __future__ import with_statement\n" - f = run(s, expected_last_future=(1, 0)) + f = run(s) assert f == 0 # because of the INDENT def test_continuation_lines_in_docstring_single_quoted(): s = '"\\\n\\\n\\\n\\\n\\\n\\\n"\nfrom __future__ import division\n' - f = run(s) + f = run(s, (8, 24)) assert f == 0 def test_continuation_lines_in_docstring_triple_quoted(): s = '"""\\\n\\\n\\\n\\\n\\\n\\\n"""\nfrom __future__ import division\n' - f = run(s) + f = run(s, (8, 24)) assert f == 0 def test_blank_lines(): s = ('\n\t\n\nfrom __future__ import with_statement' ' \n \n \nfrom __future__ import division') - f = run(s) + f = run(s, (7, 23)) assert f == 0 def test_dummy_semicolons(): s = ('from __future__ import division;\n' 'from __future__ import with_statement;') - f = run(s) + f = run(s, (2, 23)) assert f == 0 diff --git a/pypy/interpreter/test/test_syntax.py b/pypy/interpreter/test/test_syntax.py --- a/pypy/interpreter/test/test_syntax.py +++ b/pypy/interpreter/test/test_syntax.py @@ -308,6 +308,15 @@ assert isinstance(ns["c"], bytes) assert isinstance(ns["d"], bytes) + def test_both_futures_with_semicolon(self): + # Issue #2526: a corner case which crashes only if the file + # contains *nothing more* than two __future__ imports separated + # by a semicolon. + s = """ +from __future__ import unicode_literals; from __future__ import print_function +""" + exec s in {} + class AppTestComprehensions: diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py --- a/pypy/module/__pypy__/__init__.py +++ b/pypy/module/__pypy__/__init__.py @@ -6,6 +6,8 @@ class BuildersModule(MixedModule): + """ Module containing string and unicode builders """ + appleveldefs = {} interpleveldefs = { @@ -34,6 +36,8 @@ class IntOpModule(MixedModule): + """ Module for integer operations that have two-complement overflow + behaviour instead of overflowing to longs """ appleveldefs = {} interpleveldefs = { 'int_add': 'interp_intop.int_add', @@ -55,6 +59,8 @@ class Module(MixedModule): + """ PyPy specific "magic" functions. A lot of them are experimental and + subject to change, many are internal. """ appleveldefs = { } 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 @@ -106,13 +106,15 @@ raise wrap_oserror(space, e) @unwrap_spec(sizehint=int) -def resizelist_hint(space, w_iterable, sizehint): - if not isinstance(w_iterable, W_ListObject): +def resizelist_hint(space, w_list, sizehint): + """ Reallocate the underlying storage of the argument list to sizehint """ + if not isinstance(w_list, W_ListObject): raise oefmt(space.w_TypeError, "arg 1 must be a 'list'") - w_iterable._resize_hint(sizehint) + w_list._resize_hint(sizehint) @unwrap_spec(sizehint=int) def newlist_hint(space, sizehint): + """ Create a new empty list that has an underlying storage of length sizehint """ return space.newlist_hint(sizehint) @unwrap_spec(debug=int) @@ -125,6 +127,9 @@ @unwrap_spec(estimate=int) def add_memory_pressure(estimate): + """ Add memory pressure of estimate bytes. Useful when calling a C function + that internally allocates a big chunk of memory. This instructs the GC to + garbage collect sooner than it would otherwise.""" rgc.add_memory_pressure(estimate) @unwrap_spec(w_frame=PyFrame) 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 @@ -1471,8 +1471,13 @@ with self.StdErrCapture(fd=True) as f: res = lib.bar(4, 5) assert res == 0 - assert f.getvalue() == ( + assert f.getvalue() in ( + # If the underlying cffi is <= 1.9 "extern \"Python\": function bar() called, but no code was attached " + "to it yet with @ffi.def_extern(). Returning 0.\n", + # If the underlying cffi is >= 1.10 + "extern \"Python\": function _CFFI_test_extern_python_1.bar() " + "called, but no code was attached " "to it yet with @ffi.def_extern(). Returning 0.\n") @ffi.def_extern("bar") diff --git a/pypy/module/_vmprof/interp_vmprof.py b/pypy/module/_vmprof/interp_vmprof.py --- a/pypy/module/_vmprof/interp_vmprof.py +++ b/pypy/module/_vmprof/interp_vmprof.py @@ -50,8 +50,8 @@ return OperationError(w_VMProfError, space.newtext(e.msg)) - at unwrap_spec(fileno=int, period=float) -def enable(space, fileno, period): + at unwrap_spec(fileno=int, period=float, memory=int, lines=int, native=int) +def enable(space, fileno, period, memory, lines, native): """Enable vmprof. Writes go to the given 'fileno', a file descriptor opened for writing. *The file descriptor must remain open at least until disable() is called.* @@ -65,7 +65,7 @@ # "with vmprof will crash"), # space.w_RuntimeWarning) try: - rvmprof.enable(fileno, period) + rvmprof.enable(fileno, period, memory, native) except rvmprof.VMProfError as e: raise VMProfError(space, e) diff --git a/pypy/module/_vmprof/test/test__vmprof.py b/pypy/module/_vmprof/test/test__vmprof.py --- a/pypy/module/_vmprof/test/test__vmprof.py +++ b/pypy/module/_vmprof/test/test__vmprof.py @@ -24,10 +24,11 @@ i += 5 * WORD # header assert s[i ] == 5 # MARKER_HEADER assert s[i + 1] == 0 # 0 - assert s[i + 2] == 2 # VERSION_THREAD_ID - assert s[i + 3] == 4 # len('pypy') - assert s[i + 4: i + 8] == b'pypy' - i += 8 + assert s[i + 2] == 6 # VERSION_TIMESTAMP + assert s[i + 3] == 8 # PROFILE_RPYTHON + assert s[i + 4] == 4 # len('pypy') + assert s[i + 5: i + 9] == b'pypy' + i += 9 while i < len(s): if s[i] == 3: break @@ -41,6 +42,17 @@ _, size = struct.unpack("ll", s[i:i + 2 * WORD]) count += 1 i += 2 * WORD + size + elif s[i] == '\x06': + print(s[i:i+24]) + i += 1+8+8+8 + elif s[i] == '\x07': + i += 1 + # skip string + size, = struct.unpack("l", s[i:i + WORD]) + i += WORD+size + # skip string + size, = struct.unpack("l", s[i:i + WORD]) + i += WORD+size else: raise AssertionError(s[i]) return count @@ -48,7 +60,7 @@ import _vmprof gc.collect() # try to make the weakref list deterministic gc.collect() # by freeing all dead code objects - _vmprof.enable(tmpfileno, 0.01) + _vmprof.enable(tmpfileno, 0.01, 0, 0, 0) _vmprof.disable() s = open(self.tmpfilename, 'rb').read() no_of_codes = count(s) @@ -64,7 +76,7 @@ gc.collect() gc.collect() - _vmprof.enable(tmpfileno2, 0.01) + _vmprof.enable(tmpfileno2, 0.01, 0, 0, 0) exec_("""def foo2(): pass @@ -79,9 +91,9 @@ def test_enable_ovf(self): import _vmprof - raises(_vmprof.VMProfError, _vmprof.enable, 2, 0) - raises(_vmprof.VMProfError, _vmprof.enable, 2, -2.5) - raises(_vmprof.VMProfError, _vmprof.enable, 2, 1e300) - raises(_vmprof.VMProfError, _vmprof.enable, 2, 1e300 * 1e300) + raises(_vmprof.VMProfError, _vmprof.enable, 2, 0, 0, 0, 0) + raises(_vmprof.VMProfError, _vmprof.enable, 2, -2.5, 0, 0, 0) + raises(_vmprof.VMProfError, _vmprof.enable, 2, 1e300, 0, 0, 0) + raises(_vmprof.VMProfError, _vmprof.enable, 2, 1e300 * 1e300, 0, 0, 0) NaN = (1e300*1e300) / (1e300*1e300) - raises(_vmprof.VMProfError, _vmprof.enable, 2, NaN) + raises(_vmprof.VMProfError, _vmprof.enable, 2, NaN, 0, 0, 0) diff --git a/pypy/module/_vmprof/test/test_direct.py b/pypy/module/_vmprof/test/test_direct.py --- a/pypy/module/_vmprof/test/test_direct.py +++ b/pypy/module/_vmprof/test/test_direct.py @@ -43,7 +43,7 @@ } -""" + open(str(srcdir.join("vmprof_get_custom_offset.h"))).read(), include_dirs=[str(srcdir)]) +""" + open(str(srcdir.join("shared/vmprof_get_custom_offset.h"))).read(), include_dirs=[str(srcdir)]) class TestDirect(object): def test_infrastructure(self): diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -4,10 +4,10 @@ from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rlib.rarithmetic import widen -from rpython.rlib import rgc # Force registration of gc.collect +from rpython.rlib import rgc # Force registration of gc.collect from pypy.module.cpyext.api import ( slot_function, generic_cpy_call, PyObject, Py_ssize_t, - pypy_decl, Py_buffer, Py_bufferP, PyTypeObjectPtr, cts) + Py_buffer, Py_bufferP, PyTypeObjectPtr, cts) from pypy.module.cpyext.typeobjectdefs import ( unaryfunc, ternaryfunc, binaryfunc, getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc, inquiry, @@ -793,6 +793,16 @@ return 0 return buff_w +missing_wrappers = ['wrap_indexargfunc', 'wrap_del'] +for name in missing_wrappers: + assert name not in globals() + def missing_wrapper(space, w_self, w_args, func, w_kwds): + print "cpyext: missing slot wrapper " + name + raise NotImplementedError("Slot wrapper " + name) + missing_wrapper.__name__ = name + globals()[name] = missing_wrapper + + PyWrapperFlag_KEYWORDS = 1 class TypeSlot: @@ -810,7 +820,7 @@ if WRAPPER is None: wrapper = None else: - wrapper = globals().get(WRAPPER, Ellipsis) + wrapper = globals()[WRAPPER] # irregular interface, because of tp_getattr/tp_getattro confusion if NAME == "__getattr__": @@ -824,17 +834,9 @@ function = getattr(userslot, FUNCTION or '!missing', None) assert FLAGS == 0 or FLAGS == PyWrapperFlag_KEYWORDS if FLAGS: - if wrapper is Ellipsis: - @func_renamer(WRAPPER) - def wrapper(space, w_self, w_args, func, w_kwds): - raise NotImplementedError("Wrapper for slot " + NAME) wrapper1 = None wrapper2 = wrapper else: - if wrapper is Ellipsis: - @func_renamer(WRAPPER) - def wrapper(space, w_self, w_args, func): - raise NotImplementedError("Wrapper for slot " + NAME) wrapper1 = wrapper wrapper2 = None return TypeSlot(NAME, SLOT, function, wrapper1, wrapper2, DOC) diff --git a/pypy/module/cpyext/test/buffer_test.c b/pypy/module/cpyext/test/buffer_test.c --- a/pypy/module/cpyext/test/buffer_test.c +++ b/pypy/module/cpyext/test/buffer_test.c @@ -344,7 +344,6 @@ #endif if (m == NULL) INITERROR; - PyMyArrayType.tp_new = PyType_GenericNew; if (PyType_Ready(&PyMyArrayType) < 0) INITERROR; Py_INCREF(&PyMyArrayType); diff --git a/pypy/module/cpyext/test/comparisons.c b/pypy/module/cpyext/test/comparisons.c --- a/pypy/module/cpyext/test/comparisons.c +++ b/pypy/module/cpyext/test/comparisons.c @@ -68,7 +68,7 @@ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ - 0, /* tp_new */ + PyType_GenericNew, /* tp_new */ 0 /* tp_free */ }; @@ -87,7 +87,6 @@ { PyObject *m, *d; - CmpType.tp_new = PyType_GenericNew; if (PyType_Ready(&CmpType) < 0) return NULL; m = PyModule_Create(&moduledef); diff --git a/pypy/module/cpyext/test/foo.c b/pypy/module/cpyext/test/foo.c --- a/pypy/module/cpyext/test/foo.c +++ b/pypy/module/cpyext/test/foo.c @@ -36,14 +36,14 @@ Py_ssize_t foo_ssizet; } fooobject; -static PyTypeObject footype; +static PyTypeObject fooType; static fooobject * newfooobject(void) { fooobject *foop; - foop = PyObject_New(fooobject, &footype); + foop = PyObject_New(fooobject, &fooType); if (foop == NULL) return NULL; @@ -160,6 +160,28 @@ return PyObject_GenericSetAttr((PyObject *)self, name, value); } +static PyObject * +new_fooType(PyTypeObject * t, PyObject *args, PyObject *kwds) +{ + PyObject * o; + /* copied from numpy scalartypes.c for inherited classes */ + if (t->tp_bases && (PyTuple_GET_SIZE(t->tp_bases) > 1)) + { + PyTypeObject *sup; + /* We are inheriting from a Python type as well so + give it first dibs on conversion */ + sup = (PyTypeObject *)PyTuple_GET_ITEM(t->tp_bases, 1); + /* Prevent recursion */ + if (new_fooType != sup->tp_new) + { + o = sup->tp_new(t, args, kwds); + return o; + } + } + o = t->tp_alloc(t, 0); + return o; +}; + static PyMemberDef foo_members[] = { {"int_member", T_INT, offsetof(fooobject, foo), 0, "A helpful docstring."}, @@ -194,7 +216,7 @@ PyDoc_STRVAR(foo_doc, "foo is for testing."); -static PyTypeObject footype = { +static PyTypeObject fooType = { PyVarObject_HEAD_INIT(NULL, 0) "foo.foo", /*tp_name*/ sizeof(fooobject), /*tp_size*/ @@ -592,7 +614,7 @@ 0, /*tp_init*/ 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ - 0, /*tp_new*/ + PyType_GenericNew, /*tp_new*/ 0, /*tp_free Low-level free-memory routine */ 0, /*tp_is_gc For PyObject_IS_GC */ 0, /*tp_bases*/ @@ -648,6 +670,37 @@ return PyInt_FromLong(tf); } +static PyTypeObject GetType1 = { + PyVarObject_HEAD_INIT(NULL, 0) + "foo.GetType1", /*tp_name*/ + sizeof(PyObject), /*tp_size*/ +}; +static PyTypeObject GetType2 = { + PyVarObject_HEAD_INIT(NULL, 0) + "foo.GetType2", /*tp_name*/ + sizeof(PyObject), /*tp_size*/ +}; +static PyObject *gettype1, *gettype2; + +static PyObject *gettype1_getattr(PyObject *self, char *name) +{ + char buf[200]; + strcpy(buf, "getattr:"); + strcat(buf, name); + return PyBytes_FromString(buf); +} +static PyObject *gettype2_getattro(PyObject *self, PyObject *name) +{ + char buf[200]; + PyObject* temp; + temp = PyUnicode_AsASCIIString(name); + if (temp == NULL) return NULL; + strcpy(buf, "getattro:"); + strcat(buf, PyBytes_AS_STRING(temp)); + return PyBytes_FromString(buf); +} + + /* List of functions exported by this module */ static PyMethodDef foo_functions[] = { @@ -706,13 +759,14 @@ if (module == NULL) INITERROR; - footype.tp_new = PyType_GenericNew; - UnicodeSubtype.tp_base = &PyUnicode_Type; UnicodeSubtype2.tp_base = &UnicodeSubtype; MetaType.tp_base = &PyType_Type; - if (PyType_Ready(&footype) < 0) + fooType.tp_new = &new_fooType; + InitErrType.tp_new = PyType_GenericNew; + + if (PyType_Ready(&fooType) < 0) INITERROR; if (PyType_Ready(&UnicodeSubtype) < 0) INITERROR; @@ -725,8 +779,6 @@ if (PyType_Ready(&SimplePropertyType) < 0) INITERROR; - SimplePropertyType.tp_new = PyType_GenericNew; - InitErrType.tp_new = PyType_GenericNew; Py_TYPE(&CustomType) = &MetaType; if (PyType_Ready(&CustomType) < 0) @@ -744,11 +796,23 @@ if (PyType_Ready(&TupleLike) < 0) INITERROR; + GetType1.tp_flags = Py_TPFLAGS_DEFAULT; + GetType1.tp_getattr = &gettype1_getattr; + if (PyType_Ready(&GetType1) < 0) + INITERROR; + gettype1 = PyObject_New(PyObject, &GetType1); + + GetType2.tp_flags = Py_TPFLAGS_DEFAULT; + GetType2.tp_getattro = &gettype2_getattro; + if (PyType_Ready(&GetType2) < 0) + INITERROR; + gettype2 = PyObject_New(PyObject, &GetType2); + d = PyModule_GetDict(module); if (d == NULL) INITERROR; - if (PyDict_SetItemString(d, "fooType", (PyObject *)&footype) < 0) + if (PyDict_SetItemString(d, "fooType", (PyObject *)&fooType) < 0) INITERROR; if (PyDict_SetItemString(d, "UnicodeSubtype", (PyObject *) &UnicodeSubtype) < 0) INITERROR; @@ -766,6 +830,10 @@ INITERROR; if (PyDict_SetItemString(d, "TupleLike", (PyObject *) &TupleLike) < 0) INITERROR; + if (PyDict_SetItemString(d, "gettype1", gettype1) < 0) + INITERROR; + if (PyDict_SetItemString(d, "gettype2", gettype2) < 0) + INITERROR; #if PY_MAJOR_VERSION >=3 return module; #endif diff --git a/pypy/module/cpyext/test/test_memoryobject.py b/pypy/module/cpyext/test/test_memoryobject.py --- a/pypy/module/cpyext/test/test_memoryobject.py +++ b/pypy/module/cpyext/test/test_memoryobject.py @@ -187,6 +187,10 @@ " on too long format string" finally: warnings.resetwarnings() + # calling get_buffer_info on x creates a memory leak, + # which is detected as an error at test teardown: + # Exception TypeError: "'NoneType' object is not callable" + # in ignored def test_releasebuffer(self): if not self.runappdirect: diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -16,12 +16,12 @@ assert 'foo' in sys.modules assert "copy" in dir(module.fooType) obj = module.new() - print(obj.foo) + #print(obj.foo) assert obj.foo == 42 - print("Obj has type", type(obj)) + #print("Obj has type", type(obj)) assert type(obj) is module.fooType - print("type of obj has type", type(type(obj))) - print("type of type of obj has type", type(type(type(obj)))) + #print("type of obj has type", type(type(obj))) + #print("type of type of obj has type", type(type(type(obj)))) assert module.fooType.__doc__ == "foo is for testing." def test_typeobject_method_descriptor(self): @@ -949,6 +949,8 @@ pass class foo(f2, f1): pass + + x = foo() assert bar.__base__ is f2 # On cpython, the size changes. if '__pypy__' in sys.builtin_module_names: @@ -1159,8 +1161,8 @@ ((PyHeapTypeObject*)Base2)->ht_name = dummyname; ((PyHeapTypeObject*)Base12)->ht_name = dummyname; } - #endif - #endif + #endif + #endif Base1->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE; Base2->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE; Base12->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE; @@ -1197,3 +1199,14 @@ pass bases = module.foo(C) assert bases == (A, B) + + def test_getattr_getattro(self): + module = self.import_module(name='foo') + assert module.gettype2.dcba == b'getattro:dcba' + assert (type(module.gettype2).__getattribute__(module.gettype2, 'dcBA') + == b'getattro:dcBA') + assert module.gettype1.abcd == b'getattr:abcd' + # GetType1 objects have a __getattribute__ method, but this + # doesn't call tp_getattr at all, also on CPython + raises(AttributeError, type(module.gettype1).__getattribute__, + module.gettype1, 'dcBA') diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py --- a/pypy/module/cpyext/typeobject.py +++ b/pypy/module/cpyext/typeobject.py @@ -682,10 +682,6 @@ if pto.c_tp_itemsize < pto.c_tp_base.c_tp_itemsize: pto.c_tp_itemsize = pto.c_tp_base.c_tp_itemsize - if space.is_w(w_type, space.w_object): - # will be filled later on with the correct value - # may not be 0 - pto.c_tp_new = cts.cast('newfunc', 1) update_all_slots(space, w_type, pto) if not pto.c_tp_new: base_object_pyo = make_ref(space, space.w_object) diff --git a/pypy/module/faulthandler/cintf.py b/pypy/module/faulthandler/cintf.py --- a/pypy/module/faulthandler/cintf.py +++ b/pypy/module/faulthandler/cintf.py @@ -5,10 +5,14 @@ cwd = py.path.local(__file__).dirpath() +rvmp = cwd.join('../../..') +rvmp = rvmp.join('rpython/rlib/rvmprof/src') + eci = ExternalCompilationInfo( includes=[cwd.join('faulthandler.h')], - include_dirs=[str(cwd), cdir], - separate_module_files=[cwd.join('faulthandler.c')]) + include_dirs=[str(cwd), cdir, rvmp], + separate_module_files=[cwd.join('faulthandler.c')], + compile_extra=['-DRPYTHON_VMPROF=1']) eci_later = eci.merge(ExternalCompilationInfo( pre_include_bits=['#define PYPY_FAULTHANDLER_LATER\n'])) diff --git a/pypy/module/struct/interp_struct.py b/pypy/module/struct/interp_struct.py --- a/pypy/module/struct/interp_struct.py +++ b/pypy/module/struct/interp_struct.py @@ -42,10 +42,12 @@ def calcsize(space, w_format): """Return size of C struct described by format string fmt.""" format = text_or_bytes_w(space, w_format) + """Return size of C struct described by format string fmt.""" return space.newint(_calcsize(space, format)) def _pack(space, format, args_w): + """Return string containing values v1, v2, ... packed according to fmt.""" if jit.isconstant(format): size = _calcsize(space, format) else: @@ -79,6 +81,9 @@ # XXX inefficient def do_pack_into(space, format, w_buffer, offset, args_w): + """ Pack the values v1, v2, ... according to fmt. +Write the packed bytes into the writable buffer buf starting at offset + """ res = _pack(space, format, args_w) buf = space.getarg_w('w*', w_buffer) if offset < 0: @@ -119,6 +124,8 @@ return do_unpack_from(space, format, w_buffer, offset) def do_unpack_from(space, format, w_buffer, offset=0): + """Unpack the buffer, containing packed C structure data, according to +fmt, starting at offset. Requires len(buffer[offset:]) >= calcsize(fmt).""" size = _calcsize(space, format) buf = space.buffer_w(w_buffer, space.BUF_SIMPLE) if offset < 0: diff --git a/pypy/tool/release/repackage.sh b/pypy/tool/release/repackage.sh --- a/pypy/tool/release/repackage.sh +++ b/pypy/tool/release/repackage.sh @@ -1,7 +1,7 @@ # Edit these appropriately before running this script maj=5 min=7 -rev=0 +rev=1 branchname=release-pypy2.7-5.x # ==OR== release-$maj.x # ==OR== release-$maj.$min.x tagname=release-pypy2.7-v$maj.$min.$rev # ==OR== release-$maj.$min @@ -50,8 +50,8 @@ rm -rf $rel-src # Print out the md5, sha1, sha256 -md5sum *.bz2 *.zip -sha1sum *.bz2 *.zip +#md5sum *.bz2 *.zip +#sha1sum *.bz2 *.zip sha256sum *.bz2 *.zip # Now upload all the bz2 and zip diff --git a/rpython/jit/backend/x86/detect_feature.py b/rpython/jit/backend/x86/detect_feature.py --- a/rpython/jit/backend/x86/detect_feature.py +++ b/rpython/jit/backend/x86/detect_feature.py @@ -21,7 +21,11 @@ return bool(code & (1<<25)) and bool(code & (1<<26)) def cpu_id(eax = 1, ret_edx = True, ret_ecx = False): - asm = ["\xB8", chr(eax), "\x00\x00\x00", # MOV EAX, $eax + asm = ["\xB8", # MOV EAX, $eax + chr(eax & 0xff), + chr((eax >> 8) & 0xff), + chr((eax >> 16) & 0xff), + chr((eax >> 24) & 0xff), "\x53", # PUSH EBX "\x0F\xA2", # CPUID "\x5B", # POP EBX diff --git a/rpython/jit/backend/x86/vector_ext.py b/rpython/jit/backend/x86/vector_ext.py --- a/rpython/jit/backend/x86/vector_ext.py +++ b/rpython/jit/backend/x86/vector_ext.py @@ -60,6 +60,7 @@ class VectorAssemblerMixin(object): _mixin_ = True + element_ones = [] # overridden in assembler.py def setup_once_vector(self): pass @@ -342,6 +343,7 @@ else: assert lhsloc is xmm0 maskloc = X86_64_XMM_SCRATCH_REG + assert len(self.element_ones) > 0 self.mc.MOVAPD(maskloc, heap(self.element_ones[get_scale(size)])) self.mc.PXOR(resloc, resloc) # note that resloc contains true false for each element by the last compare operation diff --git a/rpython/jit/metainterp/test/test_ajit.py b/rpython/jit/metainterp/test/test_ajit.py --- a/rpython/jit/metainterp/test/test_ajit.py +++ b/rpython/jit/metainterp/test/test_ajit.py @@ -4637,8 +4637,8 @@ self.meta_interp(f, [10]) - @py.test.skip("loops!") def test_finalizer_bug(self): + py.test.skip("loops!") from rpython.rlib import rgc driver = JitDriver(greens=[], reds=[]) class Fin(object): diff --git a/rpython/rlib/jit.py b/rpython/rlib/jit.py --- a/rpython/rlib/jit.py +++ b/rpython/rlib/jit.py @@ -244,6 +244,10 @@ return inner def oopspec(spec): + """ The JIT compiler won't look inside this decorated function, + but instead during translation, rewrites it according to the handler in + rpython/jit/codewriter/jtransform.py. + """ def decorator(func): func.oopspec = spec return func diff --git a/rpython/rlib/rstrategies/rstrategies.py b/rpython/rlib/rstrategies/rstrategies.py --- a/rpython/rlib/rstrategies/rstrategies.py +++ b/rpython/rlib/rstrategies/rstrategies.py @@ -1,7 +1,7 @@ import weakref, sys from rpython.rlib.rstrategies import logger -from rpython.rlib import jit, objectmodel, rerased +from rpython.rlib import jit, objectmodel, rerased, rarithmetic from rpython.rlib.objectmodel import specialize, not_rpython def make_accessors(strategy='strategy', storage='storage'): @@ -443,6 +443,7 @@ def store(self, w_self, index0, wrapped_value): self.check_index_store(w_self, index0) + assert index0 >= 0 if self._check_can_handle(wrapped_value): unwrapped = self._unwrap(wrapped_value) self.get_storage(w_self)[index0] = unwrapped @@ -451,6 +452,7 @@ def fetch(self, w_self, index0): self.check_index_fetch(w_self, index0) + assert index0 >= 0 unwrapped = self.get_storage(w_self)[index0] return self._wrap(unwrapped) @@ -517,7 +519,7 @@ self.check_index(w_self, start) self.check_index(w_self, end) def check_index(self, w_self, index0): - if index0 < 0 or index0 >= self.size(w_self): + if not rarithmetic.int_between(0, index0, self.size(w_self)): raise IndexError class UnsafeIndexingMixin(object): diff --git a/rpython/rlib/rstrategies/test/test_rstrategies.py b/rpython/rlib/rstrategies/test/test_rstrategies.py --- a/rpython/rlib/rstrategies/test/test_rstrategies.py +++ b/rpython/rlib/rstrategies/test/test_rstrategies.py @@ -204,7 +204,7 @@ if is_safe: py.test.raises(IndexError, s.fetch, l, -1) else: - assert s.fetch(l, -1) == s.fetch(l, size - 1) + py.test.raises(AssertionError, s.fetch, l, -1) def test_init_Empty(): l = W_List(EmptyStrategy, 0) @@ -249,7 +249,7 @@ if is_safe: py.test.raises(IndexError, s.store, l, -1, stored_value) else: - store_test(-1) + py.test.raises(AssertionError, s.store, l, -1, stored_value) def test_store_Nil(): do_test_store(NilStrategy, stored_value=w_nil) diff --git a/rpython/rlib/rvmprof/__init__.py b/rpython/rlib/rvmprof/__init__.py --- a/rpython/rlib/rvmprof/__init__.py +++ b/rpython/rlib/rvmprof/__init__.py @@ -32,8 +32,8 @@ return code._vmprof_unique_id return 0 -def enable(fileno, interval): - _get_vmprof().enable(fileno, interval) +def enable(fileno, interval, memory=0, native=0): + _get_vmprof().enable(fileno, interval, memory, native) def disable(): _get_vmprof().disable() diff --git a/rpython/rlib/rvmprof/cintf.py b/rpython/rlib/rvmprof/cintf.py --- a/rpython/rlib/rvmprof/cintf.py +++ b/rpython/rlib/rvmprof/cintf.py @@ -14,32 +14,70 @@ ROOT = py.path.local(rpythonroot).join('rpython', 'rlib', 'rvmprof') SRC = ROOT.join('src') +SHARED = SRC.join('shared') +BACKTRACE = SHARED.join('libbacktrace') +compile_extra = ['-DRPYTHON_VMPROF', '-O3'] +separate_module_files = [ + SHARED.join('symboltable.c') +] if sys.platform.startswith('linux'): + if sys.maxint > 2**32: # doesn't seem to compile on 32-bit Linux + separate_module_files += [ + BACKTRACE.join('backtrace.c'), + BACKTRACE.join('state.c'), + BACKTRACE.join('elf.c'), + BACKTRACE.join('dwarf.c'), + BACKTRACE.join('fileline.c'), + BACKTRACE.join('mmap.c'), + BACKTRACE.join('mmapio.c'), + BACKTRACE.join('posix.c'), + BACKTRACE.join('sort.c'), + ] + compile_extra += ['-DVMPROF_BACKTRACE'] _libs = ['dl'] + compile_extra += ['-DVMPROF_UNIX'] + compile_extra += ['-DVMPROF_LINUX'] +elif sys.platform == 'win32': + compile_extra = ['-DRPYTHON_VMPROF', '-DVMPROF_WINDOWS'] + separate_module_files = [SHARED.join('vmprof_main_win32.c')] + _libs = [] else: + # Guessing a BSD-like Unix platform + compile_extra += ['-DVMPROF_UNIX'] + compile_extra += ['-DVMPROF_MAC'] _libs = [] + + eci_kwds = dict( - include_dirs = [SRC], - includes = ['rvmprof.h', 'vmprof_stack.h'], + include_dirs = [SRC, SHARED, BACKTRACE], + includes = ['rvmprof.h','vmprof_stack.h'], libraries = _libs, - separate_module_files = [SRC.join('rvmprof.c')], - post_include_bits=['#define RPYTHON_VMPROF\n'], + separate_module_files = [ + SRC.join('rvmprof.c'), + SHARED.join('compat.c'), + SHARED.join('machine.c'), + SHARED.join('vmp_stack.c'), + # symbol table already in separate_module_files + ] + separate_module_files, + post_include_bits=[], + compile_extra=compile_extra ) global_eci = ExternalCompilationInfo(**eci_kwds) def setup(): - compile_extra = ['-DRPYTHON_LL2CTYPES'] + eci_kwds['compile_extra'].append('-DRPYTHON_LL2CTYPES') platform.verify_eci(ExternalCompilationInfo( - compile_extra=compile_extra, - **eci_kwds)) + **eci_kwds)) eci = global_eci vmprof_init = rffi.llexternal("vmprof_init", - [rffi.INT, rffi.DOUBLE, rffi.CCHARP], + [rffi.INT, rffi.DOUBLE, rffi.INT, rffi.INT, + rffi.CCHARP, rffi.INT], rffi.CCHARP, compilation_info=eci) - vmprof_enable = rffi.llexternal("vmprof_enable", [], rffi.INT, + vmprof_enable = rffi.llexternal("vmprof_enable", [rffi.INT, rffi.INT], + rffi.INT, compilation_info=eci, save_err=rffi.RFFI_SAVE_ERRNO) vmprof_disable = rffi.llexternal("vmprof_disable", [], rffi.INT, @@ -62,6 +100,7 @@ return CInterface(locals()) + class CInterface(object): def __init__(self, namespace): for k, v in namespace.iteritems(): diff --git a/rpython/rlib/rvmprof/rvmprof.py b/rpython/rlib/rvmprof/rvmprof.py --- a/rpython/rlib/rvmprof/rvmprof.py +++ b/rpython/rlib/rvmprof/rvmprof.py @@ -10,6 +10,8 @@ MAX_FUNC_NAME = 1023 +PLAT_WINDOWS = sys.platform == 'win32' + # ____________________________________________________________ # keep in sync with vmprof_stack.h @@ -122,7 +124,7 @@ self._gather_all_code_objs = gather_all_code_objs @jit.dont_look_inside - def enable(self, fileno, interval): + def enable(self, fileno, interval, memory=0, native=0): """Enable vmprof. Writes go to the given 'fileno'. The sampling interval is given by 'interval' as a number of seconds, as a float which must be smaller than 1.0. @@ -132,12 +134,16 @@ if self.is_enabled: raise VMProfError("vmprof is already enabled") - p_error = self.cintf.vmprof_init(fileno, interval, "pypy") + if PLAT_WINDOWS: + native = 0 # force disabled on Windows + lines = 0 # not supported on PyPy currently + + p_error = self.cintf.vmprof_init(fileno, interval, lines, memory, "pypy", native) if p_error: raise VMProfError(rffi.charp2str(p_error)) self._gather_all_code_objs() - res = self.cintf.vmprof_enable() + res = self.cintf.vmprof_enable(memory, native) if res < 0: raise VMProfError(os.strerror(rposix.get_saved_errno())) self.is_enabled = True @@ -154,6 +160,7 @@ if res < 0: raise VMProfError(os.strerror(rposix.get_saved_errno())) + def _write_code_registration(self, uid, name): assert name.count(':') == 3 and len(name) <= MAX_FUNC_NAME, ( "the name must be 'class:func_name:func_line:filename' " @@ -171,6 +178,23 @@ arguments given to the decorated function. 'result_class' is ignored (backward compatibility). + + ==================================== + TRANSLATION NOTE CALL THIS ONLY ONCE + ==================================== + + This function can only be called once during translation. + It generates a C function called __vmprof_eval_vmprof which is used by + the vmprof C source code and is bound as an extern function. + This is necessary while walking the native stack. + If you see __vmprof_eval_vmprof defined twice during + translation, read on: + + To remove this restriction do the following: + + *) Extend the macro IS_VMPROF_EVAL in the vmprof source repo to check several + sybmols. + *) Give each function provided to this decorator a unique symbol name in C """ if _hack_update_stack_untranslated: from rpython.rtyper.annlowlevel import llhelper @@ -198,16 +222,27 @@ unique_id = get_code_fn(*args)._vmprof_unique_id unique_id = rffi.cast(lltype.Signed, unique_id) # ^^^ removes the "known non-negative" hint for annotation + # + # Signals can occur at the two places (1) and (2), that will + # have added a stack entry, but the function __vmprof_eval_vmprof + # is not entered. This behaviour will swallow one Python stack frame + # + # Current fix: vmprof will discard this sample. (happens + # very infrequently) + # if not jit.we_are_jitted(): x = enter_code(unique_id) + # (1) signal here try: return func(*args) finally: + # (2) signal here leave_code(x) else: return decorated_jitted_function(unique_id, *args) decorated_function.__name__ = func.__name__ + '_rvmprof' + decorated_function.c_name = '__vmprof_eval_vmprof' return decorated_function return decorate @@ -216,7 +251,6 @@ def _was_registered(CodeClass): return hasattr(CodeClass, '_vmprof_unique_id') - _vmprof_instance = None @specialize.memo() diff --git a/rpython/rlib/rvmprof/src/rvmprof.c b/rpython/rlib/rvmprof/src/rvmprof.c --- a/rpython/rlib/rvmprof/src/rvmprof.c +++ b/rpython/rlib/rvmprof/src/rvmprof.c @@ -2,25 +2,30 @@ #ifdef RPYTHON_LL2CTYPES /* only for testing: ll2ctypes sets RPY_EXTERN from the command-line */ -#ifndef RPY_EXTERN -#define RPY_EXTERN RPY_EXPORTED -#endif -#ifdef _WIN32 -#define RPY_EXPORTED __declspec(dllexport) -#else -#define RPY_EXPORTED extern __attribute__((visibility("default"))) -#endif #else # include "common_header.h" # include "structdef.h" # include "src/threadlocal.h" # include "rvmprof.h" +# include "forwarddecl.h" #endif -#if defined(__unix__) || defined(__APPLE__) -#include "vmprof_main.h" + +#include "shared/vmprof_get_custom_offset.h" +#ifdef VMPROF_UNIX +#include "shared/vmprof_main.h" #else -#include "vmprof_main_win32.h" +#include "shared/vmprof_main_win32.h" #endif + + +#ifdef RPYTHON_LL2CTYPES +int IS_VMPROF_EVAL(void * ptr) { return 0; } +#else +int IS_VMPROF_EVAL(void * ptr) +{ + return ptr == __vmprof_eval_vmprof; +} +#endif diff --git a/rpython/rlib/rvmprof/src/rvmprof.h b/rpython/rlib/rvmprof/src/rvmprof.h --- a/rpython/rlib/rvmprof/src/rvmprof.h +++ b/rpython/rlib/rvmprof/src/rvmprof.h @@ -1,18 +1,41 @@ -#ifdef _WIN32 -typedef long intptr_t; +#pragma once + +#include "shared/vmprof.h" + +#define SINGLE_BUF_SIZE (8192 - 2 * sizeof(unsigned int)) + +#ifdef VMPROF_WINDOWS +#include "msiinttypes/inttypes.h" +#include "msiinttypes/stdint.h" #else -# include +#include +#include #endif -RPY_EXTERN char *vmprof_init(int, double, char *); +#ifndef RPY_EXTERN +#define RPY_EXTERN RPY_EXPORTED +#endif +#ifdef _WIN32 +#ifndef RPY_EXPORTED +#define RPY_EXPORTED __declspec(dllexport) +#endif +#else +#define RPY_EXPORTED extern __attribute__((visibility("default"))) +#endif + +RPY_EXTERN char *vmprof_init(int fd, double interval, int memory, + int lines, const char *interp_name, int native); RPY_EXTERN void vmprof_ignore_signals(int); -RPY_EXTERN int vmprof_enable(void); +RPY_EXTERN int vmprof_enable(int memory, int native); RPY_EXTERN int vmprof_disable(void); -RPY_EXTERN int vmprof_register_virtual_function(char *, long, int); +RPY_EXTERN int vmprof_register_virtual_function(char *, intptr_t, int); RPY_EXTERN void* vmprof_stack_new(void); RPY_EXTERN int vmprof_stack_append(void*, long); RPY_EXTERN long vmprof_stack_pop(void*); RPY_EXTERN void vmprof_stack_free(void*); RPY_EXTERN intptr_t vmprof_get_traceback(void *, void *, intptr_t*, intptr_t); +long vmprof_write_header_for_jit_addr(intptr_t *result, long n, + intptr_t addr, int max_depth); + #define RVMPROF_TRACEBACK_ESTIMATE_N(num_entries) (2 * (num_entries) + 4) diff --git a/rpython/rlib/rvmprof/src/shared/_vmprof.c b/rpython/rlib/rvmprof/src/shared/_vmprof.c new file mode 100644 --- /dev/null +++ b/rpython/rlib/rvmprof/src/shared/_vmprof.c @@ -0,0 +1,354 @@ +/*[clinic input] +module _vmprof +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b443489e38f2be7d]*/ + +#define _GNU_SOURCE 1 + +#include +#include +#include + +#include "_vmprof.h" + +static volatile int is_enabled = 0; +static destructor Original_code_dealloc = 0; +static PyObject* (*_default_eval_loop)(PyFrameObject *, int) = 0; +void dump_native_symbols(int fileno); + +#if VMPROF_UNIX +#include "trampoline.h" +#include "machine.h" +#include "symboltable.h" +#include "vmprof_main.h" +#else +#include "vmprof_main_win32.h" +#endif +#include "vmp_stack.h" + +#ifdef VMPROF_UNIX +#ifdef __clang__ +__attribute__((optnone)) +#elif defined(__GNUC__) +__attribute__((optimize("O1"))) +#endif +PY_EVAL_RETURN_T * vmprof_eval(PY_STACK_FRAME_T *f, int throwflag) +{ +#ifdef X86_64 + register PY_STACK_FRAME_T * callee_saved asm("rbx"); +#elif defined(X86_32) + register PY_STACK_FRAME_T * callee_saved asm("edi"); +#else +# error "platform not supported" +#endif + + asm volatile( +#ifdef X86_64 + "movq %1, %0\t\n" +#elif defined(X86_32) + "mov %1, %0\t\n" +#else +# error "platform not supported" +#endif + : "=r" (callee_saved) + : "r" (f) ); + return _default_eval_loop(f, throwflag); +} +#endif + +static int emit_code_object(PyCodeObject *co) +{ + char buf[MAX_FUNC_NAME + 1]; + char *co_name, *co_filename; + int co_firstlineno; + int sz; +#if PY_MAJOR_VERSION >= 3 + co_name = PyUnicode_AsUTF8(co->co_name); + if (co_name == NULL) + return -1; + co_filename = PyUnicode_AsUTF8(co->co_filename); + if (co_filename == NULL) + return -1; +#else + co_name = PyString_AS_STRING(co->co_name); + co_filename = PyString_AS_STRING(co->co_filename); +#endif + co_firstlineno = co->co_firstlineno; + + sz = snprintf(buf, MAX_FUNC_NAME / 2, "py:%s", co_name); + if (sz < 0) sz = 0; + if (sz > MAX_FUNC_NAME / 2) sz = MAX_FUNC_NAME / 2; + snprintf(buf + sz, MAX_FUNC_NAME / 2, ":%d:%s", co_firstlineno, + co_filename); + return vmprof_register_virtual_function(buf, CODE_ADDR_TO_UID(co), 500000); +} + +static int _look_for_code_object(PyObject *o, void *all_codes) +{ + if (PyCode_Check(o) && !PySet_Contains((PyObject *)all_codes, o)) { + Py_ssize_t i; + PyCodeObject *co = (PyCodeObject *)o; + if (emit_code_object(co) < 0) + return -1; + if (PySet_Add((PyObject *)all_codes, o) < 0) + return -1; + + /* as a special case, recursively look for and add code + objects found in the co_consts. The problem is that code + objects are not created as GC-aware in CPython, so we need + to hack like this to hope to find most of them. + */ + i = PyTuple_Size(co->co_consts); + while (i > 0) { + --i; + if (_look_for_code_object(PyTuple_GET_ITEM(co->co_consts, i), + all_codes) < 0) + return -1; + } + } + return 0; +} + +static void emit_all_code_objects(void) +{ + PyObject *gc_module = NULL, *lst = NULL, *all_codes = NULL; + Py_ssize_t i, size; + + gc_module = PyImport_ImportModuleNoBlock("gc"); + if (gc_module == NULL) + goto error; + + lst = PyObject_CallMethod(gc_module, "get_objects", ""); + if (lst == NULL || !PyList_Check(lst)) + goto error; + + all_codes = PySet_New(NULL); + if (all_codes == NULL) + goto error; + + size = PyList_GET_SIZE(lst); + for (i = 0; i < size; i++) { + PyObject *o = PyList_GET_ITEM(lst, i); + if (o->ob_type->tp_traverse && + o->ob_type->tp_traverse(o, _look_for_code_object, (void *)all_codes) + < 0) + goto error; + } + + error: + Py_XDECREF(all_codes); + Py_XDECREF(lst); + Py_XDECREF(gc_module); +} + +static void cpyprof_code_dealloc(PyObject *co) +{ + if (is_enabled) { + emit_code_object((PyCodeObject *)co); + /* xxx error return values are ignored */ + } + Original_code_dealloc(co); +} + +static PyObject *enable_vmprof(PyObject* self, PyObject *args) +{ + int fd; + int memory = 0; + int lines = 0; + int native = 0; + double interval; + char *p_error; + + if (!PyArg_ParseTuple(args, "id|iii", &fd, &interval, &memory, &lines, &native)) { + return NULL; + } + assert(fd >= 0 && "file descripter provided to vmprof must not" \ + " be less then zero."); + + if (is_enabled) { + PyErr_SetString(PyExc_ValueError, "vmprof is already enabled"); + return NULL; + } + + vmp_profile_lines(lines); + + if (!Original_code_dealloc) { + Original_code_dealloc = PyCode_Type.tp_dealloc; + PyCode_Type.tp_dealloc = &cpyprof_code_dealloc; + } + + p_error = vmprof_init(fd, interval, memory, lines, "cpython", native); + if (p_error) { + PyErr_SetString(PyExc_ValueError, p_error); + return NULL; + } + + if (vmprof_enable(memory, native) < 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + is_enabled = 1; + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +disable_vmprof(PyObject *module, PyObject *noarg) +{ + if (!is_enabled) { + PyErr_SetString(PyExc_ValueError, "vmprof is not enabled"); + return NULL; + } + is_enabled = 0; + vmprof_ignore_signals(1); + emit_all_code_objects(); + + if (vmprof_disable() < 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + if (PyErr_Occurred()) + return NULL; + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +write_all_code_objects(PyObject *module, PyObject *noargs) +{ + if (!is_enabled) { + PyErr_SetString(PyExc_ValueError, "vmprof is not enabled"); + return NULL; + } + emit_all_code_objects(); + if (PyErr_Occurred()) + return NULL; + Py_INCREF(Py_None); + return Py_None; +} + + +static PyObject * +sample_stack_now(PyObject *module, PyObject * args) +{ + PyThreadState * tstate = NULL; + PyObject * list = NULL; + int i; + int entry_count; + void ** m; + void * routine_ip; + long skip = 0; + + // stop any signal to occur + vmprof_ignore_signals(1); + + list = PyList_New(0); + if (list == NULL) { + goto error; + } + + if (!PyArg_ParseTuple(args, "l", &skip)) { + goto error; + } + + tstate = PyGILState_GetThisThreadState(); + m = (void**)malloc(SINGLE_BUF_SIZE); + if (m == NULL) { + PyErr_SetString(PyExc_MemoryError, "could not allocate buffer for stack trace"); + vmprof_ignore_signals(0); + return NULL; + } + entry_count = vmp_walk_and_record_stack(tstate->frame, m, MAX_STACK_DEPTH-1, skip, 0); + + for (i = 0; i < entry_count; i++) { + routine_ip = m[i]; + PyList_Append(list, PyLong_NEW((ssize_t)routine_ip)); + } + + free(m); + + Py_INCREF(list); + + vmprof_ignore_signals(0); + return list; +error: + Py_DECREF(list); + Py_INCREF(Py_None); + + vmprof_ignore_signals(0); + return Py_None; +} + +#ifdef VMP_SUPPORTS_NATIVE_PROFILING +static PyObject * +resolve_addr(PyObject *module, PyObject *args) { + long long addr; + PyObject * o_name = NULL; + PyObject * o_lineno = NULL; + PyObject * o_srcfile = NULL; + char name[128]; + int lineno = 0; + char srcfile[256]; + + if (!PyArg_ParseTuple(args, "L", &addr)) { + return NULL; + } + name[0] = '\x00'; + srcfile[0] = '-'; + srcfile[1] = '\x00'; + if (vmp_resolve_addr((void*)addr, name, 128, &lineno, srcfile, 256) != 0) { + goto error; + } + + o_name = PyStr_NEW(name); + if (o_name == NULL) goto error; + o_lineno = PyLong_NEW(lineno); + if (o_lineno == NULL) goto error; + o_srcfile = PyStr_NEW(srcfile); + if (o_srcfile == NULL) goto error; + // + return PyTuple_Pack(3, o_name, o_lineno, o_srcfile); +error: + Py_XDECREF(o_name); + Py_XDECREF(o_lineno); + Py_XDECREF(o_srcfile); + + Py_INCREF(Py_None); + return Py_None; +} +#endif + +static PyMethodDef VMProfMethods[] = { + {"enable", enable_vmprof, METH_VARARGS, "Enable profiling."}, + {"disable", disable_vmprof, METH_NOARGS, "Disable profiling."}, + {"write_all_code_objects", write_all_code_objects, METH_NOARGS, + "Write eagerly all the IDs of code objects"}, + {"sample_stack_now", sample_stack_now, METH_VARARGS, "Sample the stack now"}, +#ifdef VMP_SUPPORTS_NATIVE_PROFILING + {"resolve_addr", resolve_addr, METH_VARARGS, "Return the name of the addr"}, +#endif + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef VmprofModule = { + PyModuleDef_HEAD_INIT, + "_vmprof", + "", // doc + -1, // size + VMProfMethods +}; + +PyMODINIT_FUNC PyInit__vmprof(void) +{ + return PyModule_Create(&VmprofModule); +} +#else +PyMODINIT_FUNC init_vmprof(void) +{ + Py_InitModule("_vmprof", VMProfMethods); +} +#endif diff --git a/rpython/rlib/rvmprof/src/shared/_vmprof.h b/rpython/rlib/rvmprof/src/shared/_vmprof.h new file mode 100644 --- /dev/null +++ b/rpython/rlib/rvmprof/src/shared/_vmprof.h @@ -0,0 +1,53 @@ +#pragma once + +#include "vmprof.h" + +#ifdef VMPROF_WINDOWS + +#include +// CPython 3.6 defines all the inttypes for us, we do not need the msiinttypes +// library for that version or any newer! +#if (PY_VERSION_HEX < 0x3060000) +#include "msiinttypes/inttypes.h" +#include "msiinttypes/stdint.h" +#endif + +#else +#include +#include +#include +#endif + +/** + * This whole setup is very strange. There was just one C file called + * _vmprof.c which included all *.h files to copy code. Unsure what + * the goal was with this design, but I assume it just 'GREW' + * + * Thus I'm (plan_rich) slowly trying to separate this. *.h files + * should not have complex implementations (all of them currently have them) + */ + + +#define SINGLE_BUF_SIZE (8192 - 2 * sizeof(unsigned int)) + +#define ROUTINE_IS_PYTHON(RIP) ((unsigned long long)RIP & 0x1) == 0 +#define ROUTINE_IS_C(RIP) ((unsigned long long)RIP & 0x1) == 1 + +/* This returns the address of the code object + as the identifier. The mapping from identifiers to string + representations of the code object is done elsewhere, namely: + + * If the code object dies while vmprof is enabled, + PyCode_Type.tp_dealloc will emit it. (We don't handle nicely + for now the case where several code objects are created and die + at the same memory address.) + + * When _vmprof.disable() is called, then we look around the + process for code objects and emit all the ones that we can + find (which we hope is very close to 100% of them). +*/ +#define CODE_ADDR_TO_UID(co) (((intptr_t)(co))) + +#define CPYTHON_HAS_FRAME_EVALUATION PY_VERSION_HEX >= 0x30600B0 + +int vmp_write_all(const char *buf, size_t bufsize); diff --git a/rpython/rlib/rvmprof/src/shared/compat.c b/rpython/rlib/rvmprof/src/shared/compat.c new file mode 100644 --- /dev/null +++ b/rpython/rlib/rvmprof/src/shared/compat.c @@ -0,0 +1,140 @@ +#include "compat.h" + +#include +#include +#if VMPROF_WINDOWS +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +#include +#endif + +static int _vmp_profile_fileno = -1; + +int vmp_profile_fileno(void) { + return _vmp_profile_fileno; +} +void vmp_set_profile_fileno(int fileno) { + _vmp_profile_fileno = fileno; +} + +#ifndef VMPROF_WINDOWS +int vmp_write_all(const char *buf, size_t bufsize) +{ + ssize_t count; + if (_vmp_profile_fileno == -1) { + return -1; + } + while (bufsize > 0) { + count = write(_vmp_profile_fileno, buf, bufsize); + if (count <= 0) + return -1; /* failed */ + buf += count; + bufsize -= count; + } + return 0; +} +#endif + +int vmp_write_meta(const char * key, const char * value) +{ + char marker = MARKER_META; + long x = (long)strlen(key); + vmp_write_all(&marker, 1); + vmp_write_all((char*)&x, sizeof(long)); + vmp_write_all(key, x); + x = (long)strlen(value); + vmp_write_all((char*)&x, sizeof(long)); + vmp_write_all(value, x); + return 0; +} + +/** + * Write the time and zone now. + */ + +struct timezone_buf { + int64_t tv_sec; + int64_t tv_usec; +}; +#define __SIZE (1+sizeof(struct timezone_buf)+8) + +#ifdef VMPROF_UNIX +int vmp_write_time_now(int marker) { + char buffer[__SIZE]; + struct timezone_buf buf; + + (void)memset(&buffer, 0, __SIZE); + + assert((marker == MARKER_TRAILER || marker == MARKER_TIME_N_ZONE) && \ + "marker must be either a trailer or time_n_zone!"); + + struct timeval tv; + time_t now; + struct tm tm; + + + /* copy over to the struct */ + if (gettimeofday(&tv, NULL) != 0) { + return -1; + } + if (time(&now) == (time_t)-1) { + return -1; + } + if (localtime_r(&now, &tm) == NULL) { + return -1; + } + buf.tv_sec = tv.tv_sec; + buf.tv_usec = tv.tv_usec; + strncpy(((char*)buffer)+__SIZE-8, tm.tm_zone, 8); + + buffer[0] = marker; + (void)memcpy(buffer+1, &buf, sizeof(struct timezone_buf)); + vmp_write_all(buffer, __SIZE); + return 0; +} +#endif + +#ifdef VMPROF_WINDOWS +int vmp_write_time_now(int marker) { + char buffer[__SIZE]; + struct timezone_buf buf; + + /** + * http://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows + */ + + // Note: some broken versions only have 8 trailing zero's, the correct + // epoch has 9 trailing zero's + static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); + + SYSTEMTIME system_time; + FILETIME file_time; + uint64_t time; + + (void)memset(&buffer, 0, __SIZE); + + assert((marker == MARKER_TRAILER || marker == MARKER_TIME_N_ZONE) && \ + "marker must be either a trailer or time_n_zone!"); + + + GetSystemTime( &system_time ); + SystemTimeToFileTime( &system_time, &file_time ); + time = ((uint64_t)file_time.dwLowDateTime ) ; + time += ((uint64_t)file_time.dwHighDateTime) << 32; + + buf.tv_sec = ((time - EPOCH) / 10000000L); + buf.tv_usec = (system_time.wMilliseconds * 1000); + + // time zone not implemented on windows + memset(((char*)buffer)+__SIZE-8, 0, 8); + (void)memcpy(((char*)buffer)+__SIZE-8, "UTC", 3); + + buffer[0] = marker; + (void)memcpy(buffer+1, &buf, sizeof(struct timezone_buf)); + vmp_write_all(buffer, __SIZE); + return 0; +} +#endif +#undef __SIZE diff --git a/rpython/rlib/rvmprof/src/shared/compat.h b/rpython/rlib/rvmprof/src/shared/compat.h new file mode 100644 --- /dev/null +++ b/rpython/rlib/rvmprof/src/shared/compat.h @@ -0,0 +1,25 @@ +#pragma once + +#include "vmprof.h" + +#ifndef RPYTHON_VMPROF +# if PY_MAJOR_VERSION >= 3 + #define PyStr_AS_STRING PyBytes_AS_STRING + #define PyStr_GET_SIZE PyBytes_GET_SIZE + #define PyStr_NEW PyUnicode_FromString + #define PyLong_NEW PyLong_FromSsize_t From pypy.commits at gmail.com Sat Apr 1 14:38:23 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sat, 01 Apr 2017 11:38:23 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: (blind) attempt to support EINTR in win32's sleep(). Message-ID: <58dff39f.6ca0df0a.13103.48ce@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90904:8a164b222d5a Date: 2017-04-01 20:37 +0200 http://bitbucket.org/pypy/pypy/changeset/8a164b222d5a/ Log: (blind) attempt to support EINTR in win32's sleep(). Based on CPython b1abd06465fc diff --git a/pypy/module/time/interp_time.py b/pypy/module/time/interp_time.py --- a/pypy/module/time/interp_time.py +++ b/pypy/module/time/interp_time.py @@ -447,17 +447,31 @@ errno = rposix.get_saved_errno() return _strerror(errno) -if sys.platform != 'win32': - from errno import EINTR - from rpython.rlib.rtime import c_select +from errno import EINTR +from rpython.rlib.rtime import c_select - @unwrap_spec(secs=float) - def sleep(space, secs): - if secs < 0: - raise oefmt(space.w_ValueError, - "sleep length must be non-negative") - end_time = timeutils.monotonic(space) + secs - while True: + at unwrap_spec(secs=float) +def sleep(space, secs): + if secs < 0: + raise oefmt(space.w_ValueError, + "sleep length must be non-negative") + end_time = timeutils.monotonic(space) + secs + while True: + if _WIN: + # as decreed by Guido, only the main thread can be + # interrupted. + main_thread = space.fromcache(State).main_thread + interruptible = (main_thread == thread.get_ident()) + millisecs = int(secs * 1000) + if millisecs == 0.0 or not interruptible: + rtime.sleep(secs) + break + interrupt_event = space.fromcache(State).get_interrupt_event() + rwin32.ResetEvent(interrupt_event) + rc = rwin32.WaitForSingleObject(interrupt_event, millisecs) + if rc != rwin32.WAIT_OBJECT_0: + break + else: void = lltype.nullptr(rffi.VOIDP.TO) with lltype.scoped_alloc(TIMEVAL) as t: frac = math.fmod(secs, 1.0) @@ -469,43 +483,10 @@ break # normal path if rposix.get_saved_errno() != EINTR: raise exception_from_saved_errno(space, space.w_OSError) - space.getexecutioncontext().checksignals() - secs = end_time - timeutils.monotonic(space) # retry - if secs <= 0.0: - break - -else: - from rpython.rlib import rwin32 - from errno import EINTR - def _simple_sleep(space, secs, interruptible): - if secs == 0.0 or not interruptible: - rtime.sleep(secs) - else: - millisecs = int(secs * 1000) - interrupt_event = space.fromcache(State).get_interrupt_event() - rwin32.ResetEvent(interrupt_event) - rc = rwin32.WaitForSingleObject(interrupt_event, millisecs) - if rc == rwin32.WAIT_OBJECT_0: - # Yield to make sure real Python signal handler - # called. - rtime.sleep(0.001) - raise wrap_oserror(space, - OSError(EINTR, "sleep() interrupted")) - @unwrap_spec(secs=float) - def sleep(space, secs): - XXX # review for EINTR / PEP475 - if secs < 0: - raise oefmt(space.w_ValueError, - "sleep length must be non-negative") - # as decreed by Guido, only the main thread can be - # interrupted. - main_thread = space.fromcache(State).main_thread - interruptible = (main_thread == thread.get_ident()) - MAX = sys.maxint / 1000.0 # > 24 days - while secs > MAX: - _simple_sleep(space, MAX, interruptible) - secs -= MAX - _simple_sleep(space, secs, interruptible) + space.getexecutioncontext().checksignals() + secs = end_time - timeutils.monotonic(space) # retry + if secs <= 0.0: + break def _get_module_object(space, obj_name): w_module = space.getbuiltinmodule('time') From pypy.commits at gmail.com Sat Apr 1 14:44:39 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sat, 01 Apr 2017 11:44:39 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: Fix imports on Windows Message-ID: <58dff517.dda1df0a.e6b93.45cb@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90905:31102549174f Date: 2017-04-01 20:44 +0200 http://bitbucket.org/pypy/pypy/changeset/31102549174f/ Log: Fix imports on Windows diff --git a/pypy/module/time/interp_time.py b/pypy/module/time/interp_time.py --- a/pypy/module/time/interp_time.py +++ b/pypy/module/time/interp_time.py @@ -448,7 +448,9 @@ return _strerror(errno) from errno import EINTR -from rpython.rlib.rtime import c_select +if not _WIN: + from rpython.rlib.rtime import c_select +from rpython.rlib import rwin32 @unwrap_spec(secs=float) def sleep(space, secs): From pypy.commits at gmail.com Sat Apr 1 15:14:08 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sat, 01 Apr 2017 12:14:08 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: Restore the check for very large sleep delays Message-ID: <58dffc00.16a1df0a.3ba5d.5652@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90906:52c431bcbf2f Date: 2017-04-01 21:13 +0200 http://bitbucket.org/pypy/pypy/changeset/52c431bcbf2f/ Log: Restore the check for very large sleep delays This code is already inside a retry loop. diff --git a/pypy/module/time/interp_time.py b/pypy/module/time/interp_time.py --- a/pypy/module/time/interp_time.py +++ b/pypy/module/time/interp_time.py @@ -468,6 +468,9 @@ if millisecs == 0.0 or not interruptible: rtime.sleep(secs) break + MAX = sys.maxint / 1000.0 # > 24 days + if millisecs > MAX: + millisecs = MAX interrupt_event = space.fromcache(State).get_interrupt_event() rwin32.ResetEvent(interrupt_event) rc = rwin32.WaitForSingleObject(interrupt_event, millisecs) From pypy.commits at gmail.com Sat Apr 1 15:30:04 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sat, 01 Apr 2017 12:30:04 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: Fix translation; millisecs should be ints. Message-ID: <58dfffbc.6d82df0a.50aa6.53a9@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90907:6c201838bca7 Date: 2017-04-01 21:29 +0200 http://bitbucket.org/pypy/pypy/changeset/6c201838bca7/ Log: Fix translation; millisecs should be ints. diff --git a/pypy/module/time/interp_time.py b/pypy/module/time/interp_time.py --- a/pypy/module/time/interp_time.py +++ b/pypy/module/time/interp_time.py @@ -465,10 +465,10 @@ main_thread = space.fromcache(State).main_thread interruptible = (main_thread == thread.get_ident()) millisecs = int(secs * 1000) - if millisecs == 0.0 or not interruptible: + if millisecs == 0 or not interruptible: rtime.sleep(secs) break - MAX = sys.maxint / 1000.0 # > 24 days + MAX = int(sys.maxint / 1000) # > 24 days if millisecs > MAX: millisecs = MAX interrupt_event = space.fromcache(State).get_interrupt_event() From pypy.commits at gmail.com Sat Apr 1 16:01:20 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sat, 01 Apr 2017 13:01:20 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: Fix translation for platforms without tm_zone Message-ID: <58e00710.c8151c0a.dbbdf.f085@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90908:4dec46cc728e Date: 2017-04-01 22:00 +0200 http://bitbucket.org/pypy/pypy/changeset/4dec46cc728e/ Log: Fix translation for platforms without tm_zone diff --git a/pypy/module/time/interp_time.py b/pypy/module/time/interp_time.py --- a/pypy/module/time/interp_time.py +++ b/pypy/module/time/interp_time.py @@ -588,10 +588,10 @@ rffi.setintfield(glob_buf, 'c_tm_yday', tm_yday) rffi.setintfield(glob_buf, 'c_tm_isdst', space.c_int_w(tup_w[8])) # - old_tm_zone = glob_buf.c_tm_zone - glob_buf.c_tm_zone = lltype.nullptr(rffi.CCHARP.TO) - rffi.setintfield(glob_buf, 'c_tm_gmtoff', 0) if HAS_TM_ZONE : + old_tm_zone = glob_buf.c_tm_zone + glob_buf.c_tm_zone = lltype.nullptr(rffi.CCHARP.TO) + rffi.setintfield(glob_buf, 'c_tm_gmtoff', 0) if len(tup_w) >= 10: # NOTE this is not cleanly solved! # it saves the string that is later deleted when this From pypy.commits at gmail.com Sat Apr 1 16:31:51 2017 From: pypy.commits at gmail.com (mattip) Date: Sat, 01 Apr 2017 13:31:51 -0700 (PDT) Subject: [pypy-commit] buildbot default: move PYPYBUILDBOT and NUMPY_64 to bencher4 buildslave Message-ID: <58e00e37.8d8e1c0a.fd105.feb7@mx.google.com> Author: Matti Picus Branch: Changeset: r1021:38147daa8ef7 Date: 2017-04-01 23:31 +0300 http://bitbucket.org/pypy/buildbot/changeset/38147daa8ef7/ Log: move PYPYBUILDBOT and NUMPY_64 to bencher4 buildslave diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -297,7 +297,7 @@ JITFREEBSD964, # on tavendo JITMACOSX64, # on xerxes # buildbot selftest - PYPYBUILDBOT # on cobra + PYPYBUILDBOT # on bencher4 ], branch='default', hour=0, minute=0), Nightly("nightly-1-00", [ @@ -522,11 +522,13 @@ "category": 'linux-ppc64', }, {'name': NUMPY_64, - 'slavenames': ["tannit64"], + 'slavenames': ["bencher4"], + #'slavenames': ["tannit64"], 'builddir': NUMPY_64, 'factory': pypyNumpyCompatability, 'category': 'numpy', - 'locks': [TannitCPU.access('counting')], + #'locks': [TannitCPU.access('counting')], + "locks": [Bencher4Lock.access('counting')], }, {'name': NUMPY_WIN, 'slavenames': ["allegro_win32", "SalsaSalsa"], @@ -536,10 +538,11 @@ 'category': 'numpy', }, {'name': PYPYBUILDBOT, - 'slavenames': ['cobra'], + 'slavenames': ['bencher4'], 'builddir': PYPYBUILDBOT, 'factory': pypybuilds.PyPyBuildbotTestFactory(), 'category': 'buildbot', + "locks": [Bencher4Lock.access('counting')], }, # S390X {"name": LINUX_S390X, From pypy.commits at gmail.com Sat Apr 1 16:57:40 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sat, 01 Apr 2017 13:57:40 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: Let set_wakeup_fd translate (and fail) on Windows Message-ID: <58e01444.52911c0a.d98af.fbab@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90909:80199bfe76d1 Date: 2017-04-01 22:56 +0200 http://bitbucket.org/pypy/pypy/changeset/80199bfe76d1/ Log: Let set_wakeup_fd translate (and fail) on Windows diff --git a/pypy/module/signal/interp_signal.py b/pypy/module/signal/interp_signal.py --- a/pypy/module/signal/interp_signal.py +++ b/pypy/module/signal/interp_signal.py @@ -253,6 +253,11 @@ raise oefmt(space.w_ValueError, "set_wakeup_fd only works in main thread or with " "__pypy__.thread.enable_signals()") + + if WIN32: + raise oefmt(space.w_NotImplementedError, + "signal.set_wakeup_fd is not implemented on Windows") + if fd != -1: if not rposix.is_valid_fd(fd): raise oefmt(space.w_ValueError, "invalid fd") From pypy.commits at gmail.com Sat Apr 1 17:20:55 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sat, 01 Apr 2017 14:20:55 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: Fix (isn't this function also used on Posix platforms?) Message-ID: <58e019b7.50231c0a.4f6c4.fdfe@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90910:96e11f7f941c Date: 2017-04-01 23:20 +0200 http://bitbucket.org/pypy/pypy/changeset/96e11f7f941c/ Log: Fix (isn't this function also used on Posix platforms?) diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -2168,7 +2168,7 @@ # not a bound method like 'getexecutioncontext().checksignals'. # Otherwise, we can't use it from several independent places. _sigcheck.space = space - return space.newbytes(rurandom.urandom(context, n, _signal_checker)) + return space.newbytes(rurandom.urandom(context, size, _signal_checker)) except OSError as e: # 'rurandom' should catch and retry internally if it gets EINTR # (at least in os.read(), which is probably enough in practice) From pypy.commits at gmail.com Sat Apr 1 17:36:51 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sat, 01 Apr 2017 14:36:51 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: Fix Message-ID: <58e01d73.d48e1c0a.fbff6.0788@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90911:d5edca577439 Date: 2017-04-01 23:36 +0200 http://bitbucket.org/pypy/pypy/changeset/d5edca577439/ Log: Fix diff --git a/pypy/module/_multiprocessing/interp_win32.py b/pypy/module/_multiprocessing/interp_win32.py --- a/pypy/module/_multiprocessing/interp_win32.py +++ b/pypy/module/_multiprocessing/interp_win32.py @@ -35,7 +35,7 @@ return rffi.cast(rwin32.HANDLE, space.int_w(w_handle)) def w_handle(space, handle): - return space.wrap(rffi.cast(rffi.INTPTR_T, handle)) + return space.newint(rffi.cast(rffi.INTPTR_T, handle)) _CreateNamedPipe = rwin32.winexternal( 'CreateNamedPipeA', [ From pypy.commits at gmail.com Sun Apr 2 04:09:26 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sun, 02 Apr 2017 01:09:26 -0700 (PDT) Subject: [pypy-commit] pypy default: Fix translation: these missing wrappers take no keyword arguments. Message-ID: <58e0b1b6.d28a1c0a.d944.75e0@mx.google.com> Author: Amaury Forgeot d'Arc Branch: Changeset: r90912:a01f47870f2b Date: 2017-04-02 10:08 +0200 http://bitbucket.org/pypy/pypy/changeset/a01f47870f2b/ Log: Fix translation: these missing wrappers take no keyword arguments. diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -795,7 +795,7 @@ missing_wrappers = ['wrap_indexargfunc', 'wrap_delslice', 'wrap_coercefunc'] for name in missing_wrappers: assert name not in globals() - def missing_wrapper(space, w_self, w_args, func, w_kwds): + def missing_wrapper(space, w_self, w_args, func): print "cpyext: missing slot wrapper " + name raise NotImplementedError("Slot wrapper " + name) missing_wrapper.__name__ = name From pypy.commits at gmail.com Sun Apr 2 04:09:29 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sun, 02 Apr 2017 01:09:29 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: hg merge default Message-ID: <58e0b1b9.5aa5df0a.d8d35.848f@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90913:8923cca262cd Date: 2017-04-02 10:08 +0200 http://bitbucket.org/pypy/pypy/changeset/8923cca262cd/ Log: hg merge default diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -796,7 +796,7 @@ missing_wrappers = ['wrap_indexargfunc', 'wrap_del'] for name in missing_wrappers: assert name not in globals() - def missing_wrapper(space, w_self, w_args, func, w_kwds): + def missing_wrapper(space, w_self, w_args, func): print "cpyext: missing slot wrapper " + name raise NotImplementedError("Slot wrapper " + name) missing_wrapper.__name__ = name From pypy.commits at gmail.com Sun Apr 2 05:03:45 2017 From: pypy.commits at gmail.com (nanjekye) Date: Sun, 02 Apr 2017 02:03:45 -0700 (PDT) Subject: [pypy-commit] pypy superjumbo: solving typos in test_rposix.py Message-ID: <58e0be71.9285df0a.3ae37.f03b@mx.google.com> Author: Joannah Nanjekye Branch: superjumbo Changeset: r90916:02d3198db10f Date: 2017-04-01 17:03 +0300 http://bitbucket.org/pypy/pypy/changeset/02d3198db10f/ Log: solving typos in test_rposix.py diff --git a/rpython/rlib/test/test_rposix.py b/rpython/rlib/test/test_rposix.py --- a/rpython/rlib/test/test_rposix.py +++ b/rpython/rlib/test/test_rposix.py @@ -752,25 +752,24 @@ py.test.raises(OSError, rposix.pwrite, fd, b'ea', 1) @rposix_requires('posix_fadvise') -def posix_fadvise(): +def test_posix_fadvise(): fname = str(udir.join('test_os_posix_fadvise')) localdir = os.getcwd() - os.mkdir(self.path2 + 'test_os_posix_fadvise') + os.mkdir(fname) try: fd = os.open(fname, os.O_RDONLY, 0777) try: mypath = os.getcwd() assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_WILLNEED) == 0 assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_NORMAL) == 0 - assert rposix.posix_fadvise(fd, 0, 0, rPOSIX_FADV_SEQUENTIAL) == 0 + assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_SEQUENTIAL) == 0 assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_RANDOM) == 0 assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_NOREUSE) == 0 - assert rposix.posix_fadvise(fd, 0, 0, rPOSIX_FADV_DONTNEED) == 0 + assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_DONTNEED) == 0 finally: os.close(fd) finally: os.chdir(localdir) - py.test.raises(OSError, rposix.posix_fadvise, fd, 0, 0, rPOSIX_FADV_DONTNEED) @rposix_requires('posix_fallocate') def test_posix_fallocate(): From pypy.commits at gmail.com Sun Apr 2 05:03:40 2017 From: pypy.commits at gmail.com (nanjekye) Date: Sun, 02 Apr 2017 02:03:40 -0700 (PDT) Subject: [pypy-commit] pypy superjumbo: posix_fallocate and posix_fadvise implementation Message-ID: <58e0be6c.87d91c0a.5b3f3.c83a@mx.google.com> Author: Joannah Nanjekye Branch: superjumbo Changeset: r90914:45f6af71a2e5 Date: 2017-03-27 15:06 +0300 http://bitbucket.org/pypy/pypy/changeset/45f6af71a2e5/ Log: posix_fallocate and posix_fadvise implementation diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py --- a/pypy/module/posix/__init__.py +++ b/pypy/module/posix/__init__.py @@ -222,6 +222,14 @@ if hasattr(rposix, 'pwrite'): interpleveldefs['pwrite'] = 'interp_posix.pwrite' + if hasattr(rposix, 'posix_fadvise'): + interpleveldefs['posix_fadvise'] = 'interp_posix.posix_fadvise' + interpleveldefs['posix_fallocate'] = 'interp_posix.posix_fallocate' + for _name in ['POSIX_FADV_WILLNEED', 'POSIX_FADV_NORMAL', 'POSIX_FADV_SEQUENTIAL', + 'POSIX_FADV_RANDOM', 'POSIX_FADV_NOREUSE', 'POSIX_FADV_DONTNEED']: + assert getattr(rposix, _name) is not None, "missing %r" % (_name,) + interpleveldefs[_name] = 'space.wrap(%d)' % getattr(rposix, _name) + for _name in ["O_CLOEXEC"]: if getattr(rposix, _name) is not None: interpleveldefs[_name] = 'space.wrap(%d)' % getattr(rposix, _name) diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -401,6 +401,30 @@ else: return space.newint(res) + at unwrap_spec(fd=c_int, length=r_longlong, offset=r_longlong) +def posix_fallocate(space, fd, offset, length): + """allocate file space . + """ + while True: + try: + s = rposix.posix_fallocate(fd, offset, length) + except OSError as e: + wrap_oserror(space, e, eintr_retry=True) + else: + return space.newint(s) + + at unwrap_spec(fd=c_int, offset=r_longlong, length=r_longlong, advice=int) +def posix_fadvise(space, fd, offset, length, advice): + """predeclare an access pattern for file data . + """ + while True: + try: + res = rposix.posix_fadvise(fd, offset, length, advice) + except OSError as e: + wrap_oserror(space, e, eintr_retry=True) + else: + return space.newint(res) + # ____________________________________________________________ STAT_FIELDS = unrolling_iterable(enumerate(rposix_stat.STAT_FIELDS)) diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -860,6 +860,42 @@ finally: os.close(fd) + if hasattr(rposix, 'posix_fadvise'): + def test_os_posix_fadvise(self): + posix, os = self.posix, self.os + localdir = os.getcwd() + os.mkdir(self.path2 + 'test_os_posix_fadvise') + try: + fd = os.open(self.path2 + 'test_os_posix_fadvise', os.O_RDONLY) + try: + mypath = os.getcwd() + assert posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_WILLNEED) == 0 + assert posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_NORMAL) == 0 + assert posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_SEQUENTIAL) == 0 + assert posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_RANDOM) == 0 + assert posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_NOREUSE) == 0 + assert posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_DONTNEED) == 0 + finally: + os.close(fd) + finally: + os.chdir(localdir) + + if hasattr(rposix, 'posix_fallocate'): + def test_os_posix_posix_fallocate(self): + posix, os = self.posix, self.os + fd = os.open(self.path2 + 'test_os_posix_fallocate', os.O_WRONLY | os.O_CREAT) + try: + assert posix.posix_fallocate(fd, 0, 10) == 0 + except OSError as inst: + """ ZFS seems not to support fallocate. + so skipping solaris-based since it is likely to come with ZFS + """ + if inst.errno != errno.EINVAL or not sys.platform.startswith("sunos"): + raise + finally: + os.close(fd) + + def test_largefile(self): os = self.posix fd = os.open(self.path2 + 'test_largefile', diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -255,6 +255,12 @@ PRIO_PROCESS = rffi_platform.DefinedConstantInteger('PRIO_PROCESS') PRIO_PGRP = rffi_platform.DefinedConstantInteger('PRIO_PGRP') PRIO_USER = rffi_platform.DefinedConstantInteger('PRIO_USER') + POSIX_FADV_WILLNEED = rffi_platform.DefinedConstantInteger('POSIX_FADV_WILLNEED') + POSIX_FADV_NORMAL = rffi_platform.DefinedConstantInteger('POSIX_FADV_NORMAL') + POSIX_FADV_SEQUENTIAL = rffi_platform.DefinedConstantInteger('POSIX_FADV_SEQUENTIAL') + POSIX_FADV_RANDOM= rffi_platform.DefinedConstantInteger('POSIX_FADV_RANDOM') + POSIX_FADV_NOREUSE = rffi_platform.DefinedConstantInteger('POSIX_FADV_NOREUSE') + POSIX_FADV_DONTNEED = rffi_platform.DefinedConstantInteger('POSIX_FADV_DONTNEED') O_NONBLOCK = rffi_platform.DefinedConstantInteger('O_NONBLOCK') OFF_T = rffi_platform.SimpleType('off_t') OFF_T_SIZE = rffi_platform.SizeOf('off_t') @@ -450,6 +456,12 @@ validate_fd(fd) handle_posix_error('close', c_close(fd)) +def write(fd, data): + count = len(data) + validate_fd(fd) + with rffi.scoped_nonmovingbuffer(data) as buf: + return handle_posix_error('write', c_write(fd, buf, count)) + c_lseek = external('_lseeki64' if _WIN32 else 'lseek', [rffi.INT, rffi.LONGLONG, rffi.INT], rffi.LONGLONG, macro=_MACRO_ON_POSIX, save_err=rffi.RFFI_SAVE_ERRNO) @@ -490,6 +502,23 @@ with rffi.scoped_nonmovingbuffer(data) as buf: return handle_posix_error('pwrite', c_pwrite(fd, buf, count, offset)) + c_posix_fallocate = external('posix_fallocate', + [rffi.INT, OFF_T, OFF_T], rffi.INT, + save_err=rffi.RFFI_SAVE_ERRNO) + c_posix_fadvise = external('posix_fadvise', + [rffi.INT, OFF_T, OFF_T, rffi.INT], rffi.INT, + save_err=rffi.RFFI_SAVE_ERRNO) + + @enforceargs(int, None, None) + def posix_fallocate(fd, offset, length): + validate_fd(fd) + return handle_posix_error('posix_fallocate', c_posix_fallocate(fd, offset, length)) + + @enforceargs(int, None, None, int) + def posix_fadvise(fd, offset, length, advice): + validate_fd(fd) + return handle_posix_error('posix_fadvise', c_posix_fadvise(fd, offset, length, advice)) + c_ftruncate = external('ftruncate', [rffi.INT, rffi.LONGLONG], rffi.INT, macro=_MACRO_ON_POSIX, save_err=rffi.RFFI_SAVE_ERRNO) c_fsync = external('fsync' if not _WIN32 else '_commit', [rffi.INT], rffi.INT, diff --git a/rpython/rlib/test/test_rposix.py b/rpython/rlib/test/test_rposix.py --- a/rpython/rlib/test/test_rposix.py +++ b/rpython/rlib/test/test_rposix.py @@ -750,3 +750,39 @@ finally: os.close(fd) py.test.raises(OSError, rposix.pwrite, fd, b'ea', 1) + + at rposix_requires('posix_fadvise') +def posix_fadvise(): + fname = str(udir.join('test_os_posix_fadvise')) + localdir = os.getcwd() + os.mkdir(self.path2 + 'test_os_posix_fadvise') + try: + fd = os.open(fname, os.O_RDONLY, 0777) + try: + mypath = os.getcwd() + assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_WILLNEED) == 0 + assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_NORMAL) == 0 + assert rposix.posix_fadvise(fd, 0, 0, rPOSIX_FADV_SEQUENTIAL) == 0 + assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_RANDOM) == 0 + assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_NOREUSE) == 0 + assert rposix.posix_fadvise(fd, 0, 0, rPOSIX_FADV_DONTNEED) == 0 + finally: + os.close(fd) + finally: + os.chdir(localdir) + py.test.raises(OSError, rposix.posix_fadvise, fd, 0, 0, rPOSIX_FADV_DONTNEED) + + at rposix_requires('posix_fallocate') +def test_posix_fallocate(): + fname = str(udir.join('os_test.txt')) + fd = os.open(fname, os.O_WRONLY | os.O_CREAT, 0777) + try: + assert rposix.posix_fallocate(fd, 0, 10) == 0 + except OSError as inst: + """ ZFS seems not to support fallocate. + so skipping solaris-based since it is likely to come with ZFS + """ + if inst.errno != errno.EINVAL or not sys.platform.startswith("sunos"): + raise + finally: + os.close(fd) From pypy.commits at gmail.com Sun Apr 2 05:03:48 2017 From: pypy.commits at gmail.com (arigo) Date: Sun, 02 Apr 2017 02:03:48 -0700 (PDT) Subject: [pypy-commit] pypy superjumbo: close branch, ready to merge Message-ID: <58e0be74.c791df0a.48e0c.f201@mx.google.com> Author: Armin Rigo Branch: superjumbo Changeset: r90917:218b82c4e242 Date: 2017-04-02 11:01 +0200 http://bitbucket.org/pypy/pypy/changeset/218b82c4e242/ Log: close branch, ready to merge From pypy.commits at gmail.com Sun Apr 2 05:03:50 2017 From: pypy.commits at gmail.com (arigo) Date: Sun, 02 Apr 2017 02:03:50 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: PR #530 from nanjekye (manual merge) Message-ID: <58e0be76.52911c0a.d98af.7c91@mx.google.com> Author: Armin Rigo Branch: py3.5 Changeset: r90918:debef6d067cc Date: 2017-04-02 11:02 +0200 http://bitbucket.org/pypy/pypy/changeset/debef6d067cc/ Log: PR #530 from nanjekye (manual merge) posix_fallocate and posix_fadvise implementation diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py --- a/pypy/module/posix/__init__.py +++ b/pypy/module/posix/__init__.py @@ -222,6 +222,14 @@ if hasattr(rposix, 'pwrite'): interpleveldefs['pwrite'] = 'interp_posix.pwrite' + if hasattr(rposix, 'posix_fadvise'): + interpleveldefs['posix_fadvise'] = 'interp_posix.posix_fadvise' + interpleveldefs['posix_fallocate'] = 'interp_posix.posix_fallocate' + for _name in ['POSIX_FADV_WILLNEED', 'POSIX_FADV_NORMAL', 'POSIX_FADV_SEQUENTIAL', + 'POSIX_FADV_RANDOM', 'POSIX_FADV_NOREUSE', 'POSIX_FADV_DONTNEED']: + assert getattr(rposix, _name) is not None, "missing %r" % (_name,) + interpleveldefs[_name] = 'space.wrap(%d)' % getattr(rposix, _name) + for _name in ["O_CLOEXEC"]: if getattr(rposix, _name) is not None: interpleveldefs[_name] = 'space.wrap(%d)' % getattr(rposix, _name) diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -401,6 +401,30 @@ else: return space.newint(res) + at unwrap_spec(fd=c_int, length=r_longlong, offset=r_longlong) +def posix_fallocate(space, fd, offset, length): + """allocate file space . + """ + while True: + try: + s = rposix.posix_fallocate(fd, offset, length) + except OSError as e: + wrap_oserror(space, e, eintr_retry=True) + else: + return space.newint(s) + + at unwrap_spec(fd=c_int, offset=r_longlong, length=r_longlong, advice=int) +def posix_fadvise(space, fd, offset, length, advice): + """predeclare an access pattern for file data . + """ + while True: + try: + res = rposix.posix_fadvise(fd, offset, length, advice) + except OSError as e: + wrap_oserror(space, e, eintr_retry=True) + else: + return space.newint(res) + # ____________________________________________________________ STAT_FIELDS = unrolling_iterable(enumerate(rposix_stat.STAT_FIELDS)) diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -860,6 +860,42 @@ finally: os.close(fd) + if hasattr(rposix, 'posix_fadvise'): + def test_os_posix_fadvise(self): + posix, os = self.posix, self.os + localdir = os.getcwd() + os.mkdir(self.path2 + 'test_os_posix_fadvise') + try: + fd = os.open(self.path2 + 'test_os_posix_fadvise', os.O_RDONLY) + try: + mypath = os.getcwd() + assert posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_WILLNEED) == 0 + assert posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_NORMAL) == 0 + assert posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_SEQUENTIAL) == 0 + assert posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_RANDOM) == 0 + assert posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_NOREUSE) == 0 + assert posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_DONTNEED) == 0 + finally: + os.close(fd) + finally: + os.chdir(localdir) + + if hasattr(rposix, 'posix_fallocate'): + def test_os_posix_posix_fallocate(self): + posix, os = self.posix, self.os + fd = os.open(self.path2 + 'test_os_posix_fallocate', os.O_WRONLY | os.O_CREAT) + try: + assert posix.posix_fallocate(fd, 0, 10) == 0 + except OSError as inst: + """ ZFS seems not to support fallocate. + so skipping solaris-based since it is likely to come with ZFS + """ + if inst.errno != errno.EINVAL or not sys.platform.startswith("sunos"): + raise + finally: + os.close(fd) + + def test_largefile(self): os = self.posix fd = os.open(self.path2 + 'test_largefile', diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -255,6 +255,12 @@ PRIO_PROCESS = rffi_platform.DefinedConstantInteger('PRIO_PROCESS') PRIO_PGRP = rffi_platform.DefinedConstantInteger('PRIO_PGRP') PRIO_USER = rffi_platform.DefinedConstantInteger('PRIO_USER') + POSIX_FADV_WILLNEED = rffi_platform.DefinedConstantInteger('POSIX_FADV_WILLNEED') + POSIX_FADV_NORMAL = rffi_platform.DefinedConstantInteger('POSIX_FADV_NORMAL') + POSIX_FADV_SEQUENTIAL = rffi_platform.DefinedConstantInteger('POSIX_FADV_SEQUENTIAL') + POSIX_FADV_RANDOM= rffi_platform.DefinedConstantInteger('POSIX_FADV_RANDOM') + POSIX_FADV_NOREUSE = rffi_platform.DefinedConstantInteger('POSIX_FADV_NOREUSE') + POSIX_FADV_DONTNEED = rffi_platform.DefinedConstantInteger('POSIX_FADV_DONTNEED') O_NONBLOCK = rffi_platform.DefinedConstantInteger('O_NONBLOCK') OFF_T = rffi_platform.SimpleType('off_t') OFF_T_SIZE = rffi_platform.SizeOf('off_t') @@ -449,7 +455,7 @@ def close(fd): validate_fd(fd) handle_posix_error('close', c_close(fd)) - + c_lseek = external('_lseeki64' if _WIN32 else 'lseek', [rffi.INT, rffi.LONGLONG, rffi.INT], rffi.LONGLONG, macro=_MACRO_ON_POSIX, save_err=rffi.RFFI_SAVE_ERRNO) @@ -490,6 +496,23 @@ with rffi.scoped_nonmovingbuffer(data) as buf: return handle_posix_error('pwrite', c_pwrite(fd, buf, count, offset)) + c_posix_fallocate = external('posix_fallocate', + [rffi.INT, OFF_T, OFF_T], rffi.INT, + save_err=rffi.RFFI_SAVE_ERRNO) + c_posix_fadvise = external('posix_fadvise', + [rffi.INT, OFF_T, OFF_T, rffi.INT], rffi.INT, + save_err=rffi.RFFI_SAVE_ERRNO) + + @enforceargs(int, None, None) + def posix_fallocate(fd, offset, length): + validate_fd(fd) + return handle_posix_error('posix_fallocate', c_posix_fallocate(fd, offset, length)) + + @enforceargs(int, None, None, int) + def posix_fadvise(fd, offset, length, advice): + validate_fd(fd) + return handle_posix_error('posix_fadvise', c_posix_fadvise(fd, offset, length, advice)) + c_ftruncate = external('ftruncate', [rffi.INT, rffi.LONGLONG], rffi.INT, macro=_MACRO_ON_POSIX, save_err=rffi.RFFI_SAVE_ERRNO) c_fsync = external('fsync' if not _WIN32 else '_commit', [rffi.INT], rffi.INT, diff --git a/rpython/rlib/test/test_rposix.py b/rpython/rlib/test/test_rposix.py --- a/rpython/rlib/test/test_rposix.py +++ b/rpython/rlib/test/test_rposix.py @@ -750,3 +750,38 @@ finally: os.close(fd) py.test.raises(OSError, rposix.pwrite, fd, b'ea', 1) + + at rposix_requires('posix_fadvise') +def test_posix_fadvise(): + fname = str(udir.join('test_os_posix_fadvise')) + localdir = os.getcwd() + os.mkdir(fname) + try: + fd = os.open(fname, os.O_RDONLY, 0777) + try: + mypath = os.getcwd() + assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_WILLNEED) == 0 + assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_NORMAL) == 0 + assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_SEQUENTIAL) == 0 + assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_RANDOM) == 0 + assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_NOREUSE) == 0 + assert rposix.posix_fadvise(fd, 0, 0, rposix.POSIX_FADV_DONTNEED) == 0 + finally: + os.close(fd) + finally: + os.chdir(localdir) + + at rposix_requires('posix_fallocate') +def test_posix_fallocate(): + fname = str(udir.join('os_test.txt')) + fd = os.open(fname, os.O_WRONLY | os.O_CREAT, 0777) + try: + assert rposix.posix_fallocate(fd, 0, 10) == 0 + except OSError as inst: + """ ZFS seems not to support fallocate. + so skipping solaris-based since it is likely to come with ZFS + """ + if inst.errno != errno.EINVAL or not sys.platform.startswith("sunos"): + raise + finally: + os.close(fd) From pypy.commits at gmail.com Sun Apr 2 05:03:42 2017 From: pypy.commits at gmail.com (nanjekye) Date: Sun, 02 Apr 2017 02:03:42 -0700 (PDT) Subject: [pypy-commit] pypy superjumbo: removed extra code Message-ID: <58e0be6e.0e2f1c0a.34901.8428@mx.google.com> Author: Joannah Nanjekye Branch: superjumbo Changeset: r90915:1c4ccc021d87 Date: 2017-03-27 15:27 +0300 http://bitbucket.org/pypy/pypy/changeset/1c4ccc021d87/ Log: removed extra code diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -455,13 +455,7 @@ def close(fd): validate_fd(fd) handle_posix_error('close', c_close(fd)) - -def write(fd, data): - count = len(data) - validate_fd(fd) - with rffi.scoped_nonmovingbuffer(data) as buf: - return handle_posix_error('write', c_write(fd, buf, count)) - + c_lseek = external('_lseeki64' if _WIN32 else 'lseek', [rffi.INT, rffi.LONGLONG, rffi.INT], rffi.LONGLONG, macro=_MACRO_ON_POSIX, save_err=rffi.RFFI_SAVE_ERRNO) From pypy.commits at gmail.com Sun Apr 2 05:59:29 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sun, 02 Apr 2017 02:59:29 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: Attempt to fix build_cffi_imports on Windows: args should be passed as unicode strings. Message-ID: <58e0cb81.0eb7df0a.8f5d2.b9e3@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90919:541dbb06046f Date: 2017-04-02 11:57 +0200 http://bitbucket.org/pypy/pypy/changeset/541dbb06046f/ Log: Attempt to fix build_cffi_imports on Windows: args should be passed as unicode strings. diff --git a/rpython/tool/runsubprocess.py b/rpython/tool/runsubprocess.py --- a/rpython/tool/runsubprocess.py +++ b/rpython/tool/runsubprocess.py @@ -15,7 +15,7 @@ text = str def run_subprocess(executable, args, env=None, cwd=None): - if isinstance(args, list): + if isinstance(args, list) and sys.platform != 'win32': args = [a.encode('latin1') if isinstance(a, text) else a for a in args] return _run(executable, args, env, cwd) From pypy.commits at gmail.com Sun Apr 2 11:10:40 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sun, 02 Apr 2017 08:10:40 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: Popen.communicate() returns bytes if no encoding was specified. Message-ID: <58e11470.179d1c0a.74294.e6d8@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90920:1fb74e166444 Date: 2017-04-02 17:09 +0200 http://bitbucket.org/pypy/pypy/changeset/1fb74e166444/ Log: Popen.communicate() returns bytes if no encoding was specified. diff --git a/rpython/tool/runsubprocess.py b/rpython/tool/runsubprocess.py --- a/rpython/tool/runsubprocess.py +++ b/rpython/tool/runsubprocess.py @@ -49,7 +49,7 @@ pipe = Popen(args, stdout=PIPE, stderr=PIPE, shell=shell, env=env, cwd=cwd) stdout, stderr = pipe.communicate() if (sys.platform == 'win32' and pipe.returncode == 1 and - 'is not recognized' in stderr): + b'is not recognized' in stderr): # Setting shell=True on windows messes up expected exceptions raise EnvironmentError(stderr) return pipe.returncode, stdout, stderr From pypy.commits at gmail.com Sun Apr 2 13:16:57 2017 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Apr 2017 10:16:57 -0700 (PDT) Subject: [pypy-commit] pypy default: Added tag release-pypy2.7-v5.7.1 for changeset 1aa2d8e03cdf Message-ID: <58e13209.47b4df0a.f1db.ef43@mx.google.com> Author: Matti Picus Branch: Changeset: r90921:f18bb27393c4 Date: 2017-04-02 19:59 +0300 http://bitbucket.org/pypy/pypy/changeset/f18bb27393c4/ Log: Added tag release-pypy2.7-v5.7.1 for changeset 1aa2d8e03cdf diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -36,3 +36,4 @@ aff251e543859ce4508159dd9f1a82a2f553de00 release-pypy2.7-v5.6.0 fa3249d55d15b9829e1be69cdf45b5a44cec902d release-pypy2.7-v5.7.0 b16a4363e930f6401bceb499b9520955504c6cb0 release-pypy3.5-v5.7.0 +1aa2d8e03cdfab54b7121e93fda7e98ea88a30bf release-pypy2.7-v5.7.1 From pypy.commits at gmail.com Sun Apr 2 13:58:23 2017 From: pypy.commits at gmail.com (alex_gaynor) Date: Sun, 02 Apr 2017 10:58:23 -0700 (PDT) Subject: [pypy-commit] pypy release-pypy3.5-5.x: Fixes #2508 -- correctly handle dict.pop where the popping key is not the same type as the dict's and pop is called with a default Message-ID: <58e13bbf.6d82df0a.50aa6.7dfd@mx.google.com> Author: Alex Gaynor Branch: release-pypy3.5-5.x Changeset: r90922:afcbd079e7f4 Date: 2017-04-02 20:36 +0300 http://bitbucket.org/pypy/pypy/changeset/afcbd079e7f4/ Log: Fixes #2508 -- correctly handle dict.pop where the popping key is not the same type as the dict's and pop is called with a default (grafted from a1b0ce5e4915a6e46c9007f81a991cbaf179f027) diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py --- a/pypy/objspace/std/dictmultiobject.py +++ b/pypy/objspace/std/dictmultiobject.py @@ -1007,6 +1007,8 @@ else: return d.pop(key, w_default) elif self._never_equal_to(space.type(w_key)): + if w_default is not None: + return w_default raise KeyError else: self.switch_to_object_strategy(w_dict) diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py --- a/pypy/objspace/std/test/test_dictmultiobject.py +++ b/pypy/objspace/std/test/test_dictmultiobject.py @@ -227,6 +227,10 @@ assert len(dd) == 1 raises(KeyError, dd.pop, 33) + assert d.pop("abc", None) is None + raises(KeyError, d.pop, "abc") + assert len(d) == 2 + def test_items(self): d = {1: 2, 3: 4} its = list(d.items()) From pypy.commits at gmail.com Sun Apr 2 13:58:25 2017 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Apr 2017 10:58:25 -0700 (PDT) Subject: [pypy-commit] pypy release-pypy3.5-5.x: add failing test for multiple bases Message-ID: <58e13bc1.f4aedf0a.18f12.741c@mx.google.com> Author: Matti Picus Branch: release-pypy3.5-5.x Changeset: r90923:22286c1b31a8 Date: 2017-04-02 20:38 +0300 http://bitbucket.org/pypy/pypy/changeset/22286c1b31a8/ Log: add failing test for multiple bases (grafted from 65ab47447a582ca2353f043d84d9d8225554d3bc) diff --git a/pypy/module/cpyext/test/foo.c b/pypy/module/cpyext/test/foo.c --- a/pypy/module/cpyext/test/foo.c +++ b/pypy/module/cpyext/test/foo.c @@ -160,6 +160,28 @@ return PyObject_GenericSetAttr((PyObject *)self, name, value); } +static PyObject * +new_fooType(PyTypeObject * t, PyObject *args, PyObject *kwds) +{ + PyObject * o; + /* copied from numpy scalartypes.c for inherited classes */ + if (t->tp_bases && (PyTuple_GET_SIZE(t->tp_bases) > 1)) + { + PyTypeObject *sup; + /* We are inheriting from a Python type as well so + give it first dibs on conversion */ + sup = (PyTypeObject *)PyTuple_GET_ITEM(t->tp_bases, 1); + /* Prevent recursion */ + if (new_fooType != sup->tp_new) + { + o = sup->tp_new(t, args, kwds); + return o; + } + } + o = t->tp_alloc(t, 0); + return o; +}; + static PyMemberDef foo_members[] = { {"int_member", T_INT, offsetof(fooobject, foo), 0, "A helpful docstring."}, diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -949,6 +949,8 @@ pass class foo(f2, f1): pass + + x = foo(1) assert bar.__base__ is f2 # On cpython, the size changes. if '__pypy__' in sys.builtin_module_names: From pypy.commits at gmail.com Sun Apr 2 13:58:27 2017 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Apr 2017 10:58:27 -0700 (PDT) Subject: [pypy-commit] pypy release-pypy3.5-5.x: fix for -A, fix issue setting tp_new to 0x1 Message-ID: <58e13bc3.2ea0df0a.6bdd4.8173@mx.google.com> Author: Matti Picus Branch: release-pypy3.5-5.x Changeset: r90924:c49045ac1e81 Date: 2017-04-02 20:45 +0300 http://bitbucket.org/pypy/pypy/changeset/c49045ac1e81/ Log: fix for -A, fix issue setting tp_new to 0x1 (grafted from c121ac248c573b43f774b4907e7d637bdeddddd6) diff --git a/pypy/module/cpyext/test/foo.c b/pypy/module/cpyext/test/foo.c --- a/pypy/module/cpyext/test/foo.c +++ b/pypy/module/cpyext/test/foo.c @@ -728,13 +728,14 @@ if (module == NULL) INITERROR; - footype.tp_new = PyType_GenericNew; - UnicodeSubtype.tp_base = &PyUnicode_Type; UnicodeSubtype2.tp_base = &UnicodeSubtype; MetaType.tp_base = &PyType_Type; - if (PyType_Ready(&footype) < 0) + fooType.tp_new = &new_fooType; + InitErrType.tp_new = PyType_GenericNew; + + if (PyType_Ready(&fooType) < 0) INITERROR; if (PyType_Ready(&UnicodeSubtype) < 0) INITERROR; diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -950,7 +950,7 @@ class foo(f2, f1): pass - x = foo(1) + x = foo() assert bar.__base__ is f2 # On cpython, the size changes. if '__pypy__' in sys.builtin_module_names: diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py --- a/pypy/module/cpyext/typeobject.py +++ b/pypy/module/cpyext/typeobject.py @@ -682,10 +682,6 @@ if pto.c_tp_itemsize < pto.c_tp_base.c_tp_itemsize: pto.c_tp_itemsize = pto.c_tp_base.c_tp_itemsize - if space.is_w(w_type, space.w_object): - # will be filled later on with the correct value - # may not be 0 - pto.c_tp_new = cts.cast('newfunc', 1) update_all_slots(space, w_type, pto) if not pto.c_tp_new: base_object_pyo = make_ref(space, space.w_object) From pypy.commits at gmail.com Sun Apr 2 13:58:29 2017 From: pypy.commits at gmail.com (arigo) Date: Sun, 02 Apr 2017 10:58:29 -0700 (PDT) Subject: [pypy-commit] pypy release-pypy3.5-5.x: Issue #2523 Message-ID: <58e13bc5.1498df0a.b8f48.72d6@mx.google.com> Author: Armin Rigo Branch: release-pypy3.5-5.x Changeset: r90925:3ade3b0bc2cf Date: 2017-04-02 20:46 +0300 http://bitbucket.org/pypy/pypy/changeset/3ade3b0bc2cf/ Log: Issue #2523 This should fix it. The slotdefs entry was removed in 1b0451031b2e but we didn't have any test for that. (grafted from f77701c9f5706a297821c43779219df4a0aa70b0) diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -1063,6 +1063,7 @@ wrap_indexargfunc, "__imul__($self, value, /)\n--\n\nImplement self*=value."), + TPSLOT("__getattr__", tp_getattr, NULL, NULL, ""), {NULL} }; """ diff --git a/pypy/module/cpyext/test/foo.c b/pypy/module/cpyext/test/foo.c --- a/pypy/module/cpyext/test/foo.c +++ b/pypy/module/cpyext/test/foo.c @@ -670,6 +670,34 @@ return PyInt_FromLong(tf); } +static PyTypeObject GetType1 = { + PyVarObject_HEAD_INIT(NULL, 0) + "foo.GetType1", /*tp_name*/ + sizeof(PyObject), /*tp_size*/ +}; +static PyTypeObject GetType2 = { + PyVarObject_HEAD_INIT(NULL, 0) + "foo.GetType2", /*tp_name*/ + sizeof(PyObject), /*tp_size*/ +}; +static PyObject *gettype1, *gettype2; + +static PyObject *gettype1_getattr(PyObject *self, char *name) +{ + char buf[200]; + strcpy(buf, "getattr:"); + strcat(buf, name); + return PyString_FromString(buf); +} +static PyObject *gettype2_getattro(PyObject *self, PyObject *name) +{ + char buf[200]; + strcpy(buf, "getattro:"); + strcat(buf, PyString_AS_STRING(name)); + return PyString_FromString(buf); +} + + /* List of functions exported by this module */ static PyMethodDef foo_functions[] = { @@ -767,6 +795,18 @@ if (PyType_Ready(&TupleLike) < 0) INITERROR; + GetType1.tp_flags = Py_TPFLAGS_DEFAULT; + GetType1.tp_getattr = &gettype1_getattr; + if (PyType_Ready(&GetType1) < 0) + INITERROR; + gettype1 = PyObject_New(PyObject, &GetType1); + + GetType2.tp_flags = Py_TPFLAGS_DEFAULT; + GetType2.tp_getattro = &gettype2_getattro; + if (PyType_Ready(&GetType2) < 0) + INITERROR; + gettype2 = PyObject_New(PyObject, &GetType2); + d = PyModule_GetDict(module); if (d == NULL) @@ -789,6 +829,10 @@ INITERROR; if (PyDict_SetItemString(d, "TupleLike", (PyObject *) &TupleLike) < 0) INITERROR; + if (PyDict_SetItemString(d, "gettype1", gettype1) < 0) + INITERROR; + if (PyDict_SetItemString(d, "gettype2", gettype2) < 0) + INITERROR; #if PY_MAJOR_VERSION >=3 return module; #endif diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -1221,3 +1221,14 @@ pass bases = module.foo(C) assert bases == (A, B) + + def test_getattr_getattro(self): + module = self.import_module(name='foo') + assert module.gettype2.dcba == 'getattro:dcba' + assert (type(module.gettype2).__getattribute__(module.gettype2, 'dcBA') + == 'getattro:dcBA') + assert module.gettype1.abcd == 'getattr:abcd' + # GetType1 objects have a __getattribute__ method, but this + # doesn't call tp_getattr at all, also on CPython + raises(AttributeError, type(module.gettype1).__getattribute__, + module.gettype1, 'dcBA') From pypy.commits at gmail.com Sun Apr 2 13:58:31 2017 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Apr 2017 10:58:31 -0700 (PDT) Subject: [pypy-commit] pypy release-pypy3.5-5.x: update version to 5.7.1 Message-ID: <58e13bc7.dd451c0a.9c183.0ce3@mx.google.com> Author: Matti Picus Branch: release-pypy3.5-5.x Changeset: r90926:2875f328eae2 Date: 2017-04-02 20:48 +0300 http://bitbucket.org/pypy/pypy/changeset/2875f328eae2/ Log: update version to 5.7.1 diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h --- a/pypy/module/cpyext/include/patchlevel.h +++ b/pypy/module/cpyext/include/patchlevel.h @@ -29,8 +29,8 @@ #define PY_VERSION "3.5.2" /* PyPy version as a string */ -#define PYPY_VERSION "5.7.0-beta0" -#define PYPY_VERSION_NUM 0x05070000 +#define PYPY_VERSION "5.7.1-beta0" +#define PYPY_VERSION_NUM 0x05070100 /* Defined to mean a PyPy where cpyext holds more regular references to PyObjects, e.g. staying alive as long as the internal PyPy object diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py --- a/pypy/module/sys/version.py +++ b/pypy/module/sys/version.py @@ -10,7 +10,7 @@ #XXX # sync CPYTHON_VERSION with patchlevel.h, package.py CPYTHON_API_VERSION = 1013 #XXX # sync with include/modsupport.h -PYPY_VERSION = (5, 7, 0, "beta", 0) #XXX # sync patchlevel.h +PYPY_VERSION = (5, 7, 1, "beta", 0) #XXX # sync patchlevel.h import pypy From pypy.commits at gmail.com Sun Apr 2 14:32:50 2017 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Apr 2017 11:32:50 -0700 (PDT) Subject: [pypy-commit] pypy default: add release note for 5.7.1 Message-ID: <58e143d2.8f8bdf0a.8999.842b@mx.google.com> Author: Matti Picus Branch: Changeset: r90927:26e8cd8592fc Date: 2017-04-02 21:31 +0300 http://bitbucket.org/pypy/pypy/changeset/26e8cd8592fc/ Log: add release note for 5.7.1 diff --git a/pypy/doc/index-of-release-notes.rst b/pypy/doc/index-of-release-notes.rst --- a/pypy/doc/index-of-release-notes.rst +++ b/pypy/doc/index-of-release-notes.rst @@ -6,6 +6,7 @@ .. toctree:: + release-v5.7.1.rst release-v5.7.0.rst release-pypy2.7-v5.6.0.rst release-pypy2.7-v5.4.1.rst @@ -59,6 +60,7 @@ .. toctree:: + release-v5.7.1.rst release-v5.7.0.rst CPython 3.3 compatible versions diff --git a/pypy/doc/release-v5.7.1.rst b/pypy/doc/release-v5.7.1.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/release-v5.7.1.rst @@ -0,0 +1,50 @@ +========== +PyPy 5.7.1 +========== + +We have released a bugfix PyPy2.7-v5.7.1 and PyPy3.5-v5.7.1 beta (Linux 64bit), +due to the following issues: + + * correctly handle an edge case in dict.pop (issue #2508_) + + * fix a regression to correctly handle multiple inheritance in a C-API type + where the seconde base is an app-level class with a ``__new__`` function + + * fix a regression to fill a C-API type's ``tp_getattr`` slot from a + ``__getattr__`` method (issue #2523_) + +Thanks to those who reported the issues. + +.. _2508: https://bitbucket.org/pypy/pypy/issues/2508 +.. _2523: https://bitbucket.org/pypy/pypy/issues/2523 + +What is PyPy? +============= + +PyPy is a very compliant Python interpreter, almost a drop-in replacement for +CPython 2.7 and CPython 3.5. It's fast (`PyPy and CPython 2.7.x`_ performance comparison) +due to its integrated tracing JIT compiler. + +We also welcome developers of other `dynamic languages`_ to see what RPython +can do for them. + +The PyPy 2.7 release supports: + + * **x86** machines on most common operating systems + (Linux 32/64 bits, Mac OS X 64 bits, Windows 32 bits, OpenBSD, FreeBSD) + + * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux, + + * big- and little-endian variants of **PPC64** running Linux, + + * **s390x** running Linux + +.. _`PyPy and CPython 2.7.x`: http://speed.pypy.org +.. _`dynamic languages`: http://rpython.readthedocs.io/en/latest/examples.html + +Please update, and continue to help us make PyPy better. + +Cheers + +The PyPy Team + From pypy.commits at gmail.com Sun Apr 2 15:31:01 2017 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Apr 2017 12:31:01 -0700 (PDT) Subject: [pypy-commit] pypy.org extradoc: update for pypy2.7 5.7.1, regen later when more complete Message-ID: <58e15175.4e8bdf0a.7d3f7.98d0@mx.google.com> Author: Matti Picus Branch: extradoc Changeset: r876:a6f73a25f6e1 Date: 2017-04-02 22:30 +0300 http://bitbucket.org/pypy/pypy.org/changeset/a6f73a25f6e1/ Log: update for pypy2.7 5.7.1, regen later when more complete diff --git a/source/download.txt b/source/download.txt --- a/source/download.txt +++ b/source/download.txt @@ -15,14 +15,14 @@ We provide binaries for x86, ARM, PPC and s390x running on different operating systems such as Linux, Mac OS/X and Windows: -* the Python2.7 compatible release — **PyPy2.7 v5.7.0** — (`what's new in PyPy2.7?`_) +* the Python2.7 compatible release — **PyPy2.7 v5.7.1** — (`what's new in PyPy2.7?`_) -* the Python3.5 compatible beta quality release — **PyPy3.5 v5.7.0** — (`what's new in PyPy3.5?`_). +* the Python3.5 compatible beta quality release — **PyPy3.5 v5.7.1** — (`what's new in PyPy3.5?`_). * the Python2.7 Software Transactional Memory special release — **PyPy-STM 2.5.1** (Linux x86-64 only) -.. _what's new in PyPy2.7?: http://doc.pypy.org/en/latest/release-v5.7.0.html -.. _what's new in PyPy3.5?: http://doc.pypy.org/en/latest/release-v5.7.0.html +.. _what's new in PyPy2.7?: http://doc.pypy.org/en/latest/release-v5.7.1.html +.. _what's new in PyPy3.5?: http://doc.pypy.org/en/latest/release-v5.7.1.html .. class:: download_menu @@ -79,7 +79,7 @@ .. _release: -Python2.7 compatible PyPy 5.7.0 +Python2.7 compatible PyPy 5.7.1 ------------------------------- * `Linux x86 binary (32bit, tar.bz2 built on Ubuntu 12.04 - 14.04)`__ (see ``[1]`` below) @@ -98,18 +98,18 @@ * `All our downloads,`__ including previous versions. We also have a mirror_, but please use only if you have troubles accessing the links above -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.0-linux32.tar.bz2 -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.0-linux64.tar.bz2 -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.0-linux-armhf-raspbian.tar.bz2 -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.0-linux-armhf-raring.tar.bz2 -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.0-linux-armel.tar.bz2 -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.0-osx64.tar.bz2 -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.0-win32.zip -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.0-ppc64.tar.bz2 -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.0-ppc64le.tar.bz2 -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.0-s390x.tar.bz2 -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.0-src.tar.bz2 -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.0-src.zip +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.1-linux32.tar.bz2 +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.1-linux64.tar.bz2 +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.1-linux-armhf-raspbian.tar.bz2 +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.1-linux-armhf-raring.tar.bz2 +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.1-linux-armel.tar.bz2 +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.1-osx64.tar.bz2 +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.1-win32.zip +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.1-ppc64.tar.bz2 +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.1-ppc64le.tar.bz2 +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.1-s390x.tar.bz2 +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.1-src.tar.bz2 +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.1-src.zip .. _`vcredist_x86.exe`: http://www.microsoft.com/en-us/download/details.aspx?id=5582 .. __: https://bitbucket.org/pypy/pypy/downloads .. _mirror: http://buildbot.pypy.org/mirror/ @@ -131,9 +131,9 @@ * `All our downloads,`__ including previous versions. We also have a mirror_, but please use only if you have troubles accessing the links above -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy3-v5.7.0-linux64.tar.bz2 -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy3-v5.7.0-src.tar.bz2 -.. __: https://bitbucket.org/pypy/pypy/downloads/pypy3-v5.7.0-src.zip +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy3-v5.7.1-linux64.tar.bz2 +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy3-v5.7.1-src.tar.bz2 +.. __: https://bitbucket.org/pypy/pypy/downloads/pypy3-v5.7.1-src.zip .. __: https://bitbucket.org/pypy/pypy/downloads If your CPU is really, really old, it may be a x86-32 without SSE2. @@ -203,7 +203,7 @@ uncompressed, they run in-place. For now you can uncompress them either somewhere in your home directory or, say, in ``/opt``, and if you want, put a symlink from somewhere like -``/usr/local/bin/pypy`` to ``/path/to/pypy2-5.7.0/bin/pypy``. Do +``/usr/local/bin/pypy`` to ``/path/to/pypy2-5.7.1/bin/pypy``. Do not move or copy the executable ``pypy`` outside the tree --- put a symlink to it, otherwise it will not find its libraries. @@ -307,9 +307,9 @@ Alternatively, the following smaller package contains the source at the same revision as the above binaries: - * `pypy2-v5.7.0-src.tar.bz2`__ (sources) + * `pypy2-v5.7.1-src.tar.bz2`__ (sources) - .. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.0-src.tar.bz2 + .. __: https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.1-src.tar.bz2 2. Make sure you **installed the dependencies.** See the list here__. @@ -439,87 +439,19 @@ Here are the checksums for each of the downloads -pypy2.7-v5.7.0 md5:: +pypy2.7-v5.7.1 sha256:: - bb55f4a28d64d40367a58139b25b02fe pypy2-v5.7.0-linux32.tar.bz2 - 84b542e3aaca2aec9b0ca3afb6a3373b pypy2-v5.7.0-linux64.tar.bz2 - 9f98c917ec1dbbda821bd23734fdc4d4 pypy2-v5.7.0-linux-armel.tar.bz2 - 509539d3f5876584fa5cad6fd125e446 pypy2-v5.7.0-linux-armhf-raring.tar.bz2 - 34739358ba2e438d27b777838154f255 pypy2-v5.7.0-linux-armhf-raspbian.tar.bz2 - 6b6180f4b0932d5a3a7499ddef1c5129 pypy2-v5.7.0-osx64.tar.bz2 - 180d5cc3f58a9f9088481c7d4c6b5d68 pypy2-v5.7.0-s390x.tar.bz2 - aa26e72c1f30b77734198af6fb6f9ad7 pypy2-v5.7.0-src.tar.bz2 - f1633ad18e0af309aa11e3425f628cf9 pypy2-v5.7.0-src.zip - 23f15d2bc0c29fe6948a99352962ebf0 pypy2-v5.7.0-win32.zip + f125a227f8c814ba1698168a639ea6ca59bb69c280529639eed29076d8429a73 pypy2-v5.7.1-linux32.tar.bz2 + c4fa3da42156bed4a9d912433b618a141e0c5161d7cc8c328786736ea5d1c2da pypy2-v5.7.1-linux64.tar.bz2 + 591a4a73cc945a1125848f3615a28559692db8febf677d7087eaef40cb119a8d pypy2-v5.7.1-linux-armel.tar.bz2 + c1b1a0968b22c58672f7492dc7900bc85e3bd02c791f219f31401a00ef387207 pypy2-v5.7.1-linux-armhf-raring.tar.bz2 + 67544f8c4b284db71cf1af74edef290722f97f82476cbdaff2015fdab244c6ee pypy2-v5.7.1-linux-armhf-raspbian.tar.bz2 + 4e99ba356432861534917a9477ace0ccee617bd631512759a530f8383e153a3d pypy2-v5.7.1-osx64.tar.bz2 + 395c57a1aa078c9ae9aa9f18263bb91fa23114bae4d133d10560eaea30c51892 pypy2-v5.7.1-s390x.tar.bz2 + d01bee43c6df79f7bbc1149bb3e85f489491fb2358a6a1f9a7f0d6e07715832f pypy2-v5.7.1-src.tar.bz2 + f580a7b41cc09e030bbff66752044bdfbc193ec617e575c64bf65c136c298076 pypy2-v5.7.1-src.zip + a3ba7c946635236836f8536d8767a0f456b3b9a86876cb5c3173a04522bf451b pypy2-v5.7.1-win32.zip -pypy 3.5-v5.7.0 md5:: - - 410fb506ac436c344f785bb77820e13e pypy3-v5.7.0-linux64.tar.bz2 - 79b1d5749eb97be36933dbdf156fec02 pypy3-v5.7.0-src.tar.bz2 - 594f3d17be1c80181d13c0f025ae25f6 pypy3-v5.7.0-src.zip - -pypy3.3-v5.5.0-alpha md5:: - - e9bdfb330a30765eaf76ddd4e826a45e pypy3.3-v5.5.0-alpha-linux32.tar.bz2 - b04022a5a549bba719c9a184c783805c pypy3.3-v5.5.0-alpha-linux64.tar.bz2 - 84424f01b2746c71f64e27cb4c7069a1 pypy3.3-v5.5.0-alpha-linux-armel.tar.bz2 - 9d18b171a7249227f3a3b74af8070c82 pypy3.3-v5.5.0-alpha-linux-armhf-raspbian.tar.bz2 - d2424a9e3ff31e26e5b1f0ceade5e9f7 pypy3.3-v5.5.0-alpha-osx64.tar.bz2 - c32728185d89f9c0fda9481f2f9ae61d pypy3.3-v5.5.0-alpha-s390x.tar.bz2 - 536008fd7b17af8878915393fc1ecfc3 pypy3.3-v5.5.0-alpha-src.tar.bz2 - 4fc66068848dbfc09b210d3115380b0a pypy3.3-v5.5.0-alpha-src.zip - -pypy-1.8 sandbox md5:: - - 2c9f0054f3b93a6473f10be35277825a pypy-1.8-sandbox-linux64.tar.bz2 - 009c970b5fa75754ae4c32a5d108a8d4 pypy-1.8-sandbox-linux.tar.bz2 - -pypy2.7-v5.7.0 sha1:: - - c8cc2cbc2b75962d0e5920f4a756f7fe3f13596c pypy2-v5.7.0-linux32.tar.bz2 - 0a831dae298fce2110626637342d0e3545a8ab47 pypy2-v5.7.0-linux64.tar.bz2 - 556face1374a75720177176a4c7517bb4f9a62a5 pypy2-v5.7.0-linux-armel.tar.bz2 - bec04d53cd2a7cc89cf67cfdab2207ad6c08781b pypy2-v5.7.0-linux-armhf-raring.tar.bz2 - c510f53447fc800b4611545d2679d596d8f0c461 pypy2-v5.7.0-linux-armhf-raspbian.tar.bz2 - 097e418d5aa61c7697a50536c5b173d8211603a9 pypy2-v5.7.0-osx64.tar.bz2 - a11cf7d95a909c8e60bafc79ff491711ecd0ee29 pypy2-v5.7.0-ppc64.tar.bz2 - 0ccb73316935c5610e5170330556443abd87d3cd pypy2-v5.7.0-ppc64le.tar.bz2 - 20f33a4d0c08a5d4935086caec73be3d92b60b2b pypy2-v5.7.0-s390x.tar.bz2 - 5976e1f19a42f64f778d385322723200b5c6d7c9 pypy2-v5.7.0-src.tar.bz2 - c84ad90184edb315031074696e805ecbc08494e3 pypy2-v5.7.0-src.zip - 15df479b08870dc6ec9cab0e4587935fc0694cb8 pypy2-v5.7.0-win32.zip - -pypy 3.5-v5.7.0 sha1:: - - e10511bde5a88c5de9fdf9234188b8df23382a6a pypy3-v5.7.0-linux64.tar.bz2 - 0b12230025d77be26bc10cbc81671c4b3719528c pypy3-v5.7.0-src.tar.bz2 - ae256d83173faaadce9602594fd752fb664b813b pypy3-v5.7.0-src.zip - -pypy3.3-v5.5.0-alpha sha1:: - - 1de17b61b8d21e408a46114961659b4c0f15cb54 pypy3.3-v5.5.0-alpha-linux32.tar.bz2 - 995ae3b983d9975006b898f098b27408949d2fdf pypy3.3-v5.5.0-alpha-linux64.tar.bz2 - 2487f726d7b50aef041beba2bb0f39fe4d7392da pypy3.3-v5.5.0-alpha-linux-armel.tar.bz2 - ed104a504664a7ccd971da202abe14302246175a pypy3.3-v5.5.0-alpha-linux-armhf-raspbian.tar.bz2 - 0f6456672b02e4856421021d2ff71ffaca2e2c3e pypy3.3-v5.5.0-alpha-osx64.tar.bz2 - 018e9e9e4c54fcef3959bc316f3e684f88231ab4 pypy3.3-v5.5.0-alpha-s390x.tar.bz2 - 9eb6aad2d41f7db16c19ae6e438c8f195b0d44fc pypy3.3-v5.5.0-alpha-src.tar.bz2 - b670cdc685c323b11bfdca2a15f12c5953e6d8b4 pypy3.3-v5.5.0-alpha-src.zip - -pypy2.7-v5.7.0 sha256:: - - aaa55085d11a49cb982b059b4159495d7a4fb9afcfda7bfd680cc0175e9fa33b pypy2-v5.7.0-linux32.tar.bz2 - 64bed80e299b09c13296f577a0f52c5d4be9f7c699a390ca6026f967aeff3846 pypy2-v5.7.0-linux64.tar.bz2 - 3bc0d2616cacef9f544e739d4c25a89e16d7aa8c1ccb18c32dceeb021ed73711 pypy2-v5.7.0-linux-armel.tar.bz2 - 413df8097c87a8e79cc46df65837b1d533de83b7cb06ce88b168697807fff696 pypy2-v5.7.0-linux-armhf-raring.tar.bz2 - 6328e4767cf20d20a290739db2d1ec769f3c9c360fa9824f61581b3356add79b pypy2-v5.7.0-linux-armhf-raspbian.tar.bz2 - 9204aa1b55771a374a3118bb43e498c88caca8c33710eecf3249855c4dd1352a pypy2-v5.7.0-osx64.tar.bz2 - ca936b034a5cd2decfd3b500fad3c28e5a6327a77bb56b2d2ba6ff0159c00f2c pypy2-v5.7.0-ppc64.tar.bz2 - 3ecb3165c85df60f8e59bfdf28304cd40894d304ee04a4d58dc8b9947cbb2b01 pypy2-v5.7.0-ppc64le.tar.bz2 - 8820b36f38b4aa44c1ef2be213c7d13818c9fdb61795f24f4fb18a7a78d2dde7 pypy2-v5.7.0-s390x.tar.bz2 - e522ea7ca51b16ee5505f22b86803664b762a263a6d69ba84c359fcf8365ad3e pypy2-v5.7.0-src.tar.bz2 - 784be3d2b8bb12a0d88d088fd991b03324d9f84a48af5dbaf2a536eaee91d8b5 pypy2-v5.7.0-src.zip - 09c8da3a7e09cea821f9b300c6f4f52f4a571d949d91839ecbce93b84a08d570 pypy2-v5.7.0-win32.zip pypy 3.5-v5.7.0 sha256:: From pypy.commits at gmail.com Sun Apr 2 15:42:40 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sun, 02 Apr 2017 12:42:40 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: Restore support for _sre.CODESIZE=2 that was present in Python 2.7 Message-ID: <58e15430.91581c0a.c4383.eb48@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90928:302d39bda33c Date: 2017-04-02 21:41 +0200 http://bitbucket.org/pypy/pypy/changeset/302d39bda33c/ Log: Restore support for _sre.CODESIZE=2 that was present in Python 2.7 diff --git a/lib-python/3/sre_compile.py b/lib-python/3/sre_compile.py --- a/lib-python/3/sre_compile.py +++ b/lib-python/3/sre_compile.py @@ -378,7 +378,11 @@ def _bytes_to_codes(b): # Convert block indices to word array - a = memoryview(b).cast('I') + if _sre.CODESIZE == 2: + code = 'H' + else: + code = 'I' + a = memoryview(b).cast(code) assert a.itemsize == _sre.CODESIZE assert len(a) * a.itemsize == len(b) return a.tolist() From pypy.commits at gmail.com Sun Apr 2 15:46:31 2017 From: pypy.commits at gmail.com (arigo) Date: Sun, 02 Apr 2017 12:46:31 -0700 (PDT) Subject: [pypy-commit] pypy release-pypy2.7-5.x: Support translation with older Linux kernel headers Message-ID: <58e15517.2780df0a.695f5.900d@mx.google.com> Author: Armin Rigo Branch: release-pypy2.7-5.x Changeset: r90929:c8a8072b284d Date: 2017-03-20 23:32 +0100 http://bitbucket.org/pypy/pypy/changeset/c8a8072b284d/ Log: Support translation with older Linux kernel headers diff --git a/rpython/rlib/rurandom.py b/rpython/rlib/rurandom.py --- a/rpython/rlib/rurandom.py +++ b/rpython/rlib/rurandom.py @@ -99,8 +99,11 @@ eci = eci.merge(ExternalCompilationInfo(includes=['linux/random.h'])) class CConfig: _compilation_info_ = eci - GRND_NONBLOCK = rffi_platform.ConstantInteger('GRND_NONBLOCK') + GRND_NONBLOCK = rffi_platform.DefinedConstantInteger( + 'GRND_NONBLOCK') globals().update(rffi_platform.configure(CConfig)) + if GRND_NONBLOCK is None: + GRND_NONBLOCK = 0x0001 # from linux/random.h # On Linux, use the syscall() function because the GNU libc doesn't # expose the Linux getrandom() syscall yet. From pypy.commits at gmail.com Sun Apr 2 16:40:39 2017 From: pypy.commits at gmail.com (sirtom67) Date: Sun, 02 Apr 2017 13:40:39 -0700 (PDT) Subject: [pypy-commit] cffi sirtom67/float_complex: merge in default again. All tests pass in 2.7 on linux. Message-ID: <58e161c7.c7321c0a.6f752.362b@mx.google.com> Author: Tom Krauss Branch: sirtom67/float_complex Changeset: r2924:67fe455916a4 Date: 2017-04-02 15:39 -0500 http://bitbucket.org/cffi/cffi/changeset/67fe455916a4/ Log: merge in default again. All tests pass in 2.7 on linux. diff --git a/c/misc_thread_common.h b/c/misc_thread_common.h --- a/c/misc_thread_common.h +++ b/c/misc_thread_common.h @@ -29,12 +29,7 @@ struct cffi_tls_s *tls = (struct cffi_tls_s *)p; if (tls->local_thread_state != NULL) { - /* We need to re-acquire the GIL temporarily to free the - thread state. I hope it is not a problem to do it in - a thread-local destructor. - */ - PyEval_RestoreThread(tls->local_thread_state); - PyThreadState_DeleteCurrent(); + PyThreadState_Delete(tls->local_thread_state); } free(tls); } From pypy.commits at gmail.com Sun Apr 2 19:17:16 2017 From: pypy.commits at gmail.com (amauryfa) Date: Sun, 02 Apr 2017 16:17:16 -0700 (PDT) Subject: [pypy-commit] pypy py3.5: See what's wrong with distutils on our win32 buildbot. Message-ID: <58e1867c.429d1c0a.1b686.614b@mx.google.com> Author: Amaury Forgeot d'Arc Branch: py3.5 Changeset: r90930:9c096b732bfc Date: 2017-04-03 01:16 +0200 http://bitbucket.org/pypy/pypy/changeset/9c096b732bfc/ Log: See what's wrong with distutils on our win32 buildbot. "Unable to find vcvarsall.bat" is a bit too terse. diff --git a/lib_pypy/_audioop_build.py b/lib_pypy/_audioop_build.py --- a/lib_pypy/_audioop_build.py +++ b/lib_pypy/_audioop_build.py @@ -656,4 +656,4 @@ ffi.set_source("_audioop_cffi", C_SOURCE) if __name__ == "__main__": - ffi.compile() + ffi.compile(verbose=2) From pypy.commits at gmail.com Mon Apr 3 11:33:35 2017 From: pypy.commits at gmail.com (mattip) Date: Mon, 03 Apr 2017 08:33:35 -0700 (PDT) Subject: [pypy-commit] pypy default: Added tag release-pypy3.5-v5.7.1 for changeset 2875f328eae2 Message-ID: <58e26b4f.caa6df0a.bbf31.da0b@mx.google.com> Author: Matti Picus Branch: Changeset: r90931:35282ed3fcab Date: 2017-04-03 18:32 +0300 http://bitbucket.org/pypy/pypy/changeset/35282ed3fcab/ Log: Added tag release-pypy3.5-v5.7.1 for changeset 2875f328eae2 diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -37,3 +37,4 @@ fa3249d55d15b9829e1be69cdf45b5a44cec902d release-pypy2.7-v5.7.0 b16a4363e930f6401bceb499b9520955504c6cb0 release-pypy3.5-v5.7.0 1aa2d8e03cdfab54b7121e93fda7e98ea88a30bf release-pypy2.7-v5.7.1 +2875f328eae2216a87f3d6f335092832eb031f56 release-pypy3.5-v5.7.1 From pypy.commits at gmail.com Mon Apr 3 11:38:04 2017 From: pypy.commits at gmail.com (plan_rich) Date: Mon, 03 Apr 2017 08:38:04 -0700 (PDT) Subject: [pypy-commit] pypy default: copy over old version of vmprof_config.h and vmprof_getpc.h, another issue because pypy grew its own version of vmprof sources Message-ID: <58e26c5c.6ca0df0a.13103.e10e@mx.google.com> Author: Richard Plangger Branch: Changeset: r90932:209327e538f7 Date: 2017-04-03 11:35 -0400 http://bitbucket.org/pypy/pypy/changeset/209327e538f7/ Log: copy over old version of vmprof_config.h and vmprof_getpc.h, another issue because pypy grew its own version of vmprof sources diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_config.h b/rpython/rlib/rvmprof/src/shared/vmprof_config.h --- a/rpython/rlib/rvmprof/src/shared/vmprof_config.h +++ b/rpython/rlib/rvmprof/src/shared/vmprof_config.h @@ -1,8 +1,30 @@ -#pragma once +#if !defined(__OpenBSD__) +# define HAVE_SYS_UCONTEXT_H +#else +# define HAVE_SIGNAL_H +#endif -#define HAVE_SYS_UCONTEXT_H -#if defined(__FreeBSD__) || defined(__APPLE__) -#define PC_FROM_UCONTEXT uc_mcontext.mc_rip +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) + #ifdef __i386__ + #define PC_FROM_UCONTEXT uc_mcontext.mc_eip + #else + #define PC_FROM_UCONTEXT uc_mcontext.mc_rip + #endif +#elif defined(__OpenBSD__) +#define PC_FROM_UCONTEXT sc_rip +#elif defined( __APPLE__) + #if ((ULONG_MAX) == (UINT_MAX)) + #define PC_FROM_UCONTEXT uc_mcontext->__ss.__eip + #else + #define PC_FROM_UCONTEXT uc_mcontext->__ss.__rip + #endif +#elif defined(__arm__) + #define PC_FROM_UCONTEXT uc_mcontext.arm_ip +#elif defined(__linux) && defined(__i386) && defined(__GNUC__) + #define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_EIP] +#elif defined(__s390x__) + #define PC_FROM_UCONTEXT uc_mcontext.psw.addr #else -#define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_RIP] + /* linux, gnuc */ + #define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_RIP] #endif diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_getpc.h b/rpython/rlib/rvmprof/src/shared/vmprof_getpc.h --- a/rpython/rlib/rvmprof/src/shared/vmprof_getpc.h +++ b/rpython/rlib/rvmprof/src/shared/vmprof_getpc.h @@ -43,15 +43,6 @@ #ifndef BASE_GETPC_H_ #define BASE_GETPC_H_ - -#if ((ULONG_MAX) == (UINT_MAX)) -# define IS32BIT -#else -# define IS64BIT -#endif - -#include "vmprof_config.h" - // On many linux systems, we may need _GNU_SOURCE to get access to // the defined constants that define the register we want to see (eg // REG_EIP). Note this #define must come first! @@ -60,8 +51,11 @@ // It will cause problems for FreeBSD though!, because it turns off // the needed __BSD_VISIBLE. #ifdef __APPLE__ +#include #define _XOPEN_SOURCE 500 -#endif // __APPLE__ +#endif + +#include "vmprof_config.h" #include // for memcmp #if defined(HAVE_SYS_UCONTEXT_H) @@ -71,6 +65,10 @@ #elif defined(HAVE_CYGWIN_SIGNAL_H) #include typedef ucontext ucontext_t; +#elif defined(HAVE_SIGNAL_H) +#include +#else +# error "don't know how to get the pc on this platform" #endif @@ -117,52 +115,8 @@ // PC_FROM_UCONTEXT in config.h. The only thing we need to do here, // then, is to do the magic call-unrolling for systems that support it. -// -- Special case 1: linux x86, for which we have CallUnrollInfo -#if defined(__linux) && defined(__i386) && defined(__GNUC__) -static const struct CallUnrollInfo callunrollinfo[] = { - // Entry to a function: push %ebp; mov %esp,%ebp - // Top-of-stack contains the caller IP. - { 0, - {0x55, 0x89, 0xe5}, 3, - 0 - }, - // Entry to a function, second instruction: push %ebp; mov %esp,%ebp - // Top-of-stack contains the old frame, caller IP is +4. - { -1, - {0x55, 0x89, 0xe5}, 3, - 4 - }, - // Return from a function: RET. - // Top-of-stack contains the caller IP. - { 0, - {0xc3}, 1, - 0 - } -}; - -void* GetPC(ucontext_t *signal_ucontext) { - // See comment above struct CallUnrollInfo. Only try instruction - // flow matching if both eip and esp looks reasonable. - const int eip = signal_ucontext->uc_mcontext.gregs[REG_EIP]; - const int esp = signal_ucontext->uc_mcontext.gregs[REG_ESP]; - if ((eip & 0xffff0000) != 0 && (~eip & 0xffff0000) != 0 && - (esp & 0xffff0000) != 0) { - char* eip_char = (char*)(eip); - int i; - for (i = 0; i < sizeof(callunrollinfo)/sizeof(*callunrollinfo); ++i) { - if (!memcmp(eip_char + callunrollinfo[i].pc_offset, - callunrollinfo[i].ins, callunrollinfo[i].ins_size)) { - // We have a match. - void **retaddr = (void**)(esp + callunrollinfo[i].return_sp_offset); - return *retaddr; - } - } - } - return (void*)eip; -} - -// Special case #2: Windows, which has to do something totally different. -#elif defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__) +// Special case Windows, which has to do something totally different. +#if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__) // If this is ever implemented, probably the way to do it is to have // profiler.cc use a high-precision timer via timeSetEvent: // http://msdn2.microsoft.com/en-us/library/ms712713.aspx @@ -172,31 +126,24 @@ // how we'd get the PC (using StackWalk64?) // http://msdn2.microsoft.com/en-us/library/ms680650.aspx -#include "base/logging.h" // for RAW_LOG -#ifndef HAVE_CYGWIN_SIGNAL_H -typedef int ucontext_t; -#endif +// #include "base/logging.h" // for RAW_LOG +// #ifndef HAVE_CYGWIN_SIGNAL_H +// typedef int ucontext_t; +// #endif -void* GetPC(ucontext_t *signal_ucontext) { - RAW_LOG(ERROR, "GetPC is not yet implemented on Windows\n"); +static intptr_t GetPC(ucontext_t *signal_ucontext) { + // RAW_LOG(ERROR, "GetPC is not yet implemented on Windows\n"); + fprintf(stderr, "GetPC is not yet implemented on Windows\n"); return NULL; } // Normal cases. If this doesn't compile, it's probably because // PC_FROM_UCONTEXT is the empty string. You need to figure out // the right value for your system, and add it to the list in -// configure.ac (or set it manually in your config.h). +// vmrpof_config.h #else -void* GetPC(ucontext_t *signal_ucontext) { -#ifdef __APPLE__ - #ifdef IS32BIT - return (void*)(signal_ucontext->uc_mcontext->__ss.__eip); - #else - return (void*)(signal_ucontext->uc_mcontext->__ss.__rip); - #endif -#else - return (void*)signal_ucontext->PC_FROM_UCONTEXT; // defined in config.h -#endif +static intptr_t GetPC(ucontext_t *signal_ucontext) { + return signal_ucontext->PC_FROM_UCONTEXT; // defined in config.h } #endif From pypy.commits at gmail.com Mon Apr 3 11:51:20 2017 From: pypy.commits at gmail.com (mattip) Date: Mon, 03 Apr 2017 08:51:20 -0700 (PDT) Subject: [pypy-commit] pypy.org extradoc: update pypy3 to 5.7.1 Message-ID: <58e26f78.0a87df0a.e22f3.e568@mx.google.com> Author: Matti Picus Branch: extradoc Changeset: r877:8dc790251912 Date: 2017-04-03 18:50 +0300 http://bitbucket.org/pypy/pypy.org/changeset/8dc790251912/ Log: update pypy3 to 5.7.1 diff --git a/source/download.txt b/source/download.txt --- a/source/download.txt +++ b/source/download.txt @@ -453,11 +453,11 @@ a3ba7c946635236836f8536d8767a0f456b3b9a86876cb5c3173a04522bf451b pypy2-v5.7.1-win32.zip -pypy 3.5-v5.7.0 sha256:: +pypy 3.5-v5.7.1 sha256:: - 921894884a647220a712ecdaad516d9c22fbadf3b4bb3a5db8f3635c60eabc7b pypy3-v5.7.0-linux64.tar.bz2 - f0f563b74f8b82ec33b022393219b93cc0d81e9f9500614fe8417b67a52e9569 pypy3-v5.7.0-src.tar.bz2 - fe8b9804a8599ef5b16114fb64ba8392342f0066dfe81103b89198a3c5d10989 pypy3-v5.7.0-src.zip + 2abaa54d88c9b70b64c37083e7e430a1d3a8f78f8de92e484a988b7aca1e50a7 pypy3-v5.7.1-linux64.tar.bz2 + 40ece0145282980ac121390f13709404c0532896507d5767496381180b631bd0 pypy3-v5.7.1-src.tar.bz2 + 97fb0075ab2ecfb912fab996c71c6a8475ff18766db6c9e060f9384b809500bd pypy3-v5.7.1-src.zip pypy3.3-v5.5.0-alpha sha256:: From pypy.commits at gmail.com Mon Apr 3 11:56:29 2017 From: pypy.commits at gmail.com (arigo) Date: Mon, 03 Apr 2017 08:56:29 -0700 (PDT) Subject: [pypy-commit] pypy.org extradoc: sha256 for the ppc tarballs Message-ID: <58e270ad.0a301c0a.54bd8.77df@mx.google.com> Author: Armin Rigo Branch: extradoc Changeset: r878:3a8409b145d5 Date: 2017-04-03 17:56 +0200 http://bitbucket.org/pypy/pypy.org/changeset/3a8409b145d5/ Log: sha256 for the ppc tarballs diff --git a/download.html b/download.html --- a/download.html +++ b/download.html @@ -77,8 +77,8 @@

We provide binaries for x86, ARM, PPC and s390x running on different operating systems such as Linux, Mac OS/X and Windows:

    -
  • the Python2.7 compatible release — PyPy2.7 v5.7.0 — (what's new in PyPy2.7?)
  • -
  • the Python3.5 compatible beta quality release — PyPy3.5 v5.7.0 — (what's new in PyPy3.5?).
  • +
  • the Python2.7 compatible release — PyPy2.7 v5.7.1 — (what's new in PyPy2.7?)
  • +
  • the Python3.5 compatible beta quality release — PyPy3.5 v5.7.1 — (what's new in PyPy3.5?).
  • the Python2.7 Software Transactional Memory special release — PyPy-STM 2.5.1 (Linux x86-64 only)
    @@ -117,22 +117,22 @@
  • or translate your own PyPy.
-
-

Python2.7 compatible PyPy 5.7.0

+
+

Python2.7 compatible PyPy 5.7.1

@@ -144,9 +144,9 @@ PyPy 2. You are welcome to use it anyway; if you're lucky it will be fast in your case.

@@ -200,7 +200,7 @@ uncompressed, they run in-place. For now you can uncompress them either somewhere in your home directory or, say, in /opt, and if you want, put a symlink from somewhere like -/usr/local/bin/pypy to /path/to/pypy2-5.7.0/bin/pypy. Do +/usr/local/bin/pypy to /path/to/pypy2-5.7.1/bin/pypy. Do not move or copy the executable pypy outside the tree – put a symlink to it, otherwise it will not find its libraries.

@@ -281,7 +281,7 @@

Alternatively, the following smaller package contains the source at the same revision as the above binaries:

  • Make sure you installed the dependencies. See the list here.

    @@ -396,93 +396,26 @@

    Checksums

    Here are the checksums for each of the downloads

    -

    pypy2.7-v5.7.0 md5:

    +

    pypy2.7-v5.7.1 sha256:

    -bb55f4a28d64d40367a58139b25b02fe  pypy2-v5.7.0-linux32.tar.bz2
    -84b542e3aaca2aec9b0ca3afb6a3373b  pypy2-v5.7.0-linux64.tar.bz2
    -9f98c917ec1dbbda821bd23734fdc4d4  pypy2-v5.7.0-linux-armel.tar.bz2
    -509539d3f5876584fa5cad6fd125e446  pypy2-v5.7.0-linux-armhf-raring.tar.bz2
    -34739358ba2e438d27b777838154f255  pypy2-v5.7.0-linux-armhf-raspbian.tar.bz2
    -6b6180f4b0932d5a3a7499ddef1c5129  pypy2-v5.7.0-osx64.tar.bz2
    -180d5cc3f58a9f9088481c7d4c6b5d68  pypy2-v5.7.0-s390x.tar.bz2
    -aa26e72c1f30b77734198af6fb6f9ad7  pypy2-v5.7.0-src.tar.bz2
    -f1633ad18e0af309aa11e3425f628cf9  pypy2-v5.7.0-src.zip
    -23f15d2bc0c29fe6948a99352962ebf0  pypy2-v5.7.0-win32.zip
    +f125a227f8c814ba1698168a639ea6ca59bb69c280529639eed29076d8429a73  pypy2-v5.7.1-linux32.tar.bz2
    +c4fa3da42156bed4a9d912433b618a141e0c5161d7cc8c328786736ea5d1c2da  pypy2-v5.7.1-linux64.tar.bz2
    +591a4a73cc945a1125848f3615a28559692db8febf677d7087eaef40cb119a8d  pypy2-v5.7.1-linux-armel.tar.bz2
    +c1b1a0968b22c58672f7492dc7900bc85e3bd02c791f219f31401a00ef387207  pypy2-v5.7.1-linux-armhf-raring.tar.bz2
    +67544f8c4b284db71cf1af74edef290722f97f82476cbdaff2015fdab244c6ee  pypy2-v5.7.1-linux-armhf-raspbian.tar.bz2
    +4e99ba356432861534917a9477ace0ccee617bd631512759a530f8383e153a3d  pypy2-v5.7.1-osx64.tar.bz2
    +395c57a1aa078c9ae9aa9f18263bb91fa23114bae4d133d10560eaea30c51892  pypy2-v5.7.1-s390x.tar.bz2
    +d01bee43c6df79f7bbc1149bb3e85f489491fb2358a6a1f9a7f0d6e07715832f  pypy2-v5.7.1-src.tar.bz2
    +f580a7b41cc09e030bbff66752044bdfbc193ec617e575c64bf65c136c298076  pypy2-v5.7.1-src.zip
    +a3ba7c946635236836f8536d8767a0f456b3b9a86876cb5c3173a04522bf451b  pypy2-v5.7.1-win32.zip
    +a4edb857c1f001bab4b545f2f87f3653e8cd882a95233d60d584edb9700722e9  pypy2-v5.7.1-ppc64.tar.bz2
    +5db9bb6429d9cf146f74360ec30b40bd0df78116f458cf14035a0b7daefa35eb  pypy2-v5.7.1-ppc64le.tar.bz2
     
    -

    pypy 3.5-v5.7.0 md5:

    +

    pypy 3.5-v5.7.1 sha256:

    -410fb506ac436c344f785bb77820e13e  pypy3-v5.7.0-linux64.tar.bz2
    -79b1d5749eb97be36933dbdf156fec02  pypy3-v5.7.0-src.tar.bz2
    -594f3d17be1c80181d13c0f025ae25f6  pypy3-v5.7.0-src.zip
    -
    -

    pypy3.3-v5.5.0-alpha md5:

    -
    -e9bdfb330a30765eaf76ddd4e826a45e  pypy3.3-v5.5.0-alpha-linux32.tar.bz2
    -b04022a5a549bba719c9a184c783805c  pypy3.3-v5.5.0-alpha-linux64.tar.bz2
    -84424f01b2746c71f64e27cb4c7069a1  pypy3.3-v5.5.0-alpha-linux-armel.tar.bz2
    -9d18b171a7249227f3a3b74af8070c82  pypy3.3-v5.5.0-alpha-linux-armhf-raspbian.tar.bz2
    -d2424a9e3ff31e26e5b1f0ceade5e9f7  pypy3.3-v5.5.0-alpha-osx64.tar.bz2
    -c32728185d89f9c0fda9481f2f9ae61d  pypy3.3-v5.5.0-alpha-s390x.tar.bz2
    -536008fd7b17af8878915393fc1ecfc3  pypy3.3-v5.5.0-alpha-src.tar.bz2
    -4fc66068848dbfc09b210d3115380b0a  pypy3.3-v5.5.0-alpha-src.zip
    -
    -

    pypy-1.8 sandbox md5:

    -
    -2c9f0054f3b93a6473f10be35277825a  pypy-1.8-sandbox-linux64.tar.bz2
    -009c970b5fa75754ae4c32a5d108a8d4  pypy-1.8-sandbox-linux.tar.bz2
    -
    -

    pypy2.7-v5.7.0 sha1:

    -
    -c8cc2cbc2b75962d0e5920f4a756f7fe3f13596c  pypy2-v5.7.0-linux32.tar.bz2
    -0a831dae298fce2110626637342d0e3545a8ab47  pypy2-v5.7.0-linux64.tar.bz2
    -556face1374a75720177176a4c7517bb4f9a62a5  pypy2-v5.7.0-linux-armel.tar.bz2
    -bec04d53cd2a7cc89cf67cfdab2207ad6c08781b  pypy2-v5.7.0-linux-armhf-raring.tar.bz2
    -c510f53447fc800b4611545d2679d596d8f0c461  pypy2-v5.7.0-linux-armhf-raspbian.tar.bz2
    -097e418d5aa61c7697a50536c5b173d8211603a9  pypy2-v5.7.0-osx64.tar.bz2
    -a11cf7d95a909c8e60bafc79ff491711ecd0ee29  pypy2-v5.7.0-ppc64.tar.bz2
    -0ccb73316935c5610e5170330556443abd87d3cd  pypy2-v5.7.0-ppc64le.tar.bz2
    -20f33a4d0c08a5d4935086caec73be3d92b60b2b  pypy2-v5.7.0-s390x.tar.bz2
    -5976e1f19a42f64f778d385322723200b5c6d7c9  pypy2-v5.7.0-src.tar.bz2
    -c84ad90184edb315031074696e805ecbc08494e3  pypy2-v5.7.0-src.zip
    -15df479b08870dc6ec9cab0e4587935fc0694cb8  pypy2-v5.7.0-win32.zip
    -
    -

    pypy 3.5-v5.7.0 sha1:

    -
    -e10511bde5a88c5de9fdf9234188b8df23382a6a  pypy3-v5.7.0-linux64.tar.bz2
    -0b12230025d77be26bc10cbc81671c4b3719528c  pypy3-v5.7.0-src.tar.bz2
    -ae256d83173faaadce9602594fd752fb664b813b  pypy3-v5.7.0-src.zip
    -
    -

    pypy3.3-v5.5.0-alpha sha1:

    -
    -1de17b61b8d21e408a46114961659b4c0f15cb54  pypy3.3-v5.5.0-alpha-linux32.tar.bz2
    -995ae3b983d9975006b898f098b27408949d2fdf  pypy3.3-v5.5.0-alpha-linux64.tar.bz2
    -2487f726d7b50aef041beba2bb0f39fe4d7392da  pypy3.3-v5.5.0-alpha-linux-armel.tar.bz2
    -ed104a504664a7ccd971da202abe14302246175a  pypy3.3-v5.5.0-alpha-linux-armhf-raspbian.tar.bz2
    -0f6456672b02e4856421021d2ff71ffaca2e2c3e  pypy3.3-v5.5.0-alpha-osx64.tar.bz2
    -018e9e9e4c54fcef3959bc316f3e684f88231ab4  pypy3.3-v5.5.0-alpha-s390x.tar.bz2
    -9eb6aad2d41f7db16c19ae6e438c8f195b0d44fc  pypy3.3-v5.5.0-alpha-src.tar.bz2
    -b670cdc685c323b11bfdca2a15f12c5953e6d8b4  pypy3.3-v5.5.0-alpha-src.zip
    -
    -

    pypy2.7-v5.7.0 sha256:

    -
    -aaa55085d11a49cb982b059b4159495d7a4fb9afcfda7bfd680cc0175e9fa33b  pypy2-v5.7.0-linux32.tar.bz2
    -64bed80e299b09c13296f577a0f52c5d4be9f7c699a390ca6026f967aeff3846  pypy2-v5.7.0-linux64.tar.bz2
    -3bc0d2616cacef9f544e739d4c25a89e16d7aa8c1ccb18c32dceeb021ed73711  pypy2-v5.7.0-linux-armel.tar.bz2
    -413df8097c87a8e79cc46df65837b1d533de83b7cb06ce88b168697807fff696  pypy2-v5.7.0-linux-armhf-raring.tar.bz2
    -6328e4767cf20d20a290739db2d1ec769f3c9c360fa9824f61581b3356add79b  pypy2-v5.7.0-linux-armhf-raspbian.tar.bz2
    -9204aa1b55771a374a3118bb43e498c88caca8c33710eecf3249855c4dd1352a  pypy2-v5.7.0-osx64.tar.bz2
    -ca936b034a5cd2decfd3b500fad3c28e5a6327a77bb56b2d2ba6ff0159c00f2c  pypy2-v5.7.0-ppc64.tar.bz2
    -3ecb3165c85df60f8e59bfdf28304cd40894d304ee04a4d58dc8b9947cbb2b01  pypy2-v5.7.0-ppc64le.tar.bz2
    -8820b36f38b4aa44c1ef2be213c7d13818c9fdb61795f24f4fb18a7a78d2dde7  pypy2-v5.7.0-s390x.tar.bz2
    -e522ea7ca51b16ee5505f22b86803664b762a263a6d69ba84c359fcf8365ad3e  pypy2-v5.7.0-src.tar.bz2
    -784be3d2b8bb12a0d88d088fd991b03324d9f84a48af5dbaf2a536eaee91d8b5  pypy2-v5.7.0-src.zip
    -09c8da3a7e09cea821f9b300c6f4f52f4a571d949d91839ecbce93b84a08d570  pypy2-v5.7.0-win32.zip
    -
    -

    pypy 3.5-v5.7.0 sha256:

    -
    -921894884a647220a712ecdaad516d9c22fbadf3b4bb3a5db8f3635c60eabc7b  pypy3-v5.7.0-linux64.tar.bz2
    -f0f563b74f8b82ec33b022393219b93cc0d81e9f9500614fe8417b67a52e9569  pypy3-v5.7.0-src.tar.bz2
    -fe8b9804a8599ef5b16114fb64ba8392342f0066dfe81103b89198a3c5d10989  pypy3-v5.7.0-src.zip
    +2abaa54d88c9b70b64c37083e7e430a1d3a8f78f8de92e484a988b7aca1e50a7  pypy3-v5.7.1-linux64.tar.bz2
    +40ece0145282980ac121390f13709404c0532896507d5767496381180b631bd0  pypy3-v5.7.1-src.tar.bz2
    +97fb0075ab2ecfb912fab996c71c6a8475ff18766db6c9e060f9384b809500bd  pypy3-v5.7.1-src.zip
     

    pypy3.3-v5.5.0-alpha sha256:

    diff --git a/source/download.txt b/source/download.txt
    --- a/source/download.txt
    +++ b/source/download.txt
    @@ -451,6 +451,8 @@
         d01bee43c6df79f7bbc1149bb3e85f489491fb2358a6a1f9a7f0d6e07715832f  pypy2-v5.7.1-src.tar.bz2
         f580a7b41cc09e030bbff66752044bdfbc193ec617e575c64bf65c136c298076  pypy2-v5.7.1-src.zip
         a3ba7c946635236836f8536d8767a0f456b3b9a86876cb5c3173a04522bf451b  pypy2-v5.7.1-win32.zip
    +    a4edb857c1f001bab4b545f2f87f3653e8cd882a95233d60d584edb9700722e9  pypy2-v5.7.1-ppc64.tar.bz2
    +    5db9bb6429d9cf146f74360ec30b40bd0df78116f458cf14035a0b7daefa35eb  pypy2-v5.7.1-ppc64le.tar.bz2
     
     
     pypy 3.5-v5.7.1 sha256::
    
    From pypy.commits at gmail.com  Mon Apr  3 12:27:21 2017
    From: pypy.commits at gmail.com (mattip)
    Date: Mon, 03 Apr 2017 09:27:21 -0700 (PDT)
    Subject: [pypy-commit] pypy default: fix links
    Message-ID: <58e277e9.c43a1c0a.e8291.8405@mx.google.com>
    
    Author: Matti Picus 
    Branch: 
    Changeset: r90933:bf1bb149e026
    Date: 2017-04-03 19:24 +0300
    http://bitbucket.org/pypy/pypy/changeset/bf1bb149e026/
    
    Log:	fix links
    
    diff --git a/pypy/doc/release-v5.7.0.rst b/pypy/doc/release-v5.7.0.rst
    --- a/pypy/doc/release-v5.7.0.rst
    +++ b/pypy/doc/release-v5.7.0.rst
    @@ -99,7 +99,7 @@
         tp_dealloc
       * refactor and clean up poor handling of unicode exposed in work on py3.5
       * builtin module cppyy_ supports C++ 11, 14, etc. via cling (reflex has been removed)
    -  * adapt ``weakref`` according to CPython issue #19542_, will be in CPython 2.7.14
    +  * adapt ``weakref`` according to CPython issue 19542_, will be in CPython 2.7.14
       * support translations with cpyext and the Boehm GC (for special cases like
         RevDB_
       * implement ``StringBuffer.get_raw_address`` for the buffer protocol, it is
    @@ -125,18 +125,18 @@
       * disable ``clock_gettime()`` on OS/X, since we support 10.11 and it was only
         added in 10.12
       * support ``HAVE_FSTATVFS`` which was unintentionally always false
    -  * fix user-created C-API heaptype, issue #2434_
    +  * fix user-created C-API heaptype, issue 2434_
       * fix ``PyDict_Update`` is not actually the same as ``dict.update``
       * assign ``tp_doc`` on ``PyTypeObject`` and tie it to the app-level ``__doc__`` attribute
    -    issue #2446_
    +    issue 2446_
       * clean up memory leaks around ``PyObject_GetBuffer``, ``PyMemoryView_GET_BUFFER``,
         ``PyMemoryView_FromBuffer``, and ``PyBuffer_Release``
       * improve support for creating C-extension objects from app-level classes,
         filling more slots, especially ``tp_new`` and ``tp_dealloc``
    -  * fix for ``ctypes.c_bool`` returning ``bool`` restype, issue #2475_
    +  * fix for ``ctypes.c_bool`` returning ``bool`` restype, issue 2475_
       * fix in corner cases with the GIL and C-API functions
    -  * allow overriding thread.local.__init__ in a subclass, issue #2501_
    -  * allow ``PyClass_New`` to be called with NULL as the first arguemnt, issue #2504_
    +  * allow overriding thread.local.__init__ in a subclass, issue 2501_
    +  * allow ``PyClass_New`` to be called with NULL as the first arguemnt, issue 2504_
     
     
     * Performance improvements:
    diff --git a/pypy/doc/release-v5.7.1.rst b/pypy/doc/release-v5.7.1.rst
    --- a/pypy/doc/release-v5.7.1.rst
    +++ b/pypy/doc/release-v5.7.1.rst
    @@ -5,13 +5,13 @@
     We have released a bugfix PyPy2.7-v5.7.1 and PyPy3.5-v5.7.1 beta (Linux 64bit),
     due to the following issues:
     
    -  * correctly handle an edge case in dict.pop (issue #2508_)
    +  * correctly handle an edge case in dict.pop (issue 2508_)
     
       * fix a regression to correctly handle multiple inheritance in a C-API type
         where the seconde base is an app-level class with a ``__new__`` function
     
       * fix a regression to fill a C-API type's ``tp_getattr`` slot from a
    -    ``__getattr__`` method (issue #2523_)
    +    ``__getattr__`` method (issue 2523_)
     
     Thanks to those who reported the issues.
     
    
    From pypy.commits at gmail.com  Mon Apr  3 12:45:20 2017
    From: pypy.commits at gmail.com (mattip)
    Date: Mon, 03 Apr 2017 09:45:20 -0700 (PDT)
    Subject: [pypy-commit] pypy default: typo (marky1991)
    Message-ID: <58e27c20.8c091c0a.f8deb.75b6@mx.google.com>
    
    Author: Matti Picus 
    Branch: 
    Changeset: r90934:5a015a054c16
    Date: 2017-04-03 19:44 +0300
    http://bitbucket.org/pypy/pypy/changeset/5a015a054c16/
    
    Log:	typo (marky1991)
    
    diff --git a/pypy/doc/release-v5.7.1.rst b/pypy/doc/release-v5.7.1.rst
    --- a/pypy/doc/release-v5.7.1.rst
    +++ b/pypy/doc/release-v5.7.1.rst
    @@ -8,7 +8,7 @@
       * correctly handle an edge case in dict.pop (issue 2508_)
     
       * fix a regression to correctly handle multiple inheritance in a C-API type
    -    where the seconde base is an app-level class with a ``__new__`` function
    +    where the second base is an app-level class with a ``__new__`` function
     
       * fix a regression to fill a C-API type's ``tp_getattr`` slot from a
         ``__getattr__`` method (issue 2523_)
    
    From pypy.commits at gmail.com  Mon Apr  3 13:20:13 2017
    From: pypy.commits at gmail.com (plan_rich)
    Date: Mon, 03 Apr 2017 10:20:13 -0700 (PDT)
    Subject: [pypy-commit] pypy default: include signal.h for mac os x
    Message-ID: <58e2844d.c3a4df0a.f3a44.1fd6@mx.google.com>
    
    Author: Richard Plangger 
    Branch: 
    Changeset: r90935:94bf0cac414f
    Date: 2017-04-03 13:14 -0400
    http://bitbucket.org/pypy/pypy/changeset/94bf0cac414f/
    
    Log:	include signal.h for mac os x
    
    diff --git a/rpython/rlib/rvmprof/src/rvmprof.h b/rpython/rlib/rvmprof/src/rvmprof.h
    --- a/rpython/rlib/rvmprof/src/rvmprof.h
    +++ b/rpython/rlib/rvmprof/src/rvmprof.h
    @@ -1,5 +1,6 @@
     #pragma once
     
    +#include 
     #include "shared/vmprof.h"
     
     #define SINGLE_BUF_SIZE (8192 - 2 * sizeof(unsigned int))
    
    From pypy.commits at gmail.com  Mon Apr  3 14:00:13 2017
    From: pypy.commits at gmail.com (plan_rich)
    Date: Mon, 03 Apr 2017 11:00:13 -0700 (PDT)
    Subject: [pypy-commit] pypy default: define VMPROF_WINDOWS if it has not
     already been defined (only on windows),
     this should simplify the vmprof setup
    Message-ID: <58e28dad.16a1df0a.1334f.93cf@mx.google.com>
    
    Author: Richard Plangger 
    Branch: 
    Changeset: r90936:a73be2d612a2
    Date: 2017-04-03 13:58 -0400
    http://bitbucket.org/pypy/pypy/changeset/a73be2d612a2/
    
    Log:	define VMPROF_WINDOWS if it has not already been defined (only on
    	windows), this should simplify the vmprof setup
    
    diff --git a/pypy/module/_vmprof/test/test_direct.py b/pypy/module/_vmprof/test/test_direct.py
    --- a/pypy/module/_vmprof/test/test_direct.py
    +++ b/pypy/module/_vmprof/test/test_direct.py
    @@ -1,4 +1,4 @@
    -
    +import sys
     import py
     try:
         import cffi
    @@ -7,6 +7,7 @@
     
     from rpython.rlib import rvmprof
     srcdir = py.path.local(rvmprof.__file__).join("..", "src")
    +shareddir = srcdir.join('shared')
     
     ffi = cffi.FFI()
     ffi.cdef("""
    @@ -43,7 +44,7 @@
     }
     
     
    -""" + open(str(srcdir.join("shared/vmprof_get_custom_offset.h"))).read(), include_dirs=[str(srcdir)])
    +""" + open(str(srcdir.join("shared/vmprof_get_custom_offset.h"))).read(), include_dirs=[str(srcdir), str(shareddir)])
     
     class TestDirect(object):
         def test_infrastructure(self):
    diff --git a/rpython/rlib/rvmprof/src/shared/vmprof.h b/rpython/rlib/rvmprof/src/shared/vmprof.h
    --- a/rpython/rlib/rvmprof/src/shared/vmprof.h
    +++ b/rpython/rlib/rvmprof/src/shared/vmprof.h
    @@ -29,6 +29,12 @@
     
     #define DYN_JIT_FLAG 0xbeefbeef
     
    +#ifdef _WIN32
    +#ifndef VMPROF_WINDOWS
    +#define VMPROF_WINDOWS
    +#endif
    +#endif
    +
     #ifdef VMPROF_UNIX
     #define VMP_SUPPORTS_NATIVE_PROFILING
     #endif
    diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_get_custom_offset.h b/rpython/rlib/rvmprof/src/shared/vmprof_get_custom_offset.h
    --- a/rpython/rlib/rvmprof/src/shared/vmprof_get_custom_offset.h
    +++ b/rpython/rlib/rvmprof/src/shared/vmprof_get_custom_offset.h
    @@ -1,5 +1,7 @@
     #pragma once
     
    +#include "vmprof.h"
    +
     #ifdef VMPROF_WINDOWS
     #include "msiinttypes/stdint.h"
     #else
    
    From pypy.commits at gmail.com  Mon Apr  3 16:11:45 2017
    From: pypy.commits at gmail.com (arigo)
    Date: Mon, 03 Apr 2017 13:11:45 -0700 (PDT)
    Subject: [pypy-commit] pypy.org extradoc: Remove checksums of outdated
     downloads
    Message-ID: <58e2ac81.08a7df0a.72f48.2fd5@mx.google.com>
    
    Author: Armin Rigo 
    Branch: extradoc
    Changeset: r879:46aed66e3f34
    Date: 2017-04-03 22:11 +0200
    http://bitbucket.org/pypy/pypy.org/changeset/46aed66e3f34/
    
    Log:	Remove checksums of outdated downloads
    
    diff --git a/download.html b/download.html
    --- a/download.html
    +++ b/download.html
    @@ -417,22 +417,6 @@
     40ece0145282980ac121390f13709404c0532896507d5767496381180b631bd0  pypy3-v5.7.1-src.tar.bz2
     97fb0075ab2ecfb912fab996c71c6a8475ff18766db6c9e060f9384b809500bd  pypy3-v5.7.1-src.zip
     
    -

    pypy3.3-v5.5.0-alpha sha256:

    -
    -966ee7951ad497ac907e01554fe48da77cc64a5e35a1307477c2f78652eba622  pypy3.3-v5.5.0-alpha-linux32.tar.bz2
    -41ef7c25fd04eeb20deaa83c5d88c10aef2bbc8bcfd9e53e7cc61136220861cc  pypy3.3-v5.5.0-alpha-linux64.tar.bz2
    -9f081041867f434f18456f936befbacd9f40c0ede24137cbf80f9f45ff37b69f  pypy3.3-v5.5.0-alpha-linux-armel.tar.bz2
    -d8e94c834307081d5c4be863fab935e34df360a77b06e8bc833624c4b712b2aa  pypy3.3-v5.5.0-alpha-linux-armhf-raspbian.tar.bz2
    -fa45f861a6c40ae44f99ec94c521adfb6b64b0c9c0b6fc6e9df018241a648986  pypy3.3-v5.5.0-alpha-osx64.tar.bz2
    -c4a0a75a987b3dacd811c653e57b6a0a01fc31cdaf671e83ad43f4c107961a02  pypy3.3-v5.5.0-alpha-s390x.tar.bz2
    -d5591c34d77253e9ed57d182b6f49585b95f7c09c3e121f0e8630e5a7e75ab5f  pypy3.3-v5.5.0-alpha-src.tar.bz2
    -43b3791f77f253d4da59fdeeec49b1daefea9a57321c726a19b4924c520a0b49  pypy3.3-v5.5.0-alpha-src.zip
    -
    -

    pypy-1.8 sandbox sha1:

    -
    -895aaf7bba5787dd30adda5cc0e0e7fc297c0ca7  pypy-1.8-sandbox-linux64.tar.bz2
    -be94460bed8b2682880495435c309b6611ae2c31  pypy-1.8-sandbox-linux.tar.bz2
    -