From 0f21ddb9ea40b0d349ff3224c4b83b53394f7a89 Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Fri, 18 Mar 2022 11:10:50 +0200 Subject: add failing test required for PEP 3123 (stric-aliasing) (issue 3706) --- rpython/tool/cparser/test/test_cts.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/rpython/tool/cparser/test/test_cts.py b/rpython/tool/cparser/test/test_cts.py index 9ae1750191..e72bd83cc2 100644 --- a/rpython/tool/cparser/test/test_cts.py +++ b/rpython/tool/cparser/test/test_cts.py @@ -179,6 +179,33 @@ def test_nested_struct(): assert isinstance(bar, lltype.Struct) hash(bar) # bar is hashable +def test_aliased_struct(): + cdef = """ + + typedef long Py_ssize_t; + + typedef struct _object { + Py_ssize_t ob_refcnt; + Py_ssize_t ob_pypy_link; + struct _typeobject *ob_type; + } PyObject; + + typedef struct _varobject { + Py_ssize_t ob_refcnt; + Py_ssize_t ob_pypy_link; + struct _typeobject *ob_type; + } PyVarObject; + + + typedef struct _typeobject { + PyVarObject ob_base; + } PyTypeObject; + """ + cts = parse_source(cdef) + bar = cts.gettype('PyTypeObject') + assert isinstance(bar, lltype.Struct) + hash(bar) # bar is hashable + def test_named_struct(): cdef = """ struct foo { -- cgit v1.2.3-65-gdbad From e80079fe13c29eda7b2a6b4cd4557051f975a2d9 Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Fri, 18 Mar 2022 12:39:59 +0200 Subject: add override=True and rearrange declarations to get test to pass --- rpython/tool/cparser/cparser.py | 2 +- rpython/tool/cparser/cts.py | 8 ++++---- rpython/tool/cparser/test/test_cts.py | 22 ++++++++++++++++------ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/rpython/tool/cparser/cparser.py b/rpython/tool/cparser/cparser.py index ae3e76ef44..18884667f3 100644 --- a/rpython/tool/cparser/cparser.py +++ b/rpython/tool/cparser/cparser.py @@ -556,7 +556,7 @@ class Parser(object): if not self._options.get('override'): raise FFIError( "multiple declarations of %s (for interactive usage, " - "try cdef(xx, override=True))" % (name,)) + "try self.parse(xx, override=True))" % (name,)) assert '__dotdotdot__' not in name.split() self._declarations[name] = (obj, quals) if included: diff --git a/rpython/tool/cparser/cts.py b/rpython/tool/cparser/cts.py index 6106a65279..ecacc665e5 100644 --- a/rpython/tool/cparser/cts.py +++ b/rpython/tool/cparser/cts.py @@ -81,9 +81,9 @@ class CTypeSpace(object): self.structs.update(other.structs) self.includes.append(other) - def parse_source(self, source, configure=True): + def parse_source(self, source, configure=True, override=False): self.sources.append(source) - self.ctx.parse(source) + self.ctx.parse(source, override=override) if configure: self.configure_types() @@ -293,7 +293,7 @@ class FunctionDeclaration(object): def get_llresult(self, cts): return cts.convert_type(self.tp.result) -def parse_source(source, includes=None, headers=None, configure_now=True): +def parse_source(source, includes=None, headers=None, configure_now=True, override=False): cts = CTypeSpace(headers=headers, includes=includes) - cts.parse_source(source) + cts.parse_source(source, override=override) return cts diff --git a/rpython/tool/cparser/test/test_cts.py b/rpython/tool/cparser/test/test_cts.py index e72bd83cc2..14b5729776 100644 --- a/rpython/tool/cparser/test/test_cts.py +++ b/rpython/tool/cparser/test/test_cts.py @@ -184,24 +184,34 @@ def test_aliased_struct(): typedef long Py_ssize_t; - typedef struct _object { - Py_ssize_t ob_refcnt; - Py_ssize_t ob_pypy_link; - struct _typeobject *ob_type; - } PyObject; + + typedef struct _object PyObject; + typedef void (*destructor)(PyObject *); typedef struct _varobject { Py_ssize_t ob_refcnt; Py_ssize_t ob_pypy_link; struct _typeobject *ob_type; + Py_ssize_t ob_size; } PyVarObject; typedef struct _typeobject { PyVarObject ob_base; + const char *tp_name; + Py_ssize_t tp_basicsize, tp_itemsize; + destructor tp_dealloc; } PyTypeObject; + + typedef struct _object { + Py_ssize_t ob_refcnt; + Py_ssize_t ob_pypy_link; + struct _typeobject *ob_type; + } PyObject; + + """ - cts = parse_source(cdef) + cts = parse_source(cdef, override=True) bar = cts.gettype('PyTypeObject') assert isinstance(bar, lltype.Struct) hash(bar) # bar is hashable -- cgit v1.2.3-65-gdbad From cca5df1e7f4e3af339bc83f4e39073f45c344bda Mon Sep 17 00:00:00 2001 From: Ronan Lamy Date: Tue, 22 Mar 2022 03:37:13 +0000 Subject: Backed out changeset 1baa930ff7e9 --- rpython/tool/cparser/cparser.py | 2 +- rpython/tool/cparser/cts.py | 8 ++++---- rpython/tool/cparser/test/test_cts.py | 22 ++++++---------------- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/rpython/tool/cparser/cparser.py b/rpython/tool/cparser/cparser.py index 18884667f3..ae3e76ef44 100644 --- a/rpython/tool/cparser/cparser.py +++ b/rpython/tool/cparser/cparser.py @@ -556,7 +556,7 @@ class Parser(object): if not self._options.get('override'): raise FFIError( "multiple declarations of %s (for interactive usage, " - "try self.parse(xx, override=True))" % (name,)) + "try cdef(xx, override=True))" % (name,)) assert '__dotdotdot__' not in name.split() self._declarations[name] = (obj, quals) if included: diff --git a/rpython/tool/cparser/cts.py b/rpython/tool/cparser/cts.py index ecacc665e5..6106a65279 100644 --- a/rpython/tool/cparser/cts.py +++ b/rpython/tool/cparser/cts.py @@ -81,9 +81,9 @@ class CTypeSpace(object): self.structs.update(other.structs) self.includes.append(other) - def parse_source(self, source, configure=True, override=False): + def parse_source(self, source, configure=True): self.sources.append(source) - self.ctx.parse(source, override=override) + self.ctx.parse(source) if configure: self.configure_types() @@ -293,7 +293,7 @@ class FunctionDeclaration(object): def get_llresult(self, cts): return cts.convert_type(self.tp.result) -def parse_source(source, includes=None, headers=None, configure_now=True, override=False): +def parse_source(source, includes=None, headers=None, configure_now=True): cts = CTypeSpace(headers=headers, includes=includes) - cts.parse_source(source, override=override) + cts.parse_source(source) return cts diff --git a/rpython/tool/cparser/test/test_cts.py b/rpython/tool/cparser/test/test_cts.py index 14b5729776..e72bd83cc2 100644 --- a/rpython/tool/cparser/test/test_cts.py +++ b/rpython/tool/cparser/test/test_cts.py @@ -184,34 +184,24 @@ def test_aliased_struct(): typedef long Py_ssize_t; - - typedef struct _object PyObject; - typedef void (*destructor)(PyObject *); + typedef struct _object { + Py_ssize_t ob_refcnt; + Py_ssize_t ob_pypy_link; + struct _typeobject *ob_type; + } PyObject; typedef struct _varobject { Py_ssize_t ob_refcnt; Py_ssize_t ob_pypy_link; struct _typeobject *ob_type; - Py_ssize_t ob_size; } PyVarObject; typedef struct _typeobject { PyVarObject ob_base; - const char *tp_name; - Py_ssize_t tp_basicsize, tp_itemsize; - destructor tp_dealloc; } PyTypeObject; - - typedef struct _object { - Py_ssize_t ob_refcnt; - Py_ssize_t ob_pypy_link; - struct _typeobject *ob_type; - } PyObject; - - """ - cts = parse_source(cdef, override=True) + cts = parse_source(cdef) bar = cts.gettype('PyTypeObject') assert isinstance(bar, lltype.Struct) hash(bar) # bar is hashable -- cgit v1.2.3-65-gdbad From 8116c8fcc6f9b82eadb3e8d592e3c68b909d84ad Mon Sep 17 00:00:00 2001 From: Ronan Lamy Date: Tue, 22 Mar 2022 04:12:39 +0000 Subject: cparser: Handle the case of structs requiring other structs to be configured first. Fixes issue #3706. --- rpython/tool/cparser/cts.py | 30 ++++++++++++++++++++++++------ rpython/tool/cparser/test/test_cts.py | 14 ++++---------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/rpython/tool/cparser/cts.py b/rpython/tool/cparser/cts.py index 6106a65279..bcc5f2f1ac 100644 --- a/rpython/tool/cparser/cts.py +++ b/rpython/tool/cparser/cts.py @@ -182,12 +182,30 @@ class CTypeSpace(object): if not self._config_entries: return eci = self.build_eci() - result = rffi_platform.configure_entries(list(self._config_entries), eci) - for entry, TYPE in izip(self._config_entries, result): - # hack: prevent the source from being pasted into common_header.h - del TYPE._hints['eci'] - self._config_entries[entry].become(TYPE) - self._config_entries.clear() + + while self._config_entries: + configure_now = [] + for entry in self._config_entries: + if self._can_configure(entry): + configure_now.append(entry) + if not configure_now: + raise ValueError("configure_types() cannot make progress. " + "Maybe the cdef is invalid?") + result = rffi_platform.configure_entries(configure_now, eci) + for entry, TYPE in izip(configure_now, result): + # hack: prevent the source from being pasted into common_header.h + del TYPE._hints['eci'] + self._config_entries[entry].become(TYPE) + del self._config_entries[entry] + + def _can_configure(self, entry): + if isinstance(entry, rffi_platform.Struct): + # A struct containing a nested struct can only be configured if + # the inner one has already been configured. + for fieldname, fieldtype in entry.interesting_fields: + if isinstance(fieldtype, lltype.ForwardReference): + return False + return True def convert_type(self, obj, quals=0): if isinstance(obj, model.DefinedType): diff --git a/rpython/tool/cparser/test/test_cts.py b/rpython/tool/cparser/test/test_cts.py index e72bd83cc2..78c890933d 100644 --- a/rpython/tool/cparser/test/test_cts.py +++ b/rpython/tool/cparser/test/test_cts.py @@ -179,24 +179,18 @@ def test_nested_struct(): assert isinstance(bar, lltype.Struct) hash(bar) # bar is hashable -def test_aliased_struct(): +def test_nested_struct_2(): cdef = """ - - typedef long Py_ssize_t; - typedef struct _object { - Py_ssize_t ob_refcnt; - Py_ssize_t ob_pypy_link; + int ob_refcnt; struct _typeobject *ob_type; } PyObject; typedef struct _varobject { - Py_ssize_t ob_refcnt; - Py_ssize_t ob_pypy_link; - struct _typeobject *ob_type; + PyObject ob_base; + int ob_size; } PyVarObject; - typedef struct _typeobject { PyVarObject ob_base; } PyTypeObject; -- cgit v1.2.3-65-gdbad From bbd2e2fb0fdb5109b2c39e56959437a2c92f774c Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Fri, 25 Mar 2022 00:06:29 +0200 Subject: use __index__ to test for int-ness in ctypes.array (issue 3712) --- extra_tests/ctypes_tests/test_array.py | 12 ++++++++++++ lib_pypy/_ctypes/array.py | 5 +++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/extra_tests/ctypes_tests/test_array.py b/extra_tests/ctypes_tests/test_array.py index bf4de49fd5..e454023252 100644 --- a/extra_tests/ctypes_tests/test_array.py +++ b/extra_tests/ctypes_tests/test_array.py @@ -62,3 +62,15 @@ def test_output_complex_test(): TP = POINTER(A) x = TP(A()) assert x[0] != b'' + +def test_non_int(): + class Index(): + def __index__(self): + return 42 + + t0 = c_int * 42 + t1 = c_int * Index() + assert t0 == t1 + with pytest.raises(TypeError) as exc: + c_int * 4.5 + assert 'non-int of type float' in str(exc.value) diff --git a/lib_pypy/_ctypes/array.py b/lib_pypy/_ctypes/array.py index 3a79a589e9..74674cb9eb 100644 --- a/lib_pypy/_ctypes/array.py +++ b/lib_pypy/_ctypes/array.py @@ -277,8 +277,9 @@ class Array(_CData, metaclass=ArrayMeta): ARRAY_CACHE = {} def create_array_type(base, length): - if not isinstance(length, int): - raise TypeError("Can't multiply a ctypes type by a non-integer") + if not hasattr(length, '__index__'): + raise TypeError("Can't multiply a ctypes type by a non-int of type %s" % type(length).__name__) + length = int(length) if length < 0: raise ValueError("Array length must be >= 0") if length * base._sizeofinstances() > sys.maxsize: -- cgit v1.2.3-65-gdbad From 43bc316793001055e1a1bb041cbe99f9db9d3636 Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Sat, 26 Mar 2022 20:36:11 +0300 Subject: update to v3.7.13 --- lib-python/3/ensurepip/__init__.py | 9 +++----- .../ensurepip/_bundled/pip-22.0.4-py3-none-any.whl | Bin 0 -> 2123599 bytes lib-python/3/pydoc_data/topics.py | 2 +- lib-python/3/test/test_minidom.py | 17 ++++++++++++-- lib-python/3/test/test_urllib2.py | 25 +++++++++++++++++---- lib-python/3/test/test_xml_etree.py | 6 ----- lib-python/3/urllib/request.py | 8 +++---- 7 files changed, 44 insertions(+), 23 deletions(-) create mode 100644 lib-python/3/ensurepip/_bundled/pip-22.0.4-py3-none-any.whl diff --git a/lib-python/3/ensurepip/__init__.py b/lib-python/3/ensurepip/__init__.py index 94d40b0c8d..8289c495d3 100644 --- a/lib-python/3/ensurepip/__init__.py +++ b/lib-python/3/ensurepip/__init__.py @@ -7,15 +7,12 @@ import tempfile __all__ = ["version", "bootstrap"] - - +_PACKAGE_NAMES = ('setuptools', 'pip') _SETUPTOOLS_VERSION = "47.1.0" - -_PIP_VERSION = "20.1.1" - +_PIP_VERSION = "22.0.4" _PROJECTS = [ ("setuptools", _SETUPTOOLS_VERSION, "py3"), - ("pip", _PIP_VERSION, "py2.py3"), + ("pip", _PIP_VERSION, "py3"), ] diff --git a/lib-python/3/ensurepip/_bundled/pip-22.0.4-py3-none-any.whl b/lib-python/3/ensurepip/_bundled/pip-22.0.4-py3-none-any.whl new file mode 100644 index 0000000000..7ba048e245 Binary files /dev/null and b/lib-python/3/ensurepip/_bundled/pip-22.0.4-py3-none-any.whl differ diff --git a/lib-python/3/pydoc_data/topics.py b/lib-python/3/pydoc_data/topics.py index f0e0f6db6e..b532fec0d1 100644 --- a/lib-python/3/pydoc_data/topics.py +++ b/lib-python/3/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Fri Sep 3 23:33:01 2021 +# Autogenerated by Sphinx on Wed Mar 16 09:24:05 2022 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' diff --git a/lib-python/3/test/test_minidom.py b/lib-python/3/test/test_minidom.py index 041a415113..0b76f6e87b 100644 --- a/lib-python/3/test/test_minidom.py +++ b/lib-python/3/test/test_minidom.py @@ -5,10 +5,12 @@ import pickle from test import support import unittest +import pyexpat import xml.dom.minidom from xml.dom.minidom import parse, Node, Document, parseString from xml.dom.minidom import getDOMImplementation +from xml.parsers.expat import ExpatError tstfile = support.findfile("test.xml", subdir="xmltestdata") @@ -1146,7 +1148,13 @@ class MinidomTest(unittest.TestCase): # Verify that character decoding errors raise exceptions instead # of crashing - self.assertRaises(UnicodeDecodeError, parseString, + if pyexpat.version_info >= (2, 4, 5): + self.assertRaises(ExpatError, parseString, + b'') + self.assertRaises(ExpatError, parseString, + b'Comment \xe7a va ? Tr\xe8s bien ?') + else: + self.assertRaises(UnicodeDecodeError, parseString, b'Comment \xe7a va ? Tr\xe8s bien ?') doc.unlink() @@ -1592,7 +1600,12 @@ class MinidomTest(unittest.TestCase): self.confirm(doc2.namespaceURI == xml.dom.EMPTY_NAMESPACE) def testExceptionOnSpacesInXMLNSValue(self): - with self.assertRaisesRegex(ValueError, 'Unsupported syntax'): + if pyexpat.version_info >= (2, 4, 5): + context = self.assertRaisesRegex(ExpatError, 'syntax error') + else: + context = self.assertRaisesRegex(ValueError, 'Unsupported syntax') + + with context: parseString('') def testDocRemoveChild(self): diff --git a/lib-python/3/test/test_urllib2.py b/lib-python/3/test/test_urllib2.py index fe9a32bfda..3bb4a12e86 100644 --- a/lib-python/3/test/test_urllib2.py +++ b/lib-python/3/test/test_urllib2.py @@ -160,7 +160,6 @@ class RequestHdrsTests(unittest.TestCase): self.assertEqual(find_user_pass("Some Realm", "http://example.com/spam"), ('joe', 'password')) - self.assertEqual(find_user_pass("Some Realm", "http://example.com/spam/spam"), ('joe', 'password')) @@ -169,12 +168,29 @@ class RequestHdrsTests(unittest.TestCase): add("c", "http://example.com/foo", "foo", "ni") add("c", "http://example.com/bar", "bar", "nini") + add("c", "http://example.com/foo/bar", "foobar", "nibar") self.assertEqual(find_user_pass("c", "http://example.com/foo"), ('foo', 'ni')) - self.assertEqual(find_user_pass("c", "http://example.com/bar"), ('bar', 'nini')) + self.assertEqual(find_user_pass("c", "http://example.com/foo/"), + ('foo', 'ni')) + self.assertEqual(find_user_pass("c", "http://example.com/foo/bar"), + ('foo', 'ni')) + self.assertEqual(find_user_pass("c", "http://example.com/foo/baz"), + ('foo', 'ni')) + self.assertEqual(find_user_pass("c", "http://example.com/foobar"), + (None, None)) + + add("c", "http://example.com/baz/", "baz", "ninini") + + self.assertEqual(find_user_pass("c", "http://example.com/baz"), + (None, None)) + self.assertEqual(find_user_pass("c", "http://example.com/baz/"), + ('baz', 'ninini')) + self.assertEqual(find_user_pass("c", "http://example.com/baz/bar"), + ('baz', 'ninini')) # For the same path, newer password should be considered. @@ -1642,8 +1658,9 @@ class HandlerTests(unittest.TestCase): auth_prior_handler.add_password( None, request_url, user, password, is_authenticated=True) - is_auth = pwd_manager.is_authenticated(request_url) - self.assertTrue(is_auth) + self.assertTrue(pwd_manager.is_authenticated(request_url)) + self.assertTrue(pwd_manager.is_authenticated(request_url + '/nested')) + self.assertFalse(pwd_manager.is_authenticated(request_url + 'plain')) opener = OpenerDirector() opener.add_handler(auth_prior_handler) diff --git a/lib-python/3/test/test_xml_etree.py b/lib-python/3/test/test_xml_etree.py index d0c11023e9..92acd991bd 100644 --- a/lib-python/3/test/test_xml_etree.py +++ b/lib-python/3/test/test_xml_etree.py @@ -1708,12 +1708,6 @@ class BugsTest(unittest.TestCase): b"\n" b'tãg') - def test_issue3151(self): - e = ET.XML('') - self.assertEqual(e.tag, '{${stuff}}localname') - t = ET.ElementTree(e) - self.assertEqual(ET.tostring(e), b'') - def test_issue6565(self): elem = ET.XML("") self.assertEqual(summarize_list(elem), ['tag']) diff --git a/lib-python/3/urllib/request.py b/lib-python/3/urllib/request.py index 16b7e1c509..993fde87b9 100644 --- a/lib-python/3/urllib/request.py +++ b/lib-python/3/urllib/request.py @@ -890,10 +890,10 @@ class HTTPPasswordMgr: return True if base[0] != test[0]: return False - common = posixpath.commonprefix((base[1], test[1])) - if len(common) == len(base[1]): - return True - return False + prefix = base[1] + if prefix[-1:] != '/': + prefix += '/' + return test[1].startswith(prefix) class HTTPPasswordMgrWithDefaultRealm(HTTPPasswordMgr): -- cgit v1.2.3-65-gdbad From 928418bf28ff8578709202c4356cdaf56eefe030 Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Sat, 26 Mar 2022 20:37:52 +0300 Subject: remove outdated bundled version of pip --- .../_bundled/pip-20.1.1-py2.py3-none-any.whl | Bin 1490666 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lib-python/3/ensurepip/_bundled/pip-20.1.1-py2.py3-none-any.whl diff --git a/lib-python/3/ensurepip/_bundled/pip-20.1.1-py2.py3-none-any.whl b/lib-python/3/ensurepip/_bundled/pip-20.1.1-py2.py3-none-any.whl deleted file mode 100644 index ea1d0f7c86..0000000000 Binary files a/lib-python/3/ensurepip/_bundled/pip-20.1.1-py2.py3-none-any.whl and /dev/null differ -- cgit v1.2.3-65-gdbad From 2cdd4f004bf9e407ca9c14e0bd1d9d0e573eb710 Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Sat, 26 Mar 2022 20:47:20 +0300 Subject: update python version to 3.7.13 --- pypy/module/cpyext/include/patchlevel.h | 4 ++-- pypy/module/sys/version.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h index 27b4cf9fac..abbaa2f4b8 100644 --- a/pypy/module/cpyext/include/patchlevel.h +++ b/pypy/module/cpyext/include/patchlevel.h @@ -21,12 +21,12 @@ /* Version parsed out into numeric values */ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 7 -#define PY_MICRO_VERSION 12 +#define PY_MICRO_VERSION 13 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.7.12" +#define PY_VERSION "3.7.13" /* PyPy version as a string: make sure to keep this in sync with: * module/sys/version.py diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py index fec8d22c35..9be84ef828 100644 --- a/pypy/module/sys/version.py +++ b/pypy/module/sys/version.py @@ -6,7 +6,7 @@ from rpython.rlib import compilerinfo from pypy.interpreter import gateway #XXX # the release serial 42 is not in range(16) -CPYTHON_VERSION = (3, 7, 12, "final", 0) +CPYTHON_VERSION = (3, 7, 13, "final", 0) #XXX # sync CPYTHON_VERSION with patchlevel.h, package.py CPYTHON_API_VERSION = 1013 #XXX # sync with include/modsupport.h -- cgit v1.2.3-65-gdbad