From pypy.commits at gmail.com Sun Feb 2 09:45:19 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Feb 2020 06:45:19 -0800 (PST) Subject: [pypy-commit] pypy default: backport some of the changes from py3.6 Message-ID: <5e36e07f.1c69fb81.6f09e.b632@mx.google.com> Author: Matti Picus Branch: Changeset: r98625:72aff1d1e6fa Date: 2020-01-30 23:14 +0200 http://bitbucket.org/pypy/pypy/changeset/72aff1d1e6fa/ Log: backport some of the changes from py3.6 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 @@ -1,18 +1,16 @@ - # -*- coding: utf-8 -*- -from pypy.objspace.std.objspace import StdObjSpace -from rpython.tool.udir import udir -from pypy.tool.pytest.objspace import gettestobjspace -from pypy import pypydir -from rpython.translator.c.test.test_extfunc import need_sparse_files -from rpython.rlib import rposix import os import py import sys import signal -USEMODULES = ['binascii', 'posix', 'struct', 'time'] +from rpython.tool.udir import udir +from pypy.tool.pytest.objspace import gettestobjspace +from rpython.translator.c.test.test_extfunc import need_sparse_files +from rpython.rlib import rposix + +USEMODULES = ['binascii', 'posix', 'signal', 'struct', 'time'] if os.name != 'nt': USEMODULES += ['fcntl'] else: @@ -24,6 +22,9 @@ mod.path = udir.join('posixtestfile.txt') mod.path.write("this is a test") mod.path2 = udir.join('test_posix2-') + mod.path3 = udir.join('unlinktestfile.txt') + mod.path3.write("delete me!") + pdir = udir.ensure('posixtestdir', dir=True) pdir = udir.ensure('posixtestdir', dir=True) pdir.join('file1').write("test1") os.chmod(str(pdir.join('file1')), 0600) @@ -50,7 +51,6 @@ # space.call_method(space.getbuiltinmodule('sys'), 'getfilesystemencoding') - GET_POSIX = "(): import %s as m ; return m" % os.name @@ -63,6 +63,7 @@ cls.w_posix = space.appexec([], GET_POSIX) cls.w_path = space.wrap(str(path)) cls.w_path2 = space.wrap(str(path2)) + cls.w_path3 = space.wrap(str(path3)) cls.w_pdir = space.wrap(str(pdir)) try: cls.w_unicode_dir = space.wrap( @@ -93,6 +94,7 @@ cls.w_confstr_result = space.wrap(os.confstr(confstr_name)) cls.w_SIGABRT = space.wrap(signal.SIGABRT) cls.w_python = space.wrap(sys.executable) + cls.w_platform = space.wrap(sys.platform) if hasattr(os, 'major'): cls.w_expected_major_12345 = space.wrap(os.major(12345)) cls.w_expected_minor_12345 = space.wrap(os.minor(12345)) @@ -118,10 +120,10 @@ fd2 = posix.dup(fd) assert not posix.isatty(fd2) s = posix.read(fd, 1) - assert s == 't' + assert s == b't' posix.lseek(fd, 5, 0) s = posix.read(fd, 1) - assert s == 'i' + assert s == b'i' st = posix.fstat(fd) posix.close(fd2) posix.close(fd) @@ -175,6 +177,7 @@ finally: posix.stat_float_times(current) + def test_stat_result(self): st = self.posix.stat_result((0, 0, 0, 0, 0, 0, 0, 41, 42.1, 43)) assert st.st_atime == 41 @@ -186,6 +189,8 @@ import stat st = self.posix.stat(".") assert stat.S_ISDIR(st.st_mode) + st = self.posix.stat(b".") + assert stat.S_ISDIR(st.st_mode) st = self.posix.lstat(".") assert stat.S_ISDIR(st.st_mode) @@ -267,6 +272,7 @@ assert 0 def test_functions_raise_error(self): + import sys def ex(func, *args): try: func(*args) @@ -281,13 +287,15 @@ ex(self.posix.lseek, UNUSEDFD, 123, 0) #apparently not posix-required: ex(self.posix.isatty, UNUSEDFD) ex(self.posix.read, UNUSEDFD, 123) - ex(self.posix.write, UNUSEDFD, "x") + ex(self.posix.write, UNUSEDFD, b"x") ex(self.posix.close, UNUSEDFD) #UMPF cpython raises IOError ex(self.posix.ftruncate, UNUSEDFD, 123) - ex(self.posix.fstat, UNUSEDFD) - ex(self.posix.stat, "qweqwehello") - # how can getcwd() raise? - ex(self.posix.dup, UNUSEDFD) + if sys.platform == 'win32' and self.runappdirect: + # XXX kills the host interpreter untranslated + ex(self.posix.fstat, UNUSEDFD) + ex(self.posix.stat, "qweqwehello") + # how can getcwd() raise? + ex(self.posix.dup, UNUSEDFD) def test_fdopen(self): import errno @@ -391,6 +399,9 @@ assert (unicode, 'caf%E9') in typed_result else: assert (unicode, u) in typed_result + assert posix.access(b'caf\xe9', posix.R_OK) is False + assert posix.access('caf\udcc0', posix.R_OK) is False + assert posix.access(b'caf\xc3', posix.R_OK) is False def test_access(self): pdir = self.pdir + '/file1' @@ -402,6 +413,13 @@ if sys.platform != "win32": assert posix.access(pdir, posix.X_OK) is False + def test_unlink(self): + os = self.posix + path = self.path3 + with open(path, 'wb'): + pass + os.unlink(path) + def test_times(self): """ posix.times() should return a five-tuple giving float-representations @@ -414,7 +432,6 @@ for value in result: assert isinstance(value, float) - def test_strerror(self): assert isinstance(self.posix.strerror(0), str) assert isinstance(self.posix.strerror(1), str) @@ -438,9 +455,9 @@ master_fd, slave_fd = os.openpty() assert isinstance(master_fd, int) assert isinstance(slave_fd, int) - os.write(slave_fd, 'x\n') + os.write(slave_fd, b'x\n') data = os.read(master_fd, 100) - assert data.startswith('x') + assert data.startswith(b'x') os.close(master_fd) os.close(slave_fd) @@ -455,11 +472,11 @@ assert isinstance(master_fd, int) if childpid == 0: data = os.read(0, 100) - if data.startswith('abc'): + if data.startswith(b'abc'): os._exit(42) else: os._exit(43) - os.write(master_fd, 'abc\n') + os.write(master_fd, b'abc\n') _, status = os.waitpid(childpid, 0) assert status >> 8 == 42 @@ -508,7 +525,8 @@ os.execv(u"/bin/sh", ["sh", "-c", u"echo caf\xe9 \u1234 > onefile"]) os.waitpid(pid, 0) - assert open("onefile").read() == output + with open("onefile") as fid: + assert fid.read() == output os.unlink("onefile") def test_execve(self): @@ -537,7 +555,8 @@ u"echo caf\xe9 \u1234 > onefile"], {'ddd': 'xxx'}) os.waitpid(pid, 0) - assert open("onefile").read() == output + with open("onefile") as fid: + assert fid.read() == output os.unlink("onefile") pass # <- please, inspect.getsource(), don't crash @@ -607,7 +626,7 @@ # XXX utimes & float support path = join(self.pdir, "test_utime.txt") fh = open(path, "w") - fh.write("x") + fh.write(b"x") fh.close() from time import time, sleep t0 = time() @@ -619,8 +638,11 @@ def test_utime_raises(self): os = self.posix + import errno raises(TypeError, "os.utime('xxx', 3)") - raises(OSError, "os.utime('somefilewhichihopewouldneverappearhere', None)") + exc = raises(OSError, + "os.utime('somefilewhichihopewouldneverappearhere', None)") + assert exc.value.errno == errno.ENOENT for name in rposix.WAIT_MACROS: if hasattr(os, name): @@ -858,23 +880,20 @@ def test_fchdir(self): os = self.posix localdir = os.getcwd() - try: - os.mkdir(self.path2 + 'dir') - fd = os.open(self.path2 + 'dir', os.O_RDONLY) + os.mkdir(self.path2 + 'fchdir') + for func in [os.fchdir, os.chdir]: + fd = os.open(self.path2 + 'fchdir', os.O_RDONLY) try: os.fchdir(fd) mypath = os.getcwd() finally: - os.close(fd) - assert mypath.endswith('test_posix2-dir') - raises(OSError, os.fchdir, fd) - raises(ValueError, os.fchdir, -1) - finally: - os.chdir(localdir) + os.chdir(localdir) + raises(ValueError, os.fchdir, -1) def test_largefile(self): os = self.posix - fd = os.open(self.path2 + 'test_largefile', os.O_RDWR | os.O_CREAT, 0666) + fd = os.open(self.path2 + 'test_largefile', + os.O_RDWR | os.O_CREAT, 0666) os.ftruncate(fd, 10000000000L) res = os.lseek(fd, 9900000000L, 0) assert res == 9900000000L @@ -896,22 +915,23 @@ count = os.write(fd, s) assert count > 0 s = s[count:] - writeall('hello, ') + writeall(b'hello, ') writeall(buffer('world!\n')) res = os.lseek(fd, 0, 0) assert res == 0 - data = '' + data = b'' while True: s = os.read(fd, 100) if not s: break data += s - assert data == 'hello, world!\n' + assert data == b'hello, world!\n' os.close(fd) def test_write_unicode(self): os = self.posix - fd = os.open(self.path2 + 'test_write_unicode', os.O_RDWR | os.O_CREAT, 0666) + fd = os.open(self.path2 + 'test_write_unicode', + os.O_RDWR | os.O_CREAT, 0666) os.write(fd, u'X') raises(UnicodeEncodeError, os.write, fd, u'\xe9') os.lseek(fd, 0, 0) @@ -945,8 +965,10 @@ os.closerange(start, stop) for fd in fds: os.close(fd) # should not have been closed - for fd in range(start, stop): - raises(OSError, os.fstat, fd) # should have been closed + if self.platform == 'win32' and self.runappdirect: + # XXX kills the host interpreter untranslated + for fd in range(start, stop): + raises(OSError, os.fstat, fd) # should have been closed if hasattr(os, 'chown'): def test_chown(self): @@ -1196,41 +1218,56 @@ @py.test.mark.skipif("sys.platform != 'win32'") def test_rename(self): os = self.posix - with open(self.path, "w") as f: + fname = self.path2 + 'rename.txt' + with open(fname, "w") as f: f.write("this is a rename test") str_name = str(self.pdir) + '/test_rename.txt' - os.rename(self.path, str_name) + os.rename(fname, str_name) with open(str_name) as f: assert f.read() == 'this is a rename test' - os.rename(str_name, self.path) + os.rename(str_name, fname) unicode_name = str(self.udir) + u'/test\u03be.txt' - os.rename(self.path, unicode_name) + os.rename(fname, unicode_name) with open(unicode_name) as f: assert f.read() == 'this is a rename test' - os.rename(unicode_name, self.path) - with open(self.path) as f: + os.rename(unicode_name, fname) + + os.rename(bytes(fname, 'utf-8'), bytes(str_name, 'utf-8')) + with open(str_name) as f: assert f.read() == 'this is a rename test' - os.unlink(self.path) - + os.rename(str_name, fname) + with open(fname) as f: + assert f.read() == 'this is a rename test' + os.unlink(fname) class AppTestEnvironment(object): def setup_class(cls): cls.w_path = space.wrap(str(path)) - if sys.platform != 'win32': - def test_environ(self): - import posix - assert posix.environ['PATH'] - del posix.environ['PATH'] - def fn(): posix.environ['PATH'] - raises(KeyError, fn) - else: - def test_environ(self): - import nt - assert 'ADLDJSSLDFKJSD' not in nt.environ - def fn(): nt.environ['ADLDJSSLDFKJSD'] - raises(KeyError, fn) + def test_environ(self): + import sys, os + environ = os.environ + if not environ: + skip('environ not filled in for untranslated tests') + for k, v in environ.items(): + assert type(k) is str + assert type(v) is str + name = next(iter(environ)) + assert environ[name] is not None + del environ[name] + raises(KeyError, lambda: environ[name]) + + @py.test.mark.dont_track_allocations('putenv intentionally keeps strings alive') + def test_environ_nonascii(self): + import sys, os + name, value = 'PYPY_TEST_日本', 'foobar日本' + os.environ[name] = value + assert os.environ[name] == value + assert os.getenv(name) == value + del os.environ[name] + assert os.environ.get(name) is None + assert os.getenv(name) is None if hasattr(__import__(os.name), "unsetenv"): def test_unsetenv_nonexisting(self): @@ -1315,9 +1352,10 @@ content = self.posix.read(fd, 50) finally: self.posix.close(fd) - assert content == "test" + assert content == b"test" +from pypy import pypydir class TestPexpect(object): # XXX replace with AppExpectTest class as soon as possible def setup_class(cls): From pypy.commits at gmail.com Sun Feb 2 09:45:21 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Feb 2020 06:45:21 -0800 (PST) Subject: [pypy-commit] pypy default: do not import stdlib os Message-ID: <5e36e081.1c69fb81.ba510.34a7@mx.google.com> Author: Matti Picus Branch: Changeset: r98626:03da8b4056eb Date: 2020-01-30 23:38 +0200 http://bitbucket.org/pypy/pypy/changeset/03da8b4056eb/ Log: do not import stdlib os 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 @@ -65,6 +65,7 @@ cls.w_path2 = space.wrap(str(path2)) cls.w_path3 = space.wrap(str(path3)) cls.w_pdir = space.wrap(str(pdir)) + cls.w_plat = space.wrap(sys.platform) try: cls.w_unicode_dir = space.wrap( str(unicode_dir).decode(sys.getfilesystemencoding())) @@ -595,11 +596,11 @@ assert res == '1\n' def test_popen_child_fds(self): - import os - with open(os.path.join(self.pdir, 'file1'), 'r') as fd: + os = self.posix + with open('/'.join([self.pdir, 'file1']), 'r') as fd: with self.posix.popen('%s -c "import os; print os.read(%d, 10)" 2>&1' % (self.python, fd.fileno())) as stream: res = stream.read() - if os.name == 'nt': + if self.plat == 'win32': assert '\nOSError: [Errno 9]' in res else: assert res == 'test1\n' @@ -614,11 +615,10 @@ def test__getfullpathname(self): # nt specific posix = self.posix - import os - sysdrv = os.getenv("SystemDrive", "C:") + sysdrv = posix.getenv("SystemDrive", "C:") # just see if it does anything path = sysdrv + 'hubber' - assert os.sep in posix._getfullpathname(path) + assert posix.sep in posix._getfullpathname(path) def test_utime(self): os = self.posix @@ -1165,7 +1165,7 @@ assert w[-1].lineno == f_tmpnam_warning.func_code.co_firstlineno def test_has_kill(self): - import os + os = self.posix assert hasattr(os, 'kill') def test_pipe_flush(self): @@ -1244,6 +1244,7 @@ class AppTestEnvironment(object): def setup_class(cls): cls.w_path = space.wrap(str(path)) + cls.w_posix = space.appexec([], GET_POSIX) def test_environ(self): import sys, os @@ -1271,7 +1272,7 @@ if hasattr(__import__(os.name), "unsetenv"): def test_unsetenv_nonexisting(self): - import os + os = self.posix os.unsetenv("XYZABC") #does not raise try: os.environ["ABCABC"] From pypy.commits at gmail.com Sun Feb 2 09:45:23 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Feb 2020 06:45:23 -0800 (PST) Subject: [pypy-commit] pypy default: simplify the call to wrap_oserror2 Message-ID: <5e36e083.1c69fb81.211e0.bfea@mx.google.com> Author: Matti Picus Branch: Changeset: r98627:2821b0633b53 Date: 2020-01-31 10:37 +0200 http://bitbucket.org/pypy/pypy/changeset/2821b0633b53/ Log: simplify the call to wrap_oserror2 diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py --- a/pypy/interpreter/error.py +++ b/pypy/interpreter/error.py @@ -471,8 +471,7 @@ return OperationError(exc, w_error) @specialize.arg(3) -def wrap_oserror2(space, e, w_filename=None, exception_name='w_OSError', - w_exception_class=None): +def wrap_oserror2(space, e, w_filename=None, w_exception_class=None): assert isinstance(e, OSError) if _WINDOWS and isinstance(e, WindowsError): @@ -488,7 +487,7 @@ except ValueError: msg = 'error %d' % errno if w_exception_class is None: - exc = getattr(space, exception_name) + exc = getattr(space, 'w_OSError') else: exc = w_exception_class if w_filename is not None: @@ -500,15 +499,12 @@ return OperationError(exc, w_error) @specialize.arg(3) -def wrap_oserror(space, e, filename=None, exception_name='w_OSError', - w_exception_class=None): +def wrap_oserror(space, e, filename=None, w_exception_class=None): if filename is not None: return wrap_oserror2(space, e, space.newtext(filename), - exception_name=exception_name, w_exception_class=w_exception_class) else: return wrap_oserror2(space, e, None, - exception_name=exception_name, w_exception_class=w_exception_class) def exception_from_errno(space, w_type, errno): diff --git a/pypy/interpreter/test/test_error.py b/pypy/interpreter/test/test_error.py --- a/pypy/interpreter/test/test_error.py +++ b/pypy/interpreter/test/test_error.py @@ -113,7 +113,7 @@ # e = wrap_oserror(space, OSError(errno.EBADF, "foobar"), filename = "test.py", - exception_name = "w_EnvironmentError") + w_exception_class = space.w_EnvironmentError) assert isinstance(e, OperationError) assert e.w_type == [EnvironmentError] assert e.get_w_value(space) == ([EnvironmentError], [errno.EBADF], diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py --- a/pypy/module/_io/interp_fileio.py +++ b/pypy/module/_io/interp_fileio.py @@ -173,7 +173,7 @@ space, w_name, flags, 0666) except OSError as e: raise wrap_oserror2(space, e, w_name, - exception_name='w_IOError') + w_exception_class=space.w_IOError) finally: fd_is_own = True @@ -186,7 +186,7 @@ try: os.lseek(self.fd, 0, os.SEEK_END) except OSError as e: - raise wrap_oserror(space, e, exception_name='w_IOError') + raise wrap_oserror(space, e, w_exception_class=space.w_IOError) except: if not fd_is_own: self.fd = -1 @@ -235,8 +235,7 @@ try: os.close(fd) except OSError as e: - raise wrap_oserror(space, e, - exception_name='w_IOError') + raise wrap_oserror(space, e, w_exception_class=space.w_IOError) def close_w(self, space): try: @@ -264,7 +263,7 @@ return if stat.S_ISDIR(st.st_mode): raise wrap_oserror2(space, OSError(errno.EISDIR, "fstat"), - w_filename, exception_name='w_IOError') + w_filename, w_exception_class=space.w_IOError) @unwrap_spec(pos=r_longlong, whence=int) def seek_w(self, space, pos, whence=0): @@ -273,7 +272,7 @@ pos = os.lseek(self.fd, pos, whence) except OSError as e: raise wrap_oserror(space, e, - exception_name='w_IOError') + w_exception_class=space.w_IOError) return space.newint(pos) def tell_w(self, space): @@ -282,7 +281,7 @@ pos = os.lseek(self.fd, 0, 1) except OSError as e: raise wrap_oserror(space, e, - exception_name='w_IOError') + w_exception_class=space.w_IOError) return space.newint(pos) def readable_w(self, space): @@ -315,7 +314,7 @@ try: res = os.isatty(self.fd) except OSError as e: - raise wrap_oserror(space, e, exception_name='w_IOError') + raise wrap_oserror(space, e, w_exception_class=space.w_IOError) return space.newbool(res) def repr_w(self, space): @@ -345,7 +344,7 @@ if e.errno == errno.EAGAIN: return space.w_None raise wrap_oserror(space, e, - exception_name='w_IOError') + w_exception_class=space.w_IOError) return space.newint(n) @@ -363,7 +362,7 @@ if e.errno == errno.EAGAIN: return space.w_None raise wrap_oserror(space, e, - exception_name='w_IOError') + w_exception_class=space.w_IOError) return space.newbytes(s) @@ -388,7 +387,7 @@ if e.errno == errno.EAGAIN: return space.w_None raise wrap_oserror(space, e, - exception_name='w_IOError') + w_exception_class=space.w_IOError) self.output_slice(space, rwbuffer, 0, buf) return space.newint(len(buf)) else: @@ -404,7 +403,7 @@ if err == errno.EAGAIN: return space.w_None e = OSError(err, "read failed") - raise wrap_oserror(space, e, exception_name='w_IOError') + raise wrap_oserror(space, e, w_exception_class=space.w_IOError) def readall_w(self, space): self._check_closed(space) @@ -427,7 +426,7 @@ if e.errno == errno.EAGAIN: return space.w_None raise wrap_oserror(space, e, - exception_name='w_IOError') + w_exception_class=space.w_IOError) if not chunk: break @@ -452,7 +451,7 @@ try: self._truncate(space.r_longlong_w(w_size)) except OSError as e: - raise wrap_oserror(space, e, exception_name='w_IOError') + raise wrap_oserror(space, e, w_exception_class=space.w_IOError) return w_size diff --git a/pypy/module/fcntl/interp_fcntl.py b/pypy/module/fcntl/interp_fcntl.py --- a/pypy/module/fcntl/interp_fcntl.py +++ b/pypy/module/fcntl/interp_fcntl.py @@ -80,7 +80,7 @@ def _get_error(space, funcname): errno = rposix.get_saved_errno() return wrap_oserror(space, OSError(errno, funcname), - exception_name = 'w_IOError') + w_exception_class = space.w_IOError) @unwrap_spec(op=int, w_arg=WrappedDefault(0)) def fcntl(space, w_fd, op, w_arg): 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 @@ -1232,13 +1232,6 @@ assert f.read() == 'this is a rename test' os.rename(unicode_name, fname) - os.rename(bytes(fname, 'utf-8'), bytes(str_name, 'utf-8')) - with open(str_name) as f: - assert f.read() == 'this is a rename test' - os.rename(str_name, fname) - with open(fname) as f: - assert f.read() == 'this is a rename test' - os.unlink(fname) class AppTestEnvironment(object): diff --git a/pypy/module/select/interp_select.py b/pypy/module/select/interp_select.py --- a/pypy/module/select/interp_select.py +++ b/pypy/module/select/interp_select.py @@ -40,7 +40,7 @@ fd = space.c_filedescriptor_w(w_fd) if fd not in self.fddict: raise wrap_oserror(space, OSError(errno.ENOENT, "poll.modify"), - exception_name='w_IOError') + w_exception_class = space.w_IOError) self.fddict[fd] = events def unregister(self, space, w_fd): From pypy.commits at gmail.com Sun Feb 2 09:45:24 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Feb 2020 06:45:24 -0800 (PST) Subject: [pypy-commit] pypy default: pep-8 cleanup Message-ID: <5e36e084.1c69fb81.cb39e.7306@mx.google.com> Author: Matti Picus Branch: Changeset: r98628:30cf519fd69a Date: 2020-01-31 11:45 +0200 http://bitbucket.org/pypy/pypy/changeset/30cf519fd69a/ Log: pep-8 cleanup diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py --- a/pypy/interpreter/error.py +++ b/pypy/interpreter/error.py @@ -487,7 +487,7 @@ except ValueError: msg = 'error %d' % errno if w_exception_class is None: - exc = getattr(space, 'w_OSError') + exc = space.w_OSError else: exc = w_exception_class if w_filename is not None: diff --git a/pypy/interpreter/test/test_error.py b/pypy/interpreter/test/test_error.py --- a/pypy/interpreter/test/test_error.py +++ b/pypy/interpreter/test/test_error.py @@ -112,8 +112,8 @@ [os.strerror(errno.EBADF)], None) # e = wrap_oserror(space, OSError(errno.EBADF, "foobar"), - filename = "test.py", - w_exception_class = space.w_EnvironmentError) + filename="test.py", + w_exception_class=space.w_EnvironmentError) assert isinstance(e, OperationError) assert e.w_type == [EnvironmentError] assert e.get_w_value(space) == ([EnvironmentError], [errno.EBADF], @@ -121,8 +121,8 @@ ["test.py"]) # e = wrap_oserror(space, OSError(errno.EBADF, "foobar"), - filename = "test.py", - w_exception_class = [SystemError]) + filename="test.py", + w_exception_class=[SystemError]) assert isinstance(e, OperationError) assert e.w_type == [SystemError] assert e.get_w_value(space) == ([SystemError], [errno.EBADF], diff --git a/pypy/module/fcntl/interp_fcntl.py b/pypy/module/fcntl/interp_fcntl.py --- a/pypy/module/fcntl/interp_fcntl.py +++ b/pypy/module/fcntl/interp_fcntl.py @@ -80,7 +80,7 @@ def _get_error(space, funcname): errno = rposix.get_saved_errno() return wrap_oserror(space, OSError(errno, funcname), - w_exception_class = space.w_IOError) + w_exception_class=space.w_IOError) @unwrap_spec(op=int, w_arg=WrappedDefault(0)) def fcntl(space, w_fd, op, w_arg): diff --git a/pypy/module/select/interp_select.py b/pypy/module/select/interp_select.py --- a/pypy/module/select/interp_select.py +++ b/pypy/module/select/interp_select.py @@ -40,7 +40,7 @@ fd = space.c_filedescriptor_w(w_fd) if fd not in self.fddict: raise wrap_oserror(space, OSError(errno.ENOENT, "poll.modify"), - w_exception_class = space.w_IOError) + w_exception_class=space.w_IOError) self.fddict[fd] = events def unregister(self, space, w_fd): From pypy.commits at gmail.com Sun Feb 2 09:45:26 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Feb 2020 06:45:26 -0800 (PST) Subject: [pypy-commit] pypy default: fix failing win32 test Message-ID: <5e36e086.1c69fb81.56a85.c1ad@mx.google.com> Author: Matti Picus Branch: Changeset: r98629:c14832883def Date: 2020-01-31 12:11 +0200 http://bitbucket.org/pypy/pypy/changeset/c14832883def/ Log: fix failing win32 test 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 @@ -615,10 +615,10 @@ def test__getfullpathname(self): # nt specific posix = self.posix - sysdrv = posix.getenv("SystemDrive", "C:") + sysdrv = posix.environ.get("SystemDrive", "C:") # just see if it does anything path = sysdrv + 'hubber' - assert posix.sep in posix._getfullpathname(path) + assert '\\' in posix._getfullpathname(path) def test_utime(self): os = self.posix From pypy.commits at gmail.com Sun Feb 2 12:49:32 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Feb 2020 09:49:32 -0800 (PST) Subject: [pypy-commit] pypy py3.6: move test to extra_tests, speed up unstranslated tests by 50% Message-ID: <5e370bac.1c69fb81.561a2.7ccc@mx.google.com> Author: Matti Picus Branch: py3.6 Changeset: r98638:eee8317e40c5 Date: 2020-01-31 07:38 +0200 http://bitbucket.org/pypy/pypy/changeset/eee8317e40c5/ Log: move test to extra_tests, speed up unstranslated tests by 50% diff --git a/extra_tests/test_posix.py b/extra_tests/test_posix.py new file mode 100644 --- /dev/null +++ b/extra_tests/test_posix.py @@ -0,0 +1,13 @@ +# Tests variant functions which also accept file descriptors, +# dir_fd and follow_symlinks. +def test_have_functions(): + import os + assert os.stat in os.supports_fd # fstat() is supported everywhere + if os.name != 'nt': + assert os.chdir in os.supports_fd # fchdir() + else: + assert os.chdir not in os.supports_fd + if os.name == 'posix': + assert os.open in os.supports_dir_fd # openat() + + 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 @@ -1502,7 +1502,7 @@ if os.name == 'nt': def test__getfileinformation(self): - import os + os = self.posix path = os.path.join(self.pdir, 'file1') with open(path) as fp: info = self.posix._getfileinformation(fp.fileno()) @@ -1510,7 +1510,7 @@ assert all(isinstance(obj, int) for obj in info) def test__getfinalpathname(self): - import os + os = self.posix path = os.path.join(self.pdir, 'file1') try: result = self.posix._getfinalpathname(path) @@ -1669,27 +1669,27 @@ @py.test.mark.usefixtures('check_fsencoding') class AppTestPosixUnicode: + def setup_class(cls): + cls.w_posix = space.appexec([], GET_POSIX) + def test_stat_unicode(self): # test that passing unicode would not raise UnicodeDecodeError - import os try: - os.stat(u"ą") + self.posix.stat(u"ą") except OSError: pass def test_open_unicode(self): # Ensure passing unicode doesn't raise UnicodeEncodeError - import os try: - os.open(u"ą", os.O_WRONLY) + self.posix.open(u"ą", os.O_WRONLY) except OSError: pass def test_remove_unicode(self): # See 2 above ;) - import os try: - os.remove(u"ą") + self.posix.remove(u"ą") except OSError: pass @@ -1717,20 +1717,6 @@ assert content == b"test" -class AppTestFdVariants: - # Tests variant functions which also accept file descriptors, - # dir_fd and follow_symlinks. - def test_have_functions(self): - import os - assert os.stat in os.supports_fd # fstat() is supported everywhere - if os.name != 'nt': - assert os.chdir in os.supports_fd # fchdir() - else: - assert os.chdir not in os.supports_fd - if os.name == 'posix': - assert os.open in os.supports_dir_fd # openat() - - class AppTestPep475Retry: spaceconfig = {'usemodules': USEMODULES} From pypy.commits at gmail.com Sun Feb 2 12:49:33 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Feb 2020 09:49:33 -0800 (PST) Subject: [pypy-commit] pypy py3.6: redo tests to not import app-level lib-python/3/os.py Message-ID: <5e370bad.1c69fb81.fc43d.b676@mx.google.com> Author: Matti Picus Branch: py3.6 Changeset: r98639:3b12b05e7a25 Date: 2020-02-02 15:55 +0200 http://bitbucket.org/pypy/pypy/changeset/3b12b05e7a25/ Log: redo tests to not import app-level lib-python/3/os.py diff --git a/extra_tests/test_posix.py b/extra_tests/test_posix.py --- a/extra_tests/test_posix.py +++ b/extra_tests/test_posix.py @@ -10,4 +10,30 @@ if os.name == 'posix': assert os.open in os.supports_dir_fd # openat() +def test_popen(): + import os + for i in range(5): + stream = os.popen('echo 1') + res = stream.read() + assert res == '1\n' + assert stream.close() is None +def test_popen_with(): + import os + stream = os.popen('echo 1') + with stream as fp: + res = fp.read() + assert res == '1\n' + +def test_pickle(): + import pickle + import os + st = os.stat('.') + # print(type(st).__module__) + s = pickle.dumps(st) + # print(repr(s)) + new = pickle.loads(s) + assert new == st + assert type(new) is type(st) + + 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 @@ -140,6 +140,12 @@ self.as_unicode = unicode self.w_path = w_path + def __repr__(self): + # For debugging + return ''.join(['Path(', str(self.as_fd), ', ', str(self.as_bytes), + ', ', str(self.as_unicode), ', [', str(self.w_path), + ', ', str(getattr(self.w_path, '_length', 'bytes')), '])']) + @specialize.arg(2) def _unwrap_path(space, w_value, allow_fd=True): # equivalent of posixmodule.c:path_converter() in CPython 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 @@ -16,7 +16,7 @@ if os.name != 'nt': USEMODULES += ['fcntl', 'select', '_posixsubprocess', '_socket'] else: - USEMODULES += ['_rawffi', 'thread', 'signal', '_cffi_backend'] + USEMODULES += ['_rawffi', 'thread', '_cffi_backend'] def setup_module(mod): mod.space = gettestobjspace(usemodules=USEMODULES) @@ -65,7 +65,6 @@ space = cls.space cls.w_runappdirect = space.wrap(cls.runappdirect) cls.w_posix = space.appexec([], GET_POSIX) - cls.w_os = space.appexec([], "(): import os as m ; return m") cls.w_path = space.wrap(str(path)) cls.w_path2 = space.wrap(str(path2)) cls.w_path3 = space.wrap(str(path3)) @@ -100,6 +99,7 @@ cls.w_expected_major_12345 = space.wrap(os.major(12345)) cls.w_expected_minor_12345 = space.wrap(os.minor(12345)) cls.w_udir = space.wrap(str(udir)) + cls.w_env_path = space.wrap(os.environ['PATH']) cls.w_Path = space.appexec([], """(): class Path: def __init__(self, _path): @@ -240,16 +240,6 @@ ]: assert hasattr(st, field) - def test_pickle(self): - import pickle, os - st = self.posix.stat(os.curdir) - # print(type(st).__module__) - s = pickle.dumps(st) - # print(repr(s)) - new = pickle.loads(s) - assert new == st - assert type(new) is type(st) - def test_open_exception(self): posix = self.posix try: @@ -326,15 +316,27 @@ ex(self.posix.dup, UNUSEDFD) def test_getcwd(self): - os, posix = self.os, self.posix + posix = self.posix + import sys + + # avoid importing stdlib os, copy fsencode instead + def fsencode(filename): + encoding = sys.getfilesystemencoding() + errors = sys.getfilesystemencodeerrors() + filename = posix.fspath(filename) # Does type-checking of `filename`. + if isinstance(filename, str): + return filename.encode(encoding, errors) + else: + return filename + assert isinstance(posix.getcwd(), str) cwdb = posix.getcwdb() - os.chdir(self.esurrogate_dir) + posix.chdir(self.esurrogate_dir) try: cwd = posix.getcwd() - assert os.fsencode(cwd) == posix.getcwdb() + assert fsencode(cwd) == posix.getcwdb() finally: - os.chdir(cwdb) + posix.chdir(cwdb) def test_getcwdb(self): assert isinstance(self.posix.getcwdb(), bytes) @@ -363,13 +365,27 @@ assert expected in result def test_listdir_memoryview_returns_unicode(self): + import sys # XXX unknown why CPython has this behaviour + + # avoid importing stdlib os, copy fsencode instead + def fsencode(filename): + encoding = sys.getfilesystemencoding() + errors = sys.getfilesystemencodeerrors() + filename = posix.fspath(filename) # Does type-checking of `filename`. + if isinstance(filename, str): + return filename.encode(encoding, errors) + else: + return filename + + bytes_dir = self.bytes_dir - os, posix = self.os, self.posix + posix = self.posix result1 = posix.listdir(bytes_dir) # -> list of bytes result2 = posix.listdir(memoryview(bytes_dir)) # -> list of unicodes - assert [os.fsencode(x) for x in result2] == result1 + assert [fsencode(x) for x in result2] == result1 + @py.test.mark.skipif("sys.platform == 'win32'") def test_fdlistdir(self): posix = self.posix dirfd = posix.open('.', posix.O_RDONLY) @@ -568,42 +584,24 @@ if hasattr(__import__(os.name), "spawnv"): def test_spawnv(self): os = self.posix + P_WAIT = 0 import sys print(self.python) - ret = os.spawnv(os.P_WAIT, self.python, + ret = os.spawnv(P_WAIT, self.python, ['python', '-c', 'raise(SystemExit(42))']) assert ret == 42 if hasattr(__import__(os.name), "spawnve"): def test_spawnve(self): os = self.posix - env = {'PATH':os.environ['PATH'], 'FOOBAR': '42'} - ret = os.spawnve(os.P_WAIT, self.python, + P_WAIT = 0 + env = {'PATH':self.env_path, 'FOOBAR': '42'} + ret = os.spawnve(P_WAIT, self.python, ['python', '-c', "raise(SystemExit(int(__import__('os').environ['FOOBAR'])))"], env) assert ret == 42 - def test_popen(self): - os = self.os - for i in range(5): - stream = os.popen('echo 1') - res = stream.read() - assert res == '1\n' - assert stream.close() is None - - def test_popen_with(self): - os = self.os - stream = os.popen('echo 1') - with stream as fp: - res = fp.read() - assert res == '1\n' - - if sys.platform == "win32": - # using startfile in app_startfile creates global state - test_popen.dont_track_allocations = True - test_popen_with.dont_track_allocations = True - if hasattr(__import__(os.name), '_getfullpathname'): def test__getfullpathname(self): # nt specific @@ -936,9 +934,9 @@ if hasattr(rposix, 'posix_fallocate'): def test_os_posix_posix_fallocate(self): - posix, os = self.posix, self.os + posix, self.posix import errno - fd = os.open(self.path2 + 'test_os_posix_fallocate', os.O_WRONLY | os.O_CREAT) + fd = posix.open(self.path2 + 'test_os_posix_fallocate', os.O_WRONLY | os.O_CREAT) try: ret = posix.posix_fallocate(fd, 0, 10) if ret == errno.EINVAL and not self.runappdirect: @@ -953,7 +951,7 @@ if inst.errno != errno.EINVAL or not sys.platform.startswith("sunos"): raise finally: - os.close(fd) + posix.close(fd) def test_largefile(self): @@ -975,7 +973,7 @@ if hasattr(rposix, 'getpriority'): def test_os_set_get_priority(self): - posix, os = self.posix, self.os + posix = os = self.posix childpid = os.fork() if childpid == 0: # in the child (avoids changing the priority of the parent @@ -1001,7 +999,7 @@ if hasattr(rposix, 'sched_get_priority_max'): def test_os_sched_get_priority_max(self): import sys - posix, os = self.posix, self.os + posix = self.posix assert posix.sched_get_priority_max(posix.SCHED_FIFO) != -1 assert posix.sched_get_priority_max(posix.SCHED_RR) != -1 assert posix.sched_get_priority_max(posix.SCHED_OTHER) != -1 @@ -1011,7 +1009,7 @@ if hasattr(rposix, 'sched_get_priority_min'): def test_os_sched_get_priority_min(self): import sys - posix, os = self.posix, self.os + posix = self.posix assert posix.sched_get_priority_min(posix.SCHED_FIFO) != -1 assert posix.sched_get_priority_min(posix.SCHED_RR) != -1 assert posix.sched_get_priority_min(posix.SCHED_OTHER) != -1 @@ -1020,7 +1018,7 @@ if hasattr(rposix, 'sched_get_priority_min'): def test_os_sched_priority_max_greater_than_min(self): - posix, os = self.posix, self.os + posix = self.posix policy = posix.SCHED_RR low = posix.sched_get_priority_min(policy) high = posix.sched_get_priority_max(policy) @@ -1301,9 +1299,10 @@ assert hasattr(os, 'kill') def test_pipe_flush(self): + import io ffd, gfd = self.posix.pipe() - f = self.os.fdopen(ffd, 'r') - g = self.os.fdopen(gfd, 'w') + f = io.open(ffd, 'r') + g = io.open(gfd, 'w') g.write('he') g.flush() x = f.read(1) @@ -1424,7 +1423,7 @@ s1.close() def test_os_lockf(self): - posix, os = self.posix, self.os + posix = os = self.posix fd = os.open(self.path2 + 'test_os_lockf', os.O_WRONLY | os.O_CREAT) try: os.write(fd, b'test') @@ -1503,7 +1502,7 @@ if os.name == 'nt': def test__getfileinformation(self): os = self.posix - path = os.path.join(self.pdir, 'file1') + path = '\\'.join([self.pdir, 'file1']) with open(path) as fp: info = self.posix._getfileinformation(fp.fileno()) assert len(info) == 3 @@ -1511,12 +1510,12 @@ def test__getfinalpathname(self): os = self.posix - path = os.path.join(self.pdir, 'file1') + path = '\\'.join([self.pdir, 'file1']) try: result = self.posix._getfinalpathname(path) except NotImplementedError: skip("_getfinalpathname not supported on this platform") - assert os.path.exists(result) + assert os.stat(result) is not None @py.test.mark.skipif("sys.platform == 'win32'") def test_rtld_constants(self): @@ -1606,8 +1605,7 @@ cls.w_path = space.wrap(str(path)) def test_environ(self): - import sys, os - environ = os.environ + environ = self.posix.environ if not environ: skip('environ not filled in for untranslated tests') for k, v in environ.items(): @@ -1620,7 +1618,8 @@ @py.test.mark.dont_track_allocations('putenv intentionally keeps strings alive') def test_environ_nonascii(self): - import sys, os + import sys + os = self.posix name, value = 'PYPY_TEST_日本', 'foobar日本' if not sys.platform == 'win32': fsencoding = sys.getfilesystemencoding() @@ -1633,10 +1632,8 @@ os.environ[name] = value assert os.environ[name] == value - assert os.getenv(name) == value del os.environ[name] assert os.environ.get(name) is None - assert os.getenv(name) is None if hasattr(__import__(os.name), "unsetenv"): def test_unsetenv_nonexisting(self): @@ -1680,9 +1677,10 @@ pass def test_open_unicode(self): + os = self.posix # Ensure passing unicode doesn't raise UnicodeEncodeError try: - self.posix.open(u"ą", os.O_WRONLY) + os.open(u"ą", os.O_WRONLY) except OSError: pass From pypy.commits at gmail.com Sun Feb 2 12:49:35 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Feb 2020 09:49:35 -0800 (PST) Subject: [pypy-commit] pypy py3.6: fix for path-as-memoryview on win32, avoid app-level code in _io.open Message-ID: <5e370baf.1c69fb81.b953.ed68@mx.google.com> Author: Matti Picus Branch: py3.6 Changeset: r98640:8fb4dc6f07e6 Date: 2020-02-02 15:56 +0200 http://bitbucket.org/pypy/pypy/changeset/8fb4dc6f07e6/ Log: fix for path-as-memoryview on win32, avoid app-level code in _io.open diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -8,12 +8,14 @@ interp_attrproperty_w) from pypy.module._codecs import interp_codecs from pypy.module._io.interp_iobase import W_IOBase, convert_size, trap_eintr +from pypy.module.posix.interp_posix import device_encoding from rpython.rlib.rarithmetic import intmask, r_uint, r_ulonglong from rpython.rlib.rbigint import rbigint from rpython.rlib.rstring import StringBuilder from rpython.rlib.rutf8 import (check_utf8, next_codepoint_pos, codepoints_in_utf8, codepoints_in_utf8, Utf8StringBuilder) +from rpython.rlib import rlocale STATE_ZERO, STATE_OK, STATE_DETACHED = range(3) @@ -235,7 +237,7 @@ if encoding is not None: return space.newtext(encoding) - # Try os.device_encoding(fileno) + # Try os.device_encoding(fileno) which is interp_posix.device_encoding try: w_fileno = space.call_method(w_buffer, 'fileno') except OperationError as e: @@ -244,11 +246,22 @@ e.match(space, space.fromcache(Cache).w_unsupportedoperation)): raise else: - w_os = space.call_method(space.builtin, '__import__', space.newtext('os')) - w_encoding = space.call_method(w_os, 'device_encoding', w_fileno) + w_encoding = device_encoding(space, space.int_w(w_fileno)) if space.isinstance_w(w_encoding, space.w_unicode): return w_encoding + # Try to shortcut the app-level call if locale.CODESET works + if _WINDOWS: + return space.newtext(rlocale.getdefaultlocale()[1]) + else: + if rlocale.HAVE_LANGINFO: + codeset = rlocale.nl_langinfo(rlocale.CODESET) + if codeset: + return space.newtext(codeset) + + + # On legacy systems or darwin, try app-level + # _bootlocale.getprefferedencoding(False) try: w_locale = space.call_method(space.builtin, '__import__', space.newtext('_bootlocale')) 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 @@ -51,6 +51,8 @@ def __init__(self, space, w_obj): self.space = space self.w_obj = w_obj + if space.isinstance_w(w_obj, space.w_memoryview): + self.is_unicode = False def as_bytes(self): return self.space.fsencode_w(self.w_obj) From pypy.commits at gmail.com Sun Feb 2 12:49:37 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Feb 2020 09:49:37 -0800 (PST) Subject: [pypy-commit] pypy py3.6: emit correct exception class Message-ID: <5e370bb1.1c69fb81.34e76.b633@mx.google.com> Author: Matti Picus Branch: py3.6 Changeset: r98641:c7efe1e62575 Date: 2020-01-31 12:02 +0200 http://bitbucket.org/pypy/pypy/changeset/c7efe1e62575/ Log: emit correct exception class diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py --- a/pypy/interpreter/error.py +++ b/pypy/interpreter/error.py @@ -649,6 +649,7 @@ w_errno = space.w_None w_winerror = space.newint(winerror) w_msg = space.newtext(msg, lgt) + w_exc = space.w_WindowsError else: errno = e.errno if errno == EINTR: From pypy.commits at gmail.com Sun Feb 2 12:49:38 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Feb 2020 09:49:38 -0800 (PST) Subject: [pypy-commit] pypy py3.6: fix typos, also posix.environ returns bytes Message-ID: <5e370bb2.1c69fb81.bb672.0966@mx.google.com> Author: Matti Picus Branch: py3.6 Changeset: r98642:4611cc30e74d Date: 2020-02-02 19:32 +0200 http://bitbucket.org/pypy/pypy/changeset/4611cc30e74d/ Log: fix typos, also posix.environ returns bytes 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 @@ -934,11 +934,11 @@ if hasattr(rposix, 'posix_fallocate'): def test_os_posix_posix_fallocate(self): - posix, self.posix + os = self.posix import errno - fd = posix.open(self.path2 + 'test_os_posix_fallocate', os.O_WRONLY | os.O_CREAT) + fd = os.open(self.path2 + 'test_os_posix_fallocate', os.O_WRONLY | os.O_CREAT) try: - ret = posix.posix_fallocate(fd, 0, 10) + ret = os.posix_fallocate(fd, 0, 10) if ret == errno.EINVAL and not self.runappdirect: # Does not work untranslated on a 32-bit chroot/docker pass @@ -951,7 +951,7 @@ if inst.errno != errno.EINVAL or not sys.platform.startswith("sunos"): raise finally: - posix.close(fd) + os.close(fd) def test_largefile(self): @@ -1602,6 +1602,7 @@ class AppTestEnvironment(object): def setup_class(cls): + cls.w_posix = space.appexec([], GET_POSIX) cls.w_path = space.wrap(str(path)) def test_environ(self): @@ -1609,8 +1610,8 @@ if not environ: skip('environ not filled in for untranslated tests') for k, v in environ.items(): - assert type(k) is str - assert type(v) is str + assert type(k) is bytes + assert type(v) is bytes name = next(iter(environ)) assert environ[name] is not None del environ[name] From pypy.commits at gmail.com Sun Feb 2 12:49:40 2020 From: pypy.commits at gmail.com (cfbolz) Date: Sun, 02 Feb 2020 09:49:40 -0800 (PST) Subject: [pypy-commit] pypy py3.6: make putenv complain about bad names (test already existed) Message-ID: <5e370bb4.1c69fb81.3aabf.c5f9@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: py3.6 Changeset: r98643:23ce279ad084 Date: 2020-01-31 23:29 +0100 http://bitbucket.org/pypy/pypy/changeset/23ce279ad084/ Log: make putenv complain about bad names (test already existed) (grafted from 89255ed57e9fa884c8bbeb50f19f2194b4fe698f) 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 @@ -943,9 +943,21 @@ def putenv(space, w_name, w_value): """Change or add an environment variable.""" try: - dispatch_filename_2(rposix.putenv)(space, w_name, w_value) + dispatch_filename_2(putenv_impl)(space, w_name, w_value) except OSError as e: raise wrap_oserror(space, e, eintr_retry=False) + except ValueError: + raise oefmt(space.w_ValueError, + "illegal environment variable name") + + @specialize.argtype(0, 1) + def putenv_impl(name, value): + from rpython.rlib.rposix import _as_bytes + name = _as_bytes(name) + value = _as_bytes(value) + if "=" in name: + raise ValueError + return rposix.putenv(name, value) def unsetenv(space, w_name): """Delete an environment variable.""" From pypy.commits at gmail.com Sun Feb 2 13:05:47 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Feb 2020 10:05:47 -0800 (PST) Subject: [pypy-commit] pypy default: backport part of 8fb4dc6f07e6 Message-ID: <5e370f7b.1c69fb81.faa77.d1e2@mx.google.com> Author: Matti Picus Branch: Changeset: r98644:0395c16d6bbe Date: 2020-02-02 19:54 +0200 http://bitbucket.org/pypy/pypy/changeset/0395c16d6bbe/ Log: backport part of 8fb4dc6f07e6 diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -14,6 +14,7 @@ from rpython.rlib.rutf8 import (check_utf8, next_codepoint_pos, codepoints_in_utf8, codepoints_in_utf8, Utf8StringBuilder) +from rpython.rlib import rlocale STATE_ZERO, STATE_OK, STATE_DETACHED = range(3) @@ -235,6 +236,15 @@ if encoding is not None: return space.newtext(encoding) + # Try to shortcut the app-level call if locale.CODESET works + if _WINDOWS: + return space.newtext(rlocale.getdefaultlocale()[1]) + else: + if rlocale.HAVE_LANGINFO: + codeset = rlocale.nl_langinfo(rlocale.CODESET) + if codeset: + return space.newtext(codeset) + try: w_locale = space.call_method(space.builtin, '__import__', space.newtext('locale')) From pypy.commits at gmail.com Sun Feb 2 15:41:26 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 02 Feb 2020 12:41:26 -0800 (PST) Subject: [pypy-commit] pypy py3.6: revert bogus code Message-ID: <5e3733f6.1c69fb81.c1dd8.240f@mx.google.com> Author: Matti Picus Branch: py3.6 Changeset: r98645:0ce9e1439a97 Date: 2020-02-02 22:40 +0200 http://bitbucket.org/pypy/pypy/changeset/0ce9e1439a97/ Log: revert bogus code 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 @@ -51,8 +51,6 @@ def __init__(self, space, w_obj): self.space = space self.w_obj = w_obj - if space.isinstance_w(w_obj, space.w_memoryview): - self.is_unicode = False def as_bytes(self): return self.space.fsencode_w(self.w_obj) From pypy.commits at gmail.com Mon Feb 3 12:00:09 2020 From: pypy.commits at gmail.com (cfbolz) Date: Mon, 03 Feb 2020 09:00:09 -0800 (PST) Subject: [pypy-commit] pypy py3.7: merge py3.6 Message-ID: <5e385199.1c69fb81.95024.8cb8@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: py3.7 Changeset: r98646:db4cbac378ec Date: 2020-02-03 14:01 +0100 http://bitbucket.org/pypy/pypy/changeset/db4cbac378ec/ Log: merge py3.6 diff --git a/extra_tests/test_posix.py b/extra_tests/test_posix.py new file mode 100644 --- /dev/null +++ b/extra_tests/test_posix.py @@ -0,0 +1,39 @@ +# Tests variant functions which also accept file descriptors, +# dir_fd and follow_symlinks. +def test_have_functions(): + import os + assert os.stat in os.supports_fd # fstat() is supported everywhere + if os.name != 'nt': + assert os.chdir in os.supports_fd # fchdir() + else: + assert os.chdir not in os.supports_fd + if os.name == 'posix': + assert os.open in os.supports_dir_fd # openat() + +def test_popen(): + import os + for i in range(5): + stream = os.popen('echo 1') + res = stream.read() + assert res == '1\n' + assert stream.close() is None + +def test_popen_with(): + import os + stream = os.popen('echo 1') + with stream as fp: + res = fp.read() + assert res == '1\n' + +def test_pickle(): + import pickle + import os + st = os.stat('.') + # print(type(st).__module__) + s = pickle.dumps(st) + # print(repr(s)) + new = pickle.loads(s) + assert new == st + assert type(new) is type(st) + + diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py --- a/pypy/interpreter/error.py +++ b/pypy/interpreter/error.py @@ -649,6 +649,7 @@ w_errno = space.w_None w_winerror = space.newint(winerror) w_msg = space.newtext(msg, lgt) + w_exc = space.w_WindowsError else: errno = e.errno if errno == EINTR: diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -8,12 +8,14 @@ interp_attrproperty_w) from pypy.module._codecs import interp_codecs from pypy.module._io.interp_iobase import W_IOBase, convert_size, trap_eintr +from pypy.module.posix.interp_posix import device_encoding from rpython.rlib.rarithmetic import intmask, r_uint, r_ulonglong from rpython.rlib.rbigint import rbigint from rpython.rlib.rstring import StringBuilder from rpython.rlib.rutf8 import (check_utf8, next_codepoint_pos, codepoints_in_utf8, codepoints_in_utf8, Utf8StringBuilder) +from rpython.rlib import rlocale STATE_ZERO, STATE_OK, STATE_DETACHED = range(3) @@ -235,7 +237,7 @@ if encoding is not None: return space.newtext(encoding) - # Try os.device_encoding(fileno) + # Try os.device_encoding(fileno) which is interp_posix.device_encoding try: w_fileno = space.call_method(w_buffer, 'fileno') except OperationError as e: @@ -244,11 +246,22 @@ e.match(space, space.fromcache(Cache).w_unsupportedoperation)): raise else: - w_os = space.call_method(space.builtin, '__import__', space.newtext('os')) - w_encoding = space.call_method(w_os, 'device_encoding', w_fileno) + w_encoding = device_encoding(space, space.int_w(w_fileno)) if space.isinstance_w(w_encoding, space.w_unicode): return w_encoding + # Try to shortcut the app-level call if locale.CODESET works + if _WINDOWS: + return space.newtext(rlocale.getdefaultlocale()[1]) + else: + if rlocale.HAVE_LANGINFO: + codeset = rlocale.nl_langinfo(rlocale.CODESET) + if codeset: + return space.newtext(codeset) + + + # On legacy systems or darwin, try app-level + # _bootlocale.getprefferedencoding(False) try: w_locale = space.call_method(space.builtin, '__import__', space.newtext('_bootlocale')) 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 @@ -140,6 +140,12 @@ self.as_unicode = unicode self.w_path = w_path + def __repr__(self): + # For debugging + return ''.join(['Path(', str(self.as_fd), ', ', str(self.as_bytes), + ', ', str(self.as_unicode), ', [', str(self.w_path), + ', ', str(getattr(self.w_path, '_length', 'bytes')), '])']) + @specialize.arg(2) def _unwrap_path(space, w_value, allow_fd=True): # equivalent of posixmodule.c:path_converter() in CPython 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 @@ -16,7 +16,7 @@ if os.name != 'nt': USEMODULES += ['fcntl', 'select', '_posixsubprocess', '_socket'] else: - USEMODULES += ['_rawffi', 'thread', 'signal', '_cffi_backend'] + USEMODULES += ['_rawffi', 'thread', '_cffi_backend'] def setup_module(mod): mod.space = gettestobjspace(usemodules=USEMODULES) @@ -65,7 +65,6 @@ space = cls.space cls.w_runappdirect = space.wrap(cls.runappdirect) cls.w_posix = space.appexec([], GET_POSIX) - cls.w_os = space.appexec([], "(): import os as m ; return m") cls.w_path = space.wrap(str(path)) cls.w_path2 = space.wrap(str(path2)) cls.w_path3 = space.wrap(str(path3)) @@ -100,6 +99,7 @@ cls.w_expected_major_12345 = space.wrap(os.major(12345)) cls.w_expected_minor_12345 = space.wrap(os.minor(12345)) cls.w_udir = space.wrap(str(udir)) + cls.w_env_path = space.wrap(os.environ['PATH']) cls.w_Path = space.appexec([], """(): class Path: def __init__(self, _path): @@ -240,16 +240,6 @@ ]: assert hasattr(st, field) - def test_pickle(self): - import pickle, os - st = self.posix.stat(os.curdir) - # print(type(st).__module__) - s = pickle.dumps(st) - # print(repr(s)) - new = pickle.loads(s) - assert new == st - assert type(new) is type(st) - def test_open_exception(self): posix = self.posix try: @@ -326,15 +316,27 @@ ex(self.posix.dup, UNUSEDFD) def test_getcwd(self): - os, posix = self.os, self.posix + posix = self.posix + import sys + + # avoid importing stdlib os, copy fsencode instead + def fsencode(filename): + encoding = sys.getfilesystemencoding() + errors = sys.getfilesystemencodeerrors() + filename = posix.fspath(filename) # Does type-checking of `filename`. + if isinstance(filename, str): + return filename.encode(encoding, errors) + else: + return filename + assert isinstance(posix.getcwd(), str) cwdb = posix.getcwdb() - os.chdir(self.esurrogate_dir) + posix.chdir(self.esurrogate_dir) try: cwd = posix.getcwd() - assert os.fsencode(cwd) == posix.getcwdb() + assert fsencode(cwd) == posix.getcwdb() finally: - os.chdir(cwdb) + posix.chdir(cwdb) def test_getcwdb(self): assert isinstance(self.posix.getcwdb(), bytes) @@ -363,13 +365,27 @@ assert expected in result def test_listdir_memoryview_returns_unicode(self): + import sys # XXX unknown why CPython has this behaviour + + # avoid importing stdlib os, copy fsencode instead + def fsencode(filename): + encoding = sys.getfilesystemencoding() + errors = sys.getfilesystemencodeerrors() + filename = posix.fspath(filename) # Does type-checking of `filename`. + if isinstance(filename, str): + return filename.encode(encoding, errors) + else: + return filename + + bytes_dir = self.bytes_dir - os, posix = self.os, self.posix + posix = self.posix result1 = posix.listdir(bytes_dir) # -> list of bytes result2 = posix.listdir(memoryview(bytes_dir)) # -> list of unicodes - assert [os.fsencode(x) for x in result2] == result1 + assert [fsencode(x) for x in result2] == result1 + @py.test.mark.skipif("sys.platform == 'win32'") def test_fdlistdir(self): posix = self.posix dirfd = posix.open('.', posix.O_RDONLY) @@ -568,42 +584,24 @@ if hasattr(__import__(os.name), "spawnv"): def test_spawnv(self): os = self.posix + P_WAIT = 0 import sys print(self.python) - ret = os.spawnv(os.P_WAIT, self.python, + ret = os.spawnv(P_WAIT, self.python, ['python', '-c', 'raise(SystemExit(42))']) assert ret == 42 if hasattr(__import__(os.name), "spawnve"): def test_spawnve(self): os = self.posix - env = {'PATH':os.environ['PATH'], 'FOOBAR': '42'} - ret = os.spawnve(os.P_WAIT, self.python, + P_WAIT = 0 + env = {'PATH':self.env_path, 'FOOBAR': '42'} + ret = os.spawnve(P_WAIT, self.python, ['python', '-c', "raise(SystemExit(int(__import__('os').environ['FOOBAR'])))"], env) assert ret == 42 - def test_popen(self): - os = self.os - for i in range(5): - stream = os.popen('echo 1') - res = stream.read() - assert res == '1\n' - assert stream.close() is None - - def test_popen_with(self): - os = self.os - stream = os.popen('echo 1') - with stream as fp: - res = fp.read() - assert res == '1\n' - - if sys.platform == "win32": - # using startfile in app_startfile creates global state - test_popen.dont_track_allocations = True - test_popen_with.dont_track_allocations = True - if hasattr(__import__(os.name), '_getfullpathname'): def test__getfullpathname(self): # nt specific @@ -936,11 +934,11 @@ if hasattr(rposix, 'posix_fallocate'): def test_os_posix_posix_fallocate(self): - posix, os = self.posix, self.os + os = self.posix import errno fd = os.open(self.path2 + 'test_os_posix_fallocate', os.O_WRONLY | os.O_CREAT) try: - ret = posix.posix_fallocate(fd, 0, 10) + ret = os.posix_fallocate(fd, 0, 10) if ret == errno.EINVAL and not self.runappdirect: # Does not work untranslated on a 32-bit chroot/docker pass @@ -975,7 +973,7 @@ if hasattr(rposix, 'getpriority'): def test_os_set_get_priority(self): - posix, os = self.posix, self.os + posix = os = self.posix childpid = os.fork() if childpid == 0: # in the child (avoids changing the priority of the parent @@ -1001,7 +999,7 @@ if hasattr(rposix, 'sched_get_priority_max'): def test_os_sched_get_priority_max(self): import sys - posix, os = self.posix, self.os + posix = self.posix assert posix.sched_get_priority_max(posix.SCHED_FIFO) != -1 assert posix.sched_get_priority_max(posix.SCHED_RR) != -1 assert posix.sched_get_priority_max(posix.SCHED_OTHER) != -1 @@ -1011,7 +1009,7 @@ if hasattr(rposix, 'sched_get_priority_min'): def test_os_sched_get_priority_min(self): import sys - posix, os = self.posix, self.os + posix = self.posix assert posix.sched_get_priority_min(posix.SCHED_FIFO) != -1 assert posix.sched_get_priority_min(posix.SCHED_RR) != -1 assert posix.sched_get_priority_min(posix.SCHED_OTHER) != -1 @@ -1020,7 +1018,7 @@ if hasattr(rposix, 'sched_get_priority_min'): def test_os_sched_priority_max_greater_than_min(self): - posix, os = self.posix, self.os + posix = self.posix policy = posix.SCHED_RR low = posix.sched_get_priority_min(policy) high = posix.sched_get_priority_max(policy) @@ -1301,9 +1299,10 @@ assert hasattr(os, 'kill') def test_pipe_flush(self): + import io ffd, gfd = self.posix.pipe() - f = self.os.fdopen(ffd, 'r') - g = self.os.fdopen(gfd, 'w') + f = io.open(ffd, 'r') + g = io.open(gfd, 'w') g.write('he') g.flush() x = f.read(1) @@ -1424,7 +1423,7 @@ s1.close() def test_os_lockf(self): - posix, os = self.posix, self.os + posix = os = self.posix fd = os.open(self.path2 + 'test_os_lockf', os.O_WRONLY | os.O_CREAT) try: os.write(fd, b'test') @@ -1502,21 +1501,21 @@ if os.name == 'nt': def test__getfileinformation(self): - import os - path = os.path.join(self.pdir, 'file1') + os = self.posix + path = '\\'.join([self.pdir, 'file1']) with open(path) as fp: info = self.posix._getfileinformation(fp.fileno()) assert len(info) == 3 assert all(isinstance(obj, int) for obj in info) def test__getfinalpathname(self): - import os - path = os.path.join(self.pdir, 'file1') + os = self.posix + path = '\\'.join([self.pdir, 'file1']) try: result = self.posix._getfinalpathname(path) except NotImplementedError: skip("_getfinalpathname not supported on this platform") - assert os.path.exists(result) + assert os.stat(result) is not None @py.test.mark.skipif("sys.platform == 'win32'") def test_rtld_constants(self): @@ -1603,16 +1602,16 @@ class AppTestEnvironment(object): def setup_class(cls): + cls.w_posix = space.appexec([], GET_POSIX) cls.w_path = space.wrap(str(path)) def test_environ(self): - import sys, os - environ = os.environ + environ = self.posix.environ if not environ: skip('environ not filled in for untranslated tests') for k, v in environ.items(): - assert type(k) is str - assert type(v) is str + assert type(k) is bytes + assert type(v) is bytes name = next(iter(environ)) assert environ[name] is not None del environ[name] @@ -1620,7 +1619,8 @@ @py.test.mark.dont_track_allocations('putenv intentionally keeps strings alive') def test_environ_nonascii(self): - import sys, os + import sys + os = self.posix name, value = 'PYPY_TEST_日本', 'foobar日本' if not sys.platform == 'win32': fsencoding = sys.getfilesystemencoding() @@ -1633,10 +1633,8 @@ os.environ[name] = value assert os.environ[name] == value - assert os.getenv(name) == value del os.environ[name] assert os.environ.get(name) is None - assert os.getenv(name) is None if hasattr(__import__(os.name), "unsetenv"): def test_unsetenv_nonexisting(self): @@ -1669,17 +1667,19 @@ @py.test.mark.usefixtures('check_fsencoding') class AppTestPosixUnicode: + def setup_class(cls): + cls.w_posix = space.appexec([], GET_POSIX) + def test_stat_unicode(self): # test that passing unicode would not raise UnicodeDecodeError - import os try: - os.stat(u"ą") + self.posix.stat(u"ą") except OSError: pass def test_open_unicode(self): + os = self.posix # Ensure passing unicode doesn't raise UnicodeEncodeError - import os try: os.open(u"ą", os.O_WRONLY) except OSError: @@ -1687,9 +1687,8 @@ def test_remove_unicode(self): # See 2 above ;) - import os try: - os.remove(u"ą") + self.posix.remove(u"ą") except OSError: pass @@ -1717,20 +1716,6 @@ assert content == b"test" -class AppTestFdVariants: - # Tests variant functions which also accept file descriptors, - # dir_fd and follow_symlinks. - def test_have_functions(self): - import os - assert os.stat in os.supports_fd # fstat() is supported everywhere - if os.name != 'nt': - assert os.chdir in os.supports_fd # fchdir() - else: - assert os.chdir not in os.supports_fd - if os.name == 'posix': - assert os.open in os.supports_dir_fd # openat() - - class AppTestPep475Retry: spaceconfig = {'usemodules': USEMODULES} From pypy.commits at gmail.com Mon Feb 3 12:00:12 2020 From: pypy.commits at gmail.com (cfbolz) Date: Mon, 03 Feb 2020 09:00:12 -0800 (PST) Subject: [pypy-commit] pypy py3.7: the weird behaviour was fixed in 3.7 Message-ID: <5e38519c.1c69fb81.5dfa.2cb1@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: py3.7 Changeset: r98647:784f031646b7 Date: 2020-02-03 14:43 +0100 http://bitbucket.org/pypy/pypy/changeset/784f031646b7/ Log: the weird behaviour was fixed in 3.7 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 @@ -982,15 +982,21 @@ If this functionality is unavailable, using it raises NotImplementedError.""" if space.is_none(w_path): w_path = space.newtext(".") - if space.isinstance_w(w_path, space.w_bytes): - # XXX CPython doesn't follow this path either if w_path is, - # for example, a memoryview or another buffer type - dirname = space.bytes0_w(w_path) + try: + dirname = space.bytesbuf0_w(w_path) + except OperationError as e: + if not e.match(space, space.w_TypeError): + raise + else: + if not space.isinstance_w(w_path, space.w_bytes): + # use fsencode to get the correct warning + space.fsencode_w(w_path) try: result = rposix.listdir(dirname) except OSError as e: raise wrap_oserror2(space, e, w_path, eintr_retry=False) return space.newlist_bytes(result) + try: path = space.fsencode_w(w_path) except OperationError as operr: 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 @@ -364,26 +364,13 @@ expected = b'caf%E9' if sys.platform == 'darwin' else b'caf\xe9' assert expected in result - def test_listdir_memoryview_returns_unicode(self): + def test_listdir_memoryview_returns_bytes(self): import sys - # XXX unknown why CPython has this behaviour - - # avoid importing stdlib os, copy fsencode instead - def fsencode(filename): - encoding = sys.getfilesystemencoding() - errors = sys.getfilesystemencodeerrors() - filename = posix.fspath(filename) # Does type-checking of `filename`. - if isinstance(filename, str): - return filename.encode(encoding, errors) - else: - return filename - - bytes_dir = self.bytes_dir posix = self.posix result1 = posix.listdir(bytes_dir) # -> list of bytes - result2 = posix.listdir(memoryview(bytes_dir)) # -> list of unicodes - assert [fsencode(x) for x in result2] == result1 + result2 = posix.listdir(memoryview(bytes_dir)) # -> list of bytes + assert result2 == result1 @py.test.mark.skipif("sys.platform == 'win32'") def test_fdlistdir(self): From pypy.commits at gmail.com Mon Feb 3 15:11:25 2020 From: pypy.commits at gmail.com (mattip) Date: Mon, 03 Feb 2020 12:11:25 -0800 (PST) Subject: [pypy-commit] pypy default: cleanup missing import; skip leak tests on win32 Message-ID: <5e387e6d.1c69fb81.b16e7.0989@mx.google.com> Author: Matti Picus Branch: Changeset: r98648:42e62fffae16 Date: 2020-02-03 10:02 +0200 http://bitbucket.org/pypy/pypy/changeset/42e62fffae16/ Log: cleanup missing import; skip leak tests on win32 diff --git a/pypy/module/_multiprocessing/test/test_connection.py b/pypy/module/_multiprocessing/test/test_connection.py --- a/pypy/module/_multiprocessing/test/test_connection.py +++ b/pypy/module/_multiprocessing/test/test_connection.py @@ -38,6 +38,9 @@ assert isinstance(e, multiprocessing.ProcessError) assert e.args == ("data",) + if sys.platform == "win32": + test_exception.dont_track_allocations = True + class BaseConnectionTest(object): def test_connection(self): import sys @@ -54,6 +57,9 @@ obj2 = rhandle.recv() assert obj == obj2 + if sys.platform == "win32": + test_connection.dont_track_allocations = True + def test_poll(self): import sys # if not translated, for win32 diff --git a/pypy/module/_multiprocessing/test/test_interp_semaphore.py b/pypy/module/_multiprocessing/test/test_interp_semaphore.py --- a/pypy/module/_multiprocessing/test/test_interp_semaphore.py +++ b/pypy/module/_multiprocessing/test/test_interp_semaphore.py @@ -6,7 +6,8 @@ from pypy.module.thread.os_lock import allocate_lock from pypy.module.thread.os_thread import start_new_thread from pypy.module._multiprocessing.interp_semaphore import ( - create_semaphore, sem_unlink, W_SemLock) + create_semaphore, W_SemLock) + @pytest.mark.parametrize('spaceconfig', [ {'usemodules': ['_multiprocessing', 'thread']}]) diff --git a/pypy/module/_multiprocessing/test/test_memory.py b/pypy/module/_multiprocessing/test/test_memory.py --- a/pypy/module/_multiprocessing/test/test_memory.py +++ b/pypy/module/_multiprocessing/test/test_memory.py @@ -15,6 +15,9 @@ raises(TypeError, _multiprocessing.address_of_buffer, None) raises(TypeError, _multiprocessing.address_of_buffer, "a") + if sys.platform == "win32": + test_address_of.dont_track_allocations = True + def test_mmap_address(self): import mmap import _multiprocessing From pypy.commits at gmail.com Mon Feb 3 15:11:26 2020 From: pypy.commits at gmail.com (mattip) Date: Mon, 03 Feb 2020 12:11:26 -0800 (PST) Subject: [pypy-commit] pypy default: remove failing test: cpython2 does not raise either Message-ID: <5e387e6e.1c69fb81.af2b6.204d@mx.google.com> Author: Matti Picus Branch: Changeset: r98649:933fe8bcc07b Date: 2020-02-03 10:03 +0200 http://bitbucket.org/pypy/pypy/changeset/933fe8bcc07b/ Log: remove failing test: cpython2 does not raise either diff --git a/pypy/module/_multiprocessing/test/test_win32.py b/pypy/module/_multiprocessing/test/test_win32.py --- a/pypy/module/_multiprocessing/test/test_win32.py +++ b/pypy/module/_multiprocessing/test/test_win32.py @@ -9,10 +9,6 @@ if sys.platform != "win32": py.test.skip("win32 only") - def test_CloseHandle(self): - from _multiprocessing import win32 - raises(WindowsError, win32.CloseHandle, -1) - def test_CreateFile(self): from _multiprocessing import win32 err = raises(WindowsError, win32.CreateFile, From pypy.commits at gmail.com Mon Feb 3 15:11:28 2020 From: pypy.commits at gmail.com (mattip) Date: Mon, 03 Feb 2020 12:11:28 -0800 (PST) Subject: [pypy-commit] pypy py3.6: save one call to fsencode, fix win32 memoryview fail Message-ID: <5e387e70.1c69fb81.bcbb9.f579@mx.google.com> Author: Matti Picus Branch: py3.6 Changeset: r98650:ed2655152694 Date: 2020-02-03 21:24 +0200 http://bitbucket.org/pypy/pypy/changeset/ed2655152694/ Log: save one call to fsencode, fix win32 memoryview fail 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 @@ -1005,9 +1005,8 @@ except OSError as e: raise wrap_oserror(space, e, eintr_retry=False) else: - dirname = FileEncoder(space, w_path) try: - result = rposix.listdir(dirname) + result = rposix.listdir(path) except OSError as e: raise wrap_oserror2(space, e, w_path, eintr_retry=False) len_result = len(result) From pypy.commits at gmail.com Mon Feb 3 15:11:30 2020 From: pypy.commits at gmail.com (mattip) Date: Mon, 03 Feb 2020 12:11:30 -0800 (PST) Subject: [pypy-commit] pypy py3.6: merge default into py3.6 Message-ID: <5e387e72.1c69fb81.55ba9.38b1@mx.google.com> Author: Matti Picus Branch: py3.6 Changeset: r98651:b0ffc7814382 Date: 2020-02-03 21:47 +0200 http://bitbucket.org/pypy/pypy/changeset/b0ffc7814382/ Log: merge default into py3.6 diff --git a/pypy/interpreter/test/test_error.py b/pypy/interpreter/test/test_error.py --- a/pypy/interpreter/test/test_error.py +++ b/pypy/interpreter/test/test_error.py @@ -146,8 +146,8 @@ [os.strerror(errno.EBADF)], None) # e = wrap_oserror(space, OSError(errno.EBADF, "foobar"), - filename = "test.py", - exception_name = "w_EnvironmentError") + filename="test.py", + w_exception_class=space.w_EnvironmentError) assert isinstance(e, OperationError) assert e.w_type == [EnvironmentError] assert e.get_w_value(space) == ([EnvironmentError], [errno.EBADF], @@ -155,8 +155,8 @@ ["test.py"]) # e = wrap_oserror(space, OSError(errno.EBADF, "foobar"), - filename = "test.py", - w_exception_class = [SystemError]) + filename="test.py", + w_exception_class=[SystemError]) assert isinstance(e, OperationError) assert e.w_type == [SystemError] assert e.get_w_value(space) == ([SystemError], [errno.EBADF], diff --git a/pypy/module/_io/interp_stringio.py b/pypy/module/_io/interp_stringio.py --- a/pypy/module/_io/interp_stringio.py +++ b/pypy/module/_io/interp_stringio.py @@ -9,19 +9,13 @@ from pypy.module._io.interp_iobase import convert_size class UnicodeIO(object): - def __init__(self, data=None, pos=0): + def __init__(self, data=None): if data is None: data = '' self.data = [] self.pos = 0 - # break the data into unicode codepoints - _pos = 0 - while _pos < pos: - _pos = next_codepoint_pos(data, _pos) - if _pos >= len(data): - break - self.write(data[_pos:]) - self.pos = pos + self.write(data) + self.pos = 0 def resize(self, newlength): if len(self.data) > newlength: diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -237,6 +237,15 @@ if encoding is not None: return space.newtext(encoding) + # Try to shortcut the app-level call if locale.CODESET works + if _WINDOWS: + return space.newtext(rlocale.getdefaultlocale()[1]) + else: + if rlocale.HAVE_LANGINFO: + codeset = rlocale.nl_langinfo(rlocale.CODESET) + if codeset: + return space.newtext(codeset) + # Try os.device_encoding(fileno) which is interp_posix.device_encoding try: w_fileno = space.call_method(w_buffer, 'fileno') diff --git a/pypy/module/_multiprocessing/test/test_interp_semaphore.py b/pypy/module/_multiprocessing/test/test_interp_semaphore.py --- a/pypy/module/_multiprocessing/test/test_interp_semaphore.py +++ b/pypy/module/_multiprocessing/test/test_interp_semaphore.py @@ -6,7 +6,8 @@ from pypy.module.thread.os_lock import _set_sentinel from pypy.module.thread.os_thread import start_new_thread from pypy.module._multiprocessing.interp_semaphore import ( - create_semaphore, sem_unlink, W_SemLock) + create_semaphore, W_SemLock) + @pytest.mark.parametrize('spaceconfig', [ {'usemodules': ['_multiprocessing', 'thread']}]) 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 @@ -26,6 +26,7 @@ mod.path3 = udir.join('unlinktestfile.txt') mod.path3.write("delete me!") pdir = udir.ensure('posixtestdir', dir=True) + pdir = udir.ensure('posixtestdir', dir=True) pdir.join('file1').write("test1") os.chmod(str(pdir.join('file1')), 0o600) pdir.join('file2').write("test2") @@ -444,7 +445,6 @@ assert isinstance(result.children_user, float) assert isinstance(result.children_system, float) assert isinstance(result.elapsed, float) - def test_strerror(self): assert isinstance(self.posix.strerror(0), str) assert isinstance(self.posix.strerror(1), str) @@ -545,7 +545,8 @@ os.execv("/bin/sh", ["sh", "-c", "echo caf\xe9 \u1234 > onefile"]) os.waitpid(pid, 0) - assert open("onefile", "rb").read() == output + with open("onefile", "rb") as fid: + asert fid.read() == output os.unlink("onefile") def test_execve(self): @@ -577,7 +578,8 @@ "echo caf\xe9 \u1234 $t > onefile"], {'ddd': 'xxx', 't': t}) os.waitpid(pid, 0) - assert open("onefile", "rb").read() == output + b'\n' + with open("onefile") as fid: + assert fid.read() == output os.unlink("onefile") pass # <- please, inspect.getsource(), don't crash @@ -606,11 +608,10 @@ def test__getfullpathname(self): # nt specific posix = self.posix - import os - sysdrv = os.getenv("SystemDrive", "C:") + sysdrv = posix.environ.get("SystemDrive", "C:") # just see if it does anything path = sysdrv + 'hubber' - assert os.sep in posix._getfullpathname(path) + assert '\\' in posix._getfullpathname(path) assert type(posix._getfullpathname(b'C:')) is bytes def test_utime(self): @@ -877,17 +878,15 @@ localdir = os.getcwd() os.mkdir(self.path2 + 'fchdir') for func in [os.fchdir, os.chdir]: + fd = os.open(self.path2 + 'fchdir', os.O_RDONLY) try: - fd = os.open(self.path2 + 'fchdir', os.O_RDONLY) - try: - func(fd) - mypath = os.getcwd() - finally: - os.close(fd) - assert mypath.endswith('test_posix2-fchdir') - raises(OSError, func, fd) + func(fd) + mypath = os.getcwd() finally: + os.close(fd) os.chdir(localdir) + assert mypath.endswith('test_posix2-fchdir') + raises(OSError, func, fd) raises(ValueError, os.fchdir, -1) if hasattr(rposix, 'pread'): @@ -1295,7 +1294,7 @@ # working? def test_has_kill(self): - import os + os = self.posix assert hasattr(os, 'kill') def test_pipe_flush(self): @@ -1604,6 +1603,7 @@ def setup_class(cls): cls.w_posix = space.appexec([], GET_POSIX) cls.w_path = space.wrap(str(path)) + cls.w_posix = space.appexec([], GET_POSIX) def test_environ(self): environ = self.posix.environ @@ -1638,7 +1638,7 @@ if hasattr(__import__(os.name), "unsetenv"): def test_unsetenv_nonexisting(self): - import os + os = self.posix os.unsetenv("XYZABC") #does not raise try: os.environ["ABCABC"] diff --git a/pypy/module/select/interp_select.py b/pypy/module/select/interp_select.py --- a/pypy/module/select/interp_select.py +++ b/pypy/module/select/interp_select.py @@ -50,7 +50,7 @@ fd = space.c_filedescriptor_w(w_fd) if fd not in self.fddict: raise wrap_oserror(space, OSError(errno.ENOENT, "poll.modify"), - exception_name='w_IOError') + w_exception_class=space.w_IOError) self.fddict[fd] = events def unregister(self, space, w_fd): From pypy.commits at gmail.com Mon Feb 3 15:11:31 2020 From: pypy.commits at gmail.com (mattip) Date: Mon, 03 Feb 2020 12:11:31 -0800 (PST) Subject: [pypy-commit] pypy py3.6: fix merge Message-ID: <5e387e73.1c69fb81.3356b.8642@mx.google.com> Author: Matti Picus Branch: py3.6 Changeset: r98652:2311bec2bb7f Date: 2020-02-03 21:53 +0200 http://bitbucket.org/pypy/pypy/changeset/2311bec2bb7f/ Log: fix merge 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 @@ -546,7 +546,7 @@ "echo caf\xe9 \u1234 > onefile"]) os.waitpid(pid, 0) with open("onefile", "rb") as fid: - asert fid.read() == output + assert fid.read() == output os.unlink("onefile") def test_execve(self): From pypy.commits at gmail.com Mon Feb 3 15:11:33 2020 From: pypy.commits at gmail.com (mattip) Date: Mon, 03 Feb 2020 12:11:33 -0800 (PST) Subject: [pypy-commit] pypy py3.6: refactor wrap_oserror: remove exception_name Message-ID: <5e387e75.1c69fb81.3a08d.7c3a@mx.google.com> Author: Matti Picus Branch: py3.6 Changeset: r98653:f2a9f4b83a5a Date: 2020-02-03 22:04 +0200 http://bitbucket.org/pypy/pypy/changeset/f2a9f4b83a5a/ Log: refactor wrap_oserror: remove exception_name diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py --- a/pypy/interpreter/error.py +++ b/pypy/interpreter/error.py @@ -606,8 +606,8 @@ ansi_print(text, esc="31", file=file, newline=newline) @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): +def wrap_oserror2(space, e, w_filename=None, w_exception_class=None, + w_filename2=None, eintr_retry=False): """A double API here: * if eintr_retry is False, always return the OperationError to @@ -623,7 +623,7 @@ assert isinstance(e, OSError) if w_exception_class is None: - w_exc = getattr(space, exception_name) + w_exc = space.w_OSError else: w_exc = w_exception_class operror = _wrap_oserror2_impl(space, e, w_filename, w_filename2, w_exc, @@ -679,8 +679,8 @@ @specialize.arg(3, 6) @dont_inline -def wrap_oserror(space, e, filename=None, exception_name='w_OSError', - w_exception_class=None, filename2=None, eintr_retry=False): +def wrap_oserror(space, e, filename=None, w_exception_class=None, + filename2=None, eintr_retry=False): w_filename = None w_filename2 = None if filename is not None: @@ -688,7 +688,6 @@ if filename2 is not None: w_filename2 = space.newfilename(filename2) return wrap_oserror2(space, e, w_filename, - exception_name=exception_name, w_exception_class=w_exception_class, w_filename2=w_filename2, eintr_retry=eintr_retry) diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py --- a/pypy/module/_io/interp_fileio.py +++ b/pypy/module/_io/interp_fileio.py @@ -195,7 +195,7 @@ break except OSError as e: wrap_oserror2(space, e, w_name, - exception_name='w_IOError', + w_exception_class=space.w_IOError, eintr_retry=True) try: _open_inhcache.set_non_inheritable(self.fd) @@ -235,7 +235,7 @@ # directories, so we need a check. if stat.S_ISDIR(st.st_mode): raise wrap_oserror2(space, OSError(errno.EISDIR, "fstat"), - w_name, exception_name='w_IOError', + w_name, w_exception_class=space.w_IOError, eintr_retry=False) self.blksize = DEFAULT_BUFFER_SIZE if HAS_BLKSIZE and st.st_blksize > 1: @@ -251,7 +251,7 @@ try: os.lseek(self.fd, 0, os.SEEK_END) except OSError as e: - raise wrap_oserror(space, e, exception_name='w_IOError', + raise wrap_oserror(space, e, w_exception_class=space.w_IOError, eintr_retry=False) except: if not fd_is_own: @@ -311,7 +311,7 @@ os.close(fd) except OSError as e: raise wrap_oserror(space, e, - exception_name='w_IOError', + w_exception_class=space.w_IOError, eintr_retry=False) def close_w(self, space): @@ -346,7 +346,7 @@ pos = os.lseek(self.fd, pos, whence) except OSError as e: raise wrap_oserror(space, e, - exception_name='w_IOError', + w_exception_class=space.w_IOError, eintr_retry=False) return space.newint(pos) @@ -356,7 +356,7 @@ pos = os.lseek(self.fd, 0, 1) except OSError as e: raise wrap_oserror(space, e, - exception_name='w_IOError', + w_exception_class=space.w_IOError, eintr_retry=False) return space.newint(pos) @@ -390,7 +390,7 @@ try: res = os.isatty(self.fd) except OSError as e: - raise wrap_oserror(space, e, exception_name='w_IOError', + raise wrap_oserror(space, e, w_exception_class=space.w_IOError, eintr_retry=False) return space.newbool(res) @@ -425,7 +425,7 @@ if e.errno == errno.EAGAIN: return space.w_None wrap_oserror(space, e, - exception_name='w_IOError', + w_exception_class=space.w_IOError, eintr_retry=True) return space.newint(n) @@ -446,7 +446,7 @@ if e.errno == errno.EAGAIN: return space.w_None wrap_oserror(space, e, - exception_name='w_IOError', + w_exception_class=space.w_IOError, eintr_retry=True) return space.newbytes(s) @@ -473,7 +473,7 @@ except OSError as e: if e.errno == errno.EAGAIN: return space.w_None - wrap_oserror(space, e, exception_name='w_IOError', + wrap_oserror(space, e, w_exception_class=space.w_IOError, eintr_retry=True) self.output_slice(space, rwbuffer, 0, buf) return space.newint(len(buf)) @@ -491,7 +491,7 @@ if err == errno.EAGAIN: return space.w_None e = OSError(err, "read failed") - wrap_oserror(space, e, exception_name='w_IOError', + wrap_oserror(space, e, w_exception_class=space.w_IOError, eintr_retry=True) def readall_w(self, space): @@ -510,7 +510,7 @@ if total > 0: break # return what we've got so far return space.w_None - wrap_oserror(space, e, exception_name='w_IOError', + wrap_oserror(space, e, w_exception_class=space.w_IOError, eintr_retry=True) continue if not chunk: @@ -536,7 +536,7 @@ try: self._truncate(space.r_longlong_w(w_size)) except OSError as e: - raise wrap_oserror(space, e, exception_name='w_IOError', + raise wrap_oserror(space, e, w_exception_class=space.w_IOError, eintr_retry=False) return w_size diff --git a/pypy/module/fcntl/interp_fcntl.py b/pypy/module/fcntl/interp_fcntl.py --- a/pypy/module/fcntl/interp_fcntl.py +++ b/pypy/module/fcntl/interp_fcntl.py @@ -82,13 +82,13 @@ # when appropriate errno = rposix.get_saved_errno() wrap_oserror(space, OSError(errno, funcname), - exception_name = 'w_IOError', eintr_retry=True) + w_exception_class=space.w_IOError, eintr_retry=True) def _raise_error_always(space, funcname): # this variant never returns normally, and doesn't retry if it gets EINTR. errno = rposix.get_saved_errno() raise wrap_oserror(space, OSError(errno, funcname), - exception_name = 'w_IOError', eintr_retry=False) + w_exception_class=space.w_IOError, eintr_retry=False) @unwrap_spec(op=int, w_arg=WrappedDefault(0)) def fcntl(space, w_fd, op, w_arg): From pypy.commits at gmail.com Mon Feb 3 16:32:51 2020 From: pypy.commits at gmail.com (mattip) Date: Mon, 03 Feb 2020 13:32:51 -0800 (PST) Subject: [pypy-commit] pypy default: back out 0395c16d6bbe, it did not improve benchmarks Message-ID: <5e389183.1c69fb81.5ecb3.0afd@mx.google.com> Author: Matti Picus Branch: Changeset: r98655:9dce88120ef6 Date: 2020-02-03 23:30 +0200 http://bitbucket.org/pypy/pypy/changeset/9dce88120ef6/ Log: back out 0395c16d6bbe, it did not improve benchmarks diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -14,7 +14,6 @@ from rpython.rlib.rutf8 import (check_utf8, next_codepoint_pos, codepoints_in_utf8, codepoints_in_utf8, Utf8StringBuilder) -from rpython.rlib import rlocale STATE_ZERO, STATE_OK, STATE_DETACHED = range(3) @@ -236,15 +235,6 @@ if encoding is not None: return space.newtext(encoding) - # Try to shortcut the app-level call if locale.CODESET works - if _WINDOWS: - return space.newtext(rlocale.getdefaultlocale()[1]) - else: - if rlocale.HAVE_LANGINFO: - codeset = rlocale.nl_langinfo(rlocale.CODESET) - if codeset: - return space.newtext(codeset) - try: w_locale = space.call_method(space.builtin, '__import__', space.newtext('locale')) From pypy.commits at gmail.com Mon Feb 3 16:50:02 2020 From: pypy.commits at gmail.com (mattip) Date: Mon, 03 Feb 2020 13:50:02 -0800 (PST) Subject: [pypy-commit] pypy py3.6: remove (duplicate) equivalent of 0395c16d6bbe Message-ID: <5e38958a.1c69fb81.12081.3bc9@mx.google.com> Author: Matti Picus Branch: py3.6 Changeset: r98656:0b996481653b Date: 2020-02-03 23:40 +0200 http://bitbucket.org/pypy/pypy/changeset/0b996481653b/ Log: remove (duplicate) equivalent of 0395c16d6bbe diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -237,15 +237,6 @@ if encoding is not None: return space.newtext(encoding) - # Try to shortcut the app-level call if locale.CODESET works - if _WINDOWS: - return space.newtext(rlocale.getdefaultlocale()[1]) - else: - if rlocale.HAVE_LANGINFO: - codeset = rlocale.nl_langinfo(rlocale.CODESET) - if codeset: - return space.newtext(codeset) - # Try os.device_encoding(fileno) which is interp_posix.device_encoding try: w_fileno = space.call_method(w_buffer, 'fileno') @@ -259,16 +250,6 @@ if space.isinstance_w(w_encoding, space.w_unicode): return w_encoding - # Try to shortcut the app-level call if locale.CODESET works - if _WINDOWS: - return space.newtext(rlocale.getdefaultlocale()[1]) - else: - if rlocale.HAVE_LANGINFO: - codeset = rlocale.nl_langinfo(rlocale.CODESET) - if codeset: - return space.newtext(codeset) - - # On legacy systems or darwin, try app-level # _bootlocale.getprefferedencoding(False) try: From pypy.commits at gmail.com Mon Feb 3 16:50:04 2020 From: pypy.commits at gmail.com (mattip) Date: Mon, 03 Feb 2020 13:50:04 -0800 (PST) Subject: [pypy-commit] pypy py3.6: merge default into py3.6 Message-ID: <5e38958c.1c69fb81.f990c.74a7@mx.google.com> Author: Matti Picus Branch: py3.6 Changeset: r98657:cf58c311679b Date: 2020-02-03 23:45 +0200 http://bitbucket.org/pypy/pypy/changeset/cf58c311679b/ Log: merge default into py3.6 From pypy.commits at gmail.com Mon Feb 3 21:26:06 2020 From: pypy.commits at gmail.com (rlamy) Date: Mon, 03 Feb 2020 18:26:06 -0800 (PST) Subject: [pypy-commit] pypy StringIO-perf: Add explicit state attribute to W_StringIO Message-ID: <5e38d63e.1c69fb81.23bc7.75be@mx.google.com> Author: Ronan Lamy Branch: StringIO-perf Changeset: r98658:4fa767ded1af Date: 2020-02-02 16:18 +0000 http://bitbucket.org/pypy/pypy/changeset/4fa767ded1af/ Log: Add explicit state attribute to W_StringIO diff --git a/pypy/module/_io/interp_stringio.py b/pypy/module/_io/interp_stringio.py --- a/pypy/module/_io/interp_stringio.py +++ b/pypy/module/_io/interp_stringio.py @@ -106,11 +106,14 @@ def getvalue(self): return u''.join(self.data).encode('utf-8') +INITIAL, CLOSED = range(2) + class W_StringIO(W_TextIOBase): def __init__(self, space): W_TextIOBase.__init__(self, space) self.buf = UnicodeIO() + self.state = INITIAL @unwrap_spec(w_newline=WrappedDefault("\n")) def descr_init(self, space, w_initvalue=None, w_newline=None): @@ -202,7 +205,7 @@ space.call_method(self.w_dict, "update", w_dict) def _check_closed(self, space, message=None): - if self.buf is None: + if self.state == CLOSED: if message is None: message = "I/O operation on closed file" raise OperationError(space.w_ValueError, space.newtext(message)) @@ -307,9 +310,10 @@ def close_w(self, space): self.buf = None + self.state = CLOSED def closed_get_w(self, space): - return space.newbool(self.buf is None) + return space.newbool(self.state == CLOSED) def line_buffering_get_w(self, space): return space.w_False From pypy.commits at gmail.com Mon Feb 3 21:26:08 2020 From: pypy.commits at gmail.com (rlamy) Date: Mon, 03 Feb 2020 18:26:08 -0800 (PST) Subject: [pypy-commit] pypy StringIO-perf: Move pos attribute from UnicodeIO to W_StringIO Message-ID: <5e38d640.1c69fb81.b953.a4e4@mx.google.com> Author: Ronan Lamy Branch: StringIO-perf Changeset: r98659:53dc1cad58b0 Date: 2020-02-04 02:25 +0000 http://bitbucket.org/pypy/pypy/changeset/53dc1cad58b0/ Log: Move pos attribute from UnicodeIO to W_StringIO diff --git a/pypy/module/_io/interp_stringio.py b/pypy/module/_io/interp_stringio.py --- a/pypy/module/_io/interp_stringio.py +++ b/pypy/module/_io/interp_stringio.py @@ -13,9 +13,7 @@ if data is None: data = '' self.data = [] - self.pos = 0 - self.write(data) - self.pos = 0 + self.write(data, 0) def resize(self, newlength): if len(self.data) > newlength: @@ -23,8 +21,7 @@ if len(self.data) < newlength: self.data.extend([u'\0'] * (newlength - len(self.data))) - def read(self, size): - start = self.pos + def read(self, start, size): available = len(self.data) - start if available <= 0: return '' @@ -33,19 +30,17 @@ else: end = len(self.data) assert 0 <= start <= end - self.pos = end - return u''.join(self.data[start:end]).encode('utf-8') + return u''.join(self.data[start:end]) - def _convert_limit(self, limit): - if limit < 0 or limit > len(self.data) - self.pos: - limit = len(self.data) - self.pos + def _convert_limit(self, limit, start): + if limit < 0 or limit > len(self.data) - start: + limit = len(self.data) - start assert limit >= 0 return limit - def readline_universal(self, limit): + def readline_universal(self, start, limit): # Universal newline search. Find any of \r, \r\n, \n - limit = self._convert_limit(limit) - start = self.pos + limit = self._convert_limit(limit, start) end = start + limit pos = start while pos < end: @@ -61,13 +56,11 @@ break else: break - self.pos = pos - result = u''.join(self.data[start:pos]).encode('utf-8') + result = u''.join(self.data[start:pos]) return result - def readline(self, marker, limit): - start = self.pos - limit = self._convert_limit(limit) + def readline(self, marker, start, limit): + limit = self._convert_limit(limit, start) end = start + limit found = False marker = marker.decode('utf-8') @@ -83,21 +76,17 @@ break if not found: pos = end - self.pos = pos - result = u''.join(self.data[start:pos]).encode('utf-8') + result = u''.join(self.data[start:pos]) return result - def write(self, string): + def write(self, string, start): ustr = string.decode('utf-8') - newlen = self.pos + len(ustr) + newlen = start + len(ustr) if newlen > len(self.data): self.resize(newlen) for i in range(len(ustr)): - self.data[self.pos + i] = ustr[i] - self.pos += len(ustr) - - def seek(self, pos): - self.pos = pos + self.data[start + i] = ustr[i] + return len(ustr) def truncate(self, size): if size < len(self.data): @@ -113,12 +102,14 @@ def __init__(self, space): W_TextIOBase.__init__(self, space) self.buf = UnicodeIO() + self.pos = 0 self.state = INITIAL @unwrap_spec(w_newline=WrappedDefault("\n")) def descr_init(self, space, w_initvalue=None, w_newline=None): # In case __init__ is called multiple times self.buf = UnicodeIO() + self.pos = 0 self.w_decoder = None self.readnl = None self.writenl = None @@ -152,7 +143,7 @@ if not space.is_none(w_initvalue): self.write_w(space, w_initvalue) - self.buf.pos = 0 + self.pos = 0 def descr_getstate(self, space): w_initialval = self.getvalue_w(space) @@ -163,7 +154,7 @@ else: w_readnl = space.str(space.newutf8(readnl, codepoints_in_utf8(readnl))) # YYY return space.newtuple([ - w_initialval, w_readnl, space.newint(self.buf.pos), w_dict + w_initialval, w_readnl, space.newint(self.pos), w_dict ]) def descr_setstate(self, space, w_state): @@ -194,7 +185,7 @@ raise oefmt(space.w_ValueError, "position value cannot be negative") self.buf = UnicodeIO(initval) - self.buf.seek(pos) + self.pos = pos if not space.is_w(w_dict, space.w_None): if not space.isinstance_w(w_dict, space.w_dict): raise oefmt( @@ -231,32 +222,32 @@ ) string = space.utf8_w(w_decoded) if string: - self.buf.write(string) + written = self.buf.write(string, self.pos) + self.pos += written return space.newint(orig_size) def read_w(self, space, w_size=None): self._check_closed(space) size = convert_size(space, w_size) - v = self.buf.read(size) - lgt = codepoints_in_utf8(v) - return space.newutf8(v, lgt) + result_u = self.buf.read(self.pos, size) + self.pos += len(result_u) + return space.newutf8(result_u.encode('utf-8'), len(result_u)) def readline_w(self, space, w_limit=None): self._check_closed(space) limit = convert_size(space, w_limit) if self.readuniversal: - result = self.buf.readline_universal(limit) + result_u = self.buf.readline_universal(self.pos, limit) else: if self.readtranslate: # Newlines are already translated, only search for \n newline = '\n' else: newline = self.readnl - result = self.buf.readline(newline, limit) - resultlen = codepoints_in_utf8(result) - return space.newutf8(result, resultlen) - + result_u = self.buf.readline(newline, self.pos, limit) + self.pos += len(result_u) + return space.newutf8(result_u.encode('utf-8'), len(result_u)) @unwrap_spec(pos=int, mode=int) def seek_w(self, space, pos, mode=0): @@ -272,17 +263,17 @@ # XXX: this makes almost no sense, but its how CPython does it. if mode == 1: - pos = self.buf.pos + pos = self.pos elif mode == 2: pos = len(self.buf.data) assert pos >= 0 - self.buf.seek(pos) + self.pos = pos return space.newint(pos) def truncate_w(self, space, w_size=None): self._check_closed(space) if space.is_none(w_size): - size = self.buf.pos + size = self.pos else: size = space.int_w(w_size) if size < 0: From pypy.commits at gmail.com Tue Feb 4 06:41:56 2020 From: pypy.commits at gmail.com (cfbolz) Date: Tue, 04 Feb 2020 03:41:56 -0800 (PST) Subject: [pypy-commit] pypy py3.7: f(x for x in y, ) raises an error now Message-ID: <5e395884.1c69fb81.c8eba.868d@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: py3.7 Changeset: r98660:57f3cbe9b2fa Date: 2020-02-03 22:31 +0100 http://bitbucket.org/pypy/pypy/changeset/57f3cbe9b2fa/ Log: f(x for x in y, ) raises an error now diff --git a/pypy/interpreter/astcompiler/astbuilder.py b/pypy/interpreter/astcompiler/astbuilder.py --- a/pypy/interpreter/astcompiler/astbuilder.py +++ b/pypy/interpreter/astcompiler/astbuilder.py @@ -1089,6 +1089,7 @@ arg_count = 0 # position args + iterable args unpackings keyword_count = 0 # keyword args + keyword args unpackings generator_count = 0 + last_is_comma = False for i in range(args_node.num_children()): argument = args_node.get_child(i) if argument.type == syms.argument: @@ -1102,8 +1103,11 @@ # argument.get_child(0).type == tokens.DOUBLESTAR # or keyword arg keyword_count += 1 - if generator_count > 1 or \ - (generator_count and (keyword_count or arg_count)): + last_is_comma = argument.type == tokens.COMMA + + if (generator_count > 1 or + (generator_count and (keyword_count or arg_count)) or + (generator_count == 1 and last_is_comma)): self.error("Generator expression must be parenthesized " "if not sole argument", args_node) args = [] diff --git a/pypy/interpreter/astcompiler/test/test_astbuilder.py b/pypy/interpreter/astcompiler/test/test_astbuilder.py --- a/pypy/interpreter/astcompiler/test/test_astbuilder.py +++ b/pypy/interpreter/astcompiler/test/test_astbuilder.py @@ -1073,6 +1073,10 @@ exc = pytest.raises(SyntaxError, self.get_ast, input).value assert exc.msg == "Generator expression must be parenthesized if not " \ "sole argument" + input = "f(x for x in y, )" + exc = pytest.raises(SyntaxError, self.get_ast, input).value + assert exc.msg == "Generator expression must be parenthesized if not " \ + "sole argument" many_args = ", ".join("x%i" % i for i in range(256)) input = "f(%s)" % (many_args,) self.get_ast(input) # doesn't crash any more From pypy.commits at gmail.com Tue Feb 4 09:19:53 2020 From: pypy.commits at gmail.com (mattip) Date: Tue, 04 Feb 2020 06:19:53 -0800 (PST) Subject: [pypy-commit] pypy py3.6: check for overflow in device_encoding (caused by a bad fileno) Message-ID: <5e397d89.1c69fb81.5f19.34f6@mx.google.com> Author: Matti Picus Branch: py3.6 Changeset: r98661:1c68a492a49e Date: 2020-02-04 16:12 +0200 http://bitbucket.org/pypy/pypy/changeset/1c68a492a49e/ Log: check for overflow in device_encoding (caused by a bad fileno) diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py --- a/pypy/module/_io/interp_textio.py +++ b/pypy/module/_io/interp_textio.py @@ -246,9 +246,14 @@ e.match(space, space.fromcache(Cache).w_unsupportedoperation)): raise else: - w_encoding = device_encoding(space, space.int_w(w_fileno)) - if space.isinstance_w(w_encoding, space.w_unicode): - return w_encoding + try: + w_encoding = device_encoding(space, space.int_w(w_fileno)) + except OverflowError: + raise oefmt(space.w_OverflowError, + "Python int too large to convert to C int") + else: + if space.isinstance_w(w_encoding, space.w_unicode): + return w_encoding # On legacy systems or darwin, try app-level # _bootlocale.getprefferedencoding(False) From pypy.commits at gmail.com Wed Feb 5 05:23:34 2020 From: pypy.commits at gmail.com (cfbolz) Date: Wed, 05 Feb 2020 02:23:34 -0800 (PST) Subject: [pypy-commit] pypy py3.7: use the Python implementation of hmac.digest for now Message-ID: <5e3a97a6.1c69fb81.ab1c7.1526@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: py3.7 Changeset: r98663:e1662647d2eb Date: 2020-02-04 13:31 +0100 http://bitbucket.org/pypy/pypy/changeset/e1662647d2eb/ Log: use the Python implementation of hmac.digest for now diff --git a/lib-python/3/hmac.py b/lib-python/3/hmac.py --- a/lib-python/3/hmac.py +++ b/lib-python/3/hmac.py @@ -164,7 +164,8 @@ Note: key and msg must be a bytes or bytearray objects. """ - if (_hashopenssl is not None and + if (False and # PyPy does not implement this shortcut yet + _hashopenssl is not None and isinstance(digest, str) and digest in _openssl_md_meths): return _hashopenssl.hmac_digest(key, msg, digest) From pypy.commits at gmail.com Wed Feb 5 15:21:19 2020 From: pypy.commits at gmail.com (mattip) Date: Wed, 05 Feb 2020 12:21:19 -0800 (PST) Subject: [pypy-commit] buildbot default: differentiate between projects in upload Message-ID: <5e3b23bf.1c69fb81.511c5.688c@mx.google.com> Author: Matti Picus Branch: Changeset: r1130:e6539bdaaa08 Date: 2020-02-05 22:20 +0200 http://bitbucket.org/pypy/buildbot/changeset/e6539bdaaa08/ Log: differentiate between projects in upload diff --git a/bot2/pypybuildbot/builds.py b/bot2/pypybuildbot/builds.py --- a/bot2/pypybuildbot/builds.py +++ b/bot2/pypybuildbot/builds.py @@ -931,6 +931,7 @@ # set from testrunner/get_info.py target = props.getProperty('target_path') exe = os.path.split(target)[-1][:-2] + project = opros.getProperty('project', default='PyPy') rev = props.getProperty('got_revision') branch = props.getProperty('branch') if branch == 'None' or branch is None: @@ -941,13 +942,13 @@ '--args', ',--jit off', '--upload', '--upload-executable', exe + postfix, - '--upload-project', 'PyPy', + '--upload-project', project, '--revision', rev, '--branch', branch, '--upload-urls', 'https://speed.pypy.org/', '--upload-baseline', '--upload-baseline-executable', exe + '-jit' + postfix, - '--upload-baseline-project', 'PyPy', + '--upload-baseline-project', project, '--upload-baseline-revision', rev, '--upload-baseline-branch', branch, '--upload-baseline-urls', 'https://speed.pypy.org/', From pypy.commits at gmail.com Wed Feb 5 16:43:27 2020 From: pypy.commits at gmail.com (rlamy) Date: Wed, 05 Feb 2020 13:43:27 -0800 (PST) Subject: [pypy-commit] pypy StringIO-perf: Add new operation mode for W_StringIO, backed by a W_UnicodeObject, for read-only operations Message-ID: <5e3b36ff.1c69fb81.75432.60ff@mx.google.com> Author: Ronan Lamy Branch: StringIO-perf Changeset: r98669:c83626075169 Date: 2020-02-05 21:42 +0000 http://bitbucket.org/pypy/pypy/changeset/c83626075169/ Log: Add new operation mode for W_StringIO, backed by a W_UnicodeObject, for read-only operations diff --git a/pypy/module/_io/interp_stringio.py b/pypy/module/_io/interp_stringio.py --- a/pypy/module/_io/interp_stringio.py +++ b/pypy/module/_io/interp_stringio.py @@ -1,12 +1,24 @@ -from rpython.rlib.rutf8 import codepoints_in_utf8, next_codepoint_pos +from rpython.rlib.rutf8 import ( + codepoints_in_utf8, codepoint_at_pos, Utf8StringIterator) from pypy.interpreter.error import OperationError, oefmt from pypy.interpreter.typedef import ( TypeDef, generic_new_descr, GetSetProperty) from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault from pypy.module._io.interp_textio import ( - W_TextIOBase, W_IncrementalNewlineDecoder) + W_TextIOBase, W_IncrementalNewlineDecoder) from pypy.module._io.interp_iobase import convert_size +from pypy.objspace.std.unicodeobject import W_UnicodeObject + + +def _find_end(start, size, total): + available = total - start + if size >= 0 and size <= available: + end = start + size + else: + end = total + assert 0 <= start and 0 <= end + return end class UnicodeIO(object): def __init__(self, data=None): @@ -22,14 +34,7 @@ self.data.extend([u'\0'] * (newlength - len(self.data))) def read(self, start, size): - available = len(self.data) - start - if available <= 0: - return '' - if size >= 0 and size <= available: - end = start + size - else: - end = len(self.data) - assert 0 <= start <= end + end = _find_end(start, size, len(self.data)) return u''.join(self.data[start:end]) def _convert_limit(self, limit, start): @@ -95,20 +100,27 @@ def getvalue(self): return u''.join(self.data).encode('utf-8') -INITIAL, CLOSED = range(2) - +READING, RWBUFFER, CLOSED = range(3) class W_StringIO(W_TextIOBase): def __init__(self, space): W_TextIOBase.__init__(self, space) - self.buf = UnicodeIO() + self.buf = None + self.w_value = W_UnicodeObject.EMPTY self.pos = 0 - self.state = INITIAL + self.state = READING + + def get_length(self): + """Return the total size (in codepoints) of the object""" + if self.state == READING: + return self.w_value._len() + else: + return len(self.buf.data) @unwrap_spec(w_newline=WrappedDefault("\n")) def descr_init(self, space, w_initvalue=None, w_newline=None): # In case __init__ is called multiple times - self.buf = UnicodeIO() + self.buf = None self.pos = 0 self.w_decoder = None self.readnl = None @@ -142,8 +154,11 @@ ) if not space.is_none(w_initvalue): - self.write_w(space, w_initvalue) - self.pos = 0 + self.w_value = self._decode_string(space, w_initvalue) + else: + self.w_value = W_UnicodeObject.EMPTY + self.pos = 0 + self.state = READING def descr_getstate(self, space): w_initialval = self.getvalue_w(space) @@ -173,18 +188,19 @@ raise oefmt(space.w_TypeError, "unicode argument expected, got '%T'", w_initval) # Initialize state - self.descr_init(space, None, w_readnl) + self.descr_init(space, w_initval, w_readnl) # Restore the buffer state. We're not doing it via __init__ # because the string value in the state tuple has already been # translated once by __init__. So we do not take any chance and replace # object's buffer completely initval = space.utf8_w(w_initval) + self.buf = UnicodeIO(initval) + pos = space.getindex_w(w_pos, space.w_TypeError) if pos < 0: raise oefmt(space.w_ValueError, "position value cannot be negative") - self.buf = UnicodeIO(initval) self.pos = pos if not space.is_w(w_dict, space.w_None): if not space.isinstance_w(w_dict, space.w_dict): @@ -201,12 +217,11 @@ message = "I/O operation on closed file" raise OperationError(space.w_ValueError, space.newtext(message)) - def write_w(self, space, w_obj): + def _decode_string(self, space, w_obj): if not space.isinstance_w(w_obj, space.w_unicode): raise oefmt(space.w_TypeError, "unicode argument expected, got '%T'", w_obj) self._check_closed(space) - orig_size = space.len_w(w_obj) if self.w_decoder is not None: w_decoded = space.call_method( @@ -220,6 +235,16 @@ space.newtext("\n"), space.newutf8(writenl, codepoints_in_utf8(writenl)), ) + return w_decoded + + def write_w(self, space, w_obj): + w_decoded = self._decode_string(space, w_obj) + orig_size = space.len_w(w_obj) + if self.state == READING: + self.buf = UnicodeIO(space.utf8_w(self.w_value)) + self.w_value = None + self.state = RWBUFFER + string = space.utf8_w(w_decoded) if string: written = self.buf.write(string, self.pos) @@ -230,6 +255,15 @@ def read_w(self, space, w_size=None): self._check_closed(space) size = convert_size(space, w_size) + if self.state == READING: + length = self.w_value._len() + end = _find_end(self.pos, size, length) + if self.pos > end: + return space.newutf8('', 0) + w_res = self.w_value._unicode_sliced(space, self.pos, end) + self.pos = end + return w_res + assert self.state == RWBUFFER result_u = self.buf.read(self.pos, size) self.pos += len(result_u) return space.newutf8(result_u.encode('utf-8'), len(result_u)) @@ -237,6 +271,61 @@ def readline_w(self, space, w_limit=None): self._check_closed(space) limit = convert_size(space, w_limit) + if self.state == READING: + length = self.w_value._len() + end = _find_end(self.pos, limit, length) + if self.readuniversal: + start = self.pos + start_offset = self.w_value._index_to_byte(start) + it = Utf8StringIterator(self.w_value._utf8) + it._pos = start_offset + for ch in it: + if ch == ord(u'\n'): + self.pos += 1 + break + elif ch == ord(u'\r'): + self.pos += 1 + if self.pos >= end: + break + if it.next() == ord(u'\n'): + self.pos += 1 + break + else: + # `it` has gone one char too far, but we don't care + break + self.pos += 1 + if self.pos >= end: + break + w_res = self.w_value._unicode_sliced(space, start, self.pos) + return w_res + else: + if self.readtranslate: + # Newlines are already translated, only search for \n + newline = '\n' + else: + newline = self.readnl + + start = self.pos + start_offset = self.w_value._index_to_byte(start) + it = Utf8StringIterator(self.w_value._utf8) + it._pos = start_offset + for ch in it: + self.pos += 1 + if ch == ord(newline[0]): + if len(newline) == 1 or self.pos >= end: + break + else: + ch = codepoint_at_pos(self.w_value._utf8, it.get_pos()) + if ch == ord(newline[1]): + self.pos += 1 + break + else: + continue + if self.pos >= end: + break + w_res = self.w_value._unicode_sliced(space, start, self.pos) + return w_res + if self.readuniversal: result_u = self.buf.readline_universal(self.pos, limit) else: @@ -265,7 +354,7 @@ if mode == 1: pos = self.pos elif mode == 2: - pos = len(self.buf.data) + pos = self.get_length() assert pos >= 0 self.pos = pos return space.newint(pos) @@ -278,11 +367,17 @@ size = space.int_w(w_size) if size < 0: raise oefmt(space.w_ValueError, "Negative size value %d", size) - self.buf.truncate(size) + if self.state == READING: + if size < self.w_value._len(): + self.w_value = self.w_value._unicode_sliced(space, 0, size) + else: + self.buf.truncate(size) return space.newint(size) def getvalue_w(self, space): self._check_closed(space) + if self.state == READING: + return self.w_value v = self.buf.getvalue() lgt = codepoints_in_utf8(v) return space.newutf8(v, lgt) From pypy.commits at gmail.com Thu Feb 6 03:38:52 2020 From: pypy.commits at gmail.com (mattip) Date: Thu, 06 Feb 2020 00:38:52 -0800 (PST) Subject: [pypy-commit] buildbot default: typo Message-ID: <5e3bd09c.1c69fb81.273cf.d3f3@mx.google.com> Author: Matti Picus Branch: Changeset: r1131:6c5059da3e8b Date: 2020-02-06 10:38 +0200 http://bitbucket.org/pypy/buildbot/changeset/6c5059da3e8b/ Log: typo diff --git a/bot2/pypybuildbot/builds.py b/bot2/pypybuildbot/builds.py --- a/bot2/pypybuildbot/builds.py +++ b/bot2/pypybuildbot/builds.py @@ -931,7 +931,7 @@ # set from testrunner/get_info.py target = props.getProperty('target_path') exe = os.path.split(target)[-1][:-2] - project = opros.getProperty('project', default='PyPy') + project = props.getProperty('project', default='PyPy') rev = props.getProperty('got_revision') branch = props.getProperty('branch') if branch == 'None' or branch is None: From pypy.commits at gmail.com Thu Feb 6 03:58:56 2020 From: pypy.commits at gmail.com (Sreepathi Pai) Date: Thu, 06 Feb 2020 00:58:56 -0800 (PST) Subject: [pypy-commit] pypy default: runpack should align for next read Message-ID: <5e3bd550.1c69fb81.3cf68.bb15@mx.google.com> Author: Sreepathi Pai Branch: Changeset: r98670:78510e758e34 Date: 2020-02-05 19:03 -0500 http://bitbucket.org/pypy/pypy/changeset/78510e758e34/ Log: runpack should align for next read diff --git a/rpython/pytest.ini b/rpython/pytest.ini --- a/rpython/pytest.ini +++ b/rpython/pytest.ini @@ -1,2 +1,2 @@ [pytest] -addopts = --assert=reinterp -rf +#addopts = --assert=reinterp -rf diff --git a/rpython/rlib/rstruct/runpack.py b/rpython/rlib/rstruct/runpack.py --- a/rpython/rlib/rstruct/runpack.py +++ b/rpython/rlib/rstruct/runpack.py @@ -86,12 +86,12 @@ for i in rg: fmtdesc, rep, mask = self.formats[i] miniglobals['unpacker%d' % i] = fmtdesc.unpack - if mask is not None: - perform_lst.append('master_reader.align(%d)' % mask) if not fmtdesc.needcount: perform_lst.append('unpacker%d(reader%d)' % (i, i)) else: perform_lst.append('unpacker%d(reader%d, %d)' % (i, i, rep)) + if mask is not None: + perform_lst.append('master_reader.align(%d)' % mask) miniglobals['reader_cls%d' % i] = reader_for_pos(i) readers = ";".join(["reader%d = reader_cls%d(master_reader, bigendian)" % (i, i) for i in rg]) diff --git a/rpython/rlib/rstruct/test/test_runpack.py b/rpython/rlib/rstruct/test/test_runpack.py --- a/rpython/rlib/rstruct/test/test_runpack.py +++ b/rpython/rlib/rstruct/test/test_runpack.py @@ -110,6 +110,15 @@ assert unpack(">q", '\xbeMLKJIHH') == -0x41B2B3B4B5B6B7B8 assert unpack(">Q", '\x81BCDEFGH') == 0x8142434445464748 + def test_align(self): + data = struct.pack('BBhi', 1, 2, 3, 4) + def fn(): + a, b, c, d = runpack('BBhi', data) + return a+(b << 8)+(c << 16) + (d << 32) + assert fn() == 0x400030201 + assert self.interpret(fn, []) == 0x400030201 + + class TestNoFastPath(TestRStruct): From pypy.commits at gmail.com Thu Feb 6 03:58:58 2020 From: pypy.commits at gmail.com (Sreepathi Pai) Date: Thu, 06 Feb 2020 00:58:58 -0800 (PST) Subject: [pypy-commit] pypy default: Revert pytest.ini, make test work on 32-bit systems Message-ID: <5e3bd552.1c69fb81.3872a.b8cb@mx.google.com> Author: Sreepathi Pai Branch: Changeset: r98671:4c44f65af534 Date: 2020-02-05 20:34 -0500 http://bitbucket.org/pypy/pypy/changeset/4c44f65af534/ Log: Revert pytest.ini, make test work on 32-bit systems diff --git a/rpython/pytest.ini b/rpython/pytest.ini --- a/rpython/pytest.ini +++ b/rpython/pytest.ini @@ -1,2 +1,2 @@ [pytest] -#addopts = --assert=reinterp -rf +addopts = --assert=reinterp -rf diff --git a/rpython/rlib/rstruct/test/test_runpack.py b/rpython/rlib/rstruct/test/test_runpack.py --- a/rpython/rlib/rstruct/test/test_runpack.py +++ b/rpython/rlib/rstruct/test/test_runpack.py @@ -114,9 +114,9 @@ data = struct.pack('BBhi', 1, 2, 3, 4) def fn(): a, b, c, d = runpack('BBhi', data) - return a+(b << 8)+(c << 16) + (d << 32) - assert fn() == 0x400030201 - assert self.interpret(fn, []) == 0x400030201 + return a + (b << 4) + (c << 8) + (d << 12) + assert fn() == 0x4321 + assert self.interpret(fn, []) == 0x4321 From pypy.commits at gmail.com Thu Feb 6 04:44:35 2020 From: pypy.commits at gmail.com (arigo) Date: Thu, 06 Feb 2020 01:44:35 -0800 (PST) Subject: [pypy-commit] pypy default: Change the FAQ entry "why not github" Message-ID: <5e3be003.1c69fb81.f94f0.c79f@mx.google.com> Author: Armin Rigo Branch: Changeset: r98672:6f72c0da3906 Date: 2020-02-06 10:43 +0100 http://bitbucket.org/pypy/pypy/changeset/6f72c0da3906/ Log: Change the FAQ entry "why not github" diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst --- a/pypy/doc/faq.rst +++ b/pypy/doc/faq.rst @@ -465,14 +465,30 @@ the GC and possibly the JIT. -Why doesn't PyPy move to GitHub, Gitlab, ...? ----------------------------------------------- +.. _git: +.. _github: -We've been quite happy with bitbucket.org. Moving version control systems and -hosting is a lot of hard work: On the one hand, PyPy's mercurial history is -long and gnarly. On the other hand, all our infrastructure (buildbots, -benchmarking, etc) would have to be adapted. So unless somebody steps up and -volunteers to do all that work, it will likely not happen. +Why doesn't PyPy use Git and move to GitHub? +--------------------------------------------- + +We discussed it during the switch away from bitbucket. We concluded that (1) +the Git workflow is not as well suited as the Mercurial workflow for our style, +and (2) moving to github "just because everybody else does" is a argument on +thin grounds. + +For (1), there are a few issues, but maybe the most important one is that the +PyPy repository has got thousands of *named* branches. Git has no equivalent +concept. Git has *branches,* of course, which in Mercurial are called +bookmarks. We're not talking about bookmarks. + +The difference between git branches and named branches is not that important in +a repo with 10 branches (no matter how big). But in the case of PyPy, we have +at the moment 1840 branches. Most are closed by now, of course. But we would +really like to retain (both now and in the future) the ability to look at a +commit from the past, and know in which branch it was made. Please make sure +you understand the difference between the Git and the Mercurial branches to +realize that this is not always possible with Git--- we looked hard, and there +is no built-in way to get this workflow. What is needed for Windows 64 support of PyPy? From pypy.commits at gmail.com Thu Feb 6 05:35:47 2020 From: pypy.commits at gmail.com (arigo) Date: Thu, 06 Feb 2020 02:35:47 -0800 (PST) Subject: [pypy-commit] cffi default: #442: memory leak in getwinerror() in py3 Message-ID: <5e3bec03.1c69fb81.87b67.0332@mx.google.com> Author: Armin Rigo Branch: Changeset: r3333:4c9bc72ff7a2 Date: 2020-02-06 11:35 +0100 http://bitbucket.org/cffi/cffi/changeset/4c9bc72ff7a2/ Log: #442: memory leak in getwinerror() in py3 diff --git a/c/misc_win32.h b/c/misc_win32.h --- a/c/misc_win32.h +++ b/c/misc_win32.h @@ -124,8 +124,10 @@ s_buf[--len] = L'\0'; message = PyUnicode_FromWideChar(s_buf, len); } - if (message != NULL) + if (message != NULL) { v = Py_BuildValue("(iO)", err, message); + Py_DECREF(message); + } else v = NULL; LocalFree(s_buf); @@ -168,7 +170,6 @@ /* Only seen this in out of mem situations */ sprintf(s_small_buf, "Windows Error 0x%X", err); s = s_small_buf; - s_buf = NULL; } else { s = s_buf; /* remove trailing cr/lf and dots */ From pypy.commits at gmail.com Thu Feb 6 10:56:59 2020 From: pypy.commits at gmail.com (mattip) Date: Thu, 06 Feb 2020 07:56:59 -0800 (PST) Subject: [pypy-commit] buildbot limit-disk-usage: close abandoned branch Message-ID: <5e3c374b.1c69fb81.ebcd1.4914@mx.google.com> Author: Matti Picus Branch: limit-disk-usage Changeset: r1132:1f96501aac81 Date: 2020-02-06 17:54 +0200 http://bitbucket.org/pypy/buildbot/changeset/1f96501aac81/ Log: close abandoned branch From pypy.commits at gmail.com Thu Feb 6 10:57:00 2020 From: pypy.commits at gmail.com (mattip) Date: Thu, 06 Feb 2020 07:57:00 -0800 (PST) Subject: [pypy-commit] buildbot coalesce-by-hash: close abandoned branch Message-ID: <5e3c374c.1c69fb81.957bd.4d4e@mx.google.com> Author: Matti Picus Branch: coalesce-by-hash Changeset: r1133:40406a7b7547 Date: 2020-02-06 17:54 +0200 http://bitbucket.org/pypy/buildbot/changeset/40406a7b7547/ Log: close abandoned branch From pypy.commits at gmail.com Thu Feb 6 10:57:02 2020 From: pypy.commits at gmail.com (mattip) Date: Thu, 06 Feb 2020 07:57:02 -0800 (PST) Subject: [pypy-commit] buildbot numpy-tests: close abandoned branch Message-ID: <5e3c374e.1c69fb81.f94f0.26fd@mx.google.com> Author: Matti Picus Branch: numpy-tests Changeset: r1134:52f7cb4cd4b1 Date: 2020-02-06 17:54 +0200 http://bitbucket.org/pypy/buildbot/changeset/52f7cb4cd4b1/ Log: close abandoned branch From pypy.commits at gmail.com Thu Feb 6 10:57:04 2020 From: pypy.commits at gmail.com (mattip) Date: Thu, 06 Feb 2020 07:57:04 -0800 (PST) Subject: [pypy-commit] buildbot cffi-build-step: close abandoned branch Message-ID: <5e3c3750.1c69fb81.87b67.5d29@mx.google.com> Author: Matti Picus Branch: cffi-build-step Changeset: r1135:acc98fc98193 Date: 2020-02-06 17:56 +0200 http://bitbucket.org/pypy/buildbot/changeset/acc98fc98193/ Log: close abandoned branch From pypy.commits at gmail.com Thu Feb 6 11:15:10 2020 From: pypy.commits at gmail.com (cfbolz) Date: Thu, 06 Feb 2020 08:15:10 -0800 (PST) Subject: [pypy-commit] pypy py3.7: sys.setrecursionlimit changes: Message-ID: <5e3c3b8e.1c69fb81.ac27c.397a@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: py3.7 Changeset: r98673:a75c90ba20f9 Date: 2020-02-05 13:33 +0100 http://bitbucket.org/pypy/pypy/changeset/a75c90ba20f9/ Log: sys.setrecursionlimit changes: - change error message in one case - skip a test: extremely low recursionlimits just lead to very strange behavior - change the skip reason of another test: there's no need to "fix" this, PyPy behaves more correctly here diff --git a/lib-python/3/test/test_sys.py b/lib-python/3/test/test_sys.py --- a/lib-python/3/test/test_sys.py +++ b/lib-python/3/test/test_sys.py @@ -193,6 +193,7 @@ self.assertEqual(sys.getrecursionlimit(), 10000) sys.setrecursionlimit(oldlimit) + @test.support.cpython_only def test_recursionlimit_recovery(self): if hasattr(sys, 'gettrace') and sys.gettrace(): self.skipTest('fatal error if run with a trace function') @@ -251,7 +252,7 @@ finally: sys.setrecursionlimit(oldlimit) - @unittest.skipIf(True, 'Fixme: hangs with pypy') + @unittest.skipIf(True, 'pypy supports this just fine') def test_recursionlimit_fatalerror(self): # A fatal error occurs if a second recursion limit is hit when recovering # from a first one. diff --git a/pypy/module/sys/test/test_sysmodule.py b/pypy/module/sys/test/test_sysmodule.py --- a/pypy/module/sys/test/test_sysmodule.py +++ b/pypy/module/sys/test/test_sysmodule.py @@ -524,6 +524,16 @@ sys.setrecursionlimit(oldlimit) raises(OverflowError, sys.setrecursionlimit, 1<<31) + def test_recursionlimit_toolow(self): + import sys + def callatlevel(l): + if l > 0: + callatlevel(l - 1) + else: + sys.setrecursionlimit(1) + with raises(RecursionError): + callatlevel(500) + def test_getwindowsversion(self): import sys if hasattr(sys, "getwindowsversion"): diff --git a/pypy/module/sys/vm.py b/pypy/module/sys/vm.py --- a/pypy/module/sys/vm.py +++ b/pypy/module/sys/vm.py @@ -79,7 +79,7 @@ old_limit = space.sys.recursionlimit _stack_set_length_fraction(old_limit * 0.001) raise oefmt(space.w_RecursionError, - "maximum recursion depth exceeded") + "cannot set the recursion limit to %s at the recursion depth: the limit is too low") space.sys.recursionlimit = new_limit increase_root_stack_depth(int(new_limit * 0.001 * 163840)) From pypy.commits at gmail.com Thu Feb 6 11:15:12 2020 From: pypy.commits at gmail.com (cfbolz) Date: Thu, 06 Feb 2020 08:15:12 -0800 (PST) Subject: [pypy-commit] pypy py3.7: those attributes are gone Message-ID: <5e3c3b90.1c69fb81.8742d.563e@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: py3.7 Changeset: r98674:11658ec64e92 Date: 2020-02-05 13:33 +0100 http://bitbucket.org/pypy/pypy/changeset/11658ec64e92/ Log: those attributes are gone diff --git a/pypy/module/sys/test/test_sysmodule.py b/pypy/module/sys/test/test_sysmodule.py --- a/pypy/module/sys/test/test_sysmodule.py +++ b/pypy/module/sys/test/test_sysmodule.py @@ -104,28 +104,6 @@ assert exc_val2 ==e2 assert tb2.tb_lineno - tb.tb_lineno == 6 - def test_dynamic_attributes(self): - try: - raise Exception - except Exception as exc: - e = exc - import sys - exc_type = sys.exc_type - exc_val = sys.exc_value - tb = sys.exc_traceback - try: - raise Exception # 8 lines below the previous one - except Exception as exc: - e2 = exc - exc_type2 = sys.exc_type - exc_val2 = sys.exc_value - tb2 = sys.exc_traceback - assert exc_type ==Exception - assert exc_val ==e - assert exc_type2 ==Exception - assert exc_val2 ==e2 - assert tb2.tb_lineno - tb.tb_lineno == 8 - def test_exc_info_normalization(self): import sys try: From pypy.commits at gmail.com Thu Feb 6 11:15:14 2020 From: pypy.commits at gmail.com (cfbolz) Date: Thu, 06 Feb 2020 08:15:14 -0800 (PST) Subject: [pypy-commit] pypy py3.7: generator expressions aren't allowed in class definitions Message-ID: <5e3c3b92.1c69fb81.78062.00c4@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: py3.7 Changeset: r98675:ccca4d0a7b52 Date: 2020-02-06 16:59 +0100 http://bitbucket.org/pypy/pypy/changeset/ccca4d0a7b52/ Log: generator expressions aren't allowed in class definitions diff --git a/lib_pypy/_tkinter/app.py b/lib_pypy/_tkinter/app.py --- a/lib_pypy/_tkinter/app.py +++ b/lib_pypy/_tkinter/app.py @@ -516,6 +516,7 @@ def getint(self, s): if isinstance(s, int): return s + import pdb; pdb.set_trace() try: s = s.encode('utf-8') except AttributeError: diff --git a/pypy/interpreter/astcompiler/astbuilder.py b/pypy/interpreter/astcompiler/astbuilder.py --- a/pypy/interpreter/astcompiler/astbuilder.py +++ b/pypy/interpreter/astcompiler/astbuilder.py @@ -466,7 +466,7 @@ # build up a fake Call node so we can extract its pieces call_name = ast.Name(name, ast.Load, classdef_node.get_lineno(), classdef_node.get_column()) - call = self.handle_call(classdef_node.get_child(3), call_name) + call = self.handle_call(classdef_node.get_child(3), call_name, genexp_allowed=False) body = self.handle_suite(classdef_node.get_child(6)) return ast.ClassDef( name, call.args, call.keywords, @@ -1085,7 +1085,7 @@ return ast.Subscript(left_expr, ast.Index(tup), ast.Load, middle.get_lineno(), middle.get_column()) - def handle_call(self, args_node, callable_expr): + def handle_call(self, args_node, callable_expr, genexp_allowed=True): arg_count = 0 # position args + iterable args unpackings keyword_count = 0 # keyword args + keyword args unpackings generator_count = 0 @@ -1105,6 +1105,9 @@ keyword_count += 1 last_is_comma = argument.type == tokens.COMMA + if generator_count and not genexp_allowed: + self.error("generator expression can't be used as bases of class definition", + args_node) if (generator_count > 1 or (generator_count and (keyword_count or arg_count)) or (generator_count == 1 and last_is_comma)): diff --git a/pypy/interpreter/astcompiler/test/test_astbuilder.py b/pypy/interpreter/astcompiler/test/test_astbuilder.py --- a/pypy/interpreter/astcompiler/test/test_astbuilder.py +++ b/pypy/interpreter/astcompiler/test/test_astbuilder.py @@ -464,6 +464,9 @@ assert isinstance(b, ast.Name) assert b.ctx == ast.Load + with pytest.raises(SyntaxError) as info: + self.get_ast("class A(x for x in T): pass") + def test_function(self): func = self.get_first_stmt("def f(): pass") assert isinstance(func, ast.FunctionDef) From pypy.commits at gmail.com Thu Feb 6 11:15:15 2020 From: pypy.commits at gmail.com (cfbolz) Date: Thu, 06 Feb 2020 08:15:15 -0800 (PST) Subject: [pypy-commit] pypy py3.7: fix error msg Message-ID: <5e3c3b93.1c69fb81.1bf85.fbdf@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: py3.7 Changeset: r98676:eabac6f35bd1 Date: 2020-02-06 17:01 +0100 http://bitbucket.org/pypy/pypy/changeset/eabac6f35bd1/ Log: fix error msg diff --git a/lib-python/3/test/test_syntax.py b/lib-python/3/test/test_syntax.py --- a/lib-python/3/test/test_syntax.py +++ b/lib-python/3/test/test_syntax.py @@ -134,25 +134,25 @@ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> f(x for x in L, 1) Traceback (most recent call last): -SyntaxError: Generator expression must be parenthesized +SyntaxError: Generator expression must be parenthesized if not sole argument >>> f(x for x in L, y=1) Traceback (most recent call last): -SyntaxError: Generator expression must be parenthesized +SyntaxError: Generator expression must be parenthesized if not sole argument >>> f(x for x in L, *[]) Traceback (most recent call last): -SyntaxError: Generator expression must be parenthesized +SyntaxError: Generator expression must be parenthesized if not sole argument >>> f(x for x in L, **{}) Traceback (most recent call last): -SyntaxError: Generator expression must be parenthesized +SyntaxError: Generator expression must be parenthesized if not sole argument >>> f(L, x for x in L) Traceback (most recent call last): -SyntaxError: Generator expression must be parenthesized +SyntaxError: Generator expression must be parenthesized if not sole argument >>> f(x for x in L, y for y in L) Traceback (most recent call last): -SyntaxError: Generator expression must be parenthesized +SyntaxError: Generator expression must be parenthesized if not sole argument >>> f(x for x in L,) Traceback (most recent call last): -SyntaxError: Generator expression must be parenthesized +SyntaxError: Generator expression must be parenthesized if not sole argument >>> f((x for x in L), 1) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> class C(x for x in L): From pypy.commits at gmail.com Thu Feb 6 11:15:17 2020 From: pypy.commits at gmail.com (cfbolz) Date: Thu, 06 Feb 2020 08:15:17 -0800 (PST) Subject: [pypy-commit] pypy py3.7: check for other async constructs outside of async functions too Message-ID: <5e3c3b95.1c69fb81.168b7.5da4@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: py3.7 Changeset: r98677:e9e80323c851 Date: 2020-02-06 17:13 +0100 http://bitbucket.org/pypy/pypy/changeset/e9e80323c851/ Log: check for other async constructs outside of async functions too diff --git a/lib-python/3/test/test_coroutines.py b/lib-python/3/test/test_coroutines.py --- a/lib-python/3/test/test_coroutines.py +++ b/lib-python/3/test/test_coroutines.py @@ -385,6 +385,12 @@ ] for code in samples: + try: + compile(code, "", "exec") + except SyntaxError: + pass + else: + print(code) with self.subTest(code=code), self.assertRaises(SyntaxError): compile(code, "", "exec") diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py --- a/pypy/interpreter/astcompiler/codegen.py +++ b/pypy/interpreter/astcompiler/codegen.py @@ -622,6 +622,8 @@ self.use_next_block(end) def visit_AsyncFor(self, fr): + if not self._check_async_function(): + self.error("'async for' outside async function", fr) self.update_position(fr.lineno, True) b_try = self.new_block() b_except = self.new_block() @@ -1067,6 +1069,8 @@ self.pop_frame_block(F_BLOCK_FINALLY_END, cleanup) def visit_AsyncWith(self, wih): + if not self._check_async_function(): + self.error("'async with' outside async function", wih) self.update_position(wih.lineno, True) self.handle_withitem(wih, 0, is_async=True) diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py --- a/pypy/interpreter/astcompiler/test/test_compiler.py +++ b/pypy/interpreter/astcompiler/test/test_compiler.py @@ -1258,6 +1258,37 @@ # ok! self.simple_test(source, "None", None) + def test_not_async_function_error(self): + source = """ +async with x: + pass +""" + with py.test.raises(SyntaxError): + self.simple_test(source, "None", None) + + source = """ +async for i in x: + pass +""" + with py.test.raises(SyntaxError): + self.simple_test(source, "None", None) + + source = """ +def f(): + async with x: + pass +""" + with py.test.raises(SyntaxError): + self.simple_test(source, "None", None) + + source = """ +def f(): + async for i in x: + pass +""" + with py.test.raises(SyntaxError): + self.simple_test(source, "None", None) + def test_load_classderef(self): source = """if 1: def f(): From pypy.commits at gmail.com Fri Feb 7 03:24:03 2020 From: pypy.commits at gmail.com (arigo) Date: Fri, 07 Feb 2020 00:24:03 -0800 (PST) Subject: [pypy-commit] cffi default: Document the memory leak fix Message-ID: <5e3d1ea3.1c69fb81.29633.9174@mx.google.com> Author: Armin Rigo Branch: Changeset: r3334:c6a071f57bf4 Date: 2020-02-07 09:23 +0100 http://bitbucket.org/cffi/cffi/changeset/c6a071f57bf4/ Log: Document the memory leak fix diff --git a/doc/source/whatsnew.rst b/doc/source/whatsnew.rst --- a/doc/source/whatsnew.rst +++ b/doc/source/whatsnew.rst @@ -27,6 +27,8 @@ equivalent but explicity builds the intermediate array as a regular Python object on the heap. +* fixed a memory leak inside ``ffi.getwinerror()`` on CPython 3.x. + v1.13.2 ======= From pypy.commits at gmail.com Fri Feb 7 03:48:13 2020 From: pypy.commits at gmail.com (arigo) Date: Fri, 07 Feb 2020 00:48:13 -0800 (PST) Subject: [pypy-commit] cffi default: Bump version number to 1.14.0 Message-ID: <5e3d244d.1c69fb81.a6663.a3af@mx.google.com> Author: Armin Rigo Branch: Changeset: r3335:336db19a4a94 Date: 2020-02-07 09:48 +0100 http://bitbucket.org/cffi/cffi/changeset/336db19a4a94/ Log: Bump version number to 1.14.0 diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c --- a/c/_cffi_backend.c +++ b/c/_cffi_backend.c @@ -2,7 +2,7 @@ #include #include "structmember.h" -#define CFFI_VERSION "1.13.2" +#define CFFI_VERSION "1.14.0" #ifdef MS_WIN32 #include diff --git a/c/test_c.py b/c/test_c.py --- a/c/test_c.py +++ b/c/test_c.py @@ -14,7 +14,7 @@ # ____________________________________________________________ import sys -assert __version__ == "1.13.2", ("This test_c.py file is for testing a version" +assert __version__ == "1.14.0", ("This test_c.py file is for testing a version" " of cffi that differs from the one that we" " get from 'import _cffi_backend'") if sys.version_info < (3,): diff --git a/cffi/__init__.py b/cffi/__init__.py --- a/cffi/__init__.py +++ b/cffi/__init__.py @@ -5,8 +5,8 @@ from .error import CDefError, FFIError, VerificationError, VerificationMissing from .error import PkgConfigError -__version__ = "1.13.2" -__version_info__ = (1, 13, 2) +__version__ = "1.14.0" +__version_info__ = (1, 14, 0) # The verifier module file names are based on the CRC32 of a string that # contains the following version number. It may be older than __version__ diff --git a/cffi/_embedding.h b/cffi/_embedding.h --- a/cffi/_embedding.h +++ b/cffi/_embedding.h @@ -224,7 +224,7 @@ if (f != NULL && f != Py_None) { PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME - "\ncompiled with cffi version: 1.13.2" + "\ncompiled with cffi version: 1.14.0" "\n_cffi_backend module: ", f); modules = PyImport_GetModuleDict(); mod = PyDict_GetItemString(modules, "_cffi_backend"); diff --git a/doc/source/conf.py b/doc/source/conf.py --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -45,9 +45,9 @@ # built documents. # # The short X.Y version. -version = '1.13' +version = '1.14' # The full version, including alpha/beta/rc tags. -release = '1.13.2' +release = '1.14.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/source/installation.rst b/doc/source/installation.rst --- a/doc/source/installation.rst +++ b/doc/source/installation.rst @@ -52,13 +52,13 @@ * https://pypi.python.org/pypi/cffi -* Checksums of the "source" package version 1.13.2: +* Checksums of the "source" package version 1.14.0: - - MD5: 652203cf99faa254efff7fab23c2f3a2 + - MD5: ... - - SHA: ad94c1b64570ec3016a945d4b226d527de81f9b9 + - SHA: ... - - SHA256: 599a1e8ff057ac530c9ad1778293c665cb81a791421f46922d80a86473c13346 + - SHA256: ... * Or grab the most current version from the `Bitbucket page`_: ``hg clone https://bitbucket.org/cffi/cffi`` diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -198,7 +198,7 @@ `Mailing list `_ """, - version='1.13.2', + version='1.14.0', packages=['cffi'] if cpython else [], package_data={'cffi': ['_cffi_include.h', 'parse_c_type.h', '_embedding.h', '_cffi_errors.h']} From pypy.commits at gmail.com Fri Feb 7 03:55:48 2020 From: pypy.commits at gmail.com (arigo) Date: Fri, 07 Feb 2020 00:55:48 -0800 (PST) Subject: [pypy-commit] cffi default: May fix test on OS/X Message-ID: <5e3d2614.1c69fb81.faef.a70b@mx.google.com> Author: Armin Rigo Branch: Changeset: r3336:f2ec51ca7510 Date: 2020-02-07 09:54 +0100 http://bitbucket.org/cffi/cffi/changeset/f2ec51ca7510/ Log: May fix test on OS/X diff --git a/testing/support.py b/testing/support.py --- a/testing/support.py +++ b/testing/support.py @@ -103,6 +103,7 @@ [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]): # assume a standard clang or gcc extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion', + '-Wno-unused-parameter', '-Wno-unreachable-code'] # special things for clang extra_compile_args.append('-Qunused-arguments') From pypy.commits at gmail.com Fri Feb 7 04:01:21 2020 From: pypy.commits at gmail.com (arigo) Date: Fri, 07 Feb 2020 01:01:21 -0800 (PST) Subject: [pypy-commit] pypy default: update to cffi/f2ec51ca7510 Message-ID: <5e3d2761.1c69fb81.aaa2f.a7bb@mx.google.com> Author: Armin Rigo Branch: Changeset: r98679:2a3fbcfca429 Date: 2020-02-07 10:00 +0100 http://bitbucket.org/pypy/pypy/changeset/2a3fbcfca429/ Log: update to cffi/f2ec51ca7510 diff --git a/extra_tests/cffi_tests/cffi0/test_function.py b/extra_tests/cffi_tests/cffi0/test_function.py --- a/extra_tests/cffi_tests/cffi0/test_function.py +++ b/extra_tests/cffi_tests/cffi0/test_function.py @@ -521,3 +521,16 @@ assert str(e.value).startswith("library '") assert str(e.value).endswith("' has already been closed") ffi.dlclose(lib) # does not raise + + def test_passing_large_list(self): + if self.Backend is CTypesBackend: + py.test.skip("the ctypes backend doesn't support this") + ffi = FFI(backend=self.Backend()) + ffi.cdef(""" + void getenv(char *); + """) + needs_dlopen_none() + m = ffi.dlopen(None) + arg = [b"F", b"O", b"O"] + [b"\x00"] * 20000000 + x = m.getenv(arg) + assert x is None diff --git a/extra_tests/cffi_tests/cffi0/test_verify.py b/extra_tests/cffi_tests/cffi0/test_verify.py --- a/extra_tests/cffi_tests/cffi0/test_verify.py +++ b/extra_tests/cffi_tests/cffi0/test_verify.py @@ -2551,3 +2551,13 @@ """.replace('?', str(a))) # the verify() crashes if the values in the enum are different from # the values we computed ourselves from the cdef() + +def test_passing_large_list(): + ffi = FFI() + ffi.cdef("""void passing_large_list(long[]);""") + lib = ffi.verify(""" + static void passing_large_list(long a[]) { } + """) + arg = list(range(20000000)) + lib.passing_large_list(arg) + # assert did not segfault diff --git a/extra_tests/cffi_tests/cffi1/test_recompiler.py b/extra_tests/cffi_tests/cffi1/test_recompiler.py --- a/extra_tests/cffi_tests/cffi1/test_recompiler.py +++ b/extra_tests/cffi_tests/cffi1/test_recompiler.py @@ -2446,3 +2446,13 @@ }; """) py.test.raises(RuntimeError, ffi.new, "struct BinaryTree *") + +def test_passing_large_list(): + ffi = FFI() + ffi.cdef("""void passing_large_list(long[]);""") + lib = verify(ffi, "test_passing_large_list", """ + static void passing_large_list(long a[]) { } + """) + arg = list(range(20000000)) + lib.passing_large_list(arg) + # assert did not segfault diff --git a/extra_tests/cffi_tests/support.py b/extra_tests/cffi_tests/support.py --- a/extra_tests/cffi_tests/support.py +++ b/extra_tests/cffi_tests/support.py @@ -104,6 +104,7 @@ [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]): # assume a standard clang or gcc extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion', + '-Wno-unused-parameter', '-Wno-unreachable-code'] # special things for clang extra_compile_args.append('-Qunused-arguments') diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO --- a/lib_pypy/cffi.egg-info/PKG-INFO +++ b/lib_pypy/cffi.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: cffi -Version: 1.13.2 +Version: 1.14.0 Summary: Foreign Function Interface for Python calling C code. Home-page: http://cffi.readthedocs.org Author: Armin Rigo, Maciej Fijalkowski diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py --- a/lib_pypy/cffi/__init__.py +++ b/lib_pypy/cffi/__init__.py @@ -5,8 +5,8 @@ from .error import CDefError, FFIError, VerificationError, VerificationMissing from .error import PkgConfigError -__version__ = "1.13.2" -__version_info__ = (1, 13, 2) +__version__ = "1.14.0" +__version_info__ = (1, 14, 0) # The verifier module file names are based on the CRC32 of a string that # contains the following version number. It may be older than __version__ diff --git a/lib_pypy/cffi/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h --- a/lib_pypy/cffi/_cffi_include.h +++ b/lib_pypy/cffi/_cffi_include.h @@ -269,6 +269,54 @@ return _cffi_from_c_wchar3216_t((int)x); } +union _cffi_union_alignment_u { + unsigned char m_char; + unsigned short m_short; + unsigned int m_int; + unsigned long m_long; + unsigned long long m_longlong; + float m_float; + double m_double; + long double m_longdouble; +}; + +struct _cffi_freeme_s { + struct _cffi_freeme_s *next; + union _cffi_union_alignment_u alignment; +}; + +_CFFI_UNUSED_FN static int +_cffi_convert_array_argument(struct _cffi_ctypedescr *ctptr, PyObject *arg, + char **output_data, Py_ssize_t datasize, + struct _cffi_freeme_s **freeme) +{ + char *p; + if (datasize < 0) + return -1; + + p = *output_data; + if (p == NULL) { + struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc( + offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize); + if (fp == NULL) + return -1; + fp->next = *freeme; + *freeme = fp; + p = *output_data = (char *)&fp->alignment; + } + memset((void *)p, 0, (size_t)datasize); + return _cffi_convert_array_from_object(p, ctptr, arg); +} + +_CFFI_UNUSED_FN static void +_cffi_free_array_arguments(struct _cffi_freeme_s *freeme) +{ + do { + void *p = (void *)freeme; + freeme = freeme->next; + PyObject_Free(p); + } while (freeme != NULL); +} /********** end CPython-specific section **********/ #else diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h --- a/lib_pypy/cffi/_embedding.h +++ b/lib_pypy/cffi/_embedding.h @@ -224,7 +224,7 @@ if (f != NULL && f != Py_None) { PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME - "\ncompiled with cffi version: 1.13.2" + "\ncompiled with cffi version: 1.14.0" "\n_cffi_backend module: ", f); modules = PyImport_GetModuleDict(); mod = PyDict_GetItemString(modules, "_cffi_backend"); diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py --- a/lib_pypy/cffi/recompiler.py +++ b/lib_pypy/cffi/recompiler.py @@ -560,23 +560,24 @@ tovar, tp.get_c_name(''), errvalue)) self._prnt(' %s;' % errcode) - def _extra_local_variables(self, tp, localvars): + def _extra_local_variables(self, tp, localvars, freelines): if isinstance(tp, model.PointerType): localvars.add('Py_ssize_t datasize') + localvars.add('struct _cffi_freeme_s *large_args_free = NULL') + freelines.add('if (large_args_free != NULL)' + ' _cffi_free_array_arguments(large_args_free);') def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( self._gettypenum(tp), fromvar, tovar)) self._prnt(' if (datasize != 0) {') - self._prnt(' if (datasize < 0)') - self._prnt(' %s;' % errcode) - self._prnt(' %s = (%s)alloca((size_t)datasize);' % ( + self._prnt(' %s = ((size_t)datasize) <= 640 ? ' + '(%s)alloca((size_t)datasize) : NULL;' % ( tovar, tp.get_c_name(''))) - self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,)) - self._prnt(' if (_cffi_convert_array_from_object(' - '(char *)%s, _cffi_type(%d), %s) < 0)' % ( - tovar, self._gettypenum(tp), fromvar)) + self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, ' + '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar)) + self._prnt(' datasize, &large_args_free) < 0)') self._prnt(' %s;' % errcode) self._prnt(' }') @@ -699,9 +700,10 @@ prnt(' %s;' % arg) # localvars = set() + freelines = set() for type in tp.args: - self._extra_local_variables(type, localvars) - for decl in localvars: + self._extra_local_variables(type, localvars, freelines) + for decl in sorted(localvars): prnt(' %s;' % (decl,)) # if not isinstance(tp.result, model.VoidType): @@ -709,6 +711,7 @@ context = 'result of %s' % name result_decl = ' %s;' % tp.result.get_c_name(' result', context) prnt(result_decl) + prnt(' PyObject *pyresult;') else: result_decl = None result_code = '' @@ -742,9 +745,14 @@ if numargs == 0: prnt(' (void)noarg; /* unused */') if result_code: - prnt(' return %s;' % + prnt(' pyresult = %s;' % self._convert_expr_from_c(tp.result, 'result', 'result type')) + for freeline in freelines: + prnt(' ' + freeline) + prnt(' return pyresult;') else: + for freeline in freelines: + prnt(' ' + freeline) prnt(' Py_INCREF(Py_None);') prnt(' return Py_None;') prnt('}') diff --git a/lib_pypy/cffi/vengine_cpy.py b/lib_pypy/cffi/vengine_cpy.py --- a/lib_pypy/cffi/vengine_cpy.py +++ b/lib_pypy/cffi/vengine_cpy.py @@ -275,22 +275,23 @@ tovar, tp.get_c_name(''), errvalue)) self._prnt(' %s;' % errcode) - def _extra_local_variables(self, tp, localvars): + def _extra_local_variables(self, tp, localvars, freelines): if isinstance(tp, model.PointerType): localvars.add('Py_ssize_t datasize') + localvars.add('struct _cffi_freeme_s *large_args_free = NULL') + freelines.add('if (large_args_free != NULL)' + ' _cffi_free_array_arguments(large_args_free);') def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( self._gettypenum(tp), fromvar, tovar)) self._prnt(' if (datasize != 0) {') - self._prnt(' if (datasize < 0)') - self._prnt(' %s;' % errcode) - self._prnt(' %s = alloca((size_t)datasize);' % (tovar,)) - self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,)) - self._prnt(' if (_cffi_convert_array_from_object(' - '(char *)%s, _cffi_type(%d), %s) < 0)' % ( - tovar, self._gettypenum(tp), fromvar)) + self._prnt(' %s = ((size_t)datasize) <= 640 ? ' + 'alloca((size_t)datasize) : NULL;' % (tovar,)) + self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, ' + '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar)) + self._prnt(' datasize, &large_args_free) < 0)') self._prnt(' %s;' % errcode) self._prnt(' }') @@ -369,15 +370,17 @@ prnt(' %s;' % type.get_c_name(' x%d' % i, context)) # localvars = set() + freelines = set() for type in tp.args: - self._extra_local_variables(type, localvars) - for decl in localvars: + self._extra_local_variables(type, localvars, freelines) + for decl in sorted(localvars): prnt(' %s;' % (decl,)) # if not isinstance(tp.result, model.VoidType): result_code = 'result = ' context = 'result of %s' % name prnt(' %s;' % tp.result.get_c_name(' result', context)) + prnt(' PyObject *pyresult;') else: result_code = '' # @@ -409,9 +412,14 @@ if numargs == 0: prnt(' (void)noarg; /* unused */') if result_code: - prnt(' return %s;' % + prnt(' pyresult = %s;' % self._convert_expr_from_c(tp.result, 'result', 'result type')) + for freeline in freelines: + prnt(' ' + freeline) + prnt(' return pyresult;') else: + for freeline in freelines: + prnt(' ' + freeline) prnt(' Py_INCREF(Py_None);') prnt(' return Py_None;') prnt('}') @@ -981,6 +989,59 @@ return PyBool_FromLong(was_alive); } +union _cffi_union_alignment_u { + unsigned char m_char; + unsigned short m_short; + unsigned int m_int; + unsigned long m_long; + unsigned long long m_longlong; + float m_float; + double m_double; + long double m_longdouble; +}; + +struct _cffi_freeme_s { + struct _cffi_freeme_s *next; + union _cffi_union_alignment_u alignment; +}; + +#ifdef __GNUC__ + __attribute__((unused)) +#endif +static int _cffi_convert_array_argument(CTypeDescrObject *ctptr, PyObject *arg, + char **output_data, Py_ssize_t datasize, + struct _cffi_freeme_s **freeme) +{ + char *p; + if (datasize < 0) + return -1; + + p = *output_data; + if (p == NULL) { + struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc( + offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize); + if (fp == NULL) + return -1; + fp->next = *freeme; + *freeme = fp; + p = *output_data = (char *)&fp->alignment; + } + memset((void *)p, 0, (size_t)datasize); + return _cffi_convert_array_from_object(p, ctptr, arg); +} + +#ifdef __GNUC__ + __attribute__((unused)) +#endif +static void _cffi_free_array_arguments(struct _cffi_freeme_s *freeme) +{ + do { + void *p = (void *)freeme; + freeme = freeme->next; + PyObject_Free(p); + } while (freeme != NULL); +} + static int _cffi_init(void) { PyObject *module, *c_api_object = NULL; diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py --- a/pypy/module/_cffi_backend/__init__.py +++ b/pypy/module/_cffi_backend/__init__.py @@ -1,1 +1,1 @@ -VERSION = "1.13.2" +VERSION = "1.14.0" diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -1,7 +1,7 @@ # ____________________________________________________________ import sys -assert __version__ == "1.13.2", ("This test_c.py file is for testing a version" +assert __version__ == "1.14.0", ("This test_c.py file is for testing a version" " of cffi that differs from the one that we" " get from 'import _cffi_backend'") if sys.version_info < (3,): From pypy.commits at gmail.com Fri Feb 7 04:33:38 2020 From: pypy.commits at gmail.com (arigo) Date: Fri, 07 Feb 2020 01:33:38 -0800 (PST) Subject: [pypy-commit] pypy py3.6: #3166 Message-ID: <5e3d2ef2.1c69fb81.47360.ad4a@mx.google.com> Author: Armin Rigo Branch: py3.6 Changeset: r98680:f13039d71ef7 Date: 2020-02-07 10:32 +0100 http://bitbucket.org/pypy/pypy/changeset/f13039d71ef7/ Log: #3166 Obscure ordering-of-which-error-to-report-first issue diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py --- a/pypy/objspace/std/test/test_unicodeobject.py +++ b/pypy/objspace/std/test/test_unicodeobject.py @@ -1281,6 +1281,15 @@ assert str(e.value) == 'decoding str is not supported' e = raises(TypeError, str, z, 'supposedly_the_encoding') assert str(e.value) == 'decoding str is not supported' + # + e = raises(TypeError, str, 42, 'supposedly_the_encoding') + assert str(e.value) in [ + 'decoding to str: a bytes-like object is required, not int', + 'decoding to str: need a bytes-like object, int found'] + e = raises(TypeError, str, None, 'supposedly_the_encoding') + assert str(e.value) in [ + 'decoding to str: a bytes-like object is required, not None', + 'decoding to str: need a bytes-like object, NoneType found'] def test_reduce_iterator(self): it = iter(u"abcdef") diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py --- a/pypy/objspace/std/unicodeobject.py +++ b/pypy/objspace/std/unicodeobject.py @@ -1370,14 +1370,23 @@ def decode_object(space, w_obj, encoding, errors=None): from pypy.module._codecs.interp_codecs import _call_codec, lookup_text_codec + # in all cases, call space.charbuf_w() first. This will fail with a + # TypeError if w_obj is of a random type. Do this even if we're not + # going to use 's' + try: + s = space.charbuf_w(w_obj) + except OperationError as e: + if not e.match(space, space.w_TypeError): + raise + raise oefmt(space.w_TypeError, "decoding to str: %S", + e.get_w_value(space)) + # if errors == 'strict' or errors is None: # fast paths if encoding == 'ascii': - s = space.charbuf_w(w_obj) unicodehelper.check_ascii_or_raise(space, s) return space.newtext(s, len(s)) if encoding == 'utf-8' or encoding == 'utf8': - s = space.charbuf_w(w_obj) lgt = unicodehelper.check_utf8_or_raise(space, s) return space.newutf8(s, lgt) if encoding is None: From pypy.commits at gmail.com Fri Feb 7 06:33:25 2020 From: pypy.commits at gmail.com (mattip) Date: Fri, 07 Feb 2020 03:33:25 -0800 (PST) Subject: [pypy-commit] benchmarks single-run: fix bad merge Message-ID: <5e3d4b05.1c69fb81.8abc6.cfe1@mx.google.com> Author: Matti Picus Branch: single-run Changeset: r448:a6fedeeb3d70 Date: 2020-02-07 13:32 +0200 http://bitbucket.org/pypy/benchmarks/changeset/a6fedeeb3d70/ Log: fix bad merge diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -218,8 +218,11 @@ os.mkdir(docdir) htmldir = os.path.join(builddir, 'html') os.mkdir(htmldir) + env = os.environ.copy() + env['PYTHONPATH'] = os.pathsep.join([relative('lib'), relative('lib/jinja2')]) args = python + [build, '-b', 'html', '-d', docdir, maindir, htmldir] - proc = subprocess.Popen(args, stderr=subprocess.PIPE, stdout=subprocess.PIPE) + proc = subprocess.Popen(args, stderr=subprocess.PIPE, stdout=subprocess.PIPE, + env=env) out, err = proc.communicate() retcode = proc.poll() if retcode != 0: From pypy.commits at gmail.com Fri Feb 7 07:05:36 2020 From: pypy.commits at gmail.com (mattip) Date: Fri, 07 Feb 2020 04:05:36 -0800 (PST) Subject: [pypy-commit] benchmarks single-run: update help for --args Message-ID: <5e3d5290.1c69fb81.b6145.de6c@mx.google.com> Author: Matti Picus Branch: single-run Changeset: r449:6f1745431542 Date: 2020-02-07 14:05 +0200 http://bitbucket.org/pypy/benchmarks/changeset/6f1745431542/ Log: update help for --args diff --git a/runner.py b/runner.py --- a/runner.py +++ b/runner.py @@ -126,13 +126,7 @@ 'result json and used for the upload. (default: None)')) benchmark_group.add_option( "-a", "--args", default="", - help=("Pass extra arguments to the python binaries." - " If there is a comma in this option's value, the" - " arguments before the comma (interpreted as a" - " space-separated list) are passed to the baseline" - " python, and the arguments after are passed to" - " the changed python. If there's no comma, the" - " same options are passed to both.")) + help=("Pass extra arguments to the python binary")) benchmark_group.add_option( "--fast", default=False, action="store_true", help="Run shorter benchmark runs.") diff --git a/unladen_swallow/perf.py b/unladen_swallow/perf.py --- a/unladen_swallow/perf.py +++ b/unladen_swallow/perf.py @@ -1325,13 +1325,7 @@ parser.add_option("-m", "--track_memory", action="store_true", help="Track memory usage. This only works on Linux.") parser.add_option("-a", "--args", default="", - help=("Pass extra arguments to the python binaries." - " If there is a comma in this option's value, the" - " arguments before the comma (interpreted as a" - " space-separated list) are passed to the baseline" - " python, and the arguments after are passed to the" - " changed python. If there's no comma, the same" - " options are passed to both.")) + help=("Pass extra arguments to the python binary.")) parser.add_option("-b", "--benchmarks", metavar="BM_LIST", default="", help=("Comma-separated list of benchmarks to run. Can" + " contain both positive and negative arguments:" + From pypy.commits at gmail.com Fri Feb 7 10:14:40 2020 From: pypy.commits at gmail.com (mattip) Date: Fri, 07 Feb 2020 07:14:40 -0800 (PST) Subject: [pypy-commit] benchmarks single-run: make sure sphinx benchmark runs use the same docutils Message-ID: <5e3d7ee0.1c69fb81.99e85.0945@mx.google.com> Author: Matti Picus Branch: single-run Changeset: r450:1d835bfd140d Date: 2020-02-07 17:14 +0200 http://bitbucket.org/pypy/benchmarks/changeset/1d835bfd140d/ Log: make sure sphinx benchmark runs use the same docutils diff --git a/benchmarks.py b/benchmarks.py --- a/benchmarks.py +++ b/benchmarks.py @@ -219,7 +219,10 @@ htmldir = os.path.join(builddir, 'html') os.mkdir(htmldir) env = os.environ.copy() - env['PYTHONPATH'] = os.pathsep.join([relative('lib'), relative('lib/jinja2')]) + major = sys.version_info.major + env['PYTHONPATH'] = os.pathsep.join([relative('lib'), + relative('lib/jinja2'), + relative('lib/cpython-doc/tools/docutils%d' % major)]) args = python + [build, '-b', 'html', '-d', docdir, maindir, htmldir] proc = subprocess.Popen(args, stderr=subprocess.PIPE, stdout=subprocess.PIPE, env=env) From pypy.commits at gmail.com Fri Feb 7 10:50:04 2020 From: pypy.commits at gmail.com (arigo) Date: Fri, 07 Feb 2020 07:50:04 -0800 (PST) Subject: [pypy-commit] cffi release-1.14: Release branch Message-ID: <5e3d872c.1c69fb81.e4555.12a8@mx.google.com> Author: Armin Rigo Branch: release-1.14 Changeset: r3337:6a87aa6bf3f3 Date: 2020-02-07 16:40 +0100 http://bitbucket.org/cffi/cffi/changeset/6a87aa6bf3f3/ Log: Release branch From pypy.commits at gmail.com Fri Feb 7 10:50:06 2020 From: pypy.commits at gmail.com (arigo) Date: Fri, 07 Feb 2020 07:50:06 -0800 (PST) Subject: [pypy-commit] cffi release-1.14: md5/sha Message-ID: <5e3d872e.1c69fb81.fd317.0c4f@mx.google.com> Author: Armin Rigo Branch: release-1.14 Changeset: r3338:694e7139131f Date: 2020-02-07 16:49 +0100 http://bitbucket.org/cffi/cffi/changeset/694e7139131f/ Log: md5/sha diff --git a/doc/source/installation.rst b/doc/source/installation.rst --- a/doc/source/installation.rst +++ b/doc/source/installation.rst @@ -54,11 +54,11 @@ * Checksums of the "source" package version 1.14.0: - - MD5: ... + - MD5: 74845f8d2b7b583dd9a3574f402edf39 - - SHA: ... + - SHA: 2a8f05a7d51d77ef1e641cb359a54e4d8fa019cb - - SHA256: ... + - SHA256: 2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6 * Or grab the most current version from the `Bitbucket page`_: ``hg clone https://bitbucket.org/cffi/cffi`` From pypy.commits at gmail.com Fri Feb 7 10:50:09 2020 From: pypy.commits at gmail.com (arigo) Date: Fri, 07 Feb 2020 07:50:09 -0800 (PST) Subject: [pypy-commit] cffi default: hg merge release-1.14 Message-ID: <5e3d8731.1c69fb81.b5c80.1e30@mx.google.com> Author: Armin Rigo Branch: Changeset: r3340:dd8402bc57e3 Date: 2020-02-07 16:49 +0100 http://bitbucket.org/cffi/cffi/changeset/dd8402bc57e3/ Log: hg merge release-1.14 diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -24,3 +24,4 @@ 17c06e75f54cf5a31865961f0b498f99232a0bc8 v1.13.0 9cc790d05bc5256eee32fddbe60aadf24f14ce44 v1.13.1 0c9be4c0d79867d108c60ac3c66e2fb3e89aaae9 v1.13.2 +694e7139131f2582e0c872b8ecbc50e8e5451dbf v1.14.0 diff --git a/doc/source/installation.rst b/doc/source/installation.rst --- a/doc/source/installation.rst +++ b/doc/source/installation.rst @@ -54,11 +54,11 @@ * Checksums of the "source" package version 1.14.0: - - MD5: ... + - MD5: 74845f8d2b7b583dd9a3574f402edf39 - - SHA: ... + - SHA: 2a8f05a7d51d77ef1e641cb359a54e4d8fa019cb - - SHA256: ... + - SHA256: 2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6 * Or grab the most current version from the `Bitbucket page`_: ``hg clone https://bitbucket.org/cffi/cffi`` From pypy.commits at gmail.com Fri Feb 7 10:50:08 2020 From: pypy.commits at gmail.com (arigo) Date: Fri, 07 Feb 2020 07:50:08 -0800 (PST) Subject: [pypy-commit] cffi release-1.14: Added tag v1.14.0 for changeset 694e7139131f Message-ID: <5e3d8730.1c69fb81.92a6f.1914@mx.google.com> Author: Armin Rigo Branch: release-1.14 Changeset: r3339:1e69882a43d7 Date: 2020-02-07 16:49 +0100 http://bitbucket.org/cffi/cffi/changeset/1e69882a43d7/ Log: Added tag v1.14.0 for changeset 694e7139131f diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -24,3 +24,4 @@ 17c06e75f54cf5a31865961f0b498f99232a0bc8 v1.13.0 9cc790d05bc5256eee32fddbe60aadf24f14ce44 v1.13.1 0c9be4c0d79867d108c60ac3c66e2fb3e89aaae9 v1.13.2 +694e7139131f2582e0c872b8ecbc50e8e5451dbf v1.14.0 From pypy.commits at gmail.com Fri Feb 7 11:04:36 2020 From: pypy.commits at gmail.com (arigo) Date: Fri, 07 Feb 2020 08:04:36 -0800 (PST) Subject: [pypy-commit] cffi default: Move some whatsnew entries into the "Older version" heading Message-ID: <5e3d8a94.1c69fb81.e4555.15eb@mx.google.com> Author: Armin Rigo Branch: Changeset: r3341:41fecd428c08 Date: 2020-02-07 17:02 +0100 http://bitbucket.org/cffi/cffi/changeset/41fecd428c08/ Log: Move some whatsnew entries into the "Older version" heading diff --git a/doc/source/whatsnew.rst b/doc/source/whatsnew.rst --- a/doc/source/whatsnew.rst +++ b/doc/source/whatsnew.rst @@ -82,8 +82,11 @@ recursion, with ``ffi.cdef("""struct X { void(*fnptr)(struct X); };""")`` +Older Versions +============== + v1.12.3 -======= +------- * Fix for nested struct types that end in a var-sized array (#405). @@ -94,13 +97,13 @@ v1.12.2 -======= +------- * Added temporary workaround to compile on CPython 3.8.0a2. v1.12.1 -======= +------- * CPython 3 on Windows: we again no longer compile with ``Py_LIMITED_API`` by default because such modules *still* cannot be used with virtualenv. @@ -116,7 +119,7 @@ v1.12 -===== +----- * `Direct support for pkg-config`__. @@ -154,9 +157,6 @@ .. _`issue #362`: https://bitbucket.org/cffi/cffi/issues/362/ -Older Versions -============== - v1.11.5 ------- From pypy.commits at gmail.com Sat Feb 8 05:19:02 2020 From: pypy.commits at gmail.com (cfbolz) Date: Sat, 08 Feb 2020 02:19:02 -0800 (PST) Subject: [pypy-commit] pypy record-known-result: optimize int(str(i)) and same for rbigints. (Note that the other direction is Message-ID: <5e3e8b16.1c69fb81.f6360.ca31@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: record-known-result Changeset: r98682:452d076e43fa Date: 2020-02-06 23:55 +0100 http://bitbucket.org/pypy/pypy/changeset/452d076e43fa/ Log: optimize int(str(i)) and same for rbigints. (Note that the other direction is not necessarily correct, because int(" 123") == 123) (this is actually more useful than it appears, as the decimal module converts its numbers back and forth between ints/longs and strs all the time) diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -312,6 +312,7 @@ # this is a weird op! we don't want to execute anything, so just record # an operation self.metainterp._record_helper_nonpure_varargs(rop.RECORD_KNOWN_RESULT, None, calldescr, allboxes) + opimpl_record_known_result_r_ir_v = opimpl_record_known_result_i_ir_v @arguments("box", "box") def opimpl_record_exact_value_r(self, box, const_box): diff --git a/rpython/jit/metainterp/test/test_string.py b/rpython/jit/metainterp/test/test_string.py --- a/rpython/jit/metainterp/test/test_string.py +++ b/rpython/jit/metainterp/test/test_string.py @@ -1075,3 +1075,33 @@ assert res == f(1) self.check_simple_loop(int_sub=1, guard_false=1) + def test_int_to_str_and_back(self): + driver = JitDriver(greens = [], reds = ['n', 'res']) + + def f(n): + res = 0 + while n < 21: + driver.jit_merge_point(n=n, res=res) + n += 1 + res += int(str(n)) + return res + + res = self.meta_interp(f, [1], backendopt=True) + assert res == f(1) + self.check_simple_loop(call_r=1, call_i=0) + + def test_rbigint_to_str_and_back(self): + from rpython.rlib.rbigint import rbigint + driver = JitDriver(greens = [], reds = ['n', 'res']) + + def f(n): + res = rbigint.fromint(0) + while n < 21: + driver.jit_merge_point(n=n, res=res) + n += 1 + res = res.add(rbigint.fromstr(res.str(), 10)) + return res.int_and_(0xffff).toint() + + res = self.meta_interp(f, [1], backendopt=True) + assert res == f(1) + self.check_simple_loop(call_r=2) # one add, one str, the fromstr is gone diff --git a/rpython/rlib/rbigint.py b/rpython/rlib/rbigint.py --- a/rpython/rlib/rbigint.py +++ b/rpython/rlib/rbigint.py @@ -509,8 +509,13 @@ return self.format(BASE10, suffix="L") return str(x) + "L" + def str(self): + res = self._str_impl() + jit.record_known_result(self, rbigint.fromstr, res, 10, False) + return res + @jit.elidable - def str(self): + def _str_impl(self): try: x = self.toint() except OverflowError: diff --git a/rpython/rtyper/rint.py b/rpython/rtyper/rint.py --- a/rpython/rtyper/rint.py +++ b/rpython/rtyper/rint.py @@ -146,10 +146,12 @@ hop.exception_cannot_occur() return vlist[0] - @jit.elidable def ll_str(self, i): from rpython.rtyper.lltypesystem.ll_str import ll_int2dec - return ll_int2dec(i) + from rpython.rtyper.lltypesystem.rstr import LLHelpers + res = ll_int2dec(i) + jit.record_known_result(i, LLHelpers.ll_int, res, 10) + return res def rtype_hex(self, hop): from rpython.rtyper.lltypesystem.ll_str import ll_int2hex From pypy.commits at gmail.com Sat Feb 8 05:18:59 2020 From: pypy.commits at gmail.com (cfbolz) Date: Sat, 08 Feb 2020 02:18:59 -0800 (PST) Subject: [pypy-commit] pypy record-known-result: merge default Message-ID: <5e3e8b13.1c69fb81.6a91c.cfb3@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: record-known-result Changeset: r98681:5db9d6a810bb Date: 2020-02-06 22:03 +0100 http://bitbucket.org/pypy/pypy/changeset/5db9d6a810bb/ Log: merge default diff too long, truncating to 2000 out of 150047 lines diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -17,8 +17,8 @@ ^site-packages$ ^site-packages/.*$ ^site-packages/.*$ -^bin$ ^pypy/bin/pypy-c +^pypy/lib/ ^pypy/module/cpyext/src/.+\.o$ ^pypy/module/cpyext/src/.+\.obj$ ^pypy/module/cpyext/test/.+\.errors$ diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -57,3 +57,16 @@ 4a68d8d3d2fc1faec2e83bcb4d28559099092574 release-pypy2.7-v7.2.0rc2 4a68d8d3d2fc1faec2e83bcb4d28559099092574 release-pypy2.7-v7.2.0 5da45ced70e515f94686be0df47c59abd1348ebc release-pypy3.6-v7.2.0 +e6471221abc16f4584a07fbfeece7ebcaeb7fc38 release-pypy2.7-v7.3.0rc1 +533398cfd64e5146a07c4824e90a1b629c8b6523 release-pypy3.6-v7.3.0rc1 +285307a0f5a77ffa46781b5c54c52eb1c385081d release-pypy2.7-v7.3.0rc2 +008914050baeedb6d3ca30fe26ef43b78bb63841 release-pypy3.6-v7.3.0rc2 +c124c11a5921bf12797b08a696753a12ae82595a release-pypy3.6-v7.2.0rc3 +e7e02dccbd8c14fa2d4880f6bd4c47362a8952f5 release-pypy3.6-v7.3.0rc3 +c124c11a5921bf12797b08a696753a12ae82595a release-pypy2.7-v7.3.0rc3 +c124c11a5921bf12797b08a696753a12ae82595a release-pypy3.6-v7.2.0rc3 +0000000000000000000000000000000000000000 release-pypy3.6-v7.2.0rc3 +1608da62bfc71e8ac775121dd0b21bb72e61c6ea release-pypy3.6-v7.3.0rc4 +724f1a7d62e8d8ac0fa20823f5c35497b29ad56f release-pypy2.7-v7.3.0rc4 +724f1a7d62e8d8ac0fa20823f5c35497b29ad56f release-pypy2.7-v7.3.0 +1608da62bfc71e8ac775121dd0b21bb72e61c6ea release-pypy3.6-v7.3.0 diff --git a/LICENSE b/LICENSE --- a/LICENSE +++ b/LICENSE @@ -3,10 +3,11 @@ License ======= -Except when otherwise stated (look for LICENSE files in directories or -information at the beginning of each file) all software and documentation in -the 'rpython', 'pypy', 'ctype_configure', 'dotviewer', 'demo', 'lib_pypy', -'py', and '_pytest' directories is licensed as follows: +Except when otherwise stated (look for LICENSE files in directories +or information at the beginning of each file) all software and +documentation in the 'rpython', 'pypy', 'ctype_configure', 'dotviewer', +'demo', 'extra_tests', 'include', 'lib_pypy', 'py', and '_pytest' +directories is licensed as follows: The MIT License @@ -30,7 +31,7 @@ DEALINGS IN THE SOFTWARE. -PyPy Copyright holders 2003-2019 +PyPy Copyright holders 2003-2020 -------------------------------- Except when otherwise stated (look for LICENSE files or information at @@ -98,16 +99,16 @@ Spenser Bauman Michal Bendowski Jan de Mooij + Stefano Rivera Tyler Wade + Stefan Beyer Vincent Legoll Michael Foord Stephan Diehl - Stefano Rivera Jean-Paul Calderone Stefan Schwarzer Tomek Meka Valentino Volonghi - Stefan Beyer Patrick Maupin Devin Jeanpierre Bob Ippolito @@ -136,9 +137,10 @@ Jean-Philippe St. Pierre Guido van Rossum Pavel Vinogradov + Stian Andreassen + Julian Berman William Leslie Paweł Piotr Przeradowski - Stian Andreassen marky1991 Ilya Osadchiy Tobias Oberstein @@ -149,7 +151,7 @@ tav Georg Brandl Joannah Nanjekye - Julian Berman + Yannick Jadoul Bert Freudenberg Wanja Saatkamp Mike Blume @@ -274,6 +276,7 @@ Lutz Paelike Ian Foote Philipp Rustemeuer + Bernd Schoeller Logan Chien Catalin Gabriel Manciu Jacob Oscarson @@ -301,7 +304,6 @@ Laurens Van Houtven Bobby Impollonia Roberto De Ioris - Yannick Jadoul Jeong YunWon Christopher Armstrong Aaron Tubbs @@ -356,6 +358,7 @@ Daniil Yarancev Min RK OlivierBlanvillain + bernd.schoeller at inf.ethz.ch dakarpov at gmail.com Jonas Pfannschmidt Zearin @@ -397,6 +400,7 @@ Jesdi Konrad Delong Dinu Gherman + Sam Edwards pizi Tomáš Pružina James Robert diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile @@ -2,7 +2,6 @@ all: pypy-c cffi_imports PYPY_EXECUTABLE := $(shell which pypy) -URAM := $(shell python -c "import sys; print 4.5 if sys.maxint>1<<32 else 2.5") ifeq ($(PYPY_EXECUTABLE),) RUNINTERP = python @@ -10,6 +9,8 @@ RUNINTERP = $(PYPY_EXECUTABLE) endif +URAM := $(shell $(RUNINTERP) -c "import sys; print 4.5 if sys.maxint>1<<32 else 2.5") + .PHONY: pypy-c cffi_imports pypy-c: diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -9,15 +9,15 @@ The home page for the interpreter is: - http://pypy.org/ + https://pypy.org/ If you want to help developing PyPy, this documentation might help you: - http://doc.pypy.org/ + https://doc.pypy.org/ More documentation about the RPython framework can be found here: - http://rpython.readthedocs.io/ + https://rpython.readthedocs.io/ The source for the documentation is in the pypy/doc directory. @@ -25,7 +25,7 @@ Using PyPy instead of CPython ----------------------------- -Please read the information at http://pypy.org/ to find the correct way to +Please read the information at https://pypy.org/ to find the correct way to download and use PyPy as an alternative to CPython. @@ -36,7 +36,7 @@ interpreter. It is time-consuming and requires significant computing resources. More information can be found here: - http://doc.pypy.org/en/latest/build.html + https://doc.pypy.org/en/latest/build.html Enjoy and send us feedback! diff --git a/extra_tests/cffi_tests/cffi0/backend_tests.py b/extra_tests/cffi_tests/cffi0/backend_tests.py --- a/extra_tests/cffi_tests/cffi0/backend_tests.py +++ b/extra_tests/cffi_tests/cffi0/backend_tests.py @@ -1242,7 +1242,7 @@ py.test.skip(str(e)) f.write(ffi.buffer(a, 1000 * ffi.sizeof("int"))) f.seek(0) - assert f.read() == array.array('i', range(1000)).tostring() + assert f.read() == arraytostring(array.array('i', range(1000))) f.seek(0) b = ffi.new("int[]", 1005) f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int"))) @@ -1261,7 +1261,7 @@ py.test.skip(str(e)) f.write(ffi.buffer(a, 1000 * ffi.sizeof("int"))) f.seek(0) - assert f.read() == array.array('i', range(1000)).tostring() + assert f.read() == arraytostring(array.array('i', range(1000))) f.seek(0) b = ffi.new("int[]", 1005) f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int"))) diff --git a/extra_tests/cffi_tests/cffi0/test_function.py b/extra_tests/cffi_tests/cffi0/test_function.py --- a/extra_tests/cffi_tests/cffi0/test_function.py +++ b/extra_tests/cffi_tests/cffi0/test_function.py @@ -114,7 +114,7 @@ ffi = FFI(backend=self.Backend()) ffi.cdef(""" int fputs(const char *, void *); - void *stderr; + extern void *stderr; """) needs_dlopen_none() ffi.C = ffi.dlopen(None) @@ -131,7 +131,7 @@ ffi = FFI(backend=self.Backend()) ffi.cdef(""" int fputs(char *, void *); - void *stderr; + extern void *stderr; """) needs_dlopen_none() ffi.C = ffi.dlopen(None) @@ -148,7 +148,7 @@ ffi = FFI(backend=self.Backend()) ffi.cdef(""" int fprintf(void *, const char *format, ...); - void *stderr; + extern void *stderr; """) needs_dlopen_none() ffi.C = ffi.dlopen(None) @@ -210,7 +210,7 @@ py.test.skip("probably no symbol 'stderr' in the lib") ffi.cdef(""" int fputs(const char *, void *); - void *stderr; + extern void *stderr; """) needs_dlopen_none() ffi.C = ffi.dlopen(None) @@ -257,7 +257,7 @@ py.test.skip("probably no symbol 'stdout' in the lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - void *stdout; + extern void *stdout; """) needs_dlopen_none() C = ffi.dlopen(None) @@ -497,7 +497,7 @@ ffi.cdef(""" typedef enum { MYE1, MYE2 } myenum_t; double myfunc(double); - double myvar; + extern double myvar; const double myconst; #define MYFOO 42 """) @@ -508,7 +508,7 @@ if self.Backend is CTypesBackend: py.test.skip("not with the ctypes backend") ffi = FFI(backend=self.Backend()) - ffi.cdef("int foobar(void); int foobaz;") + ffi.cdef("int foobar(void); extern int foobaz;") lib = ffi.dlopen(lib_m) ffi.dlclose(lib) e = py.test.raises(ValueError, getattr, lib, 'foobar') diff --git a/extra_tests/cffi_tests/cffi0/test_ownlib.py b/extra_tests/cffi_tests/cffi0/test_ownlib.py --- a/extra_tests/cffi_tests/cffi0/test_ownlib.py +++ b/extra_tests/cffi_tests/cffi0/test_ownlib.py @@ -202,7 +202,7 @@ py.test.skip("fix the auto-generation of the tiny test lib") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int my_array[7]; + extern int my_array[7]; """) ownlib = ffi.dlopen(self.module) for i in range(7): @@ -224,7 +224,7 @@ py.test.skip("not supported by the ctypes backend") ffi = FFI(backend=self.Backend()) ffi.cdef(""" - int my_array[]; + extern int my_array[]; """) ownlib = ffi.dlopen(self.module) for i in range(7): @@ -292,7 +292,7 @@ long bottom; } RECT; - long left, top, right, bottom; + extern long left, top, right, bottom; RECT ReturnRect(int i, RECT ar, RECT* br, POINT cp, RECT dr, RECT *er, POINT fp, RECT gr); @@ -322,7 +322,7 @@ if self.Backend is CTypesBackend: py.test.skip("not implemented with the ctypes backend") ffi = FFI(backend=self.Backend()) - ffi.cdef("long left; int test_getting_errno(void);") + ffi.cdef("extern long left; int test_getting_errno(void);") lib = ffi.dlopen(self.module) lib.left = 123456 p = ffi.addressof(lib, "left") @@ -372,3 +372,29 @@ assert s.top == 22 assert s.right == 33 assert s.bottom == 44 + + def test_dlopen_handle(self): + if self.module is None: + py.test.skip("fix the auto-generation of the tiny test lib") + if sys.platform == 'win32': + py.test.skip("uses 'dl' explicitly") + if self.__class__.Backend is CTypesBackend: + py.test.skip("not for the ctypes backend") + backend = self.Backend() + ffi1 = FFI(backend=backend) + ffi1.cdef("""void *dlopen(const char *filename, int flags); + int dlclose(void *handle);""") + lib1 = ffi1.dlopen('dl') + handle = lib1.dlopen(self.module.encode(sys.getfilesystemencoding()), + backend.RTLD_LAZY) + assert ffi1.typeof(handle) == ffi1.typeof("void *") + assert handle + + ffi = FFI(backend=backend) + ffi.cdef("""unsigned short foo_2bytes(unsigned short a);""") + lib = ffi.dlopen(handle) + x = lib.foo_2bytes(1000) + assert x == 1042 + + err = lib1.dlclose(handle) + assert err == 0 diff --git a/extra_tests/cffi_tests/cffi0/test_parsing.py b/extra_tests/cffi_tests/cffi0/test_parsing.py --- a/extra_tests/cffi_tests/cffi0/test_parsing.py +++ b/extra_tests/cffi_tests/cffi0/test_parsing.py @@ -325,6 +325,7 @@ assert value == sys.maxsize * 2 - 40 def test__is_constant_globalvar(): + import warnings for input, expected_output in [ ("int a;", False), ("const int a;", True), @@ -342,10 +343,13 @@ ("const int a[5][6];", False), ]: ffi = FFI() - ffi.cdef(input) + with warnings.catch_warnings(record=True) as log: + warnings.simplefilter("always") + ffi.cdef(input) declarations = ffi._parser._declarations assert ('constant a' in declarations) == expected_output assert ('variable a' in declarations) == (not expected_output) + assert len(log) == (1 - expected_output) def test_restrict(): from cffi import model @@ -355,7 +359,7 @@ ("int *a;", False), ]: ffi = FFI() - ffi.cdef(input) + ffi.cdef("extern " + input) tp, quals = ffi._parser._declarations['variable a'] assert bool(quals & model.Q_RESTRICT) == expected_output diff --git a/extra_tests/cffi_tests/cffi0/test_verify.py b/extra_tests/cffi_tests/cffi0/test_verify.py --- a/extra_tests/cffi_tests/cffi0/test_verify.py +++ b/extra_tests/cffi_tests/cffi0/test_verify.py @@ -4,6 +4,7 @@ import sys, os, math, weakref from cffi import FFI, VerificationError, VerificationMissing, model, FFIError from extra_tests.cffi_tests.support import * +from extra_tests.cffi_tests.support import extra_compile_args lib_m = ['m'] @@ -14,17 +15,6 @@ lib_m = ['msvcrt'] pass # no obvious -Werror equivalent on MSVC else: - if (sys.platform == 'darwin' and - [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]): - # assume a standard clang or gcc - extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion'] - # special things for clang - extra_compile_args.append('-Qunused-arguments') - else: - # assume a standard gcc - extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion', - '-Wno-unused-parameter'] - class FFI(FFI): def verify(self, *args, **kwds): return super(FFI, self).verify( @@ -287,7 +277,7 @@ def test_var_signed_integer_types(): ffi = FFI() lst = all_signed_integer_types(ffi) - csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_')) + csource = "\n".join(["static %s somevar_%s;" % (tp, tp.replace(' ', '_')) for tp in lst]) ffi.cdef(csource) lib = ffi.verify(csource) @@ -306,7 +296,7 @@ def test_var_unsigned_integer_types(): ffi = FFI() lst = all_unsigned_integer_types(ffi) - csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_')) + csource = "\n".join(["static %s somevar_%s;" % (tp, tp.replace(' ', '_')) for tp in lst]) ffi.cdef(csource) lib = ffi.verify(csource) @@ -818,8 +808,8 @@ def test_access_variable(): ffi = FFI() - ffi.cdef("int foo(void);\n" - "int somenumber;") + ffi.cdef("static int foo(void);\n" + "static int somenumber;") lib = ffi.verify(""" static int somenumber = 2; static int foo(void) { @@ -836,7 +826,7 @@ def test_access_address_of_variable(): # access the address of 'somenumber': need a trick ffi = FFI() - ffi.cdef("int somenumber; static int *const somenumberptr;") + ffi.cdef("static int somenumber; static int *const somenumberptr;") lib = ffi.verify(""" static int somenumber = 2; #define somenumberptr (&somenumber) @@ -849,7 +839,7 @@ def test_access_array_variable(length=5): ffi = FFI() ffi.cdef("int foo(int);\n" - "int somenumber[%s];" % (length,)) + "static int somenumber[%s];" % (length,)) lib = ffi.verify(""" static int somenumber[] = {2, 2, 3, 4, 5}; static int foo(int i) { @@ -881,7 +871,7 @@ ffi = FFI() ffi.cdef("struct foo { int x; ...; };\n" "int foo(int);\n" - "struct foo stuff;") + "static struct foo stuff;") lib = ffi.verify(""" struct foo { int x, y, z; }; static struct foo stuff = {2, 5, 8}; @@ -905,9 +895,9 @@ def test_access_callback(): ffi = FFI() - ffi.cdef("int (*cb)(int);\n" - "int foo(int);\n" - "void reset_cb(void);") + ffi.cdef("static int (*cb)(int);\n" + "static int foo(int);\n" + "static void reset_cb(void);") lib = ffi.verify(""" static int g(int x) { return x * 7; } static int (*cb)(int); @@ -923,9 +913,9 @@ def test_access_callback_function_typedef(): ffi = FFI() ffi.cdef("typedef int mycallback_t(int);\n" - "mycallback_t *cb;\n" - "int foo(int);\n" - "void reset_cb(void);") + "static mycallback_t *cb;\n" + "static int foo(int);\n" + "static void reset_cb(void);") lib = ffi.verify(""" static int g(int x) { return x * 7; } static int (*cb)(int); @@ -1075,7 +1065,7 @@ def test_autofilled_struct_as_argument_dynamic(): ffi = FFI() ffi.cdef("struct foo_s { long a; ...; };\n" - "int (*foo)(struct foo_s);") + "static int (*foo)(struct foo_s);") lib = ffi.verify(""" struct foo_s { double b; @@ -1084,7 +1074,7 @@ int foo1(struct foo_s s) { return (int)s.a - (int)s.b; } - int (*foo)(struct foo_s s) = &foo1; + static int (*foo)(struct foo_s s) = &foo1; """) e = py.test.raises(NotImplementedError, lib.foo, "?") msg = ("ctype 'struct foo_s' not supported as argument. It is a struct " @@ -1454,7 +1444,7 @@ py.test.skip("_Bool not in MSVC") ffi = FFI() ffi.cdef("struct foo_s { _Bool x; };" - "_Bool foo(_Bool); _Bool (*foop)(_Bool);") + "_Bool foo(_Bool); static _Bool (*foop)(_Bool);") lib = ffi.verify(""" struct foo_s { _Bool x; }; int foo(int arg) { @@ -1463,7 +1453,7 @@ _Bool _foofunc(_Bool x) { return !x; } - _Bool (*foop)(_Bool) = _foofunc; + static _Bool (*foop)(_Bool) = _foofunc; """) p = ffi.new("struct foo_s *") p.x = 1 @@ -1654,7 +1644,7 @@ def test_FILE_stored_explicitly(): ffi = FFI() - ffi.cdef("int myprintf11(const char *, int); FILE *myfile;") + ffi.cdef("int myprintf11(const char *, int); extern FILE *myfile;") lib = ffi.verify(""" #include FILE *myfile; @@ -1680,19 +1670,19 @@ def test_global_array_with_missing_length(): ffi = FFI() - ffi.cdef("int fooarray[];") + ffi.cdef("extern int fooarray[];") lib = ffi.verify("int fooarray[50];") assert repr(lib.fooarray).startswith("" def test_bug_const_char_ptr_array_2(): from cffi import FFI # ignore warnings ffi = FFI() - ffi.cdef("""const int a[];""") + ffi.cdef("""extern const int a[];""") lib = ffi.verify("""const int a[5];""") assert repr(ffi.typeof(lib.a)) == "" def _test_various_calls(force_libffi): cdef_source = """ - int xvalue; - long long ivalue, rvalue; - float fvalue; - double dvalue; - long double Dvalue; + extern int xvalue; + extern long long ivalue, rvalue; + extern float fvalue; + extern double dvalue; + extern long double Dvalue; signed char tf_bb(signed char x, signed char c); unsigned char tf_bB(signed char x, unsigned char c); short tf_bh(signed char x, short c); @@ -2148,7 +2138,7 @@ # exported symbols as well. So we must not export a simple name # like 'foo'! ffi1 = FFI() - ffi1.cdef("int foo_verify_dlopen_flags;") + ffi1.cdef("extern int foo_verify_dlopen_flags;") lib1 = ffi1.verify("int foo_verify_dlopen_flags;", flags=ffi1.RTLD_GLOBAL | ffi1.RTLD_LAZY) @@ -2162,7 +2152,7 @@ def get_second_lib(): # Hack, using modulename makes the test fail ffi2 = FFI() - ffi2.cdef("int foo_verify_dlopen_flags;") + ffi2.cdef("extern int foo_verify_dlopen_flags;") lib2 = ffi2.verify("int foo_verify_dlopen_flags;", flags=ffi2.RTLD_GLOBAL | ffi2.RTLD_LAZY) return lib2 diff --git a/extra_tests/cffi_tests/cffi0/test_zdistutils.py b/extra_tests/cffi_tests/cffi0/test_zdistutils.py --- a/extra_tests/cffi_tests/cffi0/test_zdistutils.py +++ b/extra_tests/cffi_tests/cffi0/test_zdistutils.py @@ -90,7 +90,7 @@ csrc = '/*hi there %s!2*/\n#include \n' % self v = Verifier(ffi, csrc, force_generic_engine=self.generic, libraries=[self.lib_m]) - basename = self.__class__.__name__ + 'test_compile_module' + basename = self.__class__.__name__[:10] + '_test_compile_module' v.modulefilename = filename = str(udir.join(basename + '.so')) v.compile_module() assert filename == v.modulefilename diff --git a/extra_tests/cffi_tests/cffi1/test_dlopen.py b/extra_tests/cffi_tests/cffi1/test_dlopen.py --- a/extra_tests/cffi_tests/cffi1/test_dlopen.py +++ b/extra_tests/cffi_tests/cffi1/test_dlopen.py @@ -7,7 +7,7 @@ def test_simple(): ffi = FFI() - ffi.cdef("int close(int); static const int BB = 42; int somevar;") + ffi.cdef("int close(int); static const int BB = 42; extern int somevar;") target = udir.join('test_simple.py') make_py_source(ffi, 'test_simple', str(target)) assert target.read() == r"""# auto-generated file @@ -197,7 +197,7 @@ def test_global_var(): ffi = FFI() - ffi.cdef("int myglob;") + ffi.cdef("extern int myglob;") target = udir.join('test_global_var.py') make_py_source(ffi, 'test_global_var', str(target)) assert target.read() == r"""# auto-generated file diff --git a/extra_tests/cffi_tests/cffi1/test_new_ffi_1.py b/extra_tests/cffi_tests/cffi1/test_new_ffi_1.py --- a/extra_tests/cffi_tests/cffi1/test_new_ffi_1.py +++ b/extra_tests/cffi_tests/cffi1/test_new_ffi_1.py @@ -1221,7 +1221,7 @@ py.test.skip(str(e)) f.write(ffi.buffer(a, 1000 * ffi.sizeof("int"))) f.seek(0) - assert f.read() == array.array('i', range(1000)).tostring() + assert f.read() == arraytostring(array.array('i', range(1000))) f.seek(0) b = ffi.new("int[]", 1005) f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int"))) @@ -1239,7 +1239,7 @@ py.test.skip(str(e)) f.write(ffi.buffer(a, 1000 * ffi.sizeof("int"))) f.seek(0) - assert f.read() == array.array('i', range(1000)).tostring() + assert f.read() == arraytostring(array.array('i', range(1000))) f.seek(0) b = ffi.new("int[]", 1005) f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int"))) @@ -1780,7 +1780,7 @@ def test_import_from_lib(self): ffi2 = cffi.FFI() - ffi2.cdef("int myfunc(int); int myvar;\n#define MYFOO ...\n") + ffi2.cdef("int myfunc(int); extern int myvar;\n#define MYFOO ...\n") outputfilename = recompile(ffi2, "_test_import_from_lib", "int myfunc(int x) { return x + 1; }\n" "int myvar = -5;\n" diff --git a/extra_tests/cffi_tests/cffi1/test_re_python.py b/extra_tests/cffi_tests/cffi1/test_re_python.py --- a/extra_tests/cffi_tests/cffi1/test_re_python.py +++ b/extra_tests/cffi_tests/cffi1/test_re_python.py @@ -64,11 +64,11 @@ #define BIGNEG -420000000000L int add42(int); int add43(int, ...); - int globalvar42; + extern int globalvar42; const int globalconst42; const char *const globalconsthello; int no_such_function(int); - int no_such_globalvar; + extern int no_such_globalvar; struct foo_s; typedef struct bar_s { int x; signed char a[]; } bar_t; enum foo_e { AA, BB, CC }; @@ -76,6 +76,7 @@ struct with_union { union { int a; char b; }; }; union with_struct { struct { int a; char b; }; }; struct NVGcolor { union { float rgba[4]; struct { float r,g,b,a; }; }; }; + typedef struct selfref { struct selfref *next; } *selfref_ptr_t; """) ffi.set_source('re_python_pysrc', None) ffi.emit_python_code(str(tmpdir.join('re_python_pysrc.py'))) @@ -255,3 +256,29 @@ assert ffi.offsetof("struct NVGcolor", "g") == FLOAT assert ffi.offsetof("struct NVGcolor", "b") == FLOAT * 2 assert ffi.offsetof("struct NVGcolor", "a") == FLOAT * 3 + +def test_selfref(): + # based on issue #429 + from re_python_pysrc import ffi + ffi.new("selfref_ptr_t") + +def test_dlopen_handle(): + import _cffi_backend + from re_python_pysrc import ffi + if sys.platform == 'win32': + py.test.skip("uses 'dl' explicitly") + ffi1 = FFI() + ffi1.cdef("""void *dlopen(const char *filename, int flags); + int dlclose(void *handle);""") + lib1 = ffi1.dlopen('dl') + handle = lib1.dlopen(extmod.encode(sys.getfilesystemencoding()), + _cffi_backend.RTLD_LAZY) + assert ffi1.typeof(handle) == ffi1.typeof("void *") + assert handle + + lib = ffi.dlopen(handle) + assert lib.add42(-10) == 32 + assert type(lib.add42) is _cffi_backend.FFI.CData + + err = lib1.dlclose(handle) + assert err == 0 diff --git a/extra_tests/cffi_tests/cffi1/test_recompiler.py b/extra_tests/cffi_tests/cffi1/test_recompiler.py --- a/extra_tests/cffi_tests/cffi1/test_recompiler.py +++ b/extra_tests/cffi_tests/cffi1/test_recompiler.py @@ -27,16 +27,18 @@ def verify(ffi, module_name, source, *args, **kwds): no_cpp = kwds.pop('no_cpp', False) + ignore_warnings = kwds.pop('ignore_warnings', False) kwds.setdefault('undef_macros', ['NDEBUG']) module_name = '_CFFI_' + module_name ffi.set_source(module_name, source) if not os.environ.get('NO_CPP') and not no_cpp: # test the .cpp mode too kwds.setdefault('source_extension', '.cpp') source = 'extern "C" {\n%s\n}' % (source,) - elif sys.platform != 'win32': + elif sys.platform != 'win32' and not ignore_warnings: # add '-Werror' to the existing 'extra_compile_args' flags + from extra_tests.cffi_tests.support import extra_compile_args kwds['extra_compile_args'] = (kwds.get('extra_compile_args', []) + - ['-Werror']) + extra_compile_args) return _verify(ffi, module_name, source, *args, **kwds) def test_set_source_no_slashes(): @@ -84,7 +86,7 @@ "(FUNCTION 1)(PRIMITIVE 7)(FUNCTION_END 1)(POINTER 0)") def test_type_table_array(): - check_type_table("int a[100];", + check_type_table("extern int a[100];", "(PRIMITIVE 7)(ARRAY 0)(None 100)") def test_type_table_typedef(): @@ -136,7 +138,8 @@ import math ffi = FFI() ffi.cdef("float sin(double); double cos(double);") - lib = verify(ffi, 'test_math_sin', '#include ') + lib = verify(ffi, 'test_math_sin', '#include ', + ignore_warnings=True) assert lib.cos(1.43) == math.cos(1.43) def test_repr_lib(): @@ -159,7 +162,7 @@ def test_global_var_array(): ffi = FFI() - ffi.cdef("int a[100];") + ffi.cdef("extern int a[100];") lib = verify(ffi, 'test_global_var_array', 'int a[100] = { 9999 };') lib.a[42] = 123456 assert lib.a[42] == 123456 @@ -183,7 +186,7 @@ def test_global_var_int(): ffi = FFI() - ffi.cdef("int a, b, c;") + ffi.cdef("extern int a, b, c;") lib = verify(ffi, 'test_global_var_int', 'int a = 999, b, c;') assert lib.a == 999 lib.a -= 1001 @@ -284,7 +287,7 @@ def test_dir(): ffi = FFI() - ffi.cdef("int ff(int); int aa; static const int my_constant;") + ffi.cdef("int ff(int); extern int aa; static const int my_constant;") lib = verify(ffi, 'test_dir', """ #define my_constant (-45) int aa; @@ -348,9 +351,9 @@ lib = verify(ffi, 'test_verify_exact_field_offset', """struct foo_s { short a; int b; };""") e = py.test.raises(ffi.error, ffi.new, "struct foo_s *", []) # lazily - assert str(e.value) == ("struct foo_s: wrong offset for field 'b' (cdef " - 'says 0, but C compiler says 4). fix it or use "...;" ' - "in the cdef for struct foo_s to make it flexible") + assert str(e.value).startswith( + "struct foo_s: wrong offset for field 'b' (cdef " + 'says 0, but C compiler says 4). fix it or use "...;" ') def test_type_caching(): ffi1 = FFI(); ffi1.cdef("struct foo_s;") @@ -406,7 +409,7 @@ def test_dotdotdot_global_array(): ffi = FFI() - ffi.cdef("int aa[...]; int bb[...];") + ffi.cdef("extern int aa[...]; extern int bb[...];") lib = verify(ffi, 'test_dotdotdot_global_array', "int aa[41]; int bb[12];") assert ffi.sizeof(lib.aa) == 41 * 4 @@ -561,37 +564,37 @@ def test_bad_size_of_global_1(): ffi = FFI() - ffi.cdef("short glob;") + ffi.cdef("extern short glob;") py.test.raises(VerificationError, verify, ffi, "test_bad_size_of_global_1", "long glob;") def test_bad_size_of_global_2(): ffi = FFI() - ffi.cdef("int glob[10];") + ffi.cdef("extern int glob[10];") py.test.raises(VerificationError, verify, ffi, "test_bad_size_of_global_2", "int glob[9];") def test_unspecified_size_of_global_1(): ffi = FFI() - ffi.cdef("int glob[];") + ffi.cdef("extern int glob[];") lib = verify(ffi, "test_unspecified_size_of_global_1", "int glob[10];") assert ffi.typeof(lib.glob) == ffi.typeof("int *") def test_unspecified_size_of_global_2(): ffi = FFI() - ffi.cdef("int glob[][5];") + ffi.cdef("extern int glob[][5];") lib = verify(ffi, "test_unspecified_size_of_global_2", "int glob[10][5];") assert ffi.typeof(lib.glob) == ffi.typeof("int(*)[5]") def test_unspecified_size_of_global_3(): ffi = FFI() - ffi.cdef("int glob[][...];") + ffi.cdef("extern int glob[][...];") lib = verify(ffi, "test_unspecified_size_of_global_3", "int glob[10][5];") assert ffi.typeof(lib.glob) == ffi.typeof("int(*)[5]") def test_unspecified_size_of_global_4(): ffi = FFI() - ffi.cdef("int glob[...][...];") + ffi.cdef("extern int glob[...][...];") lib = verify(ffi, "test_unspecified_size_of_global_4", "int glob[10][5];") assert ffi.typeof(lib.glob) == ffi.typeof("int[10][5]") @@ -645,7 +648,7 @@ ffi.cdef("sshort_t ff3(sshort_t);") lib = verify(ffi, "test_include_3", "typedef short sshort_t; //usually from a #include\n" - "sshort_t ff3(sshort_t x) { return x + 42; }") + "sshort_t ff3(sshort_t x) { return (sshort_t)(x + 42); }") assert lib.ff3(10) == 52 assert ffi.typeof(ffi.cast("sshort_t", 42)) is ffi.typeof("short") assert ffi1.typeof("sshort_t") is ffi.typeof("sshort_t") @@ -754,7 +757,7 @@ ffi = FFI() ffi.cdef(unicode("float sin(double); double cos(double);")) lib = verify(ffi, 'test_math_sin_unicode', unicode('#include '), - libraries=[unicode(lib_m)]) + libraries=[unicode(lib_m)], ignore_warnings=True) assert lib.cos(1.43) == math.cos(1.43) def test_incomplete_struct_as_arg(): @@ -814,7 +817,7 @@ def test_address_of_global_var(): ffi = FFI() ffi.cdef(""" - long bottom, bottoms[2]; + extern long bottom, bottoms[2]; long FetchRectBottom(void); long FetchRectBottoms1(void); #define FOOBAR 42 @@ -882,15 +885,20 @@ e5 = py.test.raises(TypeError, lib.foo2) e6 = py.test.raises(TypeError, lib.foo2, 42) e7 = py.test.raises(TypeError, lib.foo2, 45, 46, 47) - assert str(e1.value) == "foo0() takes no arguments (1 given)" - assert str(e2.value) == "foo0() takes no arguments (2 given)" - assert str(e3.value) == "foo1() takes exactly one argument (0 given)" - assert str(e4.value) == "foo1() takes exactly one argument (2 given)" - assert str(e5.value) in ["foo2 expected 2 arguments, got 0", + def st1(s): + s = str(s) + if s.startswith("_CFFI_test_unpack_args.CompiledLib."): + s = s[len("_CFFI_test_unpack_args.CompiledLib."):] + return s + assert st1(e1.value) == "foo0() takes no arguments (1 given)" + assert st1(e2.value) == "foo0() takes no arguments (2 given)" + assert st1(e3.value) == "foo1() takes exactly one argument (0 given)" + assert st1(e4.value) == "foo1() takes exactly one argument (2 given)" + assert st1(e5.value) in ["foo2 expected 2 arguments, got 0", "foo2() takes exactly 2 arguments (0 given)"] - assert str(e6.value) in ["foo2 expected 2 arguments, got 1", + assert st1(e6.value) in ["foo2 expected 2 arguments, got 1", "foo2() takes exactly 2 arguments (1 given)"] - assert str(e7.value) in ["foo2 expected 2 arguments, got 3", + assert st1(e7.value) in ["foo2 expected 2 arguments, got 3", "foo2() takes exactly 2 arguments (3 given)"] def test_address_of_function(): @@ -898,7 +906,7 @@ ffi.cdef("long myfunc(long x);") lib = verify(ffi, "test_addressof_function", """ char myfunc(char x) { return (char)(x + 42); } - """) + """, ignore_warnings=True) assert lib.myfunc(5) == 47 assert lib.myfunc(0xABC05) == 47 assert not isinstance(lib.myfunc, ffi.CData) @@ -969,7 +977,7 @@ ffi = FFI() ffi.cdef(""" typedef ... opaque_t; - opaque_t globvar; + extern opaque_t globvar; """) lib = verify(ffi, 'test_variable_of_unknown_size', """ typedef char opaque_t[6]; @@ -1014,7 +1022,7 @@ def test_call_with_incomplete_structs(): ffi = FFI() ffi.cdef("typedef struct {...;} foo_t; " - "foo_t myglob; " + "extern foo_t myglob; " "foo_t increment(foo_t s); " "double getx(foo_t s);") lib = verify(ffi, 'test_call_with_incomplete_structs', """ @@ -1058,7 +1066,7 @@ def test_global_var_array_2(): ffi = FFI() - ffi.cdef("int a[...][...];") + ffi.cdef("extern int a[...][...];") lib = verify(ffi, 'test_global_var_array_2', 'int a[10][8];') lib.a[9][7] = 123456 assert lib.a[9][7] == 123456 @@ -1071,7 +1079,7 @@ def test_global_var_array_3(): ffi = FFI() - ffi.cdef("int a[][...];") + ffi.cdef("extern int a[][...];") lib = verify(ffi, 'test_global_var_array_3', 'int a[10][8];') lib.a[9][7] = 123456 assert lib.a[9][7] == 123456 @@ -1082,7 +1090,7 @@ def test_global_var_array_4(): ffi = FFI() - ffi.cdef("int a[10][...];") + ffi.cdef("extern int a[10][...];") lib = verify(ffi, 'test_global_var_array_4', 'int a[10][8];') lib.a[9][7] = 123456 assert lib.a[9][7] == 123456 @@ -1171,7 +1179,7 @@ lib = verify(ffi, 'test_some_float_invalid_3', """ typedef long double foo_t; foo_t neg(foo_t x) { return -x; } - """) + """, ignore_warnings=True) if ffi.sizeof("long double") == ffi.sizeof("double"): assert lib.neg(12.3) == -12.3 else: @@ -1205,7 +1213,7 @@ def test_import_from_lib(): ffi = FFI() - ffi.cdef("int mybar(int); int myvar;\n#define MYFOO ...") + ffi.cdef("int mybar(int); static int myvar;\n#define MYFOO ...") lib = verify(ffi, 'test_import_from_lib', "#define MYFOO 42\n" "static int mybar(int x) { return x + 1; }\n" @@ -1221,7 +1229,7 @@ def test_macro_var_callback(): ffi = FFI() - ffi.cdef("int my_value; int *(*get_my_value)(void);") + ffi.cdef("extern int my_value; extern int *(*get_my_value)(void);") lib = verify(ffi, 'test_macro_var_callback', "int *(*get_my_value)(void);\n" "#define my_value (*get_my_value())") @@ -1336,7 +1344,7 @@ def test_const_function_type_args(): ffi = FFI() - ffi.cdef("""int (*foobar)(const int a, const int *b, const int c[]);""") + ffi.cdef("""extern int(*foobar)(const int a,const int*b,const int c[]);""") lib = verify(ffi, 'test_const_function_type_args', """ int (*foobar)(const int a, const int *b, const int c[]); """) @@ -1626,7 +1634,7 @@ def test_extern_python_bogus_name(): ffi = FFI() - ffi.cdef("int abc;") + ffi.cdef("extern int abc;") lib = verify(ffi, 'test_extern_python_bogus_name', "int abc;") def fn(): pass @@ -1787,8 +1795,8 @@ ffi.cdef(""" extern "Python" int __stdcall foo(int); extern "Python" int WINAPI bar(int); - int (__stdcall * mycb1)(int); - int indirect_call(int); + static int (__stdcall * mycb1)(int); + static int indirect_call(int); """) lib = verify(ffi, 'test_extern_python_stdcall', """ #ifndef _MSC_VER @@ -1845,7 +1853,7 @@ ffi = FFI() ffi.cdef("float f1(double);") lib = verify(ffi, 'test_introspect_function', """ - float f1(double x) { return x; } + float f1(double x) { return (float)x; } """) assert dir(lib) == ['f1'] FUNC = ffi.typeof(lib.f1) @@ -1856,7 +1864,7 @@ def test_introspect_global_var(): ffi = FFI() - ffi.cdef("float g1;") + ffi.cdef("extern float g1;") lib = verify(ffi, 'test_introspect_global_var', """ float g1; """) @@ -1867,7 +1875,7 @@ def test_introspect_global_var_array(): ffi = FFI() - ffi.cdef("float g1[100];") + ffi.cdef("extern float g1[100];") lib = verify(ffi, 'test_introspect_global_var_array', """ float g1[100]; """) @@ -2039,7 +2047,7 @@ ffi.cdef("float _Complex f1(float a, float b);"); lib = verify(ffi, "test_function_returns_float_complex", """ #include - static float _Complex f1(float a, float b) { return a + I*2.0*b; } + static float _Complex f1(float a, float b) { return a + I*2.0f*b; } """, no_cpp=True) # fails on some systems with C++ result = lib.f1(1.25, 5.1) assert type(result) == complex @@ -2090,7 +2098,7 @@ ffi = FFI() ffi.cdef(""" typedef int foo_t[...], bar_t[...]; - int gv[...]; + extern int gv[...]; typedef int mat_t[...][...]; typedef int vmat_t[][...]; """) @@ -2150,7 +2158,8 @@ lib = verify(ffi, "test_call_with_nested_anonymous_struct", """ struct foo { int a; union { int b, c; }; }; struct foo f(void) { - struct foo s = { 40 }; + struct foo s; + s.a = 40; s.b = 200; return s; } diff --git a/extra_tests/cffi_tests/cffi1/test_verify1.py b/extra_tests/cffi_tests/cffi1/test_verify1.py --- a/extra_tests/cffi_tests/cffi1/test_verify1.py +++ b/extra_tests/cffi_tests/cffi1/test_verify1.py @@ -5,7 +5,7 @@ from cffi import CDefError from cffi import recompiler from extra_tests.cffi_tests.support import * -from extra_tests.cffi_tests.support import _verify +from extra_tests.cffi_tests.support import _verify, extra_compile_args import _cffi_backend lib_m = ['m'] @@ -14,18 +14,6 @@ import distutils.ccompiler if distutils.ccompiler.get_default_compiler() == 'msvc': lib_m = ['msvcrt'] - extra_compile_args = [] # no obvious -Werror equivalent on MSVC -else: - if (sys.platform == 'darwin' and - [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]): - # assume a standard clang or gcc - extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion'] - # special things for clang - extra_compile_args.append('-Qunused-arguments') - else: - # assume a standard gcc - extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion', - '-Wno-unused-parameter'] class FFI(FFI): error = _cffi_backend.FFI.error @@ -268,7 +256,7 @@ def test_var_signed_integer_types(): ffi = FFI() lst = all_signed_integer_types(ffi) - csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_')) + csource = "\n".join(["static %s somevar_%s;" % (tp, tp.replace(' ', '_')) for tp in lst]) ffi.cdef(csource) lib = ffi.verify(csource) @@ -287,7 +275,7 @@ def test_var_unsigned_integer_types(): ffi = FFI() lst = all_unsigned_integer_types(ffi) - csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_')) + csource = "\n".join(["static %s somevar_%s;" % (tp, tp.replace(' ', '_')) for tp in lst]) ffi.cdef(csource) lib = ffi.verify(csource) @@ -791,8 +779,8 @@ def test_access_variable(): ffi = FFI() - ffi.cdef("int foo(void);\n" - "int somenumber;") + ffi.cdef("static int foo(void);\n" + "static int somenumber;") lib = ffi.verify(""" static int somenumber = 2; static int foo(void) { @@ -809,7 +797,7 @@ def test_access_address_of_variable(): # access the address of 'somenumber': need a trick ffi = FFI() - ffi.cdef("int somenumber; static int *const somenumberptr;") + ffi.cdef("static int somenumber; static int *const somenumberptr;") lib = ffi.verify(""" static int somenumber = 2; #define somenumberptr (&somenumber) @@ -821,8 +809,8 @@ def test_access_array_variable(length=5): ffi = FFI() - ffi.cdef("int foo(int);\n" - "int somenumber[%s];" % (length,)) + ffi.cdef("static int foo(int);\n" + "static int somenumber[%s];" % (length,)) lib = ffi.verify(""" static int somenumber[] = {2, 2, 3, 4, 5}; static int foo(int i) { @@ -853,8 +841,8 @@ def test_access_struct_variable(): ffi = FFI() ffi.cdef("struct foo { int x; ...; };\n" - "int foo(int);\n" - "struct foo stuff;") + "static int foo(int);\n" + "static struct foo stuff;") lib = ffi.verify(""" struct foo { int x, y, z; }; static struct foo stuff = {2, 5, 8}; @@ -878,9 +866,9 @@ def test_access_callback(): ffi = FFI() - ffi.cdef("int (*cb)(int);\n" - "int foo(int);\n" - "void reset_cb(void);") + ffi.cdef("static int (*cb)(int);\n" + "static int foo(int);\n" + "static void reset_cb(void);") lib = ffi.verify(""" static int g(int x) { return x * 7; } static int (*cb)(int); @@ -896,9 +884,9 @@ def test_access_callback_function_typedef(): ffi = FFI() ffi.cdef("typedef int mycallback_t(int);\n" - "mycallback_t *cb;\n" - "int foo(int);\n" - "void reset_cb(void);") + "static mycallback_t *cb;\n" + "static int foo(int);\n" + "static void reset_cb(void);") lib = ffi.verify(""" static int g(int x) { return x * 7; } static int (*cb)(int); @@ -1039,7 +1027,7 @@ def test_autofilled_struct_as_argument_dynamic(): ffi = FFI() ffi.cdef("struct foo_s { long a; ...; };\n" - "int (*foo)(struct foo_s);") + "static int (*foo)(struct foo_s);") lib = ffi.verify(""" struct foo_s { double b; @@ -1048,7 +1036,7 @@ int foo1(struct foo_s s) { return (int)s.a - (int)s.b; } - int (*foo)(struct foo_s s) = &foo1; + static int (*foo)(struct foo_s s) = &foo1; """) e = py.test.raises(NotImplementedError, lib.foo, "?") msg = ("ctype 'struct foo_s' not supported as argument. It is a struct " @@ -1424,7 +1412,7 @@ py.test.skip("_Bool not in MSVC") ffi = FFI() ffi.cdef("struct foo_s { _Bool x; };" - "_Bool foo(_Bool); _Bool (*foop)(_Bool);") + "_Bool foo(_Bool); static _Bool (*foop)(_Bool);") lib = ffi.verify(""" struct foo_s { _Bool x; }; int foo(int arg) { @@ -1433,7 +1421,7 @@ _Bool _foofunc(_Bool x) { return !x; } - _Bool (*foop)(_Bool) = _foofunc; + static _Bool (*foop)(_Bool) = _foofunc; """) p = ffi.new("struct foo_s *") p.x = 1 @@ -1618,7 +1606,7 @@ def test_FILE_stored_explicitly(): ffi = FFI() - ffi.cdef("int myprintf11(const char *, int); FILE *myfile;") + ffi.cdef("int myprintf11(const char *, int); extern FILE *myfile;") lib = ffi.verify(""" #include FILE *myfile; @@ -1644,13 +1632,13 @@ def test_global_array_with_missing_length(): ffi = FFI() - ffi.cdef("int fooarray[];") + ffi.cdef("extern int fooarray[];") lib = ffi.verify("int fooarray[50];") assert repr(lib.fooarray).startswith("" def test_bug_const_char_ptr_array_2(): ffi = FFI() - ffi.cdef("""const int a[];""") + ffi.cdef("""extern const int a[];""") lib = ffi.verify("""const int a[5];""") assert repr(ffi.typeof(lib.a)) == "" def _test_various_calls(force_libffi): cdef_source = """ - int xvalue; - long long ivalue, rvalue; - float fvalue; - double dvalue; - long double Dvalue; + extern int xvalue; + extern long long ivalue, rvalue; + extern float fvalue; + extern double dvalue; + extern long double Dvalue; signed char tf_bb(signed char x, signed char c); unsigned char tf_bB(signed char x, unsigned char c); short tf_bh(signed char x, short c); @@ -2112,7 +2100,7 @@ old = sys.getdlopenflags() try: ffi1 = FFI() - ffi1.cdef("int foo_verify_dlopen_flags_1;") + ffi1.cdef("extern int foo_verify_dlopen_flags_1;") sys.setdlopenflags(ffi1.RTLD_GLOBAL | ffi1.RTLD_NOW) lib1 = ffi1.verify("int foo_verify_dlopen_flags_1;") finally: @@ -2253,7 +2241,7 @@ def test_macro_var(): ffi = FFI() - ffi.cdef("int myarray[50], my_value;") + ffi.cdef("extern int myarray[50], my_value;") lib = ffi.verify(""" int myarray[50]; int *get_my_value(void) { diff --git a/extra_tests/cffi_tests/embedding/add1.py b/extra_tests/cffi_tests/embedding/add1.py --- a/extra_tests/cffi_tests/embedding/add1.py +++ b/extra_tests/cffi_tests/embedding/add1.py @@ -12,7 +12,11 @@ sys.stdout.write("preparing") for i in range(3): sys.stdout.flush() - time.sleep(0.2) + # Windows: sometimes time.sleep() doesn't sleep at all. + # This appears to occur on recent versions of python only. + t_end = time.time() + 0.19 + while time.time() < t_end: + time.sleep(0.2) sys.stdout.write(".") sys.stdout.write("\n") diff --git a/extra_tests/cffi_tests/embedding/add_recursive.py b/extra_tests/cffi_tests/embedding/add_recursive.py --- a/extra_tests/cffi_tests/embedding/add_recursive.py +++ b/extra_tests/cffi_tests/embedding/add_recursive.py @@ -4,7 +4,7 @@ ffi = cffi.FFI() ffi.embedding_api(""" - int (*my_callback)(int); + extern int (*my_callback)(int); int add_rec(int, int); """) diff --git a/extra_tests/cffi_tests/embedding/test_thread.py b/extra_tests/cffi_tests/embedding/test_thread.py --- a/extra_tests/cffi_tests/embedding/test_thread.py +++ b/extra_tests/cffi_tests/embedding/test_thread.py @@ -22,17 +22,21 @@ add1_cffi = self.prepare_module('add1') add2_cffi = self.prepare_module('add2') self.compile('thread2-test', [add1_cffi, add2_cffi], threads=True) - output = self.execute('thread2-test') - output = self._take_out(output, "preparing") - output = self._take_out(output, ".") - output = self._take_out(output, ".") - # at least the 3rd dot should be after everything from ADD2 - assert output == ("starting\n" - "prepADD2\n" - "adding 1000 and 200 and 30\n" - ".\n" - "adding 40 and 2\n" - "done\n") + for i in range(3): + output = self.execute('thread2-test') + print('='*79) + print(output) + print('='*79) + output = self._take_out(output, "preparing") + output = self._take_out(output, ".") + output = self._take_out(output, ".") + # at least the 3rd dot should be after everything from ADD2 + assert output == ("starting\n" + "prepADD2\n" + "adding 1000 and 200 and 30\n" + ".\n" + "adding 40 and 2\n" + "done\n") def test_alt_issue(self): add1_cffi = self.prepare_module('add1') diff --git a/extra_tests/cffi_tests/support.py b/extra_tests/cffi_tests/support.py --- a/extra_tests/cffi_tests/support.py +++ b/extra_tests/cffi_tests/support.py @@ -1,8 +1,8 @@ # Generated by pypy/tool/import_cffi.py -import sys +import sys, os if sys.version_info < (3,): - __all__ = ['u'] + __all__ = ['u', 'arraytostring'] class U(object): def __add__(self, other): @@ -13,12 +13,16 @@ assert u+'a\x00b' == eval(r"u'a\x00b'") assert u+'a\u1234b' == eval(r"u'a\u1234b'") assert u+'a\U00012345b' == eval(r"u'a\U00012345b'") + def arraytostring(a): + return a.tostring() else: - __all__ = ['u', 'unicode', 'long'] + __all__ = ['u', 'unicode', 'long', 'arraytostring'] u = "" unicode = str long = int + def arraytostring(a): + return a.tobytes() class StdErrCapture(object): @@ -87,3 +91,24 @@ if not name.startswith('_') and not hasattr(module.ffi, name): setattr(ffi, name, NotImplemented) return module.lib + + +# For testing, we call gcc with "-Werror". This is fragile because newer +# versions of gcc are always better at producing warnings, particularly for +# auto-generated code. We need here to adapt and silence them as needed. + +if sys.platform == 'win32': + extra_compile_args = [] # no obvious -Werror equivalent on MSVC +else: + if (sys.platform == 'darwin' and + [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]): + # assume a standard clang or gcc + extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion', + '-Wno-unreachable-code'] + # special things for clang + extra_compile_args.append('-Qunused-arguments') + else: + # assume a standard gcc + extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion', + '-Wno-unused-parameter', + '-Wno-unreachable-code'] diff --git a/lib-python/2.7/distutils/command/install.py b/lib-python/2.7/distutils/command/install.py --- a/lib-python/2.7/distutils/command/install.py +++ b/lib-python/2.7/distutils/command/install.py @@ -86,7 +86,7 @@ 'pypy': { 'purelib': '$base/site-packages', 'platlib': '$base/site-packages', - 'headers': '$base/include', + 'headers': '$base/include/$dist_name', 'scripts': '$base/bin', 'data' : '$base', }, diff --git a/lib-python/2.7/distutils/sysconfig_pypy.py b/lib-python/2.7/distutils/sysconfig_pypy.py --- a/lib-python/2.7/distutils/sysconfig_pypy.py +++ b/lib-python/2.7/distutils/sysconfig_pypy.py @@ -86,7 +86,7 @@ arch = platform.machine() g['LDSHARED'] += ' -undefined dynamic_lookup' g['CC'] += ' -arch %s' % (arch,) - g['MACOSX_DEPLOYMENT_TARGET'] = '10.14' + g['MACOSX_DEPLOYMENT_TARGET'] = '10.7' global _config_vars _config_vars = g diff --git a/lib-python/2.7/ensurepip/__init__.py b/lib-python/2.7/ensurepip/__init__.py --- a/lib-python/2.7/ensurepip/__init__.py +++ b/lib-python/2.7/ensurepip/__init__.py @@ -12,9 +12,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "28.8.0" +_SETUPTOOLS_VERSION = "41.2.0" -_PIP_VERSION = "9.0.1" +_PIP_VERSION = "19.2.3" _PROJECTS = [ ("setuptools", _SETUPTOOLS_VERSION), @@ -28,8 +28,8 @@ sys.path = additional_paths + sys.path # Install the bundled software - import pip - pip.main(args) + import pip._internal + return pip._internal.main(args) def version(): diff --git a/lib-python/2.7/ensurepip/_bundled/pip-19.2.3-py2.py3-none-any.whl b/lib-python/2.7/ensurepip/_bundled/pip-19.2.3-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8118df8ac1940f8c6cb410fbc18e5fae59872b95 GIT binary patch [cut] diff --git a/lib-python/2.7/ensurepip/_bundled/pip-9.0.1-py2.py3-none-any.whl b/lib-python/2.7/ensurepip/_bundled/pip-9.0.1-py2.py3-none-any.whl deleted file mode 100644 index 4b8ecc69db7e37fc6dd7b6dd8f690508f42866a1..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [cut] diff --git a/lib-python/2.7/ensurepip/_bundled/setuptools-28.8.0-py2.py3-none-any.whl b/lib-python/2.7/ensurepip/_bundled/setuptools-28.8.0-py2.py3-none-any.whl deleted file mode 100644 index 502e3cb418c154872ad6e677ef8b63557b38ec35..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [cut] diff --git a/lib-python/2.7/ensurepip/_bundled/setuptools-41.2.0-py2.py3-none-any.whl b/lib-python/2.7/ensurepip/_bundled/setuptools-41.2.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..82df6f63f4ee97380af0a29d8825ae775333b86d GIT binary patch [cut] diff --git a/lib-python/2.7/pickle.py b/lib-python/2.7/pickle.py --- a/lib-python/2.7/pickle.py +++ b/lib-python/2.7/pickle.py @@ -1444,5 +1444,14 @@ import doctest return doctest.testmod() +# ===== PyPy modification to support pickling cpyext methods ===== +try: + import cpyext +except ImportError: + pass +else: + Pickler.dispatch[cpyext.FunctionType] = Pickler.save_global +# ================= end of PyPy modification ==================== + if __name__ == "__main__": _test() diff --git a/lib-python/2.7/subprocess.py b/lib-python/2.7/subprocess.py --- a/lib-python/2.7/subprocess.py +++ b/lib-python/2.7/subprocess.py @@ -1301,6 +1301,11 @@ src_library = os.path.join(src_dir, libname) if os.path.exists(src_library): caller.f_globals['copyfile'](src_library, dest_library) + src_lib = os.path.join(src_dir, '../lib') + if os.path.exists(src_lib): + # portable build + import shutil + shutil.copytree(src_lib, os.path.join(dest_dir, '../lib')) def _demo_posix(): diff --git a/lib-python/2.7/sysconfig.py b/lib-python/2.7/sysconfig.py --- a/lib-python/2.7/sysconfig.py +++ b/lib-python/2.7/sysconfig.py @@ -382,6 +382,11 @@ vars['EXE'] = '.exe' vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable)) + # pypy only: give us control over the ABI tag in a wheel name + if '__pypy__' in sys.builtin_module_names: + import imp + so_ext = imp.get_suffixes()[0][0] + vars['SOABI']= '-'.join(so_ext.split('.')[1].split('-')[:2]) # # public APIs diff --git a/lib-python/2.7/test/test_curses.py b/lib-python/2.7/test/test_curses.py --- a/lib-python/2.7/test/test_curses.py +++ b/lib-python/2.7/test/test_curses.py @@ -15,7 +15,8 @@ import tempfile import unittest -from test.test_support import requires, import_module, verbose, run_unittest +from test.test_support import (requires, import_module, verbose, run_unittest, + cpython_only) # Optionally test curses module. This currently requires that the # 'curses' resource be given on the regrtest command line using the -u @@ -276,6 +277,7 @@ msg='userptr should fail since not set'): p.userptr() + @cpython_only def test_userptr_memory_leak(self): w = curses.newwin(10, 10) p = curses.panel.new_panel(w) @@ -288,6 +290,7 @@ self.assertEqual(sys.getrefcount(obj), nrefs, "set_userptr leaked references") + @cpython_only def test_userptr_segfault(self): panel = curses.panel.new_panel(self.stdscr) class A: diff --git a/lib_pypy/_cffi_ssl/_stdssl/__init__.py b/lib_pypy/_cffi_ssl/_stdssl/__init__.py --- a/lib_pypy/_cffi_ssl/_stdssl/__init__.py +++ b/lib_pypy/_cffi_ssl/_stdssl/__init__.py @@ -1,9 +1,20 @@ import sys +import os import time import thread as _thread import weakref -from _pypy_openssl import ffi -from _pypy_openssl import lib + +try: + from _pypy_openssl import ffi + from _pypy_openssl import lib +except ImportError as e: + import os + msg = "\n\nThe _ssl cffi module either doesn't exist or is incompatible with your machine's shared libraries.\n" + \ + "If you have a compiler installed, you can try to rebuild it by running:\n" + \ + "cd %s\n" % os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))) + \ + "%s _ssl_build.py\n" % sys.executable + raise ImportError(str(e) + msg) + from _cffi_ssl._stdssl.certificate import (_test_decode_cert, _decode_certificate, _certificate_to_der) from _cffi_ssl._stdssl.utility import (_str_with_len, _bytes_with_len, @@ -72,6 +83,11 @@ OP_NO_SSLv2 = lib.SSL_OP_NO_SSLv2 OP_NO_SSLv3 = lib.SSL_OP_NO_SSLv3 OP_NO_TLSv1_3 = lib.SSL_OP_NO_TLSv1_3 +if OPENSSL_VERSION_INFO > (1, 1, 0, 0, 0): + # OP_ENABLE_MIDDLEBOX_COMPAT = lib.SSL_OP_ENABLE_MIDDLEBOX_COMPAT + # XXX should be conditionally compiled into lib + OP_ENABLE_MIDDLEBOX_COMPAT = 0x00100000 + SSL_CLIENT = 0 @@ -99,6 +115,7 @@ PROTOCOL_TLSv1_2 = 5 # PROTOCOL_TLS_CLIENT = 0x10 # PROTOCOL_TLS_SERVER = 0x11 +HAS_TLSv1_3 = bool(lib.Cryptography_HAS_TLSv1_3) _PROTOCOL_NAMES = (name for name in dir(lib) if name.startswith('PROTOCOL_')) @@ -254,6 +271,20 @@ mode |= lib.SSL_MODE_AUTO_RETRY lib.SSL_set_mode(ssl, mode) + if HAS_TLSv1_3: + if sslctx._post_handshake_auth: + if socket_type == SSL_SERVER: + # bpo-37428: OpenSSL does not ignore SSL_VERIFY_POST_HANDSHAKE. + # Set SSL_VERIFY_POST_HANDSHAKE flag only for server sockets and + # only in combination with SSL_VERIFY_PEER flag. + mode = lib.SSL_CTX_get_verify_mode(lib.SSL_get_SSL_CTX(self.ssl)) + if (mode & lib.SSL_VERIFY_PEER): + verify_cb = lib.SSL_get_verify_callback(self.ssl) + mode |= lib.SSL_VERIFY_POST_HANDSHAKE + lib.SSL_set_verify(ssl, mode, verify_cb) + else: + lib.SSL_set_post_handshake_auth(ssl, 1) + if HAS_SNI and self.server_hostname: name = _str_to_ffi_buffer(self.server_hostname) lib.SSL_set_tlsext_host_name(ssl, name) @@ -641,6 +672,15 @@ else: return None + def verify_client_post_handshake(self): + + if not HAS_TLSv1_3: + raise NotImplementedError("Post-handshake auth is not supported by " + "your OpenSSL version.") + err = lib.SSL_verify_client_post_handshake(self.ssl); + if err == 0: + raise pyssl_error(self, err) + def pending(self): count = lib.SSL_pending(self.ssl) if count < 0: @@ -697,6 +737,7 @@ return bool(lib.SSL_session_reused(self.ssl)) + def _fs_decode(name): return name.decode(sys.getfilesystemencoding()) def _fs_converter(name): @@ -752,13 +793,13 @@ if OPENSSL_VERSION_INFO > (1, 1, 0, 0, 0): aead = lib.SSL_CIPHER_is_aead(cipher) nid = lib.SSL_CIPHER_get_cipher_nid(cipher) - skcipher = OBJ_nid2ln(nid) if nid != NID_undef else None + skcipher = lib.OBJ_nid2ln(nid) if nid != lib.NID_undef else None nid = lib.SSL_CIPHER_get_digest_nid(cipher); - digest = OBJ_nid2ln(nid) if nid != NID_undef else None + digest = lib.OBJ_nid2ln(nid) if nid != lib.NID_undef else None nid = lib.SSL_CIPHER_get_kx_nid(cipher); - kx = OBJ_nid2ln(nid) if nid != NID_undef else None - nid = SSL_CIPHER_get_auth_nid(cipher); - auth = OBJ_nid2ln(nid) if nid != NID_undef else None + kx = lib.OBJ_nid2ln(nid) if nid != lib.NID_undef else None + nid = lib.SSL_CIPHER_get_auth_nid(cipher); + auth = lib.OBJ_nid2ln(nid) if nid != lib.NID_undef else None ret.update({'aead' : bool(aead), 'symmmetric' : skcipher, 'digest' : digest, @@ -818,9 +859,8 @@ class _SSLContext(object): __slots__ = ('ctx', '_check_hostname', 'servername_callback', 'alpn_protocols', '_alpn_protocols_handle', - 'npn_protocols', 'set_hostname', + 'npn_protocols', 'set_hostname', '_post_handshake_auth', '_set_hostname_handle', '_npn_protocols_handle') - def __new__(cls, protocol): self = object.__new__(cls) self.ctx = ffi.NULL @@ -897,6 +937,9 @@ if lib.Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST: store = lib.SSL_CTX_get_cert_store(self.ctx) lib.X509_STORE_set_flags(store, lib.X509_V_FLAG_TRUSTED_FIRST) + if HAS_TLSv1_3: + self.post_handshake_auth = 0; + lib.SSL_CTX_set_post_handshake_auth(self.ctx, self.post_handshake_auth) return self @property @@ -982,6 +1025,7 @@ "CERT_OPTIONAL or CERT_REQUIRED") self._check_hostname = check_hostname + def set_ciphers(self, cipherlist): cipherlistbuf = _str_to_ffi_buffer(cipherlist) ret = lib.SSL_CTX_set_cipher_list(self.ctx, cipherlistbuf) @@ -1195,6 +1239,12 @@ return stats def set_default_verify_paths(self): + if (not os.environ.get('SSL_CERT_FILE') and + not os.environ.get('SSL_CERT_DIR') and + not sys.platform == 'win32'): + locations = get_default_verify_paths() + self.load_verify_locations(locations[1], locations[3]) + return if not lib.SSL_CTX_set_default_verify_paths(self.ctx): raise ssl_error("") @@ -1314,6 +1364,25 @@ sock = _SSLSocket._new__ssl_socket(self, None, server_side, hostname, incoming, outgoing) return sock + @property + def post_handshake_auth(self): + if HAS_TLSv1_3: + return bool(self._post_handshake_auth) + return None + + @post_handshake_auth.setter + def post_handshake_auth(self, arg): + if arg is None: + raise AttributeError("cannot delete attribute") + + pha = bool(arg) + self._post_handshake_auth = pha; + + # bpo-37428: newPySSLSocket() sets SSL_VERIFY_POST_HANDSHAKE flag for + # server sockets and SSL_set_post_handshake_auth() for client + + return 0; + # cryptography constraint: OPENSSL_NO_TLSEXT will never be set! @@ -1538,20 +1607,69 @@ lib.RAND_add(buf, len(buf), entropy) def get_default_verify_paths(): + ''' + Find a certificate store and associated values + Returns something like + `('SSL_CERT_FILE', '/usr/lib/ssl/cert.pem', 'SSL_CERT_DIR', '/usr/lib/ssl/certs')` + on Ubuntu and windows10 + + `('SSL_CERT_FILE', '/usr/local/cert.pem', 'SSL_CERT_DIR', '/usr/local/certs')` + on CentOS + + `('SSL_CERT_FILE', '/Library/Frameworks/Python.framework/Versions/2.7/etc/openssl/cert.pem', + 'SSL_CERT_DIR', '/Library/Frameworks/Python.framework/Versions/2.7/etc/openssl/certs')` + on Darwin + + For portable builds (based on CentOS, but could be running on any glibc + linux) we need to check other locations. The list of places to try was taken + from golang in Dec 2018: + https://golang.org/src/crypto/x509/root_unix.go (for the directories), + https://golang.org/src/crypto/x509/root_linux.go (for the files) + ''' + certFiles = [ + "/etc/ssl/certs/ca-certificates.crt", # Debian/Ubuntu/Gentoo etc. + "/etc/pki/tls/certs/ca-bundle.crt", # Fedora/RHEL 6 + "/etc/ssl/ca-bundle.pem", # OpenSUSE + "/etc/pki/tls/cacert.pem", # OpenELEC + "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", # CentOS/RHEL 7 + "/etc/ssl/cert.pem", # Alpine Linux + ] + certDirectories = [ + "/etc/ssl/certs", # SLES10/SLES11 + "/system/etc/security/cacerts", # Android + "/usr/local/share/certs", # FreeBSD + "/etc/pki/tls/certs", # Fedora/RHEL + "/etc/openssl/certs", # NetBSD + "/var/ssl/certs", # AIX + ] + + # optimization: reuse the values from a local varaible + if getattr(get_default_verify_paths, 'retval', None): + return get_default_verify_paths.retval + + # This should never fail, it should always return SSL_CERT_FILE and SSL_CERT_DIR ofile_env = _str_from_buf(lib.X509_get_default_cert_file_env()) - if ofile_env is None: - return None + odir_env = _str_from_buf(lib.X509_get_default_cert_dir_env()) + + # Platform depenedent ofile = _str_from_buf(lib.X509_get_default_cert_file()) - if ofile is None: - return None - odir_env = _str_from_buf(lib.X509_get_default_cert_dir_env()) - if odir_env is None: - return None odir = _str_from_buf(lib.X509_get_default_cert_dir()) - if odir is None: - return odir - return (ofile_env, ofile, odir_env, odir); + + if os.path.exists(ofile) and os.path.exists(odir): + get_default_verify_paths.retval = (ofile_env, ofile, odir_env, odir) + return get_default_verify_paths.retval + + # OpenSSL didn't supply the goods. Try some other options + for f in certFiles: + if os.path.exists(f): + ofile = f + for f in certDirectories: + if os.path.exists(f): + odir = f + get_default_verify_paths.retval = (ofile_env, ofile, odir_env, odir) + return get_default_verify_paths.retval + @ffi.callback("int(SSL*,unsigned char **,unsigned char *,const unsigned char *,unsigned int,void *)") def select_alpn_callback(ssl, out, outlen, client_protocols, client_protocols_len, args): diff --git a/lib_pypy/_cffi_ssl/_stdssl/error.py b/lib_pypy/_cffi_ssl/_stdssl/error.py --- a/lib_pypy/_cffi_ssl/_stdssl/error.py +++ b/lib_pypy/_cffi_ssl/_stdssl/error.py @@ -27,13 +27,14 @@ if self.strerror and isinstance(self.strerror, str): return self.strerror return str(self.args) -# these are expected on socket as well -socket.sslerror = SSLError -for v in [ 'SSL_ERROR_ZERO_RETURN', 'SSL_ERROR_WANT_READ', - 'SSL_ERROR_WANT_WRITE', 'SSL_ERROR_WANT_X509_LOOKUP', 'SSL_ERROR_SYSCALL', - 'SSL_ERROR_SSL', 'SSL_ERROR_WANT_CONNECT', 'SSL_ERROR_EOF', - 'SSL_ERROR_INVALID_ERROR_CODE' ]: - setattr(socket, v, locals()[v]) +# these are expected on socket in python2 as well +if sys.version_info[0] < 3: + socket.sslerror = SSLError + for v in [ 'SSL_ERROR_ZERO_RETURN', 'SSL_ERROR_WANT_READ', + 'SSL_ERROR_WANT_WRITE', 'SSL_ERROR_WANT_X509_LOOKUP', 'SSL_ERROR_SYSCALL', + 'SSL_ERROR_SSL', 'SSL_ERROR_WANT_CONNECT', 'SSL_ERROR_EOF', + 'SSL_ERROR_INVALID_ERROR_CODE' ]: + setattr(socket, v, locals()[v]) class SSLZeroReturnError(SSLError): """ SSL/TLS session closed cleanly. """ diff --git a/lib_pypy/_ctypes/array.py b/lib_pypy/_ctypes/array.py --- a/lib_pypy/_ctypes/array.py +++ b/lib_pypy/_ctypes/array.py @@ -267,6 +267,8 @@ raise TypeError("Can't multiply a ctypes type by a non-integer") if length < 0: raise ValueError("Array length must be >= 0") + if length * base._sizeofinstances() > sys.maxsize: + raise OverflowError("array too large") key = (base, length) try: return ARRAY_CACHE[key] diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py --- a/lib_pypy/_curses.py +++ b/lib_pypy/_curses.py @@ -57,7 +57,7 @@ if key_n == b"UNKNOWN KEY": continue if not isinstance(key_n, str): # python 3 - key_n = key_n.decode() + key_n = key_n.decode('utf-8') key_n = key_n.replace('(', '').replace(')', '') globals()[key_n] = key @@ -83,7 +83,9 @@ def _ensure_initialised_color(): - if not _initialised and _initialised_color: + if not _initialised: + raise error("must call initscr() first") + if not _initialised_color: raise error("must call start_color() first") @@ -420,11 +422,16 @@ val = lib.keyname(val) if val == ffi.NULL: return "" - return ffi.string(val) + key_n = ffi.string(val) + if not isinstance(key_n, str): + key_n = key_n.decode('utf-8') + return key_n @_argspec(0, 1, 2) def getstr(self, y, x, n=1023): n = min(n, 1023) + if n < 0: + raise ValueError("'n' must be nonnegative") buf = ffi.new("char[1024]") # /* This should be big enough.. I hope */ if y is None: @@ -467,6 +474,8 @@ @_argspec(0, 1, 2) def instr(self, y, x, n=1023): n = min(n, 1023) + if n < 0: + raise ValueError("'n' must be nonnegative") buf = ffi.new("char[1024]") # /* This should be big enough.. I hope */ if y is None: code = lib.winnstr(self._win, buf, n) diff --git a/lib_pypy/_curses_build.py b/lib_pypy/_curses_build.py --- a/lib_pypy/_curses_build.py +++ b/lib_pypy/_curses_build.py @@ -1,18 +1,51 @@ -from cffi import FFI +from cffi import FFI, VerificationError import os -# On some systems, the ncurses library is -# located at /usr/include/ncurses, so we must check this case. -# Let's iterate over well known paths -incdirs = [] -for _path in ['/usr/include', '/usr/include/ncurses']: - if os.path.isfile(os.path.join(_path, 'panel.h')): - incdirs.append(_path) - break +version_str = ''' + static const int NCURSES_VERSION_MAJOR; + static const int NCURSES_VERSION_MINOR; +''' +def find_library(options): + for library in options: + ffi = FFI() + ffi.cdef(version_str) + ffi.set_source("_curses_cffi_check", version_str, libraries=[library]) + try: + ffi.compile() + import _curses_cffi_check + lib = _curses_cffi_check.lib + except VerificationError as e: + e_last = e + continue + else: + return library + + # If none of the options is available, present the user a meaningful + # error message + raise e_last + +def find_curses_dir_and_name(): + for base in ('/usr', '/usr/local'): + if os.path.exists(os.path.join(base, 'include', 'ncursesw')): From pypy.commits at gmail.com Sat Feb 8 05:19:03 2020 From: pypy.commits at gmail.com (cfbolz) Date: Sat, 08 Feb 2020 02:19:03 -0800 (PST) Subject: [pypy-commit] pypy record-known-result: add missing op Message-ID: <5e3e8b17.1c69fb81.56cc5.ef1c@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: record-known-result Changeset: r98683:e0ec664096c7 Date: 2020-02-07 14:40 +0100 http://bitbucket.org/pypy/pypy/changeset/e0ec664096c7/ Log: add missing op diff --git a/rpython/translator/c/src/support.h b/rpython/translator/c/src/support.h --- a/rpython/translator/c/src/support.h +++ b/rpython/translator/c/src/support.h @@ -8,6 +8,7 @@ #define RUNNING_ON_LLINTERP 0 #define OP_JIT_RECORD_EXACT_CLASS(i, c, r) /* nothing */ #define OP_JIT_RECORD_EXACT_VALUE(i, c, r) /* nothing */ +#define OP_JIT_RECORD_KNOWN_RESULT(r, f, ...) /* nothing */ #define FAIL_OVF(msg) _RPyRaiseSimpleException(RPyExc_OverflowError) From pypy.commits at gmail.com Sat Feb 8 05:19:05 2020 From: pypy.commits at gmail.com (arigo) Date: Sat, 08 Feb 2020 02:19:05 -0800 (PST) Subject: [pypy-commit] pypy default: (cfbolz) graft 4c6c15e3e3bf to get the useful names "listview_ascii", instead Message-ID: <5e3e8b19.1c69fb81.36dd8.bee4@mx.google.com> Author: Armin Rigo Branch: Changeset: r98684:d9468d86914f Date: 2019-04-13 16:53 +0200 http://bitbucket.org/pypy/pypy/changeset/d9468d86914f/ Log: (cfbolz) graft 4c6c15e3e3bf to get the useful names "listview_ascii", instead of the confusing listview_utf8 on default too original message: Issue #2997 The problem was coming from W_UnicodeObject.listview_utf8(), which unlike its name is supposed to return a list of *ascii* strings, not *utf8*. Fixed, and also proceeded to a general renaming of this and related functions and reviewing of the related code. diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -1113,9 +1113,10 @@ """ return None - def listview_utf8(self, w_list): - """ Return a list of unwrapped unicode out of a list of unicode. If the - argument is not a list or does not contain only unicode, return None. + def listview_ascii(self, w_list): + """ Return a list of unwrapped **ASCII** strings out of a list of + unicode. If the argument is not a list, does not contain only unicode, + or contains a unicode with non-ascii characters, return None. May return None anyway. """ return None diff --git a/pypy/module/__pypy__/test/test_special.py b/pypy/module/__pypy__/test/test_special.py --- a/pypy/module/__pypy__/test/test_special.py +++ b/pypy/module/__pypy__/test/test_special.py @@ -101,7 +101,7 @@ l = ["a", "b", "c"] assert strategy(l) == "BytesListStrategy" l = [u"a", u"b", u"c"] - assert strategy(l) == "UnicodeListStrategy" + assert strategy(l) == "AsciiListStrategy" l = [1.1, 2.2, 3.3] assert strategy(l) == "FloatListStrategy" l = range(3) 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 @@ -411,7 +411,7 @@ popitem delitem clear \ length w_keys values items \ iterkeys itervalues iteritems \ - listview_bytes listview_utf8 listview_int \ + listview_bytes listview_ascii listview_int \ view_as_kwargs".split() def make_method(method): @@ -581,7 +581,7 @@ def listview_bytes(self, w_dict): return None - def listview_utf8(self, w_dict): + def listview_ascii(self, w_dict): return None def listview_int(self, w_dict): @@ -1270,7 +1270,8 @@ ## assert key is not None ## return self.unerase(w_dict.dstorage).get(key, None) - ## def listview_utf8(self, w_dict): + ## def listview_ascii(self, w_dict): + ## XXX reimplement. Also warning: must return a list of _ascii_ ## return self.unerase(w_dict.dstorage).keys() ## def w_keys(self, w_dict): diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py --- a/pypy/objspace/std/listobject.py +++ b/pypy/objspace/std/listobject.py @@ -98,13 +98,13 @@ return space.fromcache(BytesListStrategy) elif type(w_firstobj) is W_UnicodeObject and w_firstobj.is_ascii(): - # check for all-unicodes + # check for all-unicodes containing only ascii for i in range(1, len(list_w)): item = list_w[i] if type(item) is not W_UnicodeObject or not item.is_ascii(): break else: - return space.fromcache(UnicodeListStrategy) + return space.fromcache(AsciiListStrategy) elif type(w_firstobj) is W_FloatObject: # check for all-floats @@ -198,8 +198,8 @@ return W_ListObject.from_storage_and_strategy(space, storage, strategy) @staticmethod - def newlist_utf8(space, list_u): - strategy = space.fromcache(UnicodeListStrategy) + def newlist_ascii(space, list_u): + strategy = space.fromcache(AsciiListStrategy) storage = strategy.erase(list_u) return W_ListObject.from_storage_and_strategy(space, storage, strategy) @@ -337,10 +337,10 @@ not use the list strategy, return None.""" return self.strategy.getitems_bytes(self) - def getitems_utf8(self): + def getitems_ascii(self): """Return the items in the list as unwrapped unicodes. If the list does not use the list strategy, return None.""" - return self.strategy.getitems_utf8(self) + return self.strategy.getitems_ascii(self) def getitems_int(self): """Return the items in the list as unwrapped ints. If the list does not @@ -801,7 +801,7 @@ def getitems_bytes(self, w_list): return None - def getitems_utf8(self, w_list): + def getitems_ascii(self, w_list): return None def getitems_int(self, w_list): @@ -948,7 +948,7 @@ elif type(w_item) is W_BytesObject: strategy = self.space.fromcache(BytesListStrategy) elif type(w_item) is W_UnicodeObject and w_item.is_ascii(): - strategy = self.space.fromcache(UnicodeListStrategy) + strategy = self.space.fromcache(AsciiListStrategy) elif type(w_item) is W_FloatObject: strategy = self.space.fromcache(FloatListStrategy) else: @@ -1026,9 +1026,9 @@ w_list.lstorage = strategy.erase(byteslist[:]) return - unilist = space.listview_utf8(w_iterable) + unilist = space.listview_ascii(w_iterable) if unilist is not None: - w_list.strategy = strategy = space.fromcache(UnicodeListStrategy) + w_list.strategy = strategy = space.fromcache(AsciiListStrategy) # need to copy because intlist can share with w_iterable w_list.lstorage = strategy.erase(unilist[:]) return @@ -1990,7 +1990,7 @@ return self.unerase(w_list.lstorage) -class UnicodeListStrategy(ListStrategy): +class AsciiListStrategy(ListStrategy): import_from_mixin(AbstractUnwrappedStrategy) _none_value = "" @@ -2010,7 +2010,7 @@ return type(w_obj) is W_UnicodeObject and w_obj.is_ascii() def list_is_correct_type(self, w_list): - return w_list.strategy is self.space.fromcache(UnicodeListStrategy) + return w_list.strategy is self.space.fromcache(AsciiListStrategy) def sort(self, w_list, reverse): l = self.unerase(w_list.lstorage) @@ -2019,7 +2019,7 @@ if reverse: l.reverse() - def getitems_utf8(self, w_list): + def getitems_ascii(self, w_list): return self.unerase(w_list.lstorage) # _______________________________________________________ diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py --- a/pypy/objspace/std/objspace.py +++ b/pypy/objspace/std/objspace.py @@ -311,7 +311,7 @@ def newlist_utf8(self, list_u, is_ascii): if is_ascii: - return W_ListObject.newlist_utf8(self, list_u) + return W_ListObject.newlist_ascii(self, list_u) return ObjSpace.newlist_utf8(self, list_u, False) def newlist_int(self, list_i): @@ -502,20 +502,20 @@ return w_obj.getitems_bytes() return None - def listview_utf8(self, w_obj): + def listview_ascii(self, w_obj): # note: uses exact type checking for objects with strategies, # and isinstance() for others. See test_listobject.test_uses_custom... if type(w_obj) is W_ListObject: - return w_obj.getitems_utf8() + return w_obj.getitems_ascii() if type(w_obj) is W_DictObject: - return w_obj.listview_utf8() + return w_obj.listview_ascii() if type(w_obj) is W_SetObject or type(w_obj) is W_FrozensetObject: - return w_obj.listview_utf8() + return w_obj.listview_ascii() if (isinstance(w_obj, W_UnicodeObject) and self._uni_uses_no_iter(w_obj) and w_obj.is_ascii()): - return w_obj.listview_utf8() + return w_obj.listview_ascii() if isinstance(w_obj, W_ListObject) and self._uses_list_iter(w_obj): - return w_obj.getitems_utf8() + return w_obj.getitems_ascii() return None def listview_int(self, w_obj): diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py --- a/pypy/objspace/std/setobject.py +++ b/pypy/objspace/std/setobject.py @@ -87,9 +87,9 @@ """ If this is a string set return its contents as a list of uwnrapped strings. Otherwise return None. """ return self.strategy.listview_bytes(self) - def listview_utf8(self): + def listview_ascii(self): """ If this is a unicode set return its contents as a list of uwnrapped unicodes. Otherwise return None. """ - return self.strategy.listview_utf8(self) + return self.strategy.listview_ascii(self) def listview_int(self): """ If this is an int set return its contents as a list of uwnrapped ints. Otherwise return None. """ @@ -713,7 +713,7 @@ def listview_bytes(self, w_set): return None - def listview_utf8(self, w_set): + def listview_ascii(self, w_set): return None def listview_int(self, w_set): @@ -819,7 +819,7 @@ elif type(w_key) is W_BytesObject: strategy = self.space.fromcache(BytesSetStrategy) elif type(w_key) is W_UnicodeObject and w_key.is_ascii(): - strategy = self.space.fromcache(UnicodeSetStrategy) + strategy = self.space.fromcache(AsciiSetStrategy) elif self.space.type(w_key).compares_by_identity(): strategy = self.space.fromcache(IdentitySetStrategy) else: @@ -1281,7 +1281,7 @@ return BytesIteratorImplementation(self.space, self, w_set) -class UnicodeSetStrategy(AbstractUnwrappedSetStrategy, SetStrategy): +class AsciiSetStrategy(AbstractUnwrappedSetStrategy, SetStrategy): erase, unerase = rerased.new_erasing_pair("unicode") erase = staticmethod(erase) unerase = staticmethod(unerase) @@ -1295,7 +1295,7 @@ def get_empty_dict(self): return {} - def listview_utf8(self, w_set): + def listview_ascii(self, w_set): return self.unerase(w_set.sstorage).keys() def is_correct_type(self, w_key): @@ -1343,7 +1343,7 @@ def may_contain_equal_elements(self, strategy): if strategy is self.space.fromcache(BytesSetStrategy): return False - elif strategy is self.space.fromcache(UnicodeSetStrategy): + elif strategy is self.space.fromcache(AsciiSetStrategy): return False elif strategy is self.space.fromcache(EmptySetStrategy): return False @@ -1434,7 +1434,7 @@ return False if strategy is self.space.fromcache(BytesSetStrategy): return False - if strategy is self.space.fromcache(UnicodeSetStrategy): + if strategy is self.space.fromcache(AsciiSetStrategy): return False return True @@ -1614,9 +1614,9 @@ w_set.sstorage = strategy.get_storage_from_unwrapped_list(byteslist) return - unicodelist = space.listview_utf8(w_iterable) + unicodelist = space.listview_ascii(w_iterable) if unicodelist is not None: - strategy = space.fromcache(UnicodeSetStrategy) + strategy = space.fromcache(AsciiSetStrategy) w_set.strategy = strategy w_set.sstorage = strategy.get_storage_from_unwrapped_list(unicodelist) return @@ -1663,7 +1663,7 @@ if type(w_item) is not W_UnicodeObject or not w_item.is_ascii(): break else: - w_set.strategy = space.fromcache(UnicodeSetStrategy) + w_set.strategy = space.fromcache(AsciiSetStrategy) w_set.sstorage = w_set.strategy.get_storage_from_list(iterable_w) return 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 @@ -147,7 +147,7 @@ w = self.space.wrap w_d = self.space.newdict() w_d.initialize_content([(w(u"a"), w(1)), (w(u"b"), w(2))]) - assert self.space.listview_utf8(w_d) == ["a", "b"] + assert self.space.listview_ascii(w_d) == ["a", "b"] def test_listview_int_dict(self): w = self.space.wrap diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py --- a/pypy/objspace/std/test/test_listobject.py +++ b/pypy/objspace/std/test/test_listobject.py @@ -1395,6 +1395,10 @@ l3 = [s] assert l1[0].encode("ascii", "replace") == "???" + def test_unicode_bug_in_listview_utf8(self): + l1 = list(u'\u1234\u2345') + assert l1 == [u'\u1234', u'\u2345'] + def test_list_from_set(self): l = ['a'] l.__init__(set('b')) diff --git a/pypy/objspace/std/test/test_liststrategies.py b/pypy/objspace/std/test/test_liststrategies.py --- a/pypy/objspace/std/test/test_liststrategies.py +++ b/pypy/objspace/std/test/test_liststrategies.py @@ -3,7 +3,7 @@ from pypy.objspace.std.listobject import ( W_ListObject, EmptyListStrategy, ObjectListStrategy, IntegerListStrategy, FloatListStrategy, BytesListStrategy, RangeListStrategy, - SimpleRangeListStrategy, make_range_list, UnicodeListStrategy, + SimpleRangeListStrategy, make_range_list, AsciiListStrategy, IntOrFloatListStrategy) from pypy.objspace.std import listobject from pypy.objspace.std.test.test_listobject import TestW_ListObject @@ -21,7 +21,7 @@ assert isinstance(W_ListObject(space, [wb('a'), wb('b')]).strategy, BytesListStrategy) assert isinstance(W_ListObject(space, [w(u'a'), w(u'b')]).strategy, - UnicodeListStrategy) + AsciiListStrategy) assert isinstance(W_ListObject(space, [w(u'a'), wb('b')]).strategy, ObjectListStrategy) # mixed unicode and bytes @@ -47,7 +47,7 @@ l = W_ListObject(space, []) assert isinstance(l.strategy, EmptyListStrategy) l.append(w(u'a')) - assert isinstance(l.strategy, UnicodeListStrategy) + assert isinstance(l.strategy, AsciiListStrategy) l = W_ListObject(space, []) assert isinstance(l.strategy, EmptyListStrategy) @@ -76,9 +76,9 @@ def test_unicode_to_any(self): space = self.space l = W_ListObject(space, [space.wrap(u'a'), space.wrap(u'b'), space.wrap(u'c')]) - assert isinstance(l.strategy, UnicodeListStrategy) + assert isinstance(l.strategy, AsciiListStrategy) l.append(space.wrap(u'd')) - assert isinstance(l.strategy, UnicodeListStrategy) + assert isinstance(l.strategy, AsciiListStrategy) l.append(space.wrap(3)) assert isinstance(l.strategy, ObjectListStrategy) @@ -117,7 +117,7 @@ # UnicodeStrategy to ObjectStrategy l = W_ListObject(space, [w(u'a'),w(u'b'),w(u'c')]) - assert isinstance(l.strategy, UnicodeListStrategy) + assert isinstance(l.strategy, AsciiListStrategy) l.setitem(0, w(2)) assert isinstance(l.strategy, ObjectListStrategy) @@ -145,7 +145,7 @@ # UnicodeStrategy l = W_ListObject(space, [w(u'a'),w(u'b'),w(u'c')]) - assert isinstance(l.strategy, UnicodeListStrategy) + assert isinstance(l.strategy, AsciiListStrategy) l.insert(3, w(2)) assert isinstance(l.strategy, ObjectListStrategy) @@ -225,7 +225,7 @@ # UnicodeStrategy to ObjectStrategy l = W_ListObject(space, [w(u'a'), w(u'b'), w(u'c')]) - assert isinstance(l.strategy, UnicodeListStrategy) + assert isinstance(l.strategy, AsciiListStrategy) l.setslice(0, 1, 2, W_ListObject(space, [w(1), w(2), w(3)])) assert isinstance(l.strategy, ObjectListStrategy) @@ -275,7 +275,7 @@ l = W_ListObject(space, wrapitems([u"a",u"b",u"c",u"d",u"e"])) other = W_ListObject(space, wrapitems([u"a", u"b", u"c"])) keep_other_strategy(l, 0, 2, other.length(), other) - assert l.strategy is space.fromcache(UnicodeListStrategy) + assert l.strategy is space.fromcache(AsciiListStrategy) l = W_ListObject(space, wrapitems([1.1, 2.2, 3.3, 4.4, 5.5])) other = W_ListObject(space, []) @@ -345,7 +345,7 @@ empty = W_ListObject(space, []) assert isinstance(empty.strategy, EmptyListStrategy) empty.extend(W_ListObject(space, [w(u"a"), w(u"b"), w(u"c")])) - assert isinstance(empty.strategy, UnicodeListStrategy) + assert isinstance(empty.strategy, AsciiListStrategy) empty = W_ListObject(space, []) assert isinstance(empty.strategy, EmptyListStrategy) @@ -601,7 +601,7 @@ l1 = W_ListObject(self.space, [self.space.newbytes("eins"), self.space.newbytes("zwei")]) assert isinstance(l1.strategy, BytesListStrategy) l2 = W_ListObject(self.space, [self.space.newutf8("eins", 4), self.space.newutf8("zwei", 4)]) - assert isinstance(l2.strategy, UnicodeListStrategy) + assert isinstance(l2.strategy, AsciiListStrategy) l3 = W_ListObject(self.space, [self.space.newbytes("eins"), self.space.newutf8("zwei", 4)]) assert isinstance(l3.strategy, ObjectListStrategy) @@ -611,11 +611,11 @@ w_l = self.space.newlist([self.space.newbytes('a'), self.space.newbytes('b')]) assert space.listview_bytes(w_l) == ["a", "b"] - def test_listview_unicode(self): + def test_listview_ascii(self): space = self.space - assert space.listview_utf8(space.wrap(1)) == None + assert space.listview_ascii(space.wrap(1)) == None w_l = self.space.newlist([self.space.wrap(u'a'), self.space.wrap(u'b')]) - assert space.listview_utf8(w_l) == ["a", "b"] + assert space.listview_ascii(w_l) == ["a", "b"] def test_string_join_uses_listview_bytes(self): space = self.space @@ -664,7 +664,7 @@ assert space.listview_bytes(w_l3) == ["a", "b", "c"] assert space.listview_bytes(w_l4) == ["a", "b", "c"] - def test_unicode_uses_newlist_unicode(self): + def test_unicode_uses_newlist_ascii(self): space = self.space w_u = space.wrap(u"a b c") space.newlist = None @@ -675,10 +675,10 @@ w_l4 = space.call_method(w_u, "rsplit", space.wrap(" ")) finally: del space.newlist - assert space.listview_utf8(w_l) == [u"a", u"b", u"c"] - assert space.listview_utf8(w_l2) == [u"a", u"b", u"c"] - assert space.listview_utf8(w_l3) == [u"a", u"b", u"c"] - assert space.listview_utf8(w_l4) == [u"a", u"b", u"c"] + assert space.listview_ascii(w_l) == [u"a", u"b", u"c"] + assert space.listview_ascii(w_l2) == [u"a", u"b", u"c"] + assert space.listview_ascii(w_l3) == [u"a", u"b", u"c"] + assert space.listview_ascii(w_l4) == [u"a", u"b", u"c"] def test_pop_without_argument_is_fast(self): space = self.space @@ -719,10 +719,10 @@ w_l = W_ListObject(space, [space.newbytes("a"), space.newbytes("b")]) assert self.space.listview_bytes(w_l) == ["a", "b"] - def test_listview_unicode_list(self): + def test_listview_ascii_list(self): space = self.space w_l = W_ListObject(space, [space.wrap(u"a"), space.wrap(u"b")]) - assert self.space.listview_utf8(w_l) == [u"a", u"b"] + assert self.space.listview_ascii(w_l) == [u"a", u"b"] def test_listview_int_list(self): space = self.space diff --git a/pypy/objspace/std/test/test_setobject.py b/pypy/objspace/std/test/test_setobject.py --- a/pypy/objspace/std/test/test_setobject.py +++ b/pypy/objspace/std/test/test_setobject.py @@ -80,7 +80,7 @@ def test_create_set_from_list(self): from pypy.interpreter.baseobjspace import W_Root - from pypy.objspace.std.setobject import BytesSetStrategy, ObjectSetStrategy, UnicodeSetStrategy + from pypy.objspace.std.setobject import BytesSetStrategy, ObjectSetStrategy from pypy.objspace.std.floatobject import W_FloatObject w = self.space.wrap @@ -105,8 +105,6 @@ w_list = self.space.iter(W_ListObject(self.space, [w(u"1"), w(u"2"), w(u"3")])) w_set = W_SetObject(self.space) _initialize_set(self.space, w_set, w_list) - #assert w_set.strategy is self.space.fromcache(UnicodeSetStrategy) - #assert w_set.strategy.unerase(w_set.sstorage) == {u"1":None, u"2":None, u"3":None} w_list = W_ListObject(self.space, [w("1"), w(2), w("3")]) w_set = W_SetObject(self.space) diff --git a/pypy/objspace/std/test/test_setstrategies.py b/pypy/objspace/std/test/test_setstrategies.py --- a/pypy/objspace/std/test/test_setstrategies.py +++ b/pypy/objspace/std/test/test_setstrategies.py @@ -2,7 +2,7 @@ from pypy.objspace.std.setobject import ( BytesIteratorImplementation, BytesSetStrategy, EmptySetStrategy, IntegerIteratorImplementation, IntegerSetStrategy, ObjectSetStrategy, - UnicodeIteratorImplementation, UnicodeSetStrategy) + UnicodeIteratorImplementation, AsciiSetStrategy) from pypy.objspace.std.listobject import W_ListObject class TestW_SetStrategies: @@ -26,8 +26,8 @@ s = W_SetObject(self.space, self.wrapped(["a", "b"])) assert s.strategy is self.space.fromcache(BytesSetStrategy) - #s = W_SetObject(self.space, self.wrapped([u"a", u"b"])) - #assert s.strategy is self.space.fromcache(UnicodeSetStrategy) + s = W_SetObject(self.space, self.wrapped([u"a", u"b"])) + assert s.strategy is self.space.fromcache(AsciiSetStrategy) def test_switch_to_object(self): s = W_SetObject(self.space, self.wrapped([1,2,3,4,5])) @@ -42,7 +42,7 @@ def test_switch_to_unicode(self): s = W_SetObject(self.space, self.wrapped([])) s.add(self.space.wrap(u"six")) - assert s.strategy is self.space.fromcache(UnicodeSetStrategy) + assert s.strategy is self.space.fromcache(AsciiSetStrategy) def test_symmetric_difference(self): s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5])) diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py --- a/pypy/objspace/std/test/test_unicodeobject.py +++ b/pypy/objspace/std/test/test_unicodeobject.py @@ -30,9 +30,9 @@ space.warn = prev_warn assert len(warnings) == 2 - def test_listview_unicode(self): + def test_listview_ascii(self): w_str = self.space.newutf8('abcd', 4) - assert self.space.listview_utf8(w_str) == list("abcd") + assert self.space.listview_ascii(w_str) == list("abcd") def test_new_shortcut(self): space = self.space diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py --- a/pypy/objspace/std/unicodeobject.py +++ b/pypy/objspace/std/unicodeobject.py @@ -129,9 +129,10 @@ # Returns ascii-encoded str return space.text_w(encode_object(space, self, 'ascii', 'strict')) - def listview_utf8(self): - assert self.is_ascii() - return _create_list_from_unicode(self._utf8) + def listview_ascii(self): + if self.is_ascii(): + return list(self._utf8) + return None def ord(self, space): if self._len() != 1: @@ -480,7 +481,7 @@ _StringMethods_descr_join = descr_join def descr_join(self, space, w_list): - l = space.listview_utf8(w_list) + l = space.listview_ascii(w_list) if l is not None and self.is_ascii(): if len(l) == 1: return space.newutf8(l[0], len(l[0])) @@ -1808,12 +1809,6 @@ W_UnicodeObject.typedef.flag_sequence_bug_compat = True -def _create_list_from_unicode(value): - # need this helper function to allow the jit to look inside and inline - # listview_unicode - return [s for s in value] - - W_UnicodeObject.EMPTY = W_UnicodeObject('', 0) From pypy.commits at gmail.com Sat Feb 8 05:40:29 2020 From: pypy.commits at gmail.com (cfbolz) Date: Sat, 08 Feb 2020 02:40:29 -0800 (PST) Subject: [pypy-commit] pypy py3.6: merge default Message-ID: <5e3e901d.1c69fb81.74825.e2c2@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: py3.6 Changeset: r98685:3aabca3d88f7 Date: 2020-02-08 11:39 +0100 http://bitbucket.org/pypy/pypy/changeset/3aabca3d88f7/ Log: merge default diff --git a/extra_tests/cffi_tests/cffi0/test_function.py b/extra_tests/cffi_tests/cffi0/test_function.py --- a/extra_tests/cffi_tests/cffi0/test_function.py +++ b/extra_tests/cffi_tests/cffi0/test_function.py @@ -521,3 +521,16 @@ assert str(e.value).startswith("library '") assert str(e.value).endswith("' has already been closed") ffi.dlclose(lib) # does not raise + + def test_passing_large_list(self): + if self.Backend is CTypesBackend: + py.test.skip("the ctypes backend doesn't support this") + ffi = FFI(backend=self.Backend()) + ffi.cdef(""" + void getenv(char *); + """) + needs_dlopen_none() + m = ffi.dlopen(None) + arg = [b"F", b"O", b"O"] + [b"\x00"] * 20000000 + x = m.getenv(arg) + assert x is None diff --git a/extra_tests/cffi_tests/cffi0/test_verify.py b/extra_tests/cffi_tests/cffi0/test_verify.py --- a/extra_tests/cffi_tests/cffi0/test_verify.py +++ b/extra_tests/cffi_tests/cffi0/test_verify.py @@ -2551,3 +2551,13 @@ """.replace('?', str(a))) # the verify() crashes if the values in the enum are different from # the values we computed ourselves from the cdef() + +def test_passing_large_list(): + ffi = FFI() + ffi.cdef("""void passing_large_list(long[]);""") + lib = ffi.verify(""" + static void passing_large_list(long a[]) { } + """) + arg = list(range(20000000)) + lib.passing_large_list(arg) + # assert did not segfault diff --git a/extra_tests/cffi_tests/cffi1/test_recompiler.py b/extra_tests/cffi_tests/cffi1/test_recompiler.py --- a/extra_tests/cffi_tests/cffi1/test_recompiler.py +++ b/extra_tests/cffi_tests/cffi1/test_recompiler.py @@ -2446,3 +2446,13 @@ }; """) py.test.raises(RuntimeError, ffi.new, "struct BinaryTree *") + +def test_passing_large_list(): + ffi = FFI() + ffi.cdef("""void passing_large_list(long[]);""") + lib = verify(ffi, "test_passing_large_list", """ + static void passing_large_list(long a[]) { } + """) + arg = list(range(20000000)) + lib.passing_large_list(arg) + # assert did not segfault diff --git a/extra_tests/cffi_tests/support.py b/extra_tests/cffi_tests/support.py --- a/extra_tests/cffi_tests/support.py +++ b/extra_tests/cffi_tests/support.py @@ -104,6 +104,7 @@ [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]): # assume a standard clang or gcc extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion', + '-Wno-unused-parameter', '-Wno-unreachable-code'] # special things for clang extra_compile_args.append('-Qunused-arguments') diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO --- a/lib_pypy/cffi.egg-info/PKG-INFO +++ b/lib_pypy/cffi.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: cffi -Version: 1.13.2 +Version: 1.14.0 Summary: Foreign Function Interface for Python calling C code. Home-page: http://cffi.readthedocs.org Author: Armin Rigo, Maciej Fijalkowski diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py --- a/lib_pypy/cffi/__init__.py +++ b/lib_pypy/cffi/__init__.py @@ -5,8 +5,8 @@ from .error import CDefError, FFIError, VerificationError, VerificationMissing from .error import PkgConfigError -__version__ = "1.13.2" -__version_info__ = (1, 13, 2) +__version__ = "1.14.0" +__version_info__ = (1, 14, 0) # The verifier module file names are based on the CRC32 of a string that # contains the following version number. It may be older than __version__ diff --git a/lib_pypy/cffi/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h --- a/lib_pypy/cffi/_cffi_include.h +++ b/lib_pypy/cffi/_cffi_include.h @@ -269,6 +269,54 @@ return _cffi_from_c_wchar3216_t((int)x); } +union _cffi_union_alignment_u { + unsigned char m_char; + unsigned short m_short; + unsigned int m_int; + unsigned long m_long; + unsigned long long m_longlong; + float m_float; + double m_double; + long double m_longdouble; +}; + +struct _cffi_freeme_s { + struct _cffi_freeme_s *next; + union _cffi_union_alignment_u alignment; +}; + +_CFFI_UNUSED_FN static int +_cffi_convert_array_argument(struct _cffi_ctypedescr *ctptr, PyObject *arg, + char **output_data, Py_ssize_t datasize, + struct _cffi_freeme_s **freeme) +{ + char *p; + if (datasize < 0) + return -1; + + p = *output_data; + if (p == NULL) { + struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc( + offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize); + if (fp == NULL) + return -1; + fp->next = *freeme; + *freeme = fp; + p = *output_data = (char *)&fp->alignment; + } + memset((void *)p, 0, (size_t)datasize); + return _cffi_convert_array_from_object(p, ctptr, arg); +} + +_CFFI_UNUSED_FN static void +_cffi_free_array_arguments(struct _cffi_freeme_s *freeme) +{ + do { + void *p = (void *)freeme; + freeme = freeme->next; + PyObject_Free(p); + } while (freeme != NULL); +} /********** end CPython-specific section **********/ #else diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h --- a/lib_pypy/cffi/_embedding.h +++ b/lib_pypy/cffi/_embedding.h @@ -224,7 +224,7 @@ if (f != NULL && f != Py_None) { PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME - "\ncompiled with cffi version: 1.13.2" + "\ncompiled with cffi version: 1.14.0" "\n_cffi_backend module: ", f); modules = PyImport_GetModuleDict(); mod = PyDict_GetItemString(modules, "_cffi_backend"); diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py --- a/lib_pypy/cffi/recompiler.py +++ b/lib_pypy/cffi/recompiler.py @@ -560,23 +560,24 @@ tovar, tp.get_c_name(''), errvalue)) self._prnt(' %s;' % errcode) - def _extra_local_variables(self, tp, localvars): + def _extra_local_variables(self, tp, localvars, freelines): if isinstance(tp, model.PointerType): localvars.add('Py_ssize_t datasize') + localvars.add('struct _cffi_freeme_s *large_args_free = NULL') + freelines.add('if (large_args_free != NULL)' + ' _cffi_free_array_arguments(large_args_free);') def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( self._gettypenum(tp), fromvar, tovar)) self._prnt(' if (datasize != 0) {') - self._prnt(' if (datasize < 0)') - self._prnt(' %s;' % errcode) - self._prnt(' %s = (%s)alloca((size_t)datasize);' % ( + self._prnt(' %s = ((size_t)datasize) <= 640 ? ' + '(%s)alloca((size_t)datasize) : NULL;' % ( tovar, tp.get_c_name(''))) - self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,)) - self._prnt(' if (_cffi_convert_array_from_object(' - '(char *)%s, _cffi_type(%d), %s) < 0)' % ( - tovar, self._gettypenum(tp), fromvar)) + self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, ' + '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar)) + self._prnt(' datasize, &large_args_free) < 0)') self._prnt(' %s;' % errcode) self._prnt(' }') @@ -699,9 +700,10 @@ prnt(' %s;' % arg) # localvars = set() + freelines = set() for type in tp.args: - self._extra_local_variables(type, localvars) - for decl in localvars: + self._extra_local_variables(type, localvars, freelines) + for decl in sorted(localvars): prnt(' %s;' % (decl,)) # if not isinstance(tp.result, model.VoidType): @@ -709,6 +711,7 @@ context = 'result of %s' % name result_decl = ' %s;' % tp.result.get_c_name(' result', context) prnt(result_decl) + prnt(' PyObject *pyresult;') else: result_decl = None result_code = '' @@ -742,9 +745,14 @@ if numargs == 0: prnt(' (void)noarg; /* unused */') if result_code: - prnt(' return %s;' % + prnt(' pyresult = %s;' % self._convert_expr_from_c(tp.result, 'result', 'result type')) + for freeline in freelines: + prnt(' ' + freeline) + prnt(' return pyresult;') else: + for freeline in freelines: + prnt(' ' + freeline) prnt(' Py_INCREF(Py_None);') prnt(' return Py_None;') prnt('}') diff --git a/lib_pypy/cffi/vengine_cpy.py b/lib_pypy/cffi/vengine_cpy.py --- a/lib_pypy/cffi/vengine_cpy.py +++ b/lib_pypy/cffi/vengine_cpy.py @@ -275,22 +275,23 @@ tovar, tp.get_c_name(''), errvalue)) self._prnt(' %s;' % errcode) - def _extra_local_variables(self, tp, localvars): + def _extra_local_variables(self, tp, localvars, freelines): if isinstance(tp, model.PointerType): localvars.add('Py_ssize_t datasize') + localvars.add('struct _cffi_freeme_s *large_args_free = NULL') + freelines.add('if (large_args_free != NULL)' + ' _cffi_free_array_arguments(large_args_free);') def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( self._gettypenum(tp), fromvar, tovar)) self._prnt(' if (datasize != 0) {') - self._prnt(' if (datasize < 0)') - self._prnt(' %s;' % errcode) - self._prnt(' %s = alloca((size_t)datasize);' % (tovar,)) - self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,)) - self._prnt(' if (_cffi_convert_array_from_object(' - '(char *)%s, _cffi_type(%d), %s) < 0)' % ( - tovar, self._gettypenum(tp), fromvar)) + self._prnt(' %s = ((size_t)datasize) <= 640 ? ' + 'alloca((size_t)datasize) : NULL;' % (tovar,)) + self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, ' + '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar)) + self._prnt(' datasize, &large_args_free) < 0)') self._prnt(' %s;' % errcode) self._prnt(' }') @@ -369,15 +370,17 @@ prnt(' %s;' % type.get_c_name(' x%d' % i, context)) # localvars = set() + freelines = set() for type in tp.args: - self._extra_local_variables(type, localvars) - for decl in localvars: + self._extra_local_variables(type, localvars, freelines) + for decl in sorted(localvars): prnt(' %s;' % (decl,)) # if not isinstance(tp.result, model.VoidType): result_code = 'result = ' context = 'result of %s' % name prnt(' %s;' % tp.result.get_c_name(' result', context)) + prnt(' PyObject *pyresult;') else: result_code = '' # @@ -409,9 +412,14 @@ if numargs == 0: prnt(' (void)noarg; /* unused */') if result_code: - prnt(' return %s;' % + prnt(' pyresult = %s;' % self._convert_expr_from_c(tp.result, 'result', 'result type')) + for freeline in freelines: + prnt(' ' + freeline) + prnt(' return pyresult;') else: + for freeline in freelines: + prnt(' ' + freeline) prnt(' Py_INCREF(Py_None);') prnt(' return Py_None;') prnt('}') @@ -981,6 +989,59 @@ return PyBool_FromLong(was_alive); } +union _cffi_union_alignment_u { + unsigned char m_char; + unsigned short m_short; + unsigned int m_int; + unsigned long m_long; + unsigned long long m_longlong; + float m_float; + double m_double; + long double m_longdouble; +}; + +struct _cffi_freeme_s { + struct _cffi_freeme_s *next; + union _cffi_union_alignment_u alignment; +}; + +#ifdef __GNUC__ + __attribute__((unused)) +#endif +static int _cffi_convert_array_argument(CTypeDescrObject *ctptr, PyObject *arg, + char **output_data, Py_ssize_t datasize, + struct _cffi_freeme_s **freeme) +{ + char *p; + if (datasize < 0) + return -1; + + p = *output_data; + if (p == NULL) { + struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc( + offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize); + if (fp == NULL) + return -1; + fp->next = *freeme; + *freeme = fp; + p = *output_data = (char *)&fp->alignment; + } + memset((void *)p, 0, (size_t)datasize); + return _cffi_convert_array_from_object(p, ctptr, arg); +} + +#ifdef __GNUC__ + __attribute__((unused)) +#endif +static void _cffi_free_array_arguments(struct _cffi_freeme_s *freeme) +{ + do { + void *p = (void *)freeme; + freeme = freeme->next; + PyObject_Free(p); + } while (freeme != NULL); +} + static int _cffi_init(void) { PyObject *module, *c_api_object = NULL; diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst --- a/pypy/doc/faq.rst +++ b/pypy/doc/faq.rst @@ -465,14 +465,30 @@ the GC and possibly the JIT. -Why doesn't PyPy move to GitHub, Gitlab, ...? ----------------------------------------------- +.. _git: +.. _github: -We've been quite happy with bitbucket.org. Moving version control systems and -hosting is a lot of hard work: On the one hand, PyPy's mercurial history is -long and gnarly. On the other hand, all our infrastructure (buildbots, -benchmarking, etc) would have to be adapted. So unless somebody steps up and -volunteers to do all that work, it will likely not happen. +Why doesn't PyPy use Git and move to GitHub? +--------------------------------------------- + +We discussed it during the switch away from bitbucket. We concluded that (1) +the Git workflow is not as well suited as the Mercurial workflow for our style, +and (2) moving to github "just because everybody else does" is a argument on +thin grounds. + +For (1), there are a few issues, but maybe the most important one is that the +PyPy repository has got thousands of *named* branches. Git has no equivalent +concept. Git has *branches,* of course, which in Mercurial are called +bookmarks. We're not talking about bookmarks. + +The difference between git branches and named branches is not that important in +a repo with 10 branches (no matter how big). But in the case of PyPy, we have +at the moment 1840 branches. Most are closed by now, of course. But we would +really like to retain (both now and in the future) the ability to look at a +commit from the past, and know in which branch it was made. Please make sure +you understand the difference between the Git and the Mercurial branches to +realize that this is not always possible with Git--- we looked hard, and there +is no built-in way to get this workflow. What is needed for Windows 64 support of PyPy? diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py --- a/pypy/module/_cffi_backend/__init__.py +++ b/pypy/module/_cffi_backend/__init__.py @@ -1,1 +1,1 @@ -VERSION = "1.13.2" +VERSION = "1.14.0" diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -1,7 +1,7 @@ # ____________________________________________________________ import sys -assert __version__ == "1.13.2", ("This test_c.py file is for testing a version" +assert __version__ == "1.14.0", ("This test_c.py file is for testing a version" " of cffi that differs from the one that we" " get from 'import _cffi_backend'") if sys.version_info < (3,): diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py --- a/pypy/objspace/std/test/test_listobject.py +++ b/pypy/objspace/std/test/test_listobject.py @@ -1405,7 +1405,7 @@ def test_unicode_bug_in_listview_utf8(self): l1 = list(u'\u1234\u2345') - assert l1 == [u'\u1234', '\u2345'] + assert l1 == [u'\u1234', u'\u2345'] def test_list_from_set(self): l = ['a'] diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py --- a/pypy/objspace/std/test/test_unicodeobject.py +++ b/pypy/objspace/std/test/test_unicodeobject.py @@ -26,7 +26,7 @@ s2 = unicode_to_decimal_w(space, w_s) assert s2 == "10" - def test_listview_unicode(self): + def test_listview_ascii(self): w_str = self.space.newutf8('abcd', 4) assert self.space.listview_ascii(w_str) == list("abcd") diff --git a/rpython/rlib/rstruct/runpack.py b/rpython/rlib/rstruct/runpack.py --- a/rpython/rlib/rstruct/runpack.py +++ b/rpython/rlib/rstruct/runpack.py @@ -86,12 +86,12 @@ for i in rg: fmtdesc, rep, mask = self.formats[i] miniglobals['unpacker%d' % i] = fmtdesc.unpack - if mask is not None: - perform_lst.append('master_reader.align(%d)' % mask) if not fmtdesc.needcount: perform_lst.append('unpacker%d(reader%d)' % (i, i)) else: perform_lst.append('unpacker%d(reader%d, %d)' % (i, i, rep)) + if mask is not None: + perform_lst.append('master_reader.align(%d)' % mask) miniglobals['reader_cls%d' % i] = reader_for_pos(i) readers = ";".join(["reader%d = reader_cls%d(master_reader, bigendian)" % (i, i) for i in rg]) diff --git a/rpython/rlib/rstruct/test/test_runpack.py b/rpython/rlib/rstruct/test/test_runpack.py --- a/rpython/rlib/rstruct/test/test_runpack.py +++ b/rpython/rlib/rstruct/test/test_runpack.py @@ -110,6 +110,15 @@ assert unpack(">q", '\xbeMLKJIHH') == -0x41B2B3B4B5B6B7B8 assert unpack(">Q", '\x81BCDEFGH') == 0x8142434445464748 + def test_align(self): + data = struct.pack('BBhi', 1, 2, 3, 4) + def fn(): + a, b, c, d = runpack('BBhi', data) + return a + (b << 4) + (c << 8) + (d << 12) + assert fn() == 0x4321 + assert self.interpret(fn, []) == 0x4321 + + class TestNoFastPath(TestRStruct): From pypy.commits at gmail.com Sat Feb 8 07:43:43 2020 From: pypy.commits at gmail.com (cfbolz) Date: Sat, 08 Feb 2020 04:43:43 -0800 (PST) Subject: [pypy-commit] pypy default: fix translation (why does the same code work on py3.6?) Message-ID: <5e3eacff.1c69fb81.a3193.07be@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: Changeset: r98686:57362e78ee31 Date: 2020-02-08 13:31 +0100 http://bitbucket.org/pypy/pypy/changeset/57362e78ee31/ Log: fix translation (why does the same code work on py3.6?) diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py --- a/pypy/objspace/std/unicodeobject.py +++ b/pypy/objspace/std/unicodeobject.py @@ -131,7 +131,7 @@ def listview_ascii(self): if self.is_ascii(): - return list(self._utf8) + return _create_list_from_unicode(self._utf8) return None def ord(self, space): @@ -1808,6 +1808,10 @@ ) W_UnicodeObject.typedef.flag_sequence_bug_compat = True +def _create_list_from_unicode(value): + # need this helper function to allow the jit to look inside and inline + # listview_ascii + return [s for s in value] W_UnicodeObject.EMPTY = W_UnicodeObject('', 0) From pypy.commits at gmail.com Sat Feb 8 11:55:06 2020 From: pypy.commits at gmail.com (cfbolz) Date: Sat, 08 Feb 2020 08:55:06 -0800 (PST) Subject: [pypy-commit] pypy py3.6: slightly overengineered code to improve the performance of str.join (helps both Message-ID: <5e3ee7ea.1c69fb81.c2836.0df0@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: py3.6 Changeset: r98687:7666a721d2fe Date: 2020-02-08 17:49 +0100 http://bitbucket.org/pypy/pypy/changeset/7666a721d2fe/ Log: slightly overengineered code to improve the performance of str.join (helps both the list in some situations and the iterator case, but the latter is helped more. speedups of >50% when using some other iterator) diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py --- a/pypy/objspace/std/test/test_unicodeobject.py +++ b/pypy/objspace/std/test/test_unicodeobject.py @@ -145,13 +145,20 @@ assert a == b assert type(a) == type(b) check(', '.join(['a']), 'a') + check(', '.join(['a', 'b']), 'a, b') raises(TypeError, ','.join, [b'a']) - exc = raises(TypeError, ''.join, ['a', 2, 3]) + check(','.join(iter([])), '') + with raises(TypeError) as exc: + ''.join(['a', 2, 3]) + assert 'sequence item 1' in str(exc.value) + with raises(TypeError) as exc: + ''.join(iter(['a', 2, 3])) assert 'sequence item 1' in str(exc.value) # unicode lists check(''.join(['\u1234']), '\u1234') check(''.join(['\u1234', '\u2345']), '\u1234\u2345') check('\u1234'.join(['\u2345', '\u3456']), '\u2345\u1234\u3456') + check('x\u1234y'.join(['a', 'b', 'c']), 'ax\u1234ybx\u1234yc') # also checking passing a single unicode instead of a list check(''.join('\u1234'), '\u1234') check(''.join('\u1234\u2345'), '\u1234\u2345') diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py --- a/pypy/objspace/std/unicodeobject.py +++ b/pypy/objspace/std/unicodeobject.py @@ -41,6 +41,9 @@ return rutf8.codepoint_at_pos(utf8, p) +joindriver = jit.JitDriver(greens = ['selfisnotempty', 'tpfirst', 'tplist'], reds = 'auto', + name='joindriver') + class W_UnicodeObject(W_Root): import_from_mixin(StringMethods) _immutable_fields_ = ['_utf8', '_length'] @@ -166,9 +169,6 @@ def _generic_name(self): return "str" - def _generic_name(self): - return "str" - def _isupper(self, ch): return unicodedb.isupper(ch) @@ -593,15 +593,101 @@ return W_UnicodeObject(expanded, newlen) - _StringMethods_descr_join = descr_join - def descr_join(self, space, w_list): - l = space.listview_ascii(w_list) - if l is not None and self.is_ascii(): - if len(l) == 1: - return space.newutf8(l[0], len(l[0])) - s = self._utf8.join(l) - return space.newutf8(s, len(s)) - return self._StringMethods_descr_join(space, w_list) + def _join_utf8_len_w(self, space, w_element, i): + try: + return space.utf8_len_w(w_element) + except OperationError as e: + if not e.match(space, space.w_TypeError): + raise + raise oefmt(space.w_TypeError, + "sequence item %d: expected %s, %T found", + i, self._generic_name(), w_element) + + def _join_ascii(self, space, l): + if len(l) == 1: + return space.newutf8(l[0], len(l[0])) + s = self._utf8.join(l) + if self.is_ascii(): + resultlen = len(s) + else: + # carefully compute the result length + resultlen = len(s) - (len(self._utf8) - self._length) * (len(l) - 1) + return space.newutf8(s, resultlen) + + def _join_from_list(self, space, w_list): + list_w = space.listview(w_list) + if len(list_w) == 0: + return self.EMPTY + if len(list_w) == 1: + w_s = list_w[0] + # only one item, return it if it's not a subclass of str + if self._join_return_one(space, w_s): + return w_s + # the stringmethods implementation makes a copy of the list to + # pre-compute the correct size for preallocation. that sounds like the + # wrong tradeoff somehow... + builder = None + # use first element to guess preallocation size + w_first = list_w[0] + utf8first, lenfirst = self._join_utf8_len_w(space, w_first, 0) + prealloc = len(self._utf8) * (len(list_w) - 1) + len(utf8first) * len(list_w) + builder = rutf8.Utf8StringBuilder(prealloc) + builder.append_utf8(utf8first, lenfirst) + for i in range(1, len(list_w)): + w_element = list_w[i] + utf8, l = self._join_utf8_len_w(space, w_element, i) + if self._length: + builder.append_utf8(self._utf8, self._length) + builder.append_utf8(utf8, l) + return self.from_utf8builder(builder) + + def _join_from_iterable(self, space, w_iterable): + sizehint = space.length_hint(w_iterable, -1) + + # get the first element to guess the preallocation size + iterator = space.iteriterable(w_iterable) + try: + w_first = next(iterator) + except StopIteration: + return W_UnicodeObject.EMPTY + + utf8first, lenfirst = self._join_utf8_len_w(space, w_first, 0) + if sizehint >= 0: + prealloc = len(self._utf8) * (sizehint - 1) + len(utf8first) * sizehint + else: + prealloc = len(self._utf8) + len(utf8first) + + # build the result + builder = rutf8.Utf8StringBuilder(prealloc) + builder.append_utf8(utf8first, lenfirst) + size = 1 + selfisnotempty = self._length != 0 + tpfirst = space.type(w_first) + tplist = space.type(w_iterable) + for w_element in iterator: + joindriver.jit_merge_point(tpfirst=tpfirst, tplist=tplist, selfisnotempty=selfisnotempty) + if selfisnotempty: + builder.append_utf8(self._utf8, self._length) + utf8, l = self._join_utf8_len_w(space, w_element, size) + builder.append_utf8(utf8, l) + size += 1 + if size == 1 and self._join_return_one(space, w_first): + return w_first + return W_UnicodeObject.from_utf8builder(builder) + + def descr_join(self, space, w_iterable): + from pypy.objspace.std.listobject import W_ListObject + # somewhat overengineered, but it's quite common + + # first, a shortcut for when w_iterable is ascii-only + l = space.listview_ascii(w_iterable) + if l is not None: + return self._join_ascii(space, l) + + if type(w_iterable) is W_ListObject or (isinstance(w_iterable, W_ListObject) and + space._uses_list_iter(w_iterable)): + self._join_from_list(space, w_iterable) + return self._join_from_iterable(space, w_iterable) def _join_return_one(self, space, w_obj): return space.is_w(space.type(w_obj), space.w_unicode) From pypy.commits at gmail.com Sun Feb 9 07:21:32 2020 From: pypy.commits at gmail.com (cfbolz) Date: Sun, 09 Feb 2020 04:21:32 -0800 (PST) Subject: [pypy-commit] pypy pypy-jitdriver-greenkeys: a branch to try refactor the way that green keys are done on all the small Message-ID: <5e3ff94c.1c69fb81.8a39b.fd26@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: pypy-jitdriver-greenkeys Changeset: r98688:44bc458acf77 Date: 2020-02-08 17:56 +0100 http://bitbucket.org/pypy/pypy/changeset/44bc458acf77/ Log: a branch to try refactor the way that green keys are done on all the small custom jit driver that pypy uses here and there From pypy.commits at gmail.com Sun Feb 9 07:21:34 2020 From: pypy.commits at gmail.com (cfbolz) Date: Sun, 09 Feb 2020 04:21:34 -0800 (PST) Subject: [pypy-commit] pypy pypy-jitdriver-greenkeys: - introduce space.iterator_greenkey which returns "something" that can be used Message-ID: <5e3ff94e.1c69fb81.1a3c4.69e8@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: pypy-jitdriver-greenkeys Changeset: r98689:28f7848bd9ca Date: 2020-02-09 13:20 +0100 http://bitbucket.org/pypy/pypy/changeset/28f7848bd9ca/ Log: - introduce space.iterator_greenkey which returns "something" that can be used as the green key for an iterator to get the right specialization. by default it's just the type of the iterator, but generators override it to use the underlying pycode. That way, space.unpackiterable of two different generators produce two different loops. - make a pass over all jitdrivers to use this new api diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -22,12 +22,12 @@ __all__ = ['ObjSpace', 'OperationError', 'W_Root'] -def get_printable_location(tp): - return "unpackiterable: %s" % (tp, ) +def get_printable_location(greenkey): + return "unpackiterable [%s]" % (greenkey.iterator_greenkey_printable(), ) unpackiterable_driver = jit.JitDriver(name='unpackiterable', - greens=['tp'], - reds=['items', 'w_iterator'], + greens=['greenkey'], + reds='auto', get_printable_location=get_printable_location) @@ -373,6 +373,15 @@ return lst[:] return None + def iterator_greenkey(self, space): + """ Return something that can be used as a green key in jit drivers + that iterate over self. by default, it's just the type of self, but + custom iterators should override it. """ + return space.type(self) + + def iterator_greenkey_printable(self): + return "?" + class InterpIterable(object): def __init__(self, space, w_iterable): @@ -986,11 +995,9 @@ except MemoryError: items = [] # it might have lied - tp = self.type(w_iterator) + greenkey = self.iterator_greenkey(w_iterator) while True: - unpackiterable_driver.jit_merge_point(tp=tp, - w_iterator=w_iterator, - items=items) + unpackiterable_driver.jit_merge_point(greenkey=greenkey) try: w_item = self.next(w_iterator) except OperationError as e: @@ -2045,6 +2052,12 @@ finally: self.sys.track_resources = flag + def iterator_greenkey(self, w_iterable): + """ Return something that can be used as a green key in jit drivers + that iterate over self. by default, it's just the type of self, but + custom iterators should override it. """ + return w_iterable.iterator_greenkey(self) + class AppExecCache(SpaceCache): @not_rpython diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py --- a/pypy/interpreter/generator.py +++ b/pypy/interpreter/generator.py @@ -231,6 +231,9 @@ self.frame = None rgc.may_ignore_finalizer(self) + def iterator_greenkey(self): + return self.pycode + def get_printable_location_genentry(bytecode): return '%s ' % (bytecode.get_repr(),) diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py --- a/pypy/interpreter/pycode.py +++ b/pypy/interpreter/pycode.py @@ -425,6 +425,9 @@ return "" % ( self.co_name, self.co_filename, self.co_firstlineno) + def iterator_greenkey_printable(self): + return self.get_repr() + def __repr__(self): return self.get_repr() diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py --- a/pypy/module/__builtin__/functional.py +++ b/pypy/module/__builtin__/functional.py @@ -131,10 +131,21 @@ v = v.add(step) return space.newlist(res_w) +def get_printable_location(has_key, has_item, greenkey): + return "min [has_key=%s, has_item=%s, %s]" % ( + has_key, has_item, greenkey.iterator_greenkey_printable()) + min_jitdriver = jit.JitDriver(name='min', - greens=['has_key', 'has_item', 'w_type'], reds='auto') + greens=['has_key', 'has_item', 'greenkey'], reds='auto', + get_printable_location=get_printable_location) + +def get_printable_location(has_key, has_item, greenkey): + return "min [has_key=%s, has_item=%s, %s]" % ( + has_key, has_item, greenkey.iterator_greenkey_printable()) + max_jitdriver = jit.JitDriver(name='max', - greens=['has_key', 'has_item', 'w_type'], reds='auto') + greens=['has_key', 'has_item', 'greenkey'], reds='auto', + get_printable_location=get_printable_location) @specialize.arg(3) def min_max_sequence(space, w_sequence, w_key, implementation_of): @@ -145,14 +156,14 @@ compare = space.lt jitdriver = min_jitdriver w_iter = space.iter(w_sequence) - w_type = space.type(w_iter) + greenkey = space.iterator_greenkey(w_iter) has_key = w_key is not None has_item = False w_max_item = None w_max_val = None while True: jitdriver.jit_merge_point(has_key=has_key, has_item=has_item, - w_type=w_type) + greenkey=greenkey) try: w_item = space.next(w_iter) except OperationError as e: diff --git a/pypy/module/itertools/interp_itertools.py b/pypy/module/itertools/interp_itertools.py --- a/pypy/module/itertools/interp_itertools.py +++ b/pypy/module/itertools/interp_itertools.py @@ -322,10 +322,12 @@ """) +def get_printable_location(greenkey): + return "islice_ignore_items [%s]" % (greenkey.iterator_greenkey_printable(), ) islice_ignore_items_driver = jit.JitDriver(name='islice_ignore_items', - greens=['tp'], - reds=['num', 'w_islice', - 'w_iterator']) + greens=['greenkey'], + reds='auto', + get_printable_location=get_printable_location) class W_ISlice(W_Root): def __init__(self, space, w_iterable, w_startstop, args_w): @@ -418,12 +420,9 @@ if w_iterator is None: raise OperationError(self.space.w_StopIteration, self.space.w_None) - tp = self.space.type(w_iterator) + greenkey = self.space.iterator_greenkey(w_iterator) while True: - islice_ignore_items_driver.jit_merge_point(tp=tp, - num=num, - w_islice=self, - w_iterator=w_iterator) + islice_ignore_items_driver.jit_merge_point(greenkey=greenkey) try: self.space.next(w_iterator) except OperationError as e: diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py --- a/pypy/objspace/descroperation.py +++ b/pypy/objspace/descroperation.py @@ -125,7 +125,7 @@ pass contains_jitdriver = jit.JitDriver(name='contains', - greens=['w_type'], reds='auto') + greens=['itergreenkey', 'w_itemtype'], reds='auto') class DescrOperation(object): # This is meant to be a *mixin*. @@ -406,9 +406,10 @@ def _contains(space, w_container, w_item): w_iter = space.iter(w_container) - w_type = space.type(w_iter) + itergreenkey = space.iterator_greenkey(w_iter) + w_itemtype = space.type(w_item) while 1: - contains_jitdriver.jit_merge_point(w_type=w_type) + contains_jitdriver.jit_merge_point(itergreenkey=itergreenkey, w_itemtype=w_itemtype) try: w_next = space.next(w_iter) except OperationError as e: diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py --- a/pypy/objspace/std/bytearrayobject.py +++ b/pypy/objspace/std/bytearrayobject.py @@ -561,14 +561,14 @@ return list(buf.as_str()) return _from_byte_sequence(space, w_source) -def _get_printable_location(w_type): - return ('bytearray_from_byte_sequence [w_type=%s]' % - w_type.getname(w_type.space)) +def _get_printable_location(greenkey): + return ('bytearray_from_byte_sequence [%s]' % + greenkey.iterator_greenkey_printable()) _byteseq_jitdriver = jit.JitDriver( name='bytearray_from_byte_sequence', - greens=['w_type'], - reds=['w_iter', 'data'], + greens=['greenkey'], + reds='auto' get_printable_location=_get_printable_location) def _from_byte_sequence(space, w_source): @@ -586,11 +586,9 @@ return data def _from_byte_sequence_loop(space, w_iter, data): - w_type = space.type(w_iter) + greenkey = space.iterator_greenkey(w_iter) while True: - _byteseq_jitdriver.jit_merge_point(w_type=w_type, - w_iter=w_iter, - data=data) + _byteseq_jitdriver.jit_merge_point(greenkey=greenkey) try: w_item = space.next(w_iter) except OperationError as e: diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py --- a/pypy/objspace/std/listobject.py +++ b/pypy/objspace/std/listobject.py @@ -131,26 +131,26 @@ return space.fromcache(ObjectListStrategy) -def _get_printable_location(w_type): - return ('list__do_extend_from_iterable [w_type=%s]' % - w_type.getname(w_type.space)) +def _get_printable_location(greenkey): + return 'list__do_extend_from_iterable [%s, %s]' % ( + strategy, + greenkey.iterator_greenkey_printable()) _do_extend_jitdriver = jit.JitDriver( name='list__do_extend_from_iterable', - greens=['w_type'], - reds=['i', 'w_iterator', 'w_list'], + greens=['strategy', 'greenkey'], + reds='auto', get_printable_location=_get_printable_location) def _do_extend_from_iterable(space, w_list, w_iterable): w_iterator = space.iter(w_iterable) - w_type = space.type(w_iterator) + w_type = space.iterator_greenkey_printable(w_iterator) i = 0 while True: - _do_extend_jitdriver.jit_merge_point(w_type=w_type, - i=i, - w_iterator=w_iterator, - w_list=w_list) + _do_extend_jitdriver.jit_merge_point( + w_type=w_type, + strategy = w_list.strategy) try: w_list.append(space.next(w_iterator)) except OperationError as e: @@ -749,7 +749,9 @@ if mucked: raise oefmt(space.w_ValueError, "list modified during sort") -find_jmp = jit.JitDriver(greens = ['tp'], reds = 'auto', name = 'list.find') +def get_printable_location(strategy, tp): + return "list.find [%s, %s]" % (strategy, tp.getname(tp.space), ) +find_jmp = jit.JitDriver(greens = ['strategy', 'tp'], reds = 'auto', name = 'list.find', get_printable_location=get_printable_location) class ListStrategy(object): @@ -777,7 +779,7 @@ # needs to be safe against eq_w mutating stuff tp = space.type(w_item) while i < stop and i < w_list.length(): - find_jmp.jit_merge_point(tp=tp) + find_jmp.jit_merge_point(tp=tp, strategy=self) if space.eq_w(w_item, w_list.getitem(i)): return i i += 1 diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py --- a/pypy/objspace/std/setobject.py +++ b/pypy/objspace/std/setobject.py @@ -1681,7 +1681,7 @@ def get_printable_location(tp, strategy): - return "create_set: %s %s" % (tp, strategy) + return "create_set: %s %s" % (tp.iterator_greenkey_printable(), strategy) create_set_driver = jit.JitDriver(name='create_set', greens=['tp', 'strategy'], @@ -1692,7 +1692,7 @@ w_set.strategy = strategy = space.fromcache(EmptySetStrategy) w_set.sstorage = strategy.get_empty_storage() - tp = space.type(w_iterable) + tp = space.iterator_greenkey(w_iterable) w_iter = space.iter(w_iterable) while True: diff --git a/pypy/objspace/std/tupleobject.py b/pypy/objspace/std/tupleobject.py --- a/pypy/objspace/std/tupleobject.py +++ b/pypy/objspace/std/tupleobject.py @@ -27,13 +27,22 @@ jit.loop_unrolling_heuristic(other, other.length(), UNROLL_CUTOFF)) +def get_printable_location(tp): + return "tuple.contains [%s]" % (tp.getname(tp.space), ) + contains_jmp = jit.JitDriver(greens = ['tp'], reds = 'auto', - name = 'tuple.contains') + name = 'tuple.contains', + get_printable_location=get_printable_location) + +def get_printable_location(w_type): + return "tuple.hash [%s]" % (w_type.getname(w_type.space), ) hash_driver = jit.JitDriver( name='tuple.hash', greens=['w_type'], - reds='auto') + reds='auto', + get_printable_location=get_printable_location + ) class W_AbstractTupleObject(W_Root): __slots__ = () From pypy.commits at gmail.com Sun Feb 9 10:12:09 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 09 Feb 2020 07:12:09 -0800 (PST) Subject: [pypy-commit] pypy.org nikola: rework navbar Message-ID: <5e402149.1c69fb81.b0225.b080@mx.google.com> Author: Matti Picus Branch: nikola Changeset: r973:4426e5769672 Date: 2020-02-09 17:11 +0200 http://bitbucket.org/pypy/pypy.org/changeset/4426e5769672/ Log: rework navbar diff --git a/conf.py b/conf.py --- a/conf.py +++ b/conf.py @@ -167,6 +167,8 @@ # Alternative navigation links. Works the same way NAVIGATION_LINKS does, # although themes may not always support them. (translatable) # (Bootstrap 4: right-side of navbar, Bootblog 4: right side of title) +# +# Not supported in the PyPy theme NAVIGATION_ALT_LINKS = { DEFAULT_LANG: () } diff --git a/themes/pypy/assets/css/styles.css b/themes/pypy/assets/css/styles.css --- a/themes/pypy/assets/css/styles.css +++ b/themes/pypy/assets/css/styles.css @@ -1,3 +1,12 @@ +:root { + --content-width: 1000px; + --breakpoint: 799px; + --nav-height: 70px; + --nav-background: #d0dad5; + --nav-font-color: darkolivgreen; + --link-hover-color: #e0dad5; +} + body { color: #383939; } @@ -11,201 +20,6 @@ background-color: #d0dad5; } -.myTopNav { - /* background-color: #333; */ - display: flex; - flex-direction: row; - margin-bottom: 5px; - height: 47px; -} - -/* Style the links inside the navigation bar */ -.myTopNav a { - float: left; - display: block; - text-decoration: none; - font-size: 17px; -} - -.topnav { - height: 32px; -} - -.topnav a { - float: left; - display: block; - color: #383939; - text-align: center; - padding-top: 8px; - padding-left: 16px; - padding-right: 16px; - padding-bottom: 12px; - text-decoration: none; - font-size: 17px; -} - -/* Add an active class to highlight the current page */ -.active { - background-color: #4CAF50; - color: white; -} - -/* Hide the link that should open and close the topnav on small screens */ -.myTopNav .icon { - display: none; -} - -/* Dropdown container - needed to position the dropdown content */ -.dropdown { - float: left; - overflow: hidden; -} - -/* Style the dropdown button to fit inside the topnav */ -.dropdown .dropbtn { - font-size: 17px; - border: none; - outline: none; - color: #383939; - padding-top: 10px; - padding-left: 16px; - padding-right: 16px; - padding-bottom: 12px; - background-color: inherit; - font-family: inherit; - margin: 0; -} - -/* Style the dropdown content (hidden by default) */ -.dropdown-content { - display: none; - position: absolute; - background-color: #f9f9f9; - min-width: 160px; - box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); - z-index: 1; -} - -/* Style the links inside the dropdown */ -.dropdown-content a { - float: none; - color: black; - padding: 12px 16px; - text-decoration: none; - display: block; - text-align: left; -} - -/* Add a dark background on topnav links and the dropdown button on hover */ -.myTopNav a:hover, .dropdown:hover .dropbtn { - background-color: #555; - color: white; -} - -/* Add a grey background to dropdown links on hover */ -.dropdown-content a:hover { - background-color: #ddd; - color: black; -} - -/* Show the dropdown menu when the user moves the mouse over the dropdown button */ -.dropdown:hover .dropdown-content { - display: block; -} - -/* When the screen is less than 600 pixels wide, hide all links, except for the first one ("Home"). Show the link that contains should open and close the topnav (.icon) */ - at media screen and (max-width: 600px) { - .myTopNav a:not(:first-child), .dropdown .dropbtn { - display: none; - } - .myTopNav a.icon { - float: right; - display: block; - } -} - -/* The "responsive" class is added to the topnav with JavaScript when the user clicks on the icon. This class makes the topnav look good on small screens (display the links vertically instead of horizontally) */ - at media screen and (max-width: 600px) { - .myTopNav.responsive {position: relative;} - .myTopNav.responsive a.icon { - position: absolute; - right: 0; - top: 0; - } - .myTopNav.responsive a { - float: none; - display: block; - text-align: left; - } - .myTopNav.responsive .dropdown {float: none;} - .myTopNav.responsive .dropdown-content {position: relative;} - .myTopNav.responsive .dropdown .dropbtn { - display: block; - width: 100%; - text-align: left; - } - - -} .row { - display: flex; - flex-direction: column; - padding: 0; - width: 100%; } - .row .column { - display: block; - flex: 1 1 auto; - margin-left: 0; - max-width: 100%; - width: 100%; } - - at media (min-width: 40rem) { - .row { - flex-direction: row; - margin-left: -1.0rem; - width: calc(100% + 2.0rem); } - .row .column { - margin-bottom: inherit; - padding: 0 1.0rem; } } - - at media screen and (max-width: 40rem) { - .row .column { - text-align: center; } } - -.pb-4 { - padding-bottom: 6rem; } - -.text-sm { - font-size: 1rem; } - -.text-lg { - font-size: 2rem; } - -/*.button, button { - background-color: transparent; - border: 0.1rem solid #1890ff; - border-radius: .4rem; - cursor: pointer; - display: inline-block; - font-weight: 700; - height: 2rem; - letter-spacing: .1rem; - line-height: 2rem; - padding: 0 2.0rem; - text-align: center; - text-decoration: none; - text-transform: uppercase; - white-space: nowrap; -} - -.button:focus, .button:hover, -button:focus, -button:hover - { - background-color: lightblue; - border-color: #4B545C; - color: white; -} -*/ pre.literal-block { border-left: 0.3rem solid #d1d1d1; margin-left: 0; @@ -229,3 +43,167 @@ .logotext { padding-top: 4px; +} + +#toplogo { + padding-top: 18px; +} + +/* For the responsive navbar, adapted from https://www.taniarascia.com/responsive-dropdown-navigation-bar */ + + at charset "UTF-8"; +.navigation { + height: 70px; + background: var(--nav-background); +} + +.brand { + position: absolute; + padding-left: 20px; + float: left; + line-height: 70px; + text-transform: uppercase; + font-size: 1.4em; +} +.brand a, +.brand a:visited { + color: var(--nav-font-color); + text-decoration: none; +} + +.nav-container { + max-width: content-width; + margin: 0 auto; +} + +nav { + float: right; +} +nav ul { + list-style: none; + margin: 0; + padding: 0; +} +nav ul li { + float: left; + position: relative; +} +nav ul li a:link, +nav ul li a, +nav ul li a:visited { + display: block; + padding: 0 20px; + line-height: 70px; + background: var(--nav-background); + color: var(--nav-font-color); + text-decoration: none; +} +nav ul li a:hover, +nav ul li a:link:hover, +nav ul li a:visited:hover { + background: var(--link-hover-color); + color: var(--nav-font-color); +} +nav ul li a:not(:only-child):after, +nav ul li a:visited:not(:only-child):after { + padding-left: 4px; + content: ' ▾'; +} +nav ul li ul li { + min-width: 190px; +} +nav ul li ul li a { + padding: 15px; + line-height: 20px; +} + +.nav-dropdown { + position: absolute; + display: none; + z-index: 1; + box-shadow: 0 3px 12px rgba(0, 0, 0, 0.15); +} + +/* Mobile navigation */ +.nav-mobile { + display: none; + position: absolute; + top: 0; + right: 0; + background: var(--nav-background); + height: 70px; + width: 70px; +} + + at media only screen and (max-width: 798px) { + .nav-mobile { + display: block; + } + + nav { + width: 100%; + padding: 70px 0 15px; + } + nav ul { + display: none; + } + nav ul li { + float: none; + } + nav ul li a { + padding: 15px; + line-height: 20px; + } + nav ul li ul li a { + padding-left: 30px; + } + + .nav-dropdown { + position: static; + } +} + + at media screen and (min-width: 799px) { + .nav-list { + display: block !important; + } +} +#nav-toggle { + position: absolute; + left: 18px; + top: 22px; + cursor: pointer; + padding: 10px 35px 16px 0px; +} +#nav-toggle span, +#nav-toggle span:before, +#nav-toggle span:after { + cursor: pointer; + border-radius: 1px; + height: 5px; + width: 35px; + background: black; + position: absolute; + display: block; + content: ''; + transition: all 300ms ease-in-out; +} +#nav-toggle span:before { + top: -10px; +} +#nav-toggle span:after { + bottom: -10px; +} +#nav-toggle.active span { + background-color: transparent; +} +#nav-toggle.active span:before, #nav-toggle.active span:after { + top: 0; +} +#nav-toggle.active span:before { + transform: rotate(45deg); +} +#nav-toggle.active span:after { + transform: rotate(-45deg); +} + diff --git a/themes/pypy/assets/js/styles.js b/themes/pypy/assets/js/styles.js --- a/themes/pypy/assets/js/styles.js +++ b/themes/pypy/assets/js/styles.js @@ -1,12 +1,25 @@ 'use strict'; -// Navbar -/* Toggle between adding and removing the "responsive" class to topnav when the user clicks on the icon */ -function make_responsive() { - var x = document.getElementById("myTopNav"); - if (x.className === "topnav") { - x.className += " responsive"; - } else { - x.className = "topnav"; - } -} +(function($) { // Begin jQuery + $(function() { // DOM ready + // If a link has a dropdown, add sub menu toggle. + $('nav ul li a:not(:only-child)').click(function(eee) { + $(this).siblings('.nav-dropdown').toggle(); + // Close one dropdown when selecting another + $('.nav-dropdown').not($(this).siblings()).hide(); + eee.stopPropagation(); + }); + // Clicking away from dropdown will remove the dropdown class + $('html').click(function() { + $('.nav-dropdown').hide(); + }); + // Toggle open and close nav styles on click + $('#nav-toggle').click(function() { + $('nav ul').slideToggle(); + }); + // Hamburger to X toggle + $('#nav-toggle').on('click', function() { + this.classList.toggle('active'); + }); + }); // end DOM ready +})(jQuery); // end jQuery diff --git a/themes/pypy/templates/base_header.tmpl b/themes/pypy/templates/base_header.tmpl --- a/themes/pypy/templates/base_header.tmpl +++ b/themes/pypy/templates/base_header.tmpl @@ -29,43 +29,39 @@ {% endmacro %} {% macro html_navigation_links() %} -
-
- - PyPy/ - -
-
- {{ html_navigation_links_entries(navigation_links) }} - {{ html_navigation_links_entries(navigation_alt_links) }} - {{ template_hooks['menu']() }} - {{ template_hooks['menu_alt']() }} -
- -
+ + {% endmacro %} {% macro html_navigation_links_entries(navigation_links_source) %} {% for url, text in navigation_links_source[lang] %} {% if isinstance(url, tuple) %} - +
  • + {{ text}} + +
  • {% else %} - {% if rel_link(permalink, url) == "#" %} - {{ text }} {{ messages("(active)", lang) }} - {% else %} - {{ text }} - {% endif %} +
  • {{ text}}
  • {% endif %} {% endfor %} {% endmacro %} diff --git a/themes/pypy/templates/base_helper.tmpl b/themes/pypy/templates/base_helper.tmpl --- a/themes/pypy/templates/base_helper.tmpl +++ b/themes/pypy/templates/base_helper.tmpl @@ -71,6 +71,7 @@ {% endif %} {% else %} + {% endif %} {% if date_fanciness != 0 %} From pypy.commits at gmail.com Sun Feb 9 10:12:11 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 09 Feb 2020 07:12:11 -0800 (PST) Subject: [pypy-commit] pypy.org nikola: commit rendered site Message-ID: <5e40214b.1c69fb81.a97b9.2d5e@mx.google.com> Author: Matti Picus Branch: nikola Changeset: r974:b75235a396d2 Date: 2020-02-09 17:11 +0200 http://bitbucket.org/pypy/pypy.org/changeset/b75235a396d2/ Log: commit rendered site diff --git a/public/archive.html b/public/archive.html --- a/public/archive.html +++ b/public/archive.html @@ -26,41 +26,38 @@ -
    -
    - - PyPy/ -
    -
    - - -

    Archive

    +

    Archive

    No posts found.

    @@ -77,6 +74,6 @@
    - + diff --git a/public/assets/css/styles.css b/public/assets/css/styles.css --- a/public/assets/css/styles.css +++ b/public/assets/css/styles.css @@ -1,3 +1,12 @@ +:root { + --content-width: 1000px; + --breakpoint: 799px; + --nav-height: 70px; + --nav-background: #d0dad5; + --nav-font-color: darkolivgreen; + --link-hover-color: #e0dad5; +} + body { color: #383939; } @@ -11,201 +20,6 @@ background-color: #d0dad5; } -.myTopNav { - /* background-color: #333; */ - display: flex; - flex-direction: row; - margin-bottom: 5px; - height: 47px; -} - -/* Style the links inside the navigation bar */ -.myTopNav a { - float: left; - display: block; - text-decoration: none; - font-size: 17px; -} - -.topnav { - height: 32px; -} - -.topnav a { - float: left; - display: block; - color: #383939; - text-align: center; - padding-top: 8px; - padding-left: 16px; - padding-right: 16px; - padding-bottom: 12px; - text-decoration: none; - font-size: 17px; -} - -/* Add an active class to highlight the current page */ -.active { - background-color: #4CAF50; - color: white; -} - -/* Hide the link that should open and close the topnav on small screens */ -.myTopNav .icon { - display: none; -} - -/* Dropdown container - needed to position the dropdown content */ -.dropdown { - float: left; - overflow: hidden; -} - -/* Style the dropdown button to fit inside the topnav */ -.dropdown .dropbtn { - font-size: 17px; - border: none; - outline: none; - color: #383939; - padding-top: 10px; - padding-left: 16px; - padding-right: 16px; - padding-bottom: 12px; - background-color: inherit; - font-family: inherit; - margin: 0; -} - -/* Style the dropdown content (hidden by default) */ -.dropdown-content { - display: none; - position: absolute; - background-color: #f9f9f9; - min-width: 160px; - box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); - z-index: 1; -} - -/* Style the links inside the dropdown */ -.dropdown-content a { - float: none; - color: black; - padding: 12px 16px; - text-decoration: none; - display: block; - text-align: left; -} - -/* Add a dark background on topnav links and the dropdown button on hover */ -.myTopNav a:hover, .dropdown:hover .dropbtn { - background-color: #555; - color: white; -} - -/* Add a grey background to dropdown links on hover */ -.dropdown-content a:hover { - background-color: #ddd; - color: black; -} - -/* Show the dropdown menu when the user moves the mouse over the dropdown button */ -.dropdown:hover .dropdown-content { - display: block; -} - -/* When the screen is less than 600 pixels wide, hide all links, except for the first one ("Home"). Show the link that contains should open and close the topnav (.icon) */ - at media screen and (max-width: 600px) { - .myTopNav a:not(:first-child), .dropdown .dropbtn { - display: none; - } - .myTopNav a.icon { - float: right; - display: block; - } -} - -/* The "responsive" class is added to the topnav with JavaScript when the user clicks on the icon. This class makes the topnav look good on small screens (display the links vertically instead of horizontally) */ - at media screen and (max-width: 600px) { - .myTopNav.responsive {position: relative;} - .myTopNav.responsive a.icon { - position: absolute; - right: 0; - top: 0; - } - .myTopNav.responsive a { - float: none; - display: block; - text-align: left; - } - .myTopNav.responsive .dropdown {float: none;} - .myTopNav.responsive .dropdown-content {position: relative;} - .myTopNav.responsive .dropdown .dropbtn { - display: block; - width: 100%; - text-align: left; - } - - -} .row { - display: flex; - flex-direction: column; - padding: 0; - width: 100%; } - .row .column { - display: block; - flex: 1 1 auto; - margin-left: 0; - max-width: 100%; - width: 100%; } - - at media (min-width: 40rem) { - .row { - flex-direction: row; - margin-left: -1.0rem; - width: calc(100% + 2.0rem); } - .row .column { - margin-bottom: inherit; - padding: 0 1.0rem; } } - - at media screen and (max-width: 40rem) { - .row .column { - text-align: center; } } - -.pb-4 { - padding-bottom: 6rem; } - -.text-sm { - font-size: 1rem; } - -.text-lg { - font-size: 2rem; } - -/*.button, button { - background-color: transparent; - border: 0.1rem solid #1890ff; - border-radius: .4rem; - cursor: pointer; - display: inline-block; - font-weight: 700; - height: 2rem; - letter-spacing: .1rem; - line-height: 2rem; - padding: 0 2.0rem; - text-align: center; - text-decoration: none; - text-transform: uppercase; - white-space: nowrap; -} - -.button:focus, .button:hover, -button:focus, -button:hover - { - background-color: lightblue; - border-color: #4B545C; - color: white; -} -*/ pre.literal-block { border-left: 0.3rem solid #d1d1d1; margin-left: 0; @@ -229,3 +43,167 @@ .logotext { padding-top: 4px; +} + +#toplogo { + padding-top: 18px; +} + +/* For the responsive navbar, adapted from https://www.taniarascia.com/responsive-dropdown-navigation-bar */ + + at charset "UTF-8"; +.navigation { + height: 70px; + background: var(--nav-background); +} + +.brand { + position: absolute; + padding-left: 20px; + float: left; + line-height: 70px; + text-transform: uppercase; + font-size: 1.4em; +} +.brand a, +.brand a:visited { + color: var(--nav-font-color); + text-decoration: none; +} + +.nav-container { + max-width: content-width; + margin: 0 auto; +} + +nav { + float: right; +} +nav ul { + list-style: none; + margin: 0; + padding: 0; +} +nav ul li { + float: left; + position: relative; +} +nav ul li a:link, +nav ul li a, +nav ul li a:visited { + display: block; + padding: 0 20px; + line-height: 70px; + background: var(--nav-background); + color: var(--nav-font-color); + text-decoration: none; +} +nav ul li a:hover, +nav ul li a:link:hover, +nav ul li a:visited:hover { + background: var(--link-hover-color); + color: var(--nav-font-color); +} +nav ul li a:not(:only-child):after, +nav ul li a:visited:not(:only-child):after { + padding-left: 4px; + content: ' ▾'; +} +nav ul li ul li { + min-width: 190px; +} +nav ul li ul li a { + padding: 15px; + line-height: 20px; +} + +.nav-dropdown { + position: absolute; + display: none; + z-index: 1; + box-shadow: 0 3px 12px rgba(0, 0, 0, 0.15); +} + +/* Mobile navigation */ +.nav-mobile { + display: none; + position: absolute; + top: 0; + right: 0; + background: var(--nav-background); + height: 70px; + width: 70px; +} + + at media only screen and (max-width: 798px) { + .nav-mobile { + display: block; + } + + nav { + width: 100%; + padding: 70px 0 15px; + } + nav ul { + display: none; + } + nav ul li { + float: none; + } + nav ul li a { + padding: 15px; + line-height: 20px; + } + nav ul li ul li a { + padding-left: 30px; + } + + .nav-dropdown { + position: static; + } +} + + at media screen and (min-width: 799px) { + .nav-list { + display: block !important; + } +} +#nav-toggle { + position: absolute; + left: 18px; + top: 22px; + cursor: pointer; + padding: 10px 35px 16px 0px; +} +#nav-toggle span, +#nav-toggle span:before, +#nav-toggle span:after { + cursor: pointer; + border-radius: 1px; + height: 5px; + width: 35px; + background: black; + position: absolute; + display: block; + content: ''; + transition: all 300ms ease-in-out; +} +#nav-toggle span:before { + top: -10px; +} +#nav-toggle span:after { + bottom: -10px; +} +#nav-toggle.active span { + background-color: transparent; +} +#nav-toggle.active span:before, #nav-toggle.active span:after { + top: 0; +} +#nav-toggle.active span:before { + transform: rotate(45deg); +} +#nav-toggle.active span:after { + transform: rotate(-45deg); +} + diff --git a/public/assets/js/styles.js b/public/assets/js/styles.js --- a/public/assets/js/styles.js +++ b/public/assets/js/styles.js @@ -1,12 +1,25 @@ 'use strict'; -// Navbar -/* Toggle between adding and removing the "responsive" class to topnav when the user clicks on the icon */ -function make_responsive() { - var x = document.getElementById("myTopNav"); - if (x.className === "topnav") { - x.className += " responsive"; - } else { - x.className = "topnav"; - } -} +(function($) { // Begin jQuery + $(function() { // DOM ready + // If a link has a dropdown, add sub menu toggle. + $('nav ul li a:not(:only-child)').click(function(eee) { + $(this).siblings('.nav-dropdown').toggle(); + // Close one dropdown when selecting another + $('.nav-dropdown').not($(this).siblings()).hide(); + eee.stopPropagation(); + }); + // Clicking away from dropdown will remove the dropdown class + $('html').click(function() { + $('.nav-dropdown').hide(); + }); + // Toggle open and close nav styles on click + $('#nav-toggle').click(function() { + $('nav ul').slideToggle(); + }); + // Hamburger to X toggle + $('#nav-toggle').on('click', function() { + this.classList.toggle('active'); + }); + }); // end DOM ready +})(jQuery); // end jQuery diff --git a/public/blog/index.html b/public/blog/index.html --- a/public/blog/index.html +++ b/public/blog/index.html @@ -26,41 +26,38 @@ -
    -
    - - PyPy/ -
    -
    - - -
    +
    @@ -80,6 +77,6 @@
    - + diff --git a/public/categories/index.html b/public/categories/index.html --- a/public/categories/index.html +++ b/public/categories/index.html @@ -26,41 +26,38 @@ -
    -
    - - PyPy/ -
    -
    - - -

    Tags

    +

    Tags

    @@ -79,6 +76,6 @@
    - + diff --git a/public/compat.html b/public/compat.html --- a/public/compat.html +++ b/public/compat.html @@ -34,41 +34,38 @@ -
    -
    - - PyPy/ -
    -
    - - -

    Python compatibility

    +

    Python compatibility

    @@ -179,6 +176,6 @@
    - + diff --git a/public/contact.html b/public/contact.html --- a/public/contact.html +++ b/public/contact.html @@ -35,41 +35,38 @@ -
    -
    - - PyPy/ -
    -
    - - -

    Contact

    +

    Contact

    @@ -98,6 +95,6 @@
    - + diff --git a/public/download.html b/public/download.html --- a/public/download.html +++ b/public/download.html @@ -41,41 +41,38 @@ -
    -
    - - PyPy/ -
    -
    - - -

    Download and Install

    +

    Download and Install

    @@ -471,6 +468,6 @@
    - + diff --git a/public/features.html b/public/features.html --- a/public/features.html +++ b/public/features.html @@ -33,41 +33,38 @@ -
    -
    - - PyPy/ -
    -
    - - -

    PyPy - Features

    +

    PyPy - Features

    @@ -196,6 +193,6 @@
    - + diff --git a/public/index.html b/public/index.html --- a/public/index.html +++ b/public/index.html @@ -40,41 +40,38 @@ -
    -
    - - PyPy/ -
    -
    - - -

    Welcome to PyPy

    +

    Welcome to PyPy

    @@ -128,6 +125,6 @@
    - + diff --git a/public/people.html b/public/people.html --- a/public/people.html +++ b/public/people.html @@ -36,41 +36,38 @@ -
    -
    - - PyPy/ -
    -
    - - -

    The PyPy Team (from 2008)

    +

    The PyPy Team (from 2008)

    @@ -204,6 +201,6 @@
    - + diff --git a/public/performance.html b/public/performance.html --- a/public/performance.html +++ b/public/performance.html @@ -40,41 +40,38 @@ -
    -
    - - PyPy/ -
    -
    - - -

    Performance

    +

    Performance

    @@ -389,6 +386,6 @@
    - + diff --git a/public/sitemap.xml b/public/sitemap.xml --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -7,11 +7,11 @@ http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"> https://www.pypy.org/ - 2020-01-08T11:00:00Z + 2020-01-09T00:47:00Z https://www.pypy.org/archive.html - 2020-01-09T00:45:00Z + 2020-02-09T13:13:00Z https://www.pypy.org/blog/ @@ -23,26 +23,26 @@ https://www.pypy.org/compat.html - 2020-01-09T00:45:00Z + 2020-02-09T13:13:00Z https://www.pypy.org/contact.html - 2020-01-09T00:45:00Z + 2020-02-09T13:13:00Z https://www.pypy.org/download.html - 2020-01-09T00:45:00Z + 2020-02-09T13:13:00Z https://www.pypy.org/features.html - 2020-01-09T00:45:00Z + 2020-02-09T13:13:00Z https://www.pypy.org/people.html - 2020-01-09T00:45:00Z + 2020-02-09T13:13:00Z https://www.pypy.org/performance.html - 2020-01-09T00:45:00Z + 2020-02-09T13:13:00Z \ No newline at end of file diff --git a/public/sitemapindex.xml b/public/sitemapindex.xml --- a/public/sitemapindex.xml +++ b/public/sitemapindex.xml @@ -11,6 +11,6 @@ https://www.pypy.org/sitemap.xml - 2020-01-09T00:45:00Z + 2020-02-09T13:13:00Z \ No newline at end of file From pypy.commits at gmail.com Sun Feb 9 10:37:03 2020 From: pypy.commits at gmail.com (cfbolz) Date: Sun, 09 Feb 2020 07:37:03 -0800 (PST) Subject: [pypy-commit] pypy pypy-jitdriver-greenkeys: various fixes Message-ID: <5e40271f.1c69fb81.af13d.3ffc@mx.google.com> Author: Carl Friedrich Bolz-Tereick Branch: pypy-jitdriver-greenkeys Changeset: r98690:227d54204dea Date: 2020-02-09 16:36 +0100 http://bitbucket.org/pypy/pypy/changeset/227d54204dea/ Log: various fixes diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py --- a/pypy/interpreter/generator.py +++ b/pypy/interpreter/generator.py @@ -231,7 +231,7 @@ self.frame = None rgc.may_ignore_finalizer(self) - def iterator_greenkey(self): + def iterator_greenkey(self, space): return self.pycode diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py --- a/pypy/objspace/descroperation.py +++ b/pypy/objspace/descroperation.py @@ -124,8 +124,14 @@ def descr__init__(space, w_obj, __args__): pass +def get_printable_location(itergreenkey, w_itemtype): + return "DescrOperation.contains [%s, %s]" % ( + itergreenkey.iterator_greenkey_printable(), + w_itemtype.getname(w_itemtype.space)) + contains_jitdriver = jit.JitDriver(name='contains', - greens=['itergreenkey', 'w_itemtype'], reds='auto') + greens=['itergreenkey', 'w_itemtype'], reds='auto', + get_printable_location=get_printable_location) class DescrOperation(object): # This is meant to be a *mixin*. diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py --- a/pypy/objspace/std/bytearrayobject.py +++ b/pypy/objspace/std/bytearrayobject.py @@ -568,7 +568,7 @@ _byteseq_jitdriver = jit.JitDriver( name='bytearray_from_byte_sequence', greens=['greenkey'], - reds='auto' + reds='auto', get_printable_location=_get_printable_location) def _from_byte_sequence(space, w_source): diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py --- a/pypy/objspace/std/listobject.py +++ b/pypy/objspace/std/listobject.py @@ -131,7 +131,7 @@ return space.fromcache(ObjectListStrategy) -def _get_printable_location(greenkey): +def _get_printable_location(strategy, greenkey): return 'list__do_extend_from_iterable [%s, %s]' % ( strategy, greenkey.iterator_greenkey_printable()) @@ -145,11 +145,11 @@ def _do_extend_from_iterable(space, w_list, w_iterable): w_iterator = space.iter(w_iterable) - w_type = space.iterator_greenkey_printable(w_iterator) + greenkey = space.iterator_greenkey(w_iterator) i = 0 while True: _do_extend_jitdriver.jit_merge_point( - w_type=w_type, + greenkey=greenkey, strategy = w_list.strategy) try: w_list.append(space.next(w_iterator)) diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py --- a/pypy/objspace/std/typeobject.py +++ b/pypy/objspace/std/typeobject.py @@ -711,6 +711,9 @@ else: return space.newtext("<%s '%s'>" % (kind, self.name)) + def iterator_greenkey_printable(self): + return self.name + def descr_getattribute(self, space, w_name): name = space.text_w(w_name) w_descr = space.lookup(self, name) From pypy.commits at gmail.com Sun Feb 9 10:37:52 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 09 Feb 2020 07:37:52 -0800 (PST) Subject: [pypy-commit] pypy.org nikola: restore deleted css to format content Message-ID: <5e402750.1c69fb81.c1f0.36b8@mx.google.com> Author: Matti Picus Branch: nikola Changeset: r975:62179781e13a Date: 2020-02-09 17:37 +0200 http://bitbucket.org/pypy/pypy.org/changeset/62179781e13a/ Log: restore deleted css to format content diff --git a/public/assets/css/styles.css b/public/assets/css/styles.css --- a/public/assets/css/styles.css +++ b/public/assets/css/styles.css @@ -1,5 +1,5 @@ :root { - --content-width: 1000px; + --content-width: 900px; --breakpoint: 799px; --nav-height: 70px; --nav-background: #d0dad5; @@ -49,6 +49,43 @@ padding-top: 18px; } + +/* For flex layout */ +.row { + display: flex; + flex-direction: column; + padding: 0; + width: 100%; } + .row .column { + display: block; + flex: 1 1 auto; + margin-left: 0; + max-width: 100%; + width: 100%; } + + at media (min-width: 40rem) { + .row { + flex-direction: row; + margin-left: -1.0rem; + width: calc(100% + 2.0rem); } + .row .column { + margin-bottom: inherit; + padding: 0 1.0rem; } } + + at media screen and (max-width: 40rem) { + .row .column { + text-align: center; } } + +.pb-4 { + padding-bottom: 6rem; } + +.text-sm { + font-size: 1rem; } + +.text-lg { + font-size: 2rem; } + + /* For the responsive navbar, adapted from https://www.taniarascia.com/responsive-dropdown-navigation-bar */ @charset "UTF-8"; diff --git a/public/sitemap.xml b/public/sitemap.xml --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -11,7 +11,7 @@ https://www.pypy.org/archive.html - 2020-02-09T13:13:00Z + 2020-02-09T15:31:00Z https://www.pypy.org/blog/ @@ -23,26 +23,26 @@ https://www.pypy.org/compat.html - 2020-02-09T13:13:00Z + 2020-02-09T15:31:00Z https://www.pypy.org/contact.html - 2020-02-09T13:13:00Z + 2020-02-09T15:31:00Z https://www.pypy.org/download.html - 2020-02-09T13:13:00Z + 2020-02-09T15:31:00Z https://www.pypy.org/features.html - 2020-02-09T13:13:00Z + 2020-02-09T15:31:00Z https://www.pypy.org/people.html - 2020-02-09T13:13:00Z + 2020-02-09T15:31:00Z https://www.pypy.org/performance.html - 2020-02-09T13:13:00Z + 2020-02-09T15:31:00Z \ No newline at end of file diff --git a/public/sitemapindex.xml b/public/sitemapindex.xml --- a/public/sitemapindex.xml +++ b/public/sitemapindex.xml @@ -11,6 +11,6 @@ https://www.pypy.org/sitemap.xml - 2020-02-09T13:13:00Z + 2020-02-09T15:31:00Z \ No newline at end of file diff --git a/themes/pypy/assets/css/styles.css b/themes/pypy/assets/css/styles.css --- a/themes/pypy/assets/css/styles.css +++ b/themes/pypy/assets/css/styles.css @@ -1,5 +1,5 @@ :root { - --content-width: 1000px; + --content-width: 900px; --breakpoint: 799px; --nav-height: 70px; --nav-background: #d0dad5; @@ -49,6 +49,43 @@ padding-top: 18px; } + +/* For flex layout */ +.row { + display: flex; + flex-direction: column; + padding: 0; + width: 100%; } + .row .column { + display: block; + flex: 1 1 auto; + margin-left: 0; + max-width: 100%; + width: 100%; } + + at media (min-width: 40rem) { + .row { + flex-direction: row; + margin-left: -1.0rem; + width: calc(100% + 2.0rem); } + .row .column { + margin-bottom: inherit; + padding: 0 1.0rem; } } + + at media screen and (max-width: 40rem) { + .row .column { + text-align: center; } } + +.pb-4 { + padding-bottom: 6rem; } + +.text-sm { + font-size: 1rem; } + +.text-lg { + font-size: 2rem; } + + /* For the responsive navbar, adapted from https://www.taniarascia.com/responsive-dropdown-navigation-bar */ @charset "UTF-8"; From pypy.commits at gmail.com Sun Feb 9 11:49:05 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 09 Feb 2020 08:49:05 -0800 (PST) Subject: [pypy-commit] pypy.org nikola: add favicons Message-ID: <5e403801.1c69fb81.58d87.1b0f@mx.google.com> Author: Matti Picus Branch: nikola Changeset: r976:ddf8297cd244 Date: 2020-02-09 18:48 +0200 http://bitbucket.org/pypy/pypy.org/changeset/ddf8297cd244/ Log: add favicons diff --git a/conf.py b/conf.py --- a/conf.py +++ b/conf.py @@ -909,10 +909,10 @@ # FAVICONS contains (name, file, size) tuples. # Used to create favicon link like this: # -# FAVICONS = ( -# ("icon", "/favicon.ico", "16x16"), -# ("icon", "/icon_128x128.png", "128x128"), -# ) +FAVICONS = ( + ("icon", "/favicon2.ico", "16x16"), + ("icon", "/favicon32x32.ico", "32x32"), +) # Show teasers (instead of full posts) in indexes? Defaults to False. # INDEX_TEASERS = False diff --git a/files/favicon2.ico b/files/favicon2.ico new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8e5cc5a9e03ea82a00f1602329e014c635580911 GIT binary patch [cut] diff --git a/files/favicon32x32.ico b/files/favicon32x32.ico new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9e34b3f45ddaa0e318068a513ad43e4f5bb7d7fd GIT binary patch [cut] diff --git a/public/archive.html b/public/archive.html --- a/public/archive.html +++ b/public/archive.html @@ -16,6 +16,8 @@ + + diff --git a/public/assets/js/jquery.min.js b/public/assets/js/jquery.min.js new file mode 100644 --- /dev/null +++ b/public/assets/js/jquery.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;nx",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0 + + diff --git a/public/categories/index.html b/public/categories/index.html --- a/public/categories/index.html +++ b/public/categories/index.html @@ -16,6 +16,8 @@ + + diff --git a/public/compat.html b/public/compat.html --- a/public/compat.html +++ b/public/compat.html @@ -15,6 +15,8 @@ + + diff --git a/public/contact.html b/public/contact.html --- a/public/contact.html +++ b/public/contact.html @@ -15,6 +15,8 @@ + + diff --git a/public/download.html b/public/download.html --- a/public/download.html +++ b/public/download.html @@ -15,6 +15,8 @@ + + diff --git a/public/favicon2.ico b/public/favicon2.ico new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8e5cc5a9e03ea82a00f1602329e014c635580911 GIT binary patch [cut] diff --git a/public/favicon32x32.ico b/public/favicon32x32.ico new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9e34b3f45ddaa0e318068a513ad43e4f5bb7d7fd GIT binary patch [cut] diff --git a/public/features.html b/public/features.html --- a/public/features.html +++ b/public/features.html @@ -16,6 +16,8 @@ + + diff --git a/public/index.html b/public/index.html --- a/public/index.html +++ b/public/index.html @@ -15,6 +15,8 @@ + + diff --git a/public/people.html b/public/people.html --- a/public/people.html +++ b/public/people.html @@ -15,6 +15,8 @@ + + diff --git a/public/performance.html b/public/performance.html --- a/public/performance.html +++ b/public/performance.html @@ -15,6 +15,8 @@ + + diff --git a/public/sitemap.xml b/public/sitemap.xml --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -7,42 +7,42 @@ http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"> https://www.pypy.org/ - 2020-01-09T00:47:00Z + 2020-02-09T16:46:00Z https://www.pypy.org/archive.html - 2020-02-09T15:31:00Z + 2020-02-09T16:46:00Z https://www.pypy.org/blog/ - 2020-01-08T11:00:00Z + 2020-02-09T16:17:00Z https://www.pypy.org/categories/ - 2020-01-08T11:00:00Z + 2020-02-09T16:17:00Z https://www.pypy.org/compat.html - 2020-02-09T15:31:00Z + 2020-02-09T16:46:00Z https://www.pypy.org/contact.html - 2020-02-09T15:31:00Z + 2020-02-09T16:46:00Z https://www.pypy.org/download.html - 2020-02-09T15:31:00Z + 2020-02-09T16:46:00Z https://www.pypy.org/features.html - 2020-02-09T15:31:00Z + 2020-02-09T16:46:00Z https://www.pypy.org/people.html - 2020-02-09T15:31:00Z + 2020-02-09T16:46:00Z https://www.pypy.org/performance.html - 2020-02-09T15:31:00Z + 2020-02-09T16:46:00Z \ No newline at end of file diff --git a/public/sitemapindex.xml b/public/sitemapindex.xml --- a/public/sitemapindex.xml +++ b/public/sitemapindex.xml @@ -11,6 +11,6 @@ https://www.pypy.org/sitemap.xml - 2020-02-09T15:31:00Z + 2020-02-09T16:46:00Z \ No newline at end of file diff --git a/themes/pypy/assets/js/jquery.min.js b/themes/pypy/assets/js/jquery.min.js new file mode 100644 --- /dev/null +++ b/themes/pypy/assets/js/jquery.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;nx",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0 - {% if favicons %} {% for name, file, size in favicons %} From pypy.commits at gmail.com Sun Feb 9 14:22:15 2020 From: pypy.commits at gmail.com (mattip) Date: Sun, 09 Feb 2020 11:22:15 -0800 (PST) Subject: [pypy-commit] pypy.org nikola: improve small screen view Message-ID: <5e405be7.1c69fb81.92a6f.996e@mx.google.com> Author: Matti Picus Branch: nikola Changeset: r977:7dad7054ae97 Date: 2020-02-09 21:21 +0200 http://bitbucket.org/pypy/pypy.org/changeset/7dad7054ae97/ Log: improve small screen view diff --git a/public/archive.html b/public/archive.html --- a/public/archive.html +++ b/public/archive.html @@ -23,21 +23,12 @@ Skip to main content
    -

    Archive

    No posts found.