Author: Ronan Lamy <ronan.l...@gmail.com> Branch: py3.5 Changeset: r87638:2724bf3350af Date: 2016-10-09 00:23 +0100 http://bitbucket.org/pypy/pypy/changeset/2724bf3350af/
Log: hg merge py3k diff too long, truncating to 2000 out of 11272 lines diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile @@ -40,4 +40,4 @@ # http://lists.gnu.org/archive/html/help-make/2010-08/msg00106.html cffi_imports: pypy-c - PYTHONPATH=. ./pypy-c pypy/tool/build_cffi_imports.py + PYTHONPATH=. ./pypy-c pypy/tool/build_cffi_imports.py || /bin/true diff --git a/lib-python/2.7/test/test_timeit.py b/lib-python/2.7/test/test_timeit.py --- a/lib-python/2.7/test/test_timeit.py +++ b/lib-python/2.7/test/test_timeit.py @@ -13,7 +13,7 @@ DEFAULT_NUMBER = 1000000 # timeit's default number of repetitions. -DEFAULT_REPEAT = 3 +DEFAULT_REPEAT = timeit.default_repeat # XXX: some tests are commented out that would improve the coverage but take a # long time to run because they test the default number of loops, which is @@ -204,7 +204,7 @@ t.print_exc(s) self.assert_exc_string(s.getvalue(), 'ZeroDivisionError') - MAIN_DEFAULT_OUTPUT = "10 loops, best of 3: 1 sec per loop\n" + MAIN_DEFAULT_OUTPUT = "1 loops, average of 7: 1 +- 0 sec per loop (using standard deviation)\n" def run_main(self, seconds_per_increment=1.0, switches=None, timer=None): if timer is None: @@ -230,33 +230,35 @@ def test_main_seconds(self): s = self.run_main(seconds_per_increment=5.5) - self.assertEqual(s, "10 loops, best of 3: 5.5 sec per loop\n") + self.assertIn("1 loops, average of 7: 5.5 +- 0 sec per loop (using standard deviation)\n", s) def test_main_milliseconds(self): s = self.run_main(seconds_per_increment=0.0055) - self.assertEqual(s, "100 loops, best of 3: 5.5 msec per loop\n") + self.assertIn("100 loops, average of 7: 5.5 +-", s) + self.assertIn("msec per loop", s) def test_main_microseconds(self): s = self.run_main(seconds_per_increment=0.0000025, switches=['-n100']) - self.assertEqual(s, "100 loops, best of 3: 2.5 usec per loop\n") + self.assertIn("100 loops, average of 7: 2.5", s) + self.assertIn("usec per loop", s) def test_main_fixed_iters(self): s = self.run_main(seconds_per_increment=2.0, switches=['-n35']) - self.assertEqual(s, "35 loops, best of 3: 2 sec per loop\n") + self.assertIn("35 loops, average of 7: 2 +- 0 sec per loop (using standard deviation)\n", s) def test_main_setup(self): s = self.run_main(seconds_per_increment=2.0, switches=['-n35', '-s', 'print("CustomSetup")']) - self.assertEqual(s, "CustomSetup\n" * 3 + - "35 loops, best of 3: 2 sec per loop\n") + self.assertIn("CustomSetup\n" * DEFAULT_REPEAT + + "35 loops, average of 7: 2 +- 0 sec per loop (using standard deviation)\n", s) def test_main_fixed_reps(self): s = self.run_main(seconds_per_increment=60.0, switches=['-r9']) - self.assertEqual(s, "10 loops, best of 9: 60 sec per loop\n") + self.assertIn("1 loops, average of 9: 60 +- 0 sec per loop (using standard deviation)\n", s) def test_main_negative_reps(self): s = self.run_main(seconds_per_increment=60.0, switches=['-r-5']) - self.assertEqual(s, "10 loops, best of 1: 60 sec per loop\n") + self.assertIn("1 loops, average of 1: 60 +- 0 sec per loop (using standard deviation)\n", s) @unittest.skipIf(sys.flags.optimize >= 2, "need __doc__") def test_main_help(self): @@ -266,33 +268,34 @@ def test_main_using_time(self): fake_timer = FakeTimer() s = self.run_main(switches=['-t'], timer=fake_timer) - self.assertEqual(s, self.MAIN_DEFAULT_OUTPUT) + self.assertIn(self.MAIN_DEFAULT_OUTPUT, s) self.assertIs(fake_timer.saved_timer, time.time) def test_main_using_clock(self): fake_timer = FakeTimer() s = self.run_main(switches=['-c'], timer=fake_timer) - self.assertEqual(s, self.MAIN_DEFAULT_OUTPUT) + self.assertIn(self.MAIN_DEFAULT_OUTPUT, s) self.assertIs(fake_timer.saved_timer, time.clock) def test_main_verbose(self): s = self.run_main(switches=['-v']) - self.assertEqual(s, dedent("""\ - 10 loops -> 10 secs - raw times: 10 10 10 - 10 loops, best of 3: 1 sec per loop - """)) + self.assertIn(dedent("""\ + 1 loops -> 1 secs + raw times: 1 1 1 1 1 1 1 + 1 loops, average of 7: 1 +- 0 sec per loop (using standard deviation) + """), s) def test_main_very_verbose(self): s = self.run_main(seconds_per_increment=0.000050, switches=['-vv']) - self.assertEqual(s, dedent("""\ + self.assertIn(dedent("""\ + 1 loops -> 5e-05 secs 10 loops -> 0.0005 secs 100 loops -> 0.005 secs 1000 loops -> 0.05 secs 10000 loops -> 0.5 secs - raw times: 0.5 0.5 0.5 - 10000 loops, best of 3: 50 usec per loop - """)) + raw times: 0.5 0.5 0.5 0.5 0.5 0.5 0.5 + 10000 loops, average of 7: 50 +- 0 usec per loop (using standard deviation) + """), s) def test_main_exception(self): with captured_stderr() as error_stringio: @@ -304,6 +307,15 @@ s = self.run_main(switches=['-n1', '1.0/0.0']) self.assert_exc_string(error_stringio.getvalue(), 'ZeroDivisionError') + def test_main_recommends_perf(self): + s = self.run_main(seconds_per_increment=2.0, switches=['-n35', '-s', 'print("CustomSetup")']) + self.assertIn(dedent("""\ + WARNING: timeit is a very unreliable tool. use perf or something else for real measurements + pypy -m pip install perf + pypy -m perf timeit -n35 -s 'print("CustomSetup")' 'import timeit; timeit._fake_timer.inc()' + """), s) + + def test_main(): run_unittest(TestTimeit) diff --git a/lib-python/2.7/timeit.py b/lib-python/2.7/timeit.py --- a/lib-python/2.7/timeit.py +++ b/lib-python/2.7/timeit.py @@ -13,7 +13,7 @@ Options: -n/--number N: how many times to execute 'statement' (default: see below) - -r/--repeat N: how many times to repeat the timer (default 3) + -r/--repeat N: how many times to repeat the timer (default 7) -s/--setup S: statement to be executed once initially (default 'pass') -t/--time: use time.time() (default on Unix) -c/--clock: use time.clock() (default on Windows) @@ -53,6 +53,8 @@ """ import gc +import math +import os import sys import time @@ -60,7 +62,7 @@ dummy_src_name = "<timeit-src>" default_number = 1000000 -default_repeat = 3 +default_repeat = 7 if sys.platform == "win32": # On Windows, the best timer is time.clock() @@ -265,6 +267,7 @@ """ if args is None: args = sys.argv[1:] + origargs = args import getopt try: opts, args = getopt.getopt(args, "n:s:r:tcvh", @@ -281,6 +284,7 @@ repeat = default_repeat verbose = 0 precision = 3 + units = {"sec": 1, "msec": 1e3, "usec": 1e6, "ns": 1e9} for o, a in opts: if o in ("-n", "--number"): number = int(a) @@ -302,17 +306,25 @@ print __doc__, return 0 setup = "\n".join(setup) or "pass" + + print "WARNING: timeit is a very unreliable tool. use perf or something else for real measurements" + executable = os.path.basename(sys.executable) + print "%s -m pip install perf" % executable + print "%s -m perf timeit %s" % ( + executable, + " ".join([(arg if arg.startswith("-") else repr(arg)) + for arg in origargs]), ) + print "-" * 60 # Include the current directory, so that local imports work (sys.path # contains the directory of this script, rather than the current # directory) - import os sys.path.insert(0, os.curdir) if _wrap_timer is not None: timer = _wrap_timer(timer) t = Timer(stmt, setup, timer) if number == 0: # determine number so that 0.2 <= total time < 2.0 - for i in range(1, 10): + for i in range(0, 10): number = 10**i try: x = t.timeit(number) @@ -324,24 +336,34 @@ if x >= 0.2: break try: - r = t.repeat(repeat, number) + timings = t.repeat(repeat, number) except: t.print_exc() return 1 - best = min(r) if verbose: - print "raw times:", " ".join(["%.*g" % (precision, x) for x in r]) - print "%d loops," % number, - usec = best * 1e6 / number - if usec < 1000: - print "best of %d: %.*g usec per loop" % (repeat, precision, usec) - else: - msec = usec / 1000 - if msec < 1000: - print "best of %d: %.*g msec per loop" % (repeat, precision, msec) - else: - sec = msec / 1000 - print "best of %d: %.*g sec per loop" % (repeat, precision, sec) + print "raw times:", " ".join(["%.*g" % (precision, x) for x in timings]) + + timings = [dt / number for dt in timings] + + def _avg(l): + return math.fsum(l) / len(l) + def _stdev(l): + avg = _avg(l) + return (math.fsum([(x - avg) ** 2 for x in l]) / len(l)) ** 0.5 + + average = _avg(timings) + + scales = [(scale, unit) for unit, scale in units.items()] + scales.sort() + for scale, time_unit in scales: + if average * scale >= 1.0: + break + + stdev = _stdev(timings) + print("%s loops, average of %d: %.*g +- %.*g %s per loop (using standard deviation)" + % (number, repeat, + precision, average * scale, + precision, stdev * scale, time_unit)) return None if __name__ == "__main__": diff --git a/lib-python/3/imp.py b/lib-python/3/imp.py --- a/lib-python/3/imp.py +++ b/lib-python/3/imp.py @@ -125,7 +125,7 @@ elif os.path.isdir(path): raise ImportError('existing directory', path=path) - def find_module(self, fullname, path=None): + def find_module(self, fullname): """Always returns None.""" return None diff --git a/lib-python/3/test/test_peepholer.py b/lib-python/3/test/test_peepholer.py --- a/lib-python/3/test/test_peepholer.py +++ b/lib-python/3/test/test_peepholer.py @@ -4,6 +4,7 @@ from io import StringIO import unittest from math import copysign +from test.support import cpython_only from test.bytecode_helper import BytecodeTestCase @@ -184,6 +185,7 @@ code = compile('a="x"*1000', '', 'single') self.assertInBytecode(code, 'LOAD_CONST', 1000) + @cpython_only # we currently not bother to implement that def test_binary_subscr_on_unicode(self): # valid code get optimized code = compile('"foo"[0]', '', 'single') diff --git a/lib_pypy/_pypy_winbase_build.py b/lib_pypy/_pypy_winbase_build.py --- a/lib_pypy/_pypy_winbase_build.py +++ b/lib_pypy/_pypy_winbase_build.py @@ -76,9 +76,9 @@ HANDLE WINAPI GetCurrentProcess(void); BOOL WINAPI DuplicateHandle(HANDLE, HANDLE, HANDLE, LPHANDLE, DWORD, BOOL, DWORD); -BOOL WINAPI CreateProcessA(char *, char *, void *, - void *, BOOL, DWORD, char *, - char *, LPSTARTUPINFO, LPPROCESS_INFORMATION); +BOOL WINAPI CreateProcessW(wchar_t *, wchar_t *, void *, + void *, BOOL, DWORD, wchar_t *, + wchar_t *, LPSTARTUPINFO, LPPROCESS_INFORMATION); DWORD WINAPI WaitForSingleObject(HANDLE, DWORD); BOOL WINAPI GetExitCodeProcess(HANDLE, LPDWORD); BOOL WINAPI TerminateProcess(HANDLE, UINT); diff --git a/lib_pypy/_pypy_winbase_cffi.py b/lib_pypy/_pypy_winbase_cffi.py --- a/lib_pypy/_pypy_winbase_cffi.py +++ b/lib_pypy/_pypy_winbase_cffi.py @@ -3,8 +3,8 @@ ffi = _cffi_backend.FFI('_pypy_winbase_cffi', _version = 0x2601, - _types = b'\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x07\x01\x00\x00\x09\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x19\x01\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x50\x03\x00\x00\x13\x11\x00\x00\x53\x03\x00\x00\x15\x11\x00\x00\x07\x01\x00\x00\x0A\x01\x00\x00\x13\x11\x00\x00\x13\x11\x00\x00\x4F\x03\x00\x00\x4E\x03\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x03\x00\x00\x1F\x11\x00\x00\x15\x11\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x08\x01\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x18\x03\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x15\x11\x00\x00\x15\x11\x00\x00\x1F\x11\x00\x00\x0A\x01\x00\x00\x07\x01\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x0D\x0D\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x18\x0D\x00\x00\x15\x11\x00\x 00\x0A\x01\x00\x00\x02\x0F\x00\x00\x18\x0D\x00\x00\x02\x0F\x00\x00\x42\x0D\x00\x00\x06\x01\x00\x00\x00\x0F\x00\x00\x42\x0D\x00\x00\x00\x0F\x00\x00\x42\x0D\x00\x00\x10\x01\x00\x00\x00\x0F\x00\x00\x15\x0D\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x15\x0D\x00\x00\x02\x0F\x00\x00\x00\x09\x00\x00\x01\x09\x00\x00\x02\x01\x00\x00\x52\x03\x00\x00\x04\x01\x00\x00\x00\x01', - _globals = (b'\x00\x00\x24\x23CloseHandle',0,b'\x00\x00\x1E\x23CreatePipe',0,b'\x00\x00\x12\x23CreateProcessA',0,b'\x00\x00\x2F\x23DuplicateHandle',0,b'\x00\x00\x4C\x23GetCurrentProcess',0,b'\x00\x00\x2B\x23GetExitCodeProcess',0,b'\x00\x00\x49\x23GetStdHandle',0,b'\x00\x00\x3F\x23GetVersion',0,b'\x00\x00\x27\x23TerminateProcess',0,b'\x00\x00\x3B\x23WaitForSingleObject',0,b'\x00\x00\x38\x23_get_osfhandle',0,b'\x00\x00\x10\x23_getch',0,b'\x00\x00\x10\x23_getche',0,b'\x00\x00\x44\x23_getwch',0,b'\x00\x00\x44\x23_getwche',0,b'\x00\x00\x10\x23_kbhit',0,b'\x00\x00\x07\x23_locking',0,b'\x00\x00\x0C\x23_open_osfhandle',0,b'\x00\x00\x00\x23_putch',0,b'\x00\x00\x46\x23_putwch',0,b'\x00\x00\x03\x23_setmode',0,b'\x00\x00\x00\x23_ungetch',0,b'\x00\x00\x41\x23_ungetwch',0), - _struct_unions = ((b'\x00\x00\x00\x4E\x00\x00\x00\x02$PROCESS_INFORMATION',b'\x00\x00\x15\x11hProcess',b'\x00\x00\x15\x11hThread',b'\x00\x00\x18\x11dwProcessId',b'\x00\x00\x18\x11dwThreadId'),(b'\x00\x00\x00\x4F\x00\x00\x00\x02$STARTUPINFO',b'\x00\x00\x18\x11cb',b'\x00\x00\x13\x11lpReserved',b'\x00\x00\x13\x11lpDesktop',b'\x00\x00\x13\x11lpTitle',b'\x00\x00\x18\x11dwX',b'\x00\x00\x18\x11dwY',b'\x00\x00\x18\x11dwXSize',b'\x00\x00\x18\x11dwYSize',b'\x00\x00\x18\x11dwXCountChars',b'\x00\x00\x18\x11dwYCountChars',b'\x00\x00\x18\x11dwFillAttribute',b'\x00\x00\x18\x11dwFlags',b'\x00\x00\x42\x11wShowWindow',b'\x00\x00\x42\x11cbReserved2',b'\x00\x00\x51\x11lpReserved2',b'\x00\x00\x15\x11hStdInput',b'\x00\x00\x15\x11hStdOutput',b'\x00\x00\x15\x11hStdError')), - _typenames = (b'\x00\x00\x00\x1CLPPROCESS_INFORMATION',b'\x00\x00\x00\x1BLPSTARTUPINFO',b'\x00\x00\x00\x4EPROCESS_INFORMATION',b'\x00\x00\x00\x4FSTARTUPINFO',b'\x00\x00\x00\x42wint_t'), + _types = b'\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x07\x01\x00\x00\x09\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x19\x01\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x15\x03\x00\x00\x13\x11\x00\x00\x59\x03\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x08\x01\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x16\x03\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x15\x11\x00\x00\x15\x11\x00\x00\x13\x11\x00\x00\x0A\x01\x00\x00\x07\x01\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x4C\x03\x00\x00\x2D\x11\x00\x00\x15\x11\x00\x00\x15\x11\x00\x00\x07\x01\x00\x00\x0A\x01\x00\x00\x2D\x11\x00\x00\x2D\x11\x00\x00\x54\x03\x00\x00\x53\x03\x00\x00\x02\x0F\x00\x00\x0D\x0D\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x16\x0D\x00\x00\x15\x11\x00\x 00\x0A\x01\x00\x00\x02\x0F\x00\x00\x16\x0D\x00\x00\x15\x11\x00\x00\x2D\x11\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x16\x0D\x00\x00\x02\x0F\x00\x00\x47\x0D\x00\x00\x06\x01\x00\x00\x00\x0F\x00\x00\x47\x0D\x00\x00\x00\x0F\x00\x00\x47\x0D\x00\x00\x10\x01\x00\x00\x00\x0F\x00\x00\x15\x0D\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x15\x0D\x00\x00\x02\x0F\x00\x00\x00\x09\x00\x00\x01\x09\x00\x00\x56\x03\x00\x00\x02\x01\x00\x00\x58\x03\x00\x00\x04\x01\x00\x00\x00\x01', + _globals = (b'\x00\x00\x18\x23CloseHandle',0,b'\x00\x00\x12\x23CreatePipe',0,b'\x00\x00\x2C\x23CreateProcessW',0,b'\x00\x00\x23\x23DuplicateHandle',0,b'\x00\x00\x51\x23GetCurrentProcess',0,b'\x00\x00\x1F\x23GetExitCodeProcess',0,b'\x00\x00\x3F\x23GetModuleFileNameW',0,b'\x00\x00\x4E\x23GetStdHandle',0,b'\x00\x00\x44\x23GetVersion',0,b'\x00\x00\x1B\x23TerminateProcess',0,b'\x00\x00\x3B\x23WaitForSingleObject',0,b'\x00\x00\x38\x23_get_osfhandle',0,b'\x00\x00\x10\x23_getch',0,b'\x00\x00\x10\x23_getche',0,b'\x00\x00\x49\x23_getwch',0,b'\x00\x00\x49\x23_getwche',0,b'\x00\x00\x10\x23_kbhit',0,b'\x00\x00\x07\x23_locking',0,b'\x00\x00\x0C\x23_open_osfhandle',0,b'\x00\x00\x00\x23_putch',0,b'\x00\x00\x4B\x23_putwch',0,b'\x00\x00\x03\x23_setmode',0,b'\x00\x00\x00\x23_ungetch',0,b'\x00\x00\x46\x23_ungetwch',0), + _struct_unions = ((b'\x00\x00\x00\x53\x00\x00\x00\x02$PROCESS_INFORMATION',b'\x00\x00\x15\x11hProcess',b'\x00\x00\x15\x11hThread',b'\x00\x00\x16\x11dwProcessId',b'\x00\x00\x16\x11dwThreadId'),(b'\x00\x00\x00\x54\x00\x00\x00\x02$STARTUPINFO',b'\x00\x00\x16\x11cb',b'\x00\x00\x55\x11lpReserved',b'\x00\x00\x55\x11lpDesktop',b'\x00\x00\x55\x11lpTitle',b'\x00\x00\x16\x11dwX',b'\x00\x00\x16\x11dwY',b'\x00\x00\x16\x11dwXSize',b'\x00\x00\x16\x11dwYSize',b'\x00\x00\x16\x11dwXCountChars',b'\x00\x00\x16\x11dwYCountChars',b'\x00\x00\x16\x11dwFillAttribute',b'\x00\x00\x16\x11dwFlags',b'\x00\x00\x47\x11wShowWindow',b'\x00\x00\x47\x11cbReserved2',b'\x00\x00\x57\x11lpReserved2',b'\x00\x00\x15\x11hStdInput',b'\x00\x00\x15\x11hStdOutput',b'\x00\x00\x15\x11hStdError')), + _typenames = (b'\x00\x00\x00\x36LPPROCESS_INFORMATION',b'\x00\x00\x00\x35LPSTARTUPINFO',b'\x00\x00\x00\x53PROCESS_INFORMATION',b'\x00\x00\x00\x54STARTUPINFO',b'\x00\x00\x00\x47wint_t'), ) diff --git a/lib_pypy/_winapi.py b/lib_pypy/_winapi.py --- a/lib_pypy/_winapi.py +++ b/lib_pypy/_winapi.py @@ -58,12 +58,12 @@ return _handle2int(target[0]) -def _z(input): +def _Z(input): if input is None: return _ffi.NULL - if isinstance(input, basestring): - return str(input) - raise TypeError("string/unicode/None expected, got %r" % ( + if isinstance(input, str): + return input + raise TypeError("str or None expected, got %r" % ( type(input).__name__,)) def CreateProcess(name, command_line, process_attr, thread_attr, @@ -92,9 +92,9 @@ else: envbuf = _ffi.NULL - res = _kernel32.CreateProcessA(_z(name), _z(command_line), _ffi.NULL, + res = _kernel32.CreateProcessW(_Z(name), _Z(command_line), _ffi.NULL, _ffi.NULL, inherit, flags, envbuf, - _z(start_dir), si, pi) + _Z(start_dir), si, pi) if not res: raise _WinError() diff --git a/lib_pypy/stackless.py b/lib_pypy/stackless.py --- a/lib_pypy/stackless.py +++ b/lib_pypy/stackless.py @@ -535,7 +535,7 @@ _main_tasklet = coroutine.getcurrent() _main_tasklet.__class__ = tasklet # XXX HAAAAAAAAAAAAAAAAAAAAACK _last_task = _main_tasklet - tasklet._init.__func__(_main_tasklet, label='main') + tasklet._init(_main_tasklet, label='main') _squeue = deque() _scheduler_append(_main_tasklet) diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -40,13 +40,14 @@ "binascii", "_multiprocessing", '_warnings', "_collections", "_multibytecodec", "_continuation", "_cffi_backend", "_csv", "_pypyjson", "_posixsubprocess", # "cppyy", "micronumpy" - "faulthandler", "_jitlog", + "_jitlog", ]) from rpython.jit.backend import detect_cpu try: if detect_cpu.autodetect().startswith('x86'): working_modules.add('_vmprof') + working_modules.add('faulthandler') except detect_cpu.ProcessorAutodetectError: pass @@ -71,6 +72,8 @@ if "cppyy" in working_modules: working_modules.remove("cppyy") # not tested on win32 + if "faulthandler" in working_modules: + working_modules.remove("faulthandler") # missing details # The _locale module is needed by site.py on Windows default_modules.add("_locale") @@ -93,6 +96,7 @@ ('objspace.usemodules.thread', True)], 'cpyext': [('objspace.usemodules.array', True)], 'cppyy': [('objspace.usemodules.cpyext', True)], + 'faulthandler': [('objspace.usemodules._vmprof', True)], } module_suggests = { # the reason you want _rawffi is for ctypes, which @@ -118,7 +122,8 @@ "_hashlib" : ["pypy.module._ssl.interp_ssl"], "_minimal_curses": ["pypy.module._minimal_curses.fficurses"], "_continuation": ["rpython.rlib.rstacklet"], - "_vmprof" : ["pypy.module._vmprof.interp_vmprof"], + "_vmprof" : ["pypy.module._vmprof.interp_vmprof"], + "faulthandler" : ["pypy.module._vmprof.interp_vmprof"], "_lzma" : ["pypy.module._lzma.interp_lzma"], } 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 @@ -469,7 +469,12 @@ these concerns also exist on CPython, just less so. For this reason we explicitly don't implement ``sys.getsizeof()``. +* The ``timeit`` module behaves differently under PyPy: it prints the average + time and the standard deviation, instead of the minimum, since the minimum is + often misleading. + .. _`is ignored in PyPy`: http://bugs.python.org/issue14621 .. _`little point`: http://events.ccc.de/congress/2012/Fahrplan/events/5152.en.html .. _`#2072`: https://bitbucket.org/pypy/pypy/issue/2072/ + diff --git a/pypy/doc/embedding.rst b/pypy/doc/embedding.rst --- a/pypy/doc/embedding.rst +++ b/pypy/doc/embedding.rst @@ -34,9 +34,11 @@ This function searches the PyPy standard library starting from the given "PyPy home directory". The arguments are: - * ``home``: NULL terminated path to an executable inside the pypy directory + * ``home``: path to an executable inside the pypy directory (can be a .so name, can be made up). Used to look up the standard - library, and is also set as ``sys.executable``. + library, and is also set as ``sys.executable``. From PyPy 5.5, you can + just say NULL here, as long as the ``libpypy-c.so/dylib/dll`` is itself + inside this directory. * ``verbose``: if non-zero, it will print error messages to stderr @@ -82,18 +84,14 @@ Note that this API is a lot more minimal than say CPython C API, so at first it's obvious to think that you can't do much. However, the trick is to do -all the logic in Python and expose it via `cffi`_ callbacks. Let's assume -we're on linux and pypy is installed in ``/opt/pypy`` (with -subdirectories like ``lib-python`` and ``lib_pypy``), and with the -library in ``/opt/pypy/bin/libpypy-c.so``. (It doesn't need to be -installed; you can also replace these paths with a local extract of the -installation tarballs, or with your local checkout of pypy.) We write a -little C program: +all the logic in Python and expose it via `cffi`_ callbacks. +We write a little C program: .. code-block:: c #include "PyPy.h" #include <stdio.h> + #include <stdlib.h> static char source[] = "print 'hello from pypy'"; @@ -102,9 +100,9 @@ int res; rpython_startup_code(); - /* note: in the path /opt/pypy/x, the final x is ignored and - replaced with lib-python and lib_pypy. */ - res = pypy_setup_home("/opt/pypy/x", 1); + /* Before PyPy 5.5, you may need to say e.g. "/opt/pypy/bin" instead + * of NULL. */ + res = pypy_setup_home(NULL, 1); if (res) { printf("Error setting pypy home!\n"); return 1; @@ -123,11 +121,6 @@ $ LD_LIBRARY_PATH=/opt/pypy/bin ./x hello from pypy -.. note:: If the compilation fails because of missing PyPy.h header file, - you are running PyPy <= 2.2.1. Get it here__. - -.. __: https://bitbucket.org/pypy/pypy/raw/c4cd6eca9358066571500ac82aaacfdaa3889e8c/include/PyPy.h - On OSX it is necessary to set the rpath of the binary if one wants to link to it, with a command like:: @@ -181,6 +174,7 @@ /* C example */ #include "PyPy.h" #include <stdio.h> + #include <stdlib.h> struct API { double (*add_numbers)(double x, double y); @@ -196,7 +190,7 @@ int res; rpython_startup_code(); - res = pypy_setup_home("/opt/pypy/x", 1); + res = pypy_setup_home(NULL, 1); if (res) { fprintf(stderr, "Error setting pypy home!\n"); return -1; @@ -237,6 +231,8 @@ Finding pypy_home ----------------- +**You can usually skip this section if you are running PyPy >= 5.5.** + The function pypy_setup_home() takes as first parameter the path to a file from which it can deduce the location of the standard library. More precisely, it tries to remove final components until it finds 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 @@ -27,3 +27,43 @@ JIT residual calls: if the called function starts with a fast-path like "if x.foo != 0: return x.foo", then inline the check before doing the CALL. For now, string hashing is about the only case. + +.. branch: search-path-from-libpypy + +The compiled pypy now looks for its lib-python/lib_pypy path starting +from the location of the *libpypy-c* instead of the executable. This is +arguably more consistent, and also it is what occurs anyway if you're +embedding pypy. Linux distribution packagers, take note! At a minimum, +the ``libpypy-c.so`` must really be inside the path containing +``lib-python`` and ``lib_pypy``. Of course, you can put a symlink to it +from somewhere else. You no longer have to do the same with the +``pypy`` executable, as long as it finds its ``libpypy-c.so`` library. + +.. branch: _warnings + +CPython allows warning.warn(('something', 1), Warning), on PyPy this +produced a "expected a readable buffer object" error. Test and fix. + +.. branch: stricter-strip + +CPython rejects 'a'.strip(buffer(' ')); only None, str or unicode are +allowed as arguments. Test and fix for str and unicode + +.. branch: faulthandler + +Port the 'faulthandler' module to PyPy default. This module is standard +in Python 3.3 but can also be installed from CPython >= 2.6 from PyPI. + +.. branch: test-cpyext + +Refactor cpyext testing to be more pypy3-friendly. + +.. branch: better-error-missing-self + +Improve the error message when the user forgot the "self" argument of a method. + + +.. fb6bb835369e +Change the ``timeit`` module: it now prints the average time and the standard +deviation over 7 runs by default, instead of the minimum. The minimum is often +misleading. diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py --- a/pypy/goal/targetpypystandalone.py +++ b/pypy/goal/targetpypystandalone.py @@ -96,17 +96,18 @@ def pypy_setup_home(ll_home, verbose): from pypy.module.sys.initpath import pypy_find_stdlib verbose = rffi.cast(lltype.Signed, verbose) - if ll_home: + if ll_home and ord(ll_home[0]): home1 = rffi.charp2str(ll_home) home = os.path.join(home1, 'x') # <- so that 'll_home' can be # directly the root directory else: - home = home1 = pypydir + home1 = "pypy's shared library location" + home = '*' w_path = pypy_find_stdlib(space, home) if space.is_none(w_path): if verbose: debug("pypy_setup_home: directories 'lib-python' and 'lib_pypy'" - " not found in '%s' or in any parent directory" % home1) + " not found in %s or in any parent directory" % home1) return rffi.cast(rffi.INT, 1) space.startup() space.appexec([w_path], """(path): @@ -306,37 +307,20 @@ # HACKHACKHACK # ugly hack to modify target goal from compile_* to build_cffi_imports # this should probably get cleaned up and merged with driver.create_exe + from rpython.tool.runsubprocess import run_subprocess from rpython.translator.driver import taskdef import types - class Options(object): - pass - - - def mkexename(name): - if sys.platform == 'win32': - name = name.new(ext='exe') - return name - compile_goal, = driver.backend_select_goals(['compile']) @taskdef([compile_goal], "Create cffi bindings for modules") def task_build_cffi_imports(self): - from pypy.tool.build_cffi_imports import create_cffi_import_libraries ''' Use cffi to compile cffi interfaces to modules''' - exename = mkexename(driver.compute_exe_name()) - basedir = exename - while not basedir.join('include').exists(): - _basedir = basedir.dirpath() - if _basedir == basedir: - raise ValueError('interpreter %s not inside pypy repo', - str(exename)) - basedir = _basedir - modules = self.config.objspace.usemodules.getpaths() - options = Options() - # XXX possibly adapt options using modules - failures = create_cffi_import_libraries(exename, options, basedir) - # if failures, they were already printed - print >> sys.stderr, str(exename),'successfully built (errors, if any, while building the above modules are ignored)' + filename = os.path.join(pypydir, 'tool', 'build_cffi_imports.py') + status, out, err = run_subprocess(str(driver.compute_exe_name()), + [filename]) + sys.stdout.write(out) + sys.stderr.write(err) + # otherwise, ignore errors driver.task_build_cffi_imports = types.MethodType(task_build_cffi_imports, driver) driver.tasks['build_cffi_imports'] = driver.task_build_cffi_imports, [compile_goal] driver.default_goal = 'build_cffi_imports' diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py --- a/pypy/interpreter/app_main.py +++ b/pypy/interpreter/app_main.py @@ -32,6 +32,7 @@ arg ...: arguments passed to program in sys.argv[1:] PyPy options and arguments: --info : print translation information about this PyPy executable +-X faulthandler: attempt to display tracebacks when PyPy crashes """ # Missing vs CPython: PYTHONHOME USAGE2 = """ @@ -526,6 +527,14 @@ sys._xoptions = dict(x.split('=', 1) if '=' in x else (x, True) for x in options['_xoptions']) + if 'faulthandler' in sys.builtin_module_names: + if 'faulthandler' in sys._xoptions or os.getenv('PYTHONFAULTHANDLER'): + import faulthandler + try: + faulthandler.enable(2) # manually set to stderr + except ValueError: + pass # ignore "2 is not a valid file descriptor" + ## if not we_are_translated(): ## for key in sorted(options): ## print '%40s: %s' % (key, options[key]) diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py --- a/pypy/interpreter/argument.py +++ b/pypy/interpreter/argument.py @@ -23,7 +23,8 @@ ### Construction ### #@enforceargs(keywords=[unicode]) def __init__(self, space, args_w, keywords=None, keywords_w=None, - w_stararg=None, w_starstararg=None, keyword_names_w=None): + w_stararg=None, w_starstararg=None, keyword_names_w=None, + methodcall=False): self.space = space assert isinstance(args_w, list) self.arguments_w = args_w @@ -43,6 +44,9 @@ # a flag that specifies whether the JIT can unroll loops that operate # on the keywords self._jit_few_keywords = self.keywords is None or jit.isconstant(len(self.keywords)) + # a flag whether this is likely a method call, which doesn't change the + # behaviour but produces better error messages + self.methodcall = methodcall def __repr__(self): """ NOT_RPYTHON """ @@ -270,7 +274,11 @@ for i in range(co_argcount, co_argcount + co_kwonlyargcount): if scope_w[i] is not None: kwonly_given += 1 - raise ArgErrTooMany(signature.num_argnames(), + if self.methodcall: + cls = ArgErrTooManyMethod + else: + cls = ArgErrTooMany + raise cls(signature, 0 if defaults_w is None else len(defaults_w), avail, kwonly_given) @@ -498,14 +506,14 @@ class ArgErrTooMany(ArgErr): - def __init__(self, num_args, num_defaults, given, kwonly_given): - self.num_args = num_args + def __init__(self, signature, num_defaults, given, kwonly_given): + self.signature = signature self.num_defaults = num_defaults self.given = given self.kwonly_given = kwonly_given def getmsg(self): - num_args = self.num_args + num_args = self.signature.num_argnames() num_defaults = self.num_defaults if num_defaults: takes_str = "from %d to %d positional arguments" % ( @@ -524,6 +532,22 @@ msg = "takes %s but %s given" % (takes_str, given_str) return msg +class ArgErrTooManyMethod(ArgErrTooMany): + """ A subclass of ArgErrCount that is used if the argument matching is done + as part of a method call, in which case more information is added to the + error message, if the cause of the error is likely a forgotten `self` + argument. + """ + + def getmsg(self): + msg = ArgErrTooMany.getmsg(self) + n = self.signature.num_argnames() + if (self.given == n + 1 and + (n == 0 or self.signature.argnames[0] != "self")): + msg += ". Did you forget 'self' in the function definition?" + return msg + + class ArgErrMultipleValues(ArgErr): def __init__(self, argname): diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -379,12 +379,12 @@ class BufferInterfaceNotFound(Exception): pass +@specialize.memo() def wrappable_class_name(Class): try: return Class.typedef.name except AttributeError: return 'internal subclass of %s' % (Class.__name__,) -wrappable_class_name._annspecialcase_ = 'specialize:memo' class CannotHaveLock(Exception): """Raised by space.allocate_lock() if we're translating.""" @@ -841,12 +841,13 @@ return None return self.interned_strings.get(u) # may be None + @specialize.arg(1) def descr_self_interp_w(self, RequiredClass, w_obj): if not isinstance(w_obj, RequiredClass): raise DescrMismatch() return w_obj - descr_self_interp_w._annspecialcase_ = 'specialize:arg(1)' + @specialize.arg(1) def interp_w(self, RequiredClass, w_obj, can_be_None=False): """ Unwrap w_obj, checking that it is an instance of the required internal @@ -861,7 +862,6 @@ wrappable_class_name(RequiredClass), w_obj.getclass(self)) return w_obj - interp_w._annspecialcase_ = 'specialize:arg(1)' def unpackiterable(self, w_iterable, expected_length=-1): """Unpack an iterable into a real (interpreter-level) list. @@ -1122,7 +1122,8 @@ args = Arguments(self, list(args_w)) return self.call_args(w_func, args) - def call_valuestack(self, w_func, nargs, frame): + def call_valuestack(self, w_func, nargs, frame, methodcall=False): + # methodcall is only used for better error messages in argument.py from pypy.interpreter.function import Function, Method, is_builtin_code if frame.get_is_being_profiled() and is_builtin_code(w_func): # XXX: this code is copied&pasted :-( from the slow path below @@ -1136,10 +1137,12 @@ # reuse callable stack place for w_inst frame.settopvalue(w_func.w_instance, nargs) nargs += 1 + methodcall = True w_func = w_func.w_function if isinstance(w_func, Function): - return w_func.funccall_valuestack(nargs, frame) + return w_func.funccall_valuestack( + nargs, frame, methodcall=methodcall) # end of hack for performance args = frame.make_arguments(nargs) @@ -1275,6 +1278,7 @@ self.setitem(w_globals, w_key, self.wrap(self.builtin)) return statement.exec_code(self, w_globals, w_locals) + @specialize.arg(2) def appexec(self, posargs_w, source): """ return value from executing given source at applevel. EXPERIMENTAL. The source must look like @@ -1286,7 +1290,6 @@ w_func = self.fromcache(AppExecCache).getorbuild(source) args = Arguments(self, list(posargs_w)) return self.call_args(w_func, args) - appexec._annspecialcase_ = 'specialize:arg(2)' def _next_or_none(self, w_it): try: @@ -1296,6 +1299,7 @@ raise return None + @specialize.arg(3) def compare_by_iteration(self, w_iterable1, w_iterable2, op): w_it1 = self.iter(w_iterable1) w_it2 = self.iter(w_iterable2) @@ -1318,7 +1322,6 @@ if op == 'gt': return self.gt(w_x1, w_x2) if op == 'ge': return self.ge(w_x1, w_x2) assert False, "bad value for op" - compare_by_iteration._annspecialcase_ = 'specialize:arg(3)' def decode_index(self, w_index_or_slice, seqlength): """Helper for custom sequence implementations diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py --- a/pypy/interpreter/executioncontext.py +++ b/pypy/interpreter/executioncontext.py @@ -1,7 +1,7 @@ import sys from pypy.interpreter.error import OperationError, get_cleared_operation_error from rpython.rlib.unroll import unrolling_iterable -from rpython.rlib import jit, rgc +from rpython.rlib import jit, rgc, objectmodel TICK_COUNTER_STEP = 100 @@ -133,6 +133,7 @@ if self.gettrace() is not None: self._trace(frame, 'return', w_retval) + @objectmodel.always_inline def bytecode_trace(self, frame, decr_by=TICK_COUNTER_STEP): "Trace function called before each bytecode." # this is split into a fast path and a slower path that is @@ -141,7 +142,6 @@ actionflag = self.space.actionflag if actionflag.decrement_ticker(decr_by) < 0: actionflag.action_dispatcher(self, frame) # slow path - bytecode_trace._always_inline_ = True def _run_finalizers_now(self): # Tests only: run the actions now, to ensure that the @@ -149,6 +149,7 @@ # pypy.tool.pytest.apptest. self.space.actionflag.action_dispatcher(self, None) + @objectmodel.always_inline def bytecode_only_trace(self, frame): """ Like bytecode_trace() but doesn't invoke any other events besides the @@ -158,7 +159,6 @@ self.gettrace() is None): return self.run_trace_func(frame) - bytecode_only_trace._always_inline_ = True @jit.unroll_safe def run_trace_func(self, frame): @@ -205,13 +205,13 @@ d.instr_prev_plus_one = frame.last_instr + 1 + @objectmodel.try_inline def bytecode_trace_after_exception(self, frame): "Like bytecode_trace(), but without increasing the ticker." actionflag = self.space.actionflag self.bytecode_only_trace(frame) if actionflag.get_ticker() < 0: actionflag.action_dispatcher(self, frame) # slow path - bytecode_trace_after_exception._always_inline_ = 'try' # NB. this function is not inlined right now. backendopt.inline would # need some improvements to handle this case, but it's not really an # issue @@ -455,6 +455,7 @@ periodic_actions = unrolling_iterable(self._periodic_actions) @jit.unroll_safe + @objectmodel.dont_inline def action_dispatcher(ec, frame): # periodic actions (first reset the bytecode counter) self.reset_ticker(self.checkinterval_scaled) @@ -476,7 +477,6 @@ action._fired = False action.perform(ec, frame) - action_dispatcher._dont_inline_ = True self.action_dispatcher = action_dispatcher diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py --- a/pypy/interpreter/function.py +++ b/pypy/interpreter/function.py @@ -126,7 +126,8 @@ list(args_w[1:]))) return self.call_args(Arguments(self.space, list(args_w))) - def funccall_valuestack(self, nargs, frame): # speed hack + def funccall_valuestack(self, nargs, frame, methodcall=False): # speed hack + # methodcall is only for better error messages from pypy.interpreter import gateway from pypy.interpreter.pycode import PyCode @@ -173,7 +174,7 @@ args = frame.make_arguments(nargs-1) return code.funcrun_obj(self, w_obj, args) - args = frame.make_arguments(nargs) + args = frame.make_arguments(nargs, methodcall=methodcall) return self.call_args(args) @jit.unroll_safe diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py --- a/pypy/interpreter/pyframe.py +++ b/pypy/interpreter/pyframe.py @@ -445,11 +445,14 @@ depth -= 1 self.valuestackdepth = finaldepth - def make_arguments(self, nargs): - return Arguments(self.space, self.peekvalues(nargs)) + def make_arguments(self, nargs, methodcall=False): + return Arguments( + self.space, self.peekvalues(nargs), methodcall=methodcall) - def argument_factory(self, arguments, keywords, keywords_w, w_star, w_starstar): - return Arguments(self.space, arguments, keywords, keywords_w, w_star, w_starstar) + def argument_factory(self, arguments, keywords, keywords_w, w_star, w_starstar, methodcall=False): + return Arguments( + self.space, arguments, keywords, keywords_w, w_star, + w_starstar, methodcall=methodcall) @jit.dont_look_inside def descr__reduce__(self, space): diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -6,7 +6,7 @@ from rpython.rlib import jit, rstackovf, rstring from rpython.rlib.debug import check_nonneg -from rpython.rlib.objectmodel import we_are_translated, always_inline +(??)from rpython.rlib.objectmodel import we_are_translated from rpython.rlib.rarithmetic import r_uint, intmask from rpython.tool.sourcetools import func_with_new_name @@ -484,20 +484,20 @@ # of oparg failed to produce an integer which is annotated as non-neg check_nonneg(oparg) + @always_inline def LOAD_FAST(self, varindex, next_instr): # access a local variable directly w_value = self.locals_cells_stack_w[varindex] if w_value is None: self._load_fast_failed(varindex) self.pushvalue(w_value) - LOAD_FAST._always_inline_ = True + @dont_inline def _load_fast_failed(self, varindex): varname = self.getlocalvarname(varindex) raise oefmt(self.space.w_UnboundLocalError, "local variable '%s' referenced before assignment", varname) - _load_fast_failed._dont_inline_ = True def LOAD_CONST(self, constindex, next_instr): w_const = self.getconstant_w(constindex) @@ -873,26 +873,26 @@ "name %R is not defined", w_varname) self.pushvalue(w_value) + @always_inline def _load_global(self, varname): w_value = self.space.finditem_str(self.get_w_globals(), varname) if w_value is None: # not in the globals, now look in the built-ins w_value = self.get_builtin().getdictvalue(self.space, varname) return w_value - _load_global._always_inline_ = True + @dont_inline def _load_global_failed(self, w_varname): raise oefmt(self.space.w_NameError, "global name %R is not defined", w_varname) - _load_global_failed._dont_inline_ = True + @always_inline def LOAD_GLOBAL(self, nameindex, next_instr): w_varname = self.getname_w(nameindex) w_value = self._load_global(self.space.identifier_w(w_varname)) if w_value is None: self._load_global_failed(w_varname) self.pushvalue(w_value) - LOAD_GLOBAL._always_inline_ = True def DELETE_FAST(self, varindex, next_instr): if self.locals_cells_stack_w[varindex] is None: @@ -926,6 +926,7 @@ self.pushvalue(space.newlist([], sizehint=length_hint)) self.pushvalue(last_val) + @always_inline def LOAD_ATTR(self, nameindex, next_instr): "obj.attributename" w_obj = self.popvalue() @@ -936,7 +937,6 @@ w_attributename = self.getname_w(nameindex) w_value = self.space.getattr(w_obj, w_attributename) self.pushvalue(w_value) - LOAD_ATTR._always_inline_ = True @jit.unroll_safe def cmp_exc_match(self, w_1, w_2): diff --git a/pypy/interpreter/pyparser/error.py b/pypy/interpreter/pyparser/error.py --- a/pypy/interpreter/pyparser/error.py +++ b/pypy/interpreter/pyparser/error.py @@ -18,6 +18,11 @@ from rpython.rlib.runicode import str_decode_utf_8 # self.text may not be UTF-8 in case of decoding errors. # adjust the encoded text offset to a decoded offset + # XXX do the right thing about continuation lines, which + # XXX are their own fun, sometimes giving offset > + # XXX len(self.text) for example (right now, avoid crashing) + if offset > len(self.text): + offset = len(self.text) text, _ = str_decode_utf_8(self.text, offset, 'replace') offset = len(text) if len(self.text) != offset: diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py --- a/pypy/interpreter/test/test_app_main.py +++ b/pypy/interpreter/test/test_app_main.py @@ -17,8 +17,7 @@ def get_python3(): if PYTHON3: return PYTHON3 - import py.test - py.test.fail("Test requires %r (not found in PATH) or a PYTHON3 " + py.test.skip("Test requires %r (not found in PATH) or a PYTHON3 " "environment variable set" % (LOOK_FOR_PYTHON3,)) _counter = 0 @@ -51,7 +50,8 @@ # return relative path for testing purposes return py.path.local().bestrelpath(pdir) -def pytest_funcarg__demo_script(request): +@py.test.fixture +def demo_script(): return getscript(""" print('hello') print('Name:', __name__) @@ -64,7 +64,8 @@ myvalue = 6*7 """) -def pytest_funcarg__crashing_demo_script(request): +@py.test.fixture +def crashing_demo_script(): return getscript(""" print('Hello2') myvalue2 = 11 @@ -1090,23 +1091,32 @@ old_sys_path = sys.path[:] old_cwd = os.getcwd() - sys.path.append(self.goal_dir) # make sure cwd does not contain a stdlib if self.tmp_dir.startswith(self.trunkdir): skip('TMPDIR is inside the PyPy source') - os.chdir(self.tmp_dir) + sys.path.append(self.goal_dir) tmp_pypy_c = os.path.join(self.tmp_dir, 'pypy-c') try: + os.chdir(self.tmp_dir) + + # If we are running PyPy with a libpypy-c, the following + # lines find the stdlib anyway. Otherwise, it is not found. + expected_found = ( + getattr(sys, 'pypy_translation_info', {}) + .get('translation.shared')) + import app_main - app_main.setup_bootstrap_path(tmp_pypy_c) # stdlib not found + app_main.setup_bootstrap_path(tmp_pypy_c) assert sys.executable == '' - assert sys.path == old_sys_path + [self.goal_dir] + if not expected_found: + assert sys.path == old_sys_path + [self.goal_dir] app_main.setup_bootstrap_path(self.fake_exe) if not sys.platform == 'win32': # an existing file is always 'executable' on windows assert sys.executable == '' # not executable! - assert sys.path == old_sys_path + [self.goal_dir] + if not expected_found: + assert sys.path == old_sys_path + [self.goal_dir] os.chmod(self.fake_exe, 0o755) app_main.setup_bootstrap_path(self.fake_exe) @@ -1117,7 +1127,8 @@ if newpath[0].endswith('__extensions__'): newpath = newpath[1:] # we get at least 'expected_path', and maybe more (e.g.plat-linux2) - assert newpath[:len(self.expected_path)] == self.expected_path + if not expected_found: + assert newpath[:len(self.expected_path)] == self.expected_path finally: sys.path[:] = old_sys_path os.chdir(old_cwd) diff --git a/pypy/interpreter/test/test_argument.py b/pypy/interpreter/test/test_argument.py --- a/pypy/interpreter/test/test_argument.py +++ b/pypy/interpreter/test/test_argument.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- import py from pypy.interpreter.argument import (Arguments, ArgErr, ArgErrUnknownKwds, - ArgErrMultipleValues, ArgErrMissing, ArgErrTooMany) + ArgErrMultipleValues, ArgErrMissing, ArgErrTooMany, ArgErrTooManyMethod) from pypy.interpreter.signature import Signature from pypy.interpreter.error import OperationError @@ -585,38 +585,82 @@ assert s == "missing 1 required keyword-only argument: 'a'" def test_too_many(self): - err = ArgErrTooMany(0, 0, 1, 0) + sig0 = Signature([], None, None) + err = ArgErrTooMany(sig0, 0, 1, 0) s = err.getmsg() assert s == "takes 0 positional arguments but 1 was given" - err = ArgErrTooMany(0, 0, 2, 0) + err = ArgErrTooMany(sig0, 0, 2, 0) s = err.getmsg() assert s == "takes 0 positional arguments but 2 were given" - err = ArgErrTooMany(1, 0, 2, 0) + sig1 = Signature(['a'], None, None) + err = ArgErrTooMany(sig1, 0, 2, 0) s = err.getmsg() assert s == "takes 1 positional argument but 2 were given" - err = ArgErrTooMany(2, 0, 3, 0) + sig2 = Signature(['a', 'b'], None, None) + err = ArgErrTooMany(sig2, 0, 3, 0) s = err.getmsg() assert s == "takes 2 positional arguments but 3 were given" - err = ArgErrTooMany(2, 1, 3, 0) + err = ArgErrTooMany(sig2, 1, 3, 0) s = err.getmsg() assert s == "takes from 1 to 2 positional arguments but 3 were given" - err = ArgErrTooMany(0, 0, 1, 1) + err = ArgErrTooMany(sig0, 0, 1, 1) s = err.getmsg() assert s == "takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given" - err = ArgErrTooMany(0, 0, 2, 1) + err = ArgErrTooMany(sig0, 0, 2, 1) s = err.getmsg() assert s == "takes 0 positional arguments but 2 positional arguments (and 1 keyword-only argument) were given" - err = ArgErrTooMany(0, 0, 1, 2) + err = ArgErrTooMany(sig0, 0, 1, 2) s = err.getmsg() assert s == "takes 0 positional arguments but 1 positional argument (and 2 keyword-only arguments) were given" + def test_too_many_method(self): + sig0 = Signature([], None, None) + err = ArgErrTooManyMethod(sig0, 0, 1, 0) + s = err.getmsg() + assert s == "takes 0 positional arguments but 1 was given. Did you forget 'self' in the function definition?" + + err = ArgErrTooManyMethod(sig0, 0, 2, 0) + s = err.getmsg() + assert s == "takes 0 positional arguments but 2 were given" + + sig1 = Signature(['self'], None, None) + err = ArgErrTooManyMethod(sig1, 0, 2, 0) + s = err.getmsg() + assert s == "takes 1 positional argument but 2 were given" + + sig1 = Signature(['a'], None, None) + err = ArgErrTooManyMethod(sig1, 0, 2, 0) + s = err.getmsg() + assert s == "takes 1 positional argument but 2 were given. Did you forget 'self' in the function definition?" + + sig2 = Signature(['a', 'b'], None, None) + err = ArgErrTooManyMethod(sig2, 0, 3, 0) + s = err.getmsg() + assert s == "takes 2 positional arguments but 3 were given. Did you forget 'self' in the function definition?" + + err = ArgErrTooManyMethod(sig2, 1, 3, 0) + s = err.getmsg() + assert s == "takes from 1 to 2 positional arguments but 3 were given. Did you forget 'self' in the function definition?" + + err = ArgErrTooManyMethod(sig0, 0, 1, 1) + s = err.getmsg() + assert s == "takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given. Did you forget 'self' in the function definition?" + + err = ArgErrTooManyMethod(sig0, 0, 2, 1) + s = err.getmsg() + assert s == "takes 0 positional arguments but 2 positional arguments (and 1 keyword-only argument) were given" + + err = ArgErrTooManyMethod(sig0, 0, 1, 2) + s = err.getmsg() + assert s == "takes 0 positional arguments but 1 positional argument (and 2 keyword-only arguments) were given. Did you forget 'self' in the function definition?" + def test_bad_type_for_star(self): space = self.space try: @@ -748,6 +792,45 @@ exc = raises(TypeError, '(lambda *, kw: 0)(1, kw=3)') assert str(exc.value) == "<lambda>() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given" + @py.test.mark.skipif("config.option.runappdirect") + def test_error_message_method(self): + class A(object): + def f0(): + pass + def f1(a): + pass + exc = raises(TypeError, lambda : A().f0()) + assert exc.value.args[0] == "f0() takes 0 positional arguments but 1 was given. Did you forget 'self' in the function definition?" + exc = raises(TypeError, lambda : A().f1(1)) + assert exc.value.args[0] == "f1() takes 1 positional argument but 2 were given. Did you forget 'self' in the function definition?" + def f0(): + pass + exc = raises(TypeError, f0, 1) + # does not contain the warning about missing self + assert exc.value.args[0] == "f0() takes 0 positional arguments but 1 was given" + + @py.test.mark.skipif("config.option.runappdirect") + def test_error_message_module_function(self): + import operator # use countOf because it's defined at applevel + exc = raises(TypeError, lambda : operator.countOf(1, 2, 3)) + # does not contain the warning about missing self + assert exc.value.args[0] == "countOf() takes 2 positional arguments but 3 were given" + + @py.test.mark.skipif("config.option.runappdirect") + def test_error_message_bound_method(self): + class A(object): + def f0(): + pass + def f1(a): + pass + m0 = A().f0 + exc = raises(TypeError, lambda : m0()) + assert exc.value.args[0] == "f0() takes 0 positional arguments but 1 was given. Did you forget 'self' in the function definition?" + m1 = A().f1 + exc = raises(TypeError, lambda : m1(1)) + assert exc.value.args[0] == "f1() takes 1 positional argument but 2 were given. Did you forget 'self' in the function definition?" + + def test_unicode_keywords(self): """ def f(**kwargs): diff --git a/pypy/interpreter/test/test_compiler.py b/pypy/interpreter/test/test_compiler.py --- a/pypy/interpreter/test/test_compiler.py +++ b/pypy/interpreter/test/test_compiler.py @@ -83,7 +83,7 @@ code = self.compiler.compile('from __future__ import division\n', '<hello>', 'exec', 0) flags = self.compiler.getcodeflags(code) - assert flags & __future__.division.compiler_flag + assert flags & __future__.division.compiler_flag == 0 # check that we don't get more flags than the compiler can accept back code2 = self.compiler.compile('print(6*7)', '<hello>', 'exec', flags) # check that the flag remains in force @@ -767,17 +767,26 @@ assert sig == Signature(['a', 'b'], None, 'kwargs', ['m', 'n']) -class AppTestCompiler: +class AppTestCompiler(object): def setup_class(cls): cls.w_runappdirect = cls.space.wrap(cls.runappdirect) + def w_is_pypy(self): + import sys + return (not self.runappdirect) or '__pypy__' in sys.modules + def test_bom_with_future(self): s = b'\xef\xbb\xbffrom __future__ import division\nx = 1/2' ns = {} exec(s, ns) assert ns["x"] == .5 + def test_noop_future_import(self): + code1 = compile("from __future__ import division", "<test>", "exec") + code2 = compile("", "<test>", "exec") + assert code1.co_flags == code2.co_flags + def test_values_of_different_types(self): ns = {} exec("a = 0; c = 0.0; d = 0j", ns) @@ -796,9 +805,8 @@ import math, sys code = compile("x = -0.0; y = 0.0", "<test>", "exec") consts = code.co_consts - if not self.runappdirect or sys.version_info[:2] != (3, 2): - # Only CPython 3.2 does not store -0.0. - # PyPy implements 3.3 here. + if self.is_pypy(): + # Hard to test on CPython, since co_consts is randomly ordered x, y, z = consts assert isinstance(x, float) and isinstance(y, float) assert math.copysign(1, x) != math.copysign(1, y) @@ -938,10 +946,15 @@ -class AppTestOptimizer: +class AppTestOptimizer(object): def setup_class(cls): cls.w_runappdirect = cls.space.wrap(cls.runappdirect) + def w_is_pypy(self): + import sys + return not self.runappdirect or '__pypy__' in sys.modules + + def test_remove_ending(self): source = """def f(): return 3 @@ -966,7 +979,7 @@ for name in "None", "True", "False": snip = "def f(): return " + name co = compile(snip, "<test>", "exec").co_consts[0] - if not self.runappdirect: # This is a pypy optimization + if self.is_pypy(): # This is a pypy optimization assert name not in co.co_names co = co.co_code op = co[0] @@ -986,14 +999,14 @@ def code(source): return compile(source, "<test>", "exec") co = code("x = 10//4") - if self.runappdirect: + if not self.is_pypy(): assert 2 in co.co_consts else: # PyPy is more precise assert len(co.co_consts) == 2 assert co.co_consts[0] == 2 co = code("x = 10/4") - if self.runappdirect: + if not self.is_pypy(): assert 2.5 in co.co_consts else: assert len(co.co_consts) == 2 @@ -1001,19 +1014,21 @@ def test_tuple_folding(self): co = compile("x = (1, 2, 3)", "<test>", "exec") - if not self.runappdirect: + if self.is_pypy(): # PyPy is more precise assert co.co_consts == ((1, 2, 3), None) else: assert (1, 2, 3) in co.co_consts assert None in co.co_consts co = compile("x = ()", "<test>", "exec") - assert set(co.co_consts) == set(((), None)) + if self.is_pypy(): + # CPython does not constant-fold the empty tuple + assert set(co.co_consts) == set(((), None)) def test_unary_folding(self): def check_const(co, value): assert value in co.co_consts - if not self.runappdirect: + if self.is_pypy(): # This is a pypy optimization assert co.co_consts[0] == value co = compile("x = -(3)", "<test>", "exec") @@ -1023,7 +1038,7 @@ co = compile("x = +(-3)", "<test>", "exec") check_const(co, -3) co = compile("x = not None", "<test>", "exec") - if not self.runappdirect: + if self.is_pypy(): # CPython does not have this optimization assert co.co_consts == (True, None) @@ -1134,6 +1149,8 @@ assert isinstance(co.co_consts[i], frozenset) def test_call_method_kwargs(self): + if not self.is_pypy(): + skip("CALL_METHOD exists only on pypy") source = """def _f(a): return a.f(a=a) """ diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py --- a/pypy/interpreter/typedef.py +++ b/pypy/interpreter/typedef.py @@ -109,6 +109,7 @@ # we need two subclasses of the app-level type, one to add mapdict, and then one # to add del to not slow down the GC. +@specialize.memo() def get_unique_interplevel_subclass(space, cls): "NOT_RPYTHON: initialization-time only" assert cls.typedef.acceptable_as_base_class @@ -119,7 +120,6 @@ assert cls not in _unique_subclass_cache _unique_subclass_cache[cls] = subcls return subcls -get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo" _unique_subclass_cache = {} def _getusercls(cls, reallywantdict=False): 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 @@ -2,6 +2,8 @@ from pypy.interpreter.mixedmodule import MixedModule from pypy.module.imp.importing import get_pyc_magic +from rpython.rlib import rtime + class BuildersModule(MixedModule): appleveldefs = {} @@ -14,16 +16,11 @@ class TimeModule(MixedModule): appleveldefs = {} interpleveldefs = {} - if sys.platform.startswith("linux") or 'bsd' in sys.platform: - from pypy.module.__pypy__ import interp_time + if rtime.HAS_CLOCK_GETTIME: interpleveldefs["clock_gettime"] = "interp_time.clock_gettime" interpleveldefs["clock_getres"] = "interp_time.clock_getres" - for name in [ - "CLOCK_REALTIME", "CLOCK_MONOTONIC", "CLOCK_MONOTONIC_RAW", - "CLOCK_PROCESS_CPUTIME_ID", "CLOCK_THREAD_CPUTIME_ID" - ]: - if getattr(interp_time, name) is not None: - interpleveldefs[name] = "space.wrap(interp_time.%s)" % name + for name in rtime.ALL_DEFINED_CLOCKS: + interpleveldefs[name] = "space.wrap(%d)" % getattr(rtime, name) class ThreadModule(MixedModule): diff --git a/pypy/module/__pypy__/interp_time.py b/pypy/module/__pypy__/interp_time.py --- a/pypy/module/__pypy__/interp_time.py +++ b/pypy/module/__pypy__/interp_time.py @@ -4,71 +4,28 @@ from pypy.interpreter.error import exception_from_saved_errno from pypy.interpreter.gateway import unwrap_spec from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rtyper.tool import rffi_platform -from rpython.translator.tool.cbuild import ExternalCompilationInfo +from rpython.rlib import rtime +from rpython.rlib.rtime import HAS_CLOCK_GETTIME -if sys.platform == 'linux2': - libraries = ["rt"] -else: - libraries = [] - - -class CConfig: - _compilation_info_ = ExternalCompilationInfo( - includes=["time.h"], - libraries=libraries, - ) - - HAS_CLOCK_GETTIME = rffi_platform.Has('clock_gettime') - - CLOCK_REALTIME = rffi_platform.DefinedConstantInteger("CLOCK_REALTIME") - CLOCK_MONOTONIC = rffi_platform.DefinedConstantInteger("CLOCK_MONOTONIC") - CLOCK_MONOTONIC_RAW = rffi_platform.DefinedConstantInteger("CLOCK_MONOTONIC_RAW") - CLOCK_PROCESS_CPUTIME_ID = rffi_platform.DefinedConstantInteger("CLOCK_PROCESS_CPUTIME_ID") - CLOCK_THREAD_CPUTIME_ID = rffi_platform.DefinedConstantInteger("CLOCK_THREAD_CPUTIME_ID") - -cconfig = rffi_platform.configure(CConfig) - -HAS_CLOCK_GETTIME = cconfig["HAS_CLOCK_GETTIME"] - -CLOCK_REALTIME = cconfig["CLOCK_REALTIME"] -CLOCK_MONOTONIC = cconfig["CLOCK_MONOTONIC"] -CLOCK_MONOTONIC_RAW = cconfig["CLOCK_MONOTONIC_RAW"] -CLOCK_PROCESS_CPUTIME_ID = cconfig["CLOCK_PROCESS_CPUTIME_ID"] -CLOCK_THREAD_CPUTIME_ID = cconfig["CLOCK_THREAD_CPUTIME_ID"] if HAS_CLOCK_GETTIME: - #redo it for timespec - CConfig.TIMESPEC = rffi_platform.Struct("struct timespec", [ - ("tv_sec", rffi.TIME_T), - ("tv_nsec", rffi.LONG), - ]) - cconfig = rffi_platform.configure(CConfig) - TIMESPEC = cconfig['TIMESPEC'] - - c_clock_gettime = rffi.llexternal("clock_gettime", - [lltype.Signed, lltype.Ptr(TIMESPEC)], rffi.INT, - compilation_info=CConfig._compilation_info_, releasegil=False, - save_err=rffi.RFFI_SAVE_ERRNO - ) - c_clock_getres = rffi.llexternal("clock_getres", - [lltype.Signed, lltype.Ptr(TIMESPEC)], rffi.INT, - compilation_info=CConfig._compilation_info_, releasegil=False, - save_err=rffi.RFFI_SAVE_ERRNO - ) @unwrap_spec(clk_id="c_int") def clock_gettime(space, clk_id): - with lltype.scoped_alloc(TIMESPEC) as tp: - ret = c_clock_gettime(clk_id, tp) + with lltype.scoped_alloc(rtime.TIMESPEC) as tp: + ret = rtime.c_clock_gettime(clk_id, tp) if ret != 0: raise exception_from_saved_errno(space, space.w_IOError) - return space.wrap(int(tp.c_tv_sec) + 1e-9 * int(tp.c_tv_nsec)) + t = (float(rffi.getintfield(tp, 'c_tv_sec')) + + float(rffi.getintfield(tp, 'c_tv_nsec')) * 0.000000001) + return space.wrap(t) @unwrap_spec(clk_id="c_int") def clock_getres(space, clk_id): - with lltype.scoped_alloc(TIMESPEC) as tp: - ret = c_clock_getres(clk_id, tp) + with lltype.scoped_alloc(rtime.TIMESPEC) as tp: + ret = rtime.c_clock_getres(clk_id, tp) if ret != 0: raise exception_from_saved_errno(space, space.w_IOError) - return space.wrap(int(tp.c_tv_sec) + 1e-9 * int(tp.c_tv_nsec)) + t = (float(rffi.getintfield(tp, 'c_tv_sec')) + + float(rffi.getintfield(tp, 'c_tv_nsec')) * 0.000000001) + return space.wrap(t) diff --git a/pypy/module/_cffi_backend/embedding.py b/pypy/module/_cffi_backend/embedding.py --- a/pypy/module/_cffi_backend/embedding.py +++ b/pypy/module/_cffi_backend/embedding.py @@ -112,29 +112,7 @@ #define _WIN32_WINNT 0x0501 #include <windows.h> -#define CFFI_INIT_HOME_PATH_MAX _MAX_PATH static void _cffi_init(void); -static void _cffi_init_error(const char *msg, const char *extra); - -static int _cffi_init_home(char *output_home_path) -{ - HMODULE hModule = 0; - DWORD res; - - GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | - GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - (LPCTSTR)&_cffi_init, &hModule); - - if (hModule == 0 ) { - _cffi_init_error("GetModuleHandleEx() failed", ""); - return -1; - } - res = GetModuleFileName(hModule, output_home_path, CFFI_INIT_HOME_PATH_MAX); - if (res >= CFFI_INIT_HOME_PATH_MAX) { - return -1; - } - return 0; -} static void _cffi_init_once(void) { @@ -155,28 +133,9 @@ else: do_includes = r""" -#include <dlfcn.h> #include <pthread.h> -#define CFFI_INIT_HOME_PATH_MAX PATH_MAX static void _cffi_init(void); -static void _cffi_init_error(const char *msg, const char *extra); - -static int _cffi_init_home(char *output_home_path) -{ - Dl_info info; - dlerror(); /* reset */ - if (dladdr(&_cffi_init, &info) == 0) { - _cffi_init_error("dladdr() failed: ", dlerror()); - return -1; - } - if (realpath(info.dli_fname, output_home_path) == NULL) { - perror("realpath() failed"); - _cffi_init_error("realpath() failed", ""); - return -1; - } - return 0; -} static void _cffi_init_once(void) { @@ -201,14 +160,10 @@ static void _cffi_init(void) { - char home[CFFI_INIT_HOME_PATH_MAX + 1]; - rpython_startup_code(); RPyGilAllocate(); - if (_cffi_init_home(home) != 0) - return; - if (pypy_setup_home(home, 1) != 0) { + if (pypy_setup_home(NULL, 1) != 0) { _cffi_init_error("pypy_setup_home() failed", ""); return; } diff --git a/pypy/module/_collections/interp_deque.py b/pypy/module/_collections/interp_deque.py --- a/pypy/module/_collections/interp_deque.py +++ b/pypy/module/_collections/interp_deque.py @@ -6,6 +6,7 @@ from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.interpreter.error import OperationError, oefmt from rpython.rlib.debug import check_nonneg +from rpython.rlib.objectmodel import specialize # A `dequeobject` is composed of a doubly-linked list of `block` nodes. @@ -316,12 +317,12 @@ w_currently_in_repr = ec._py_repr = space.newdict() return dequerepr(space, w_currently_in_repr, space.wrap(self)) + @specialize.arg(2) def compare(self, w_other, op): space = self.space if not isinstance(w_other, W_Deque): return space.w_NotImplemented return space.compare_by_iteration(space.wrap(self), w_other, op) - compare._annspecialcase_ = 'specialize:arg(2)' def lt(self, w_other): return self.compare(w_other, 'lt') diff --git a/pypy/module/_csv/interp_reader.py b/pypy/module/_csv/interp_reader.py --- a/pypy/module/_csv/interp_reader.py +++ b/pypy/module/_csv/interp_reader.py @@ -1,4 +1,5 @@ from rpython.rlib.rstring import UnicodeBuilder +from rpython.rlib import objectmodel from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import unwrap_spec @@ -24,13 +25,13 @@ def iter_w(self): return self.space.wrap(self) + @objectmodel.dont_inline def error(self, msg): space = self.space msg = u'line %d: %s' % (self.line_num, msg) w_module = space.getbuiltinmodule('_csv') w_error = space.getattr(w_module, space.wrap('Error')) raise OperationError(w_error, space.wrap(msg)) - error._dont_inline_ = True def add_char(self, field_builder, c): assert field_builder is not None diff --git a/pypy/module/_csv/interp_writer.py b/pypy/module/_csv/interp_writer.py --- a/pypy/module/_csv/interp_writer.py +++ b/pypy/module/_csv/interp_writer.py @@ -1,4 +1,5 @@ from rpython.rlib.rstring import UnicodeBuilder +from rpython.rlib import objectmodel from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter.error import OperationError from pypy.interpreter.typedef import TypeDef, interp2app @@ -21,12 +22,12 @@ special += dialect.quotechar self.special_characters = special + @objectmodel.dont_inline def error(self, msg): space = self.space w_module = space.getbuiltinmodule('_csv') w_error = space.getattr(w_module, space.wrap('Error')) raise OperationError(w_error, space.wrap(msg)) - error._dont_inline_ = True def writerow(self, w_fields): """Construct and write a CSV record from a sequence of fields. diff --git a/pypy/module/_lsprof/interp_lsprof.py b/pypy/module/_lsprof/interp_lsprof.py --- a/pypy/module/_lsprof/interp_lsprof.py +++ b/pypy/module/_lsprof/interp_lsprof.py @@ -7,7 +7,7 @@ from pypy.interpreter.typedef import (TypeDef, GetSetProperty, interp_attrproperty) from rpython.rlib import jit -from rpython.rlib.objectmodel import we_are_translated +from rpython.rlib.objectmodel import we_are_translated, always_inline from rpython.rlib.rtimer import read_timestamp, _is_64_bit from rpython.rtyper.lltypesystem import rffi, lltype from rpython.translator.tool.cbuild import ExternalCompilationInfo @@ -258,7 +258,7 @@ return w_frame.wrap_string(space) return w_frame # actually a PyCode object - +@always_inline def prepare_spec(space, w_arg): if isinstance(w_arg, Method): return (w_arg.w_function, space.type(w_arg.w_instance)) @@ -266,8 +266,6 @@ return (w_arg, None) else: return (None, space.type(w_arg)) -prepare_spec._always_inline_ = True - def lsprof_call(space, w_self, frame, event, w_arg): assert isinstance(w_self, W_Profiler) diff --git a/pypy/module/_pypyjson/interp_decoder.py b/pypy/module/_pypyjson/interp_decoder.py --- a/pypy/module/_pypyjson/interp_decoder.py +++ b/pypy/module/_pypyjson/interp_decoder.py @@ -1,6 +1,6 @@ import sys from rpython.rlib.rstring import StringBuilder -from rpython.rlib.objectmodel import specialize +from rpython.rlib.objectmodel import specialize, always_inline from rpython.rlib import rfloat, runicode from rpython.rtyper.lltypesystem import lltype, rffi from pypy.interpreter.error import oefmt @@ -189,6 +189,7 @@ self.pos = i return self.space.call_function(self.space.w_int, self.space.wrap(s)) + @always_inline def parse_integer(self, i): "Parse a decimal number with an optional minus sign" sign = 1 @@ -219,7 +220,6 @@ # overflowed ovf_maybe = (count >= OVF_DIGITS) return i, ovf_maybe, sign * intval - parse_integer._always_inline_ = True def decode_array(self, i): w_list = self.space.newlist([]) diff --git a/pypy/module/_pypyjson/targetjson.py b/pypy/module/_pypyjson/targetjson.py --- a/pypy/module/_pypyjson/targetjson.py +++ b/pypy/module/_pypyjson/targetjson.py @@ -6,6 +6,7 @@ import time from pypy.interpreter.error import OperationError from pypy.module._pypyjson.interp_decoder import loads +from rpython.rlib.objectmodel import specialize, dont_inline ## MSG = open('msg.json').read() @@ -68,11 +69,11 @@ assert isinstance(w_x, W_String) return w_x.strval + @dont_inline def call_method(self, obj, name, arg): assert name == 'append' assert isinstance(obj, W_List) obj.listval.append(arg) - call_method._dont_inline_ = True def call_function(self, w_func, *args_w): return self.w_None # XXX @@ -91,6 +92,7 @@ def wrapfloat(self, x): return W_Float(x) + @specialize.argtype(1) def wrap(self, x): if isinstance(x, int): return W_Int(x) @@ -100,7 +102,6 @@ ## assert False else: return W_Unicode(unicode(x)) - wrap._annspecialcase_ = "specialize:argtype(1)" fakespace = FakeSpace() diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py --- a/pypy/module/_rawffi/interp_rawffi.py +++ b/pypy/module/_rawffi/interp_rawffi.py @@ -11,6 +11,7 @@ from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rtyper.tool import rffi_platform from rpython.rlib.unroll import unrolling_iterable +from rpython.rlib.objectmodel import specialize import rpython.rlib.rposix as rposix _MS_WINDOWS = os.name == "nt" @@ -262,6 +263,7 @@ _ARM = rffi_platform.getdefined('__arm__', '') +@specialize.arg(2) def read_ptr(ptr, ofs, TP): T = lltype.Ptr(rffi.CArray(TP)) for c in unroll_letters_for_floats: @@ -281,8 +283,8 @@ return ptr_val else: return rffi.cast(T, ptr)[ofs] -read_ptr._annspecialcase_ = 'specialize:arg(2)' +@specialize.argtype(2) def write_ptr(ptr, ofs, value): TP = lltype.typeOf(value) T = lltype.Ptr(rffi.CArray(TP)) @@ -303,7 +305,6 @@ return else: rffi.cast(T, ptr)[ofs] = value -write_ptr._annspecialcase_ = 'specialize:argtype(2)' def segfault_exception(space, reason): w_mod = space.getbuiltinmodule("_rawffi") @@ -375,11 +376,12 @@ def getrawsize(self): raise NotImplementedError("abstract base class") +@specialize.arg(0) def unwrap_truncate_int(TP, space, w_arg): return rffi.cast(TP, space.bigint_w(w_arg).ulonglongmask()) -unwrap_truncate_int._annspecialcase_ = 'specialize:arg(0)' +@specialize.arg(1) def unwrap_value(space, push_func, add_arg, argdesc, letter, w_arg): if letter in TYPEMAP_PTR_LETTERS: # check for NULL ptr @@ -423,10 +425,10 @@ return else: raise oefmt(space.w_TypeError, "cannot directly write value") -unwrap_value._annspecialcase_ = 'specialize:arg(1)' ll_typemap_iter = unrolling_iterable(LL_TYPEMAP.items()) +@specialize.arg(1) def wrap_value(space, func, add_arg, argdesc, letter): for c, ll_type in ll_typemap_iter: if letter == c: @@ -440,7 +442,6 @@ else: return space.wrap(func(add_arg, argdesc, ll_type)) raise oefmt(space.w_TypeError, "cannot directly read value") -wrap_value._annspecialcase_ = 'specialize:arg(1)' NARROW_INTEGER_TYPES = 'cbhiBIH?' diff --git a/pypy/module/_rawffi/structure.py b/pypy/module/_rawffi/structure.py --- a/pypy/module/_rawffi/structure.py +++ b/pypy/module/_rawffi/structure.py @@ -18,6 +18,7 @@ from rpython.rlib.rarithmetic import intmask, signedtype, r_uint, \ r_ulonglong from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rlib.objectmodel import specialize import sys IS_BIG_ENDIAN = sys.byteorder == 'big' @@ -285,6 +286,7 @@ def NUM_BITS(x): return x >> 16 +@specialize.arg(1) def BIT_MASK(x, ll_t): if ll_t is lltype.SignedLongLong or ll_t is lltype.UnsignedLongLong: one = r_ulonglong(1) @@ -292,8 +294,8 @@ one = r_uint(1) # to avoid left shift by x == sizeof(ll_t) return (((one << (x - 1)) - 1) << 1) + 1 -BIT_MASK._annspecialcase_ = 'specialize:arg(1)' +@specialize.argtype(2) def push_field(self, num, value): ptr = rffi.ptradd(self.ll_buffer, self.shape.ll_positions[num]) TP = lltype.typeOf(value) @@ -314,8 +316,8 @@ value = rffi.cast(TP, current) break write_ptr(ptr, 0, value) -push_field._annspecialcase_ = 'specialize:argtype(2)' +@specialize.arg(2) def cast_pos(self, i, ll_t): pos = rffi.ptradd(self.ll_buffer, self.shape.ll_positions[i]) value = read_ptr(pos, 0, ll_t) @@ -338,7 +340,6 @@ value = rffi.cast(ll_t, value) break return value -cast_pos._annspecialcase_ = 'specialize:arg(2)' class W_StructureInstance(W_DataInstance): def __init__(self, space, shape, address): diff --git a/pypy/module/_warnings/interp_warnings.py b/pypy/module/_warnings/interp_warnings.py --- a/pypy/module/_warnings/interp_warnings.py +++ b/pypy/module/_warnings/interp_warnings.py @@ -248,6 +248,10 @@ if space.isinstance_w(w_message, space.w_Warning): w_text = space.str(w_message) w_category = space.type(w_message) + elif (not space.isinstance_w(w_message, space.w_unicode) or + not space.isinstance_w(w_message, space.w_str)): + w_text = space.str(w_message) + w_message = space.call_function(w_category, w_message) else: w_text = w_message w_message = space.call_function(w_category, w_message) diff --git a/pypy/module/_warnings/test/test_warnings.py b/pypy/module/_warnings/test/test_warnings.py --- a/pypy/module/_warnings/test/test_warnings.py +++ b/pypy/module/_warnings/test/test_warnings.py @@ -16,6 +16,7 @@ import _warnings _warnings.warn("some message", DeprecationWarning) _warnings.warn("some message", Warning) + _warnings.warn(("some message",1), Warning) def test_lineno(self): import warnings, _warnings, sys @@ -45,7 +46,10 @@ def test_show_source_line(self): import warnings import sys, io - from test.warning_tests import inner + try: + from test.warning_tests import inner + except ImportError: + skip('no test, -A on cpython?') # With showarning() missing, make sure that output is okay. del warnings.showwarning 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 @@ -120,8 +120,8 @@ Py_TPFLAGS_READY Py_TPFLAGS_READYING Py_TPFLAGS_HAVE_GETCHARBUFFER METH_COEXIST METH_STATIC METH_CLASS Py_TPFLAGS_BASETYPE Py_MAX_FMT METH_NOARGS METH_VARARGS METH_KEYWORDS METH_O Py_TPFLAGS_HAVE_INPLACEOPS -Py_TPFLAGS_HEAPTYPE Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_HAVE_NEWBUFFER -Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE Py_TPFLAGS_CHECKTYPES Py_MAX_NDIMS +Py_TPFLAGS_HEAPTYPE Py_TPFLAGS_HAVE_CLASS +Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE Py_MAX_NDIMS Py_CLEANUP_SUPPORTED """.split() for name in constant_names: diff --git a/pypy/module/cpyext/buffer.py b/pypy/module/cpyext/buffer.py --- a/pypy/module/cpyext/buffer.py +++ b/pypy/module/cpyext/buffer.py @@ -1,7 +1,7 @@ from rpython.rtyper.lltypesystem import rffi from rpython.rlib import buffer from pypy.module.cpyext.api import ( - cpython_api, CANNOT_FAIL, Py_TPFLAGS_HAVE_NEWBUFFER) + cpython_api, CANNOT_FAIL) from pypy.module.cpyext.pyobject import PyObject, Py_DecRef class CBuffer(buffer.Buffer): diff --git a/pypy/module/cpyext/floatobject.py b/pypy/module/cpyext/floatobject.py --- a/pypy/module/cpyext/floatobject.py +++ b/pypy/module/cpyext/floatobject.py @@ -61,11 +61,12 @@ This is the equivalent of the Python expression float(o).""" return space.call_function(space.w_float, w_obj) -@cpython_api([PyObject, rffi.CCHARPP], PyObject) -def PyFloat_FromString(space, w_obj, _): - """Create a PyFloatObject object based on the string value in str, or - NULL on failure. The pend argument is ignored. It remains only for - backward compatibility.""" +@cpython_api([PyObject], PyObject) +def PyFloat_FromString(space, w_obj): + """ + Create a PyFloatObject object based on the string value in str, or + NULL on failure. _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit