forked from pool/python38
- Remove %suse_update_desktop_file macro as it is not useful any
more. OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python38?expand=0&rev=160
This commit is contained in:
commit
394799feb0
23
.gitattributes
vendored
Normal file
23
.gitattributes
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
## Default LFS
|
||||||
|
*.7z filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.bsp filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.gem filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.gz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.jar filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.lz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.lzma filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.obscpio filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.oxt filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pdf filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.png filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.rpm filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tbz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tbz2 filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tgz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ttf filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.txz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.whl filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.xz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.zst filter=lfs diff=lfs merge=lfs -text
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.osc
|
54
98437-sphinx.locale._-as-gettext-in-pyspecific.patch
Normal file
54
98437-sphinx.locale._-as-gettext-in-pyspecific.patch
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
From 5775f51691d7d64fb676586e008b41261ce64ac2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Matt.Wang" <mattwang44@gmail.com>
|
||||||
|
Date: Wed, 19 Oct 2022 14:49:08 +0800
|
||||||
|
Subject: [PATCH 1/2] fix(doc-tools): use sphinx.locale._ as gettext() for
|
||||||
|
backward-compatibility in pyspecific.py
|
||||||
|
|
||||||
|
[why] spinix 5.3 changed locale.translators from a defaultdict(gettext.NullTranslations) to a dict, which leads to failure of pyspecific.py. Use sphinx.locale._ as gettext to fix the issue.
|
||||||
|
---
|
||||||
|
Doc/tools/extensions/pyspecific.py | 8 ++++----
|
||||||
|
Misc/NEWS.d/next/Documentation/2022-10-19-07-15-52.gh-issue-98366.UskMXF.rst | 1 +
|
||||||
|
2 files changed, 5 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
--- a/Doc/tools/extensions/pyspecific.py
|
||||||
|
+++ b/Doc/tools/extensions/pyspecific.py
|
||||||
|
@@ -26,7 +26,7 @@ try:
|
||||||
|
from sphinx.errors import NoUri
|
||||||
|
except ImportError:
|
||||||
|
from sphinx.environment import NoUri
|
||||||
|
-from sphinx.locale import translators
|
||||||
|
+from sphinx.locale import _ as sphinx_gettext
|
||||||
|
from sphinx.util import status_iterator, logging
|
||||||
|
from sphinx.util.nodes import split_explicit_title
|
||||||
|
from sphinx.writers.text import TextWriter, TextTranslator
|
||||||
|
@@ -110,7 +110,7 @@ class ImplementationDetail(Directive):
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
pnode = nodes.compound(classes=['impl-detail'])
|
||||||
|
- label = translators['sphinx'].gettext(self.label_text)
|
||||||
|
+ label = sphinx_gettext(self.label_text)
|
||||||
|
content = self.content
|
||||||
|
add_text = nodes.strong(label, label)
|
||||||
|
if self.arguments:
|
||||||
|
@@ -179,7 +179,7 @@ class AuditEvent(Directive):
|
||||||
|
else:
|
||||||
|
args = []
|
||||||
|
|
||||||
|
- label = translators['sphinx'].gettext(self._label[min(2, len(args))])
|
||||||
|
+ label = sphinx_gettext(self._label[min(2, len(args))])
|
||||||
|
text = label.format(name="``{}``".format(name),
|
||||||
|
args=", ".join("``{}``".format(a) for a in args if a))
|
||||||
|
|
||||||
|
@@ -357,7 +357,7 @@ class DeprecatedRemoved(Directive):
|
||||||
|
else:
|
||||||
|
label = self._removed_label
|
||||||
|
|
||||||
|
- label = translators['sphinx'].gettext(label)
|
||||||
|
+ label = sphinx_gettext(label)
|
||||||
|
text = label.format(deprecated=self.arguments[0], removed=self.arguments[1])
|
||||||
|
if len(self.arguments) == 3:
|
||||||
|
inodes, messages = self.state.inline_text(self.arguments[2],
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Misc/NEWS.d/next/Documentation/2022-10-19-07-15-52.gh-issue-98366.UskMXF.rst
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+Use sphinx.locale._ as the gettext function in pyspecific.py.
|
79
99366-patch.dict-can-decorate-async.patch
Normal file
79
99366-patch.dict-can-decorate-async.patch
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
From c0dea0309b9a0a7cbc87727c9957f0a388fb9b0f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nikita Sobolev <mail@sobolevn.me>
|
||||||
|
Date: Fri, 11 Nov 2022 11:04:30 +0300
|
||||||
|
Subject: [PATCH] gh-98086: Now ``patch.dict`` can decorate async functions
|
||||||
|
(GH-98095) (cherry picked from commit
|
||||||
|
67b4d2772c5124b908f8ed9b13166a79bbeb88d2)
|
||||||
|
|
||||||
|
Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
|
||||||
|
---
|
||||||
|
Lib/unittest/mock.py | 18 ++++++++++
|
||||||
|
Lib/unittest/test/testmock/testasync.py | 17 +++++++++
|
||||||
|
Misc/NEWS.d/next/Library/2022-10-08-19-39-27.gh-issue-98086.y---WC.rst | 1
|
||||||
|
3 files changed, 36 insertions(+)
|
||||||
|
create mode 100644 Misc/NEWS.d/next/Library/2022-10-08-19-39-27.gh-issue-98086.y---WC.rst
|
||||||
|
|
||||||
|
--- a/Lib/unittest/mock.py
|
||||||
|
+++ b/Lib/unittest/mock.py
|
||||||
|
@@ -1749,6 +1749,12 @@ class _patch_dict(object):
|
||||||
|
def __call__(self, f):
|
||||||
|
if isinstance(f, type):
|
||||||
|
return self.decorate_class(f)
|
||||||
|
+ if inspect.iscoroutinefunction(f):
|
||||||
|
+ return self.decorate_async_callable(f)
|
||||||
|
+ return self.decorate_callable(f)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ def decorate_callable(self, f):
|
||||||
|
@wraps(f)
|
||||||
|
def _inner(*args, **kw):
|
||||||
|
self._patch_dict()
|
||||||
|
@@ -1757,6 +1763,18 @@ class _patch_dict(object):
|
||||||
|
finally:
|
||||||
|
self._unpatch_dict()
|
||||||
|
|
||||||
|
+ return _inner
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ def decorate_async_callable(self, f):
|
||||||
|
+ @wraps(f)
|
||||||
|
+ async def _inner(*args, **kw):
|
||||||
|
+ self._patch_dict()
|
||||||
|
+ try:
|
||||||
|
+ return await f(*args, **kw)
|
||||||
|
+ finally:
|
||||||
|
+ self._unpatch_dict()
|
||||||
|
+
|
||||||
|
return _inner
|
||||||
|
|
||||||
|
|
||||||
|
--- a/Lib/unittest/test/testmock/testasync.py
|
||||||
|
+++ b/Lib/unittest/test/testmock/testasync.py
|
||||||
|
@@ -143,6 +143,23 @@ class AsyncPatchCMTest(unittest.TestCase
|
||||||
|
|
||||||
|
asyncio.run(test_async())
|
||||||
|
|
||||||
|
+ def test_patch_dict_async_def(self):
|
||||||
|
+ foo = {'a': 'a'}
|
||||||
|
+ @patch.dict(foo, {'a': 'b'})
|
||||||
|
+ async def test_async():
|
||||||
|
+ self.assertEqual(foo['a'], 'b')
|
||||||
|
+
|
||||||
|
+ self.assertTrue(inspect.iscoroutinefunction(test_async))
|
||||||
|
+ asyncio.run(test_async())
|
||||||
|
+
|
||||||
|
+ def test_patch_dict_async_def_context(self):
|
||||||
|
+ foo = {'a': 'a'}
|
||||||
|
+ async def test_async():
|
||||||
|
+ with patch.dict(foo, {'a': 'b'}):
|
||||||
|
+ self.assertEqual(foo['a'], 'b')
|
||||||
|
+
|
||||||
|
+ asyncio.run(test_async())
|
||||||
|
+
|
||||||
|
|
||||||
|
class AsyncMockTest(unittest.TestCase):
|
||||||
|
def test_iscoroutinefunction_default(self):
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Misc/NEWS.d/next/Library/2022-10-08-19-39-27.gh-issue-98086.y---WC.rst
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+Make sure ``patch.dict()`` can be applied on async functions.
|
57
CVE-2019-5010-null-defer-x509-cert-DOS.patch
Normal file
57
CVE-2019-5010-null-defer-x509-cert-DOS.patch
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
From a37f52436f9aa4b9292878b72f3ff1480e2606c3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Heimes <christian@python.org>
|
||||||
|
Date: Tue, 15 Jan 2019 23:47:42 +0100
|
||||||
|
Subject: [PATCH] bpo-35746: Fix segfault in ssl's cert parser (GH-11569)
|
||||||
|
|
||||||
|
Fix a NULL pointer deref in ssl module. The cert parser did not handle CRL
|
||||||
|
distribution points with empty DP or URI correctly. A malicious or buggy
|
||||||
|
certificate can result into segfault.
|
||||||
|
|
||||||
|
Signed-off-by: Christian Heimes <christian@python.org>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
https://bugs.python.org/issue35746
|
||||||
|
---
|
||||||
|
Lib/test/test_ssl.py | 21 ++++++++++
|
||||||
|
Misc/NEWS.d/next/Security/2019-01-15-18-16-05.bpo-35746.nMSd0j.rst | 3 +
|
||||||
|
2 files changed, 24 insertions(+)
|
||||||
|
create mode 100644 Lib/test/talos-2019-0758.pem
|
||||||
|
create mode 100644 Misc/NEWS.d/next/Security/2019-01-15-18-16-05.bpo-35746.nMSd0j.rst
|
||||||
|
|
||||||
|
--- a/Lib/test/test_ssl.py
|
||||||
|
+++ b/Lib/test/test_ssl.py
|
||||||
|
@@ -507,6 +507,27 @@ class BasicSocketTests(unittest.TestCase
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
+ def test_parse_cert_CVE_2019_5010(self):
|
||||||
|
+ p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP)
|
||||||
|
+ if support.verbose:
|
||||||
|
+ sys.stdout.write("\n" + pprint.pformat(p) + "\n")
|
||||||
|
+ self.assertEqual(
|
||||||
|
+ p,
|
||||||
|
+ {
|
||||||
|
+ 'issuer': (
|
||||||
|
+ (('countryName', 'UK'),), (('commonName', 'cody-ca'),)),
|
||||||
|
+ 'notAfter': 'Jun 14 18:00:58 2028 GMT',
|
||||||
|
+ 'notBefore': 'Jun 18 18:00:58 2018 GMT',
|
||||||
|
+ 'serialNumber': '02',
|
||||||
|
+ 'subject': ((('countryName', 'UK'),),
|
||||||
|
+ (('commonName',
|
||||||
|
+ 'codenomicon-vm-2.test.lal.cisco.com'),)),
|
||||||
|
+ 'subjectAltName': (
|
||||||
|
+ ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),),
|
||||||
|
+ 'version': 3
|
||||||
|
+ }
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
def test_parse_cert_CVE_2013_4238(self):
|
||||||
|
p = ssl._ssl._test_decode_cert(NULLBYTECERT)
|
||||||
|
if support.verbose:
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Misc/NEWS.d/next/Security/2019-01-15-18-16-05.bpo-35746.nMSd0j.rst
|
||||||
|
@@ -0,0 +1,3 @@
|
||||||
|
+[CVE-2019-5010] Fix a NULL pointer deref in ssl module. The cert parser did
|
||||||
|
+not handle CRL distribution points with empty DP or URI correctly. A
|
||||||
|
+malicious or buggy certificate can result into segfault.
|
462
CVE-2023-27043-email-parsing-errors.patch
Normal file
462
CVE-2023-27043-email-parsing-errors.patch
Normal file
@ -0,0 +1,462 @@
|
|||||||
|
---
|
||||||
|
Doc/library/email.utils.rst | 19 -
|
||||||
|
Lib/email/utils.py | 151 +++++++-
|
||||||
|
Lib/test/test_email/test_email.py | 187 +++++++++-
|
||||||
|
Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst | 8
|
||||||
|
4 files changed, 344 insertions(+), 21 deletions(-)
|
||||||
|
|
||||||
|
--- a/Doc/library/email.utils.rst
|
||||||
|
+++ b/Doc/library/email.utils.rst
|
||||||
|
@@ -60,13 +60,18 @@ of the new API.
|
||||||
|
begins with angle brackets, they are stripped off.
|
||||||
|
|
||||||
|
|
||||||
|
-.. function:: parseaddr(address)
|
||||||
|
+.. function:: parseaddr(address, *, strict=True)
|
||||||
|
|
||||||
|
Parse address -- which should be the value of some address-containing field such
|
||||||
|
as :mailheader:`To` or :mailheader:`Cc` -- into its constituent *realname* and
|
||||||
|
*email address* parts. Returns a tuple of that information, unless the parse
|
||||||
|
fails, in which case a 2-tuple of ``('', '')`` is returned.
|
||||||
|
|
||||||
|
+ If *strict* is true, use a strict parser which rejects malformed inputs.
|
||||||
|
+
|
||||||
|
+ .. versionchanged:: 3.13
|
||||||
|
+ Add *strict* optional parameter and reject malformed inputs by default.
|
||||||
|
+
|
||||||
|
|
||||||
|
.. function:: formataddr(pair, charset='utf-8')
|
||||||
|
|
||||||
|
@@ -84,12 +89,15 @@ of the new API.
|
||||||
|
Added the *charset* option.
|
||||||
|
|
||||||
|
|
||||||
|
-.. function:: getaddresses(fieldvalues)
|
||||||
|
+.. function:: getaddresses(fieldvalues, *, strict=True)
|
||||||
|
|
||||||
|
This method returns a list of 2-tuples of the form returned by ``parseaddr()``.
|
||||||
|
*fieldvalues* is a sequence of header field values as might be returned by
|
||||||
|
- :meth:`Message.get_all <email.message.Message.get_all>`. Here's a simple
|
||||||
|
- example that gets all the recipients of a message::
|
||||||
|
+ :meth:`Message.get_all <email.message.Message.get_all>`.
|
||||||
|
+
|
||||||
|
+ If *strict* is true, use a strict parser which rejects malformed inputs.
|
||||||
|
+
|
||||||
|
+ Here's a simple example that gets all the recipients of a message::
|
||||||
|
|
||||||
|
from email.utils import getaddresses
|
||||||
|
|
||||||
|
@@ -99,6 +107,9 @@ of the new API.
|
||||||
|
resent_ccs = msg.get_all('resent-cc', [])
|
||||||
|
all_recipients = getaddresses(tos + ccs + resent_tos + resent_ccs)
|
||||||
|
|
||||||
|
+ .. versionchanged:: 3.13
|
||||||
|
+ Add *strict* optional parameter and reject malformed inputs by default.
|
||||||
|
+
|
||||||
|
|
||||||
|
.. function:: parsedate(date)
|
||||||
|
|
||||||
|
--- a/Lib/email/utils.py
|
||||||
|
+++ b/Lib/email/utils.py
|
||||||
|
@@ -48,6 +48,7 @@ TICK = "'"
|
||||||
|
specialsre = re.compile(r'[][\\()<>@,:;".]')
|
||||||
|
escapesre = re.compile(r'[\\"]')
|
||||||
|
|
||||||
|
+
|
||||||
|
def _has_surrogates(s):
|
||||||
|
"""Return True if s contains surrogate-escaped binary data."""
|
||||||
|
# This check is based on the fact that unless there are surrogates, utf8
|
||||||
|
@@ -105,13 +106,128 @@ def formataddr(pair, charset='utf-8'):
|
||||||
|
return '%s%s%s <%s>' % (quotes, name, quotes, address)
|
||||||
|
return address
|
||||||
|
|
||||||
|
+
|
||||||
|
+def _iter_escaped_chars(addr):
|
||||||
|
+ pos = 0
|
||||||
|
+ escape = False
|
||||||
|
+ for pos, ch in enumerate(addr):
|
||||||
|
+ if escape:
|
||||||
|
+ yield (pos, '\\' + ch)
|
||||||
|
+ escape = False
|
||||||
|
+ elif ch == '\\':
|
||||||
|
+ escape = True
|
||||||
|
+ else:
|
||||||
|
+ yield (pos, ch)
|
||||||
|
+ if escape:
|
||||||
|
+ yield (pos, '\\')
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def _strip_quoted_realnames(addr):
|
||||||
|
+ """Strip real names between quotes."""
|
||||||
|
+ if '"' not in addr:
|
||||||
|
+ # Fast path
|
||||||
|
+ return addr
|
||||||
|
+
|
||||||
|
+ start = 0
|
||||||
|
+ open_pos = None
|
||||||
|
+ result = []
|
||||||
|
+ for pos, ch in _iter_escaped_chars(addr):
|
||||||
|
+ if ch == '"':
|
||||||
|
+ if open_pos is None:
|
||||||
|
+ open_pos = pos
|
||||||
|
+ else:
|
||||||
|
+ if start != open_pos:
|
||||||
|
+ result.append(addr[start:open_pos])
|
||||||
|
+ start = pos + 1
|
||||||
|
+ open_pos = None
|
||||||
|
+
|
||||||
|
+ if start < len(addr):
|
||||||
|
+ result.append(addr[start:])
|
||||||
|
+
|
||||||
|
+ return ''.join(result)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+supports_strict_parsing = True
|
||||||
|
|
||||||
|
+def getaddresses(fieldvalues, *, strict=True):
|
||||||
|
+ """Return a list of (REALNAME, EMAIL) or ('','') for each fieldvalue.
|
||||||
|
|
||||||
|
-def getaddresses(fieldvalues):
|
||||||
|
- """Return a list of (REALNAME, EMAIL) for each fieldvalue."""
|
||||||
|
- all = COMMASPACE.join(fieldvalues)
|
||||||
|
- a = _AddressList(all)
|
||||||
|
- return a.addresslist
|
||||||
|
+ When parsing fails for a fieldvalue, a 2-tuple of ('', '') is returned in
|
||||||
|
+ its place.
|
||||||
|
+
|
||||||
|
+ If strict is true, use a strict parser which rejects malformed inputs.
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ # If strict is true, if the resulting list of parsed addresses is greater
|
||||||
|
+ # than the number of fieldvalues in the input list, a parsing error has
|
||||||
|
+ # occurred and consequently a list containing a single empty 2-tuple [('',
|
||||||
|
+ # '')] is returned in its place. This is done to avoid invalid output.
|
||||||
|
+ #
|
||||||
|
+ # Malformed input: getaddresses(['alice@example.com <bob@example.com>'])
|
||||||
|
+ # Invalid output: [('', 'alice@example.com'), ('', 'bob@example.com')]
|
||||||
|
+ # Safe output: [('', '')]
|
||||||
|
+
|
||||||
|
+ if not strict:
|
||||||
|
+ all = COMMASPACE.join(str(v) for v in fieldvalues)
|
||||||
|
+ a = _AddressList(all)
|
||||||
|
+ return a.addresslist
|
||||||
|
+
|
||||||
|
+ fieldvalues = [str(v) for v in fieldvalues]
|
||||||
|
+ fieldvalues = _pre_parse_validation(fieldvalues)
|
||||||
|
+ addr = COMMASPACE.join(fieldvalues)
|
||||||
|
+ a = _AddressList(addr)
|
||||||
|
+ result = _post_parse_validation(a.addresslist)
|
||||||
|
+
|
||||||
|
+ # Treat output as invalid if the number of addresses is not equal to the
|
||||||
|
+ # expected number of addresses.
|
||||||
|
+ n = 0
|
||||||
|
+ for v in fieldvalues:
|
||||||
|
+ # When a comma is used in the Real Name part it is not a deliminator.
|
||||||
|
+ # So strip those out before counting the commas.
|
||||||
|
+ v = _strip_quoted_realnames(v)
|
||||||
|
+ # Expected number of addresses: 1 + number of commas
|
||||||
|
+ n += 1 + v.count(',')
|
||||||
|
+ if len(result) != n:
|
||||||
|
+ return [('', '')]
|
||||||
|
+
|
||||||
|
+ return result
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def _check_parenthesis(addr):
|
||||||
|
+ # Ignore parenthesis in quoted real names.
|
||||||
|
+ addr = _strip_quoted_realnames(addr)
|
||||||
|
+
|
||||||
|
+ opens = 0
|
||||||
|
+ for pos, ch in _iter_escaped_chars(addr):
|
||||||
|
+ if ch == '(':
|
||||||
|
+ opens += 1
|
||||||
|
+ elif ch == ')':
|
||||||
|
+ opens -= 1
|
||||||
|
+ if opens < 0:
|
||||||
|
+ return False
|
||||||
|
+ return (opens == 0)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def _pre_parse_validation(email_header_fields):
|
||||||
|
+ accepted_values = []
|
||||||
|
+ for v in email_header_fields:
|
||||||
|
+ if not _check_parenthesis(v):
|
||||||
|
+ v = "('', '')"
|
||||||
|
+ accepted_values.append(v)
|
||||||
|
+
|
||||||
|
+ return accepted_values
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def _post_parse_validation(parsed_email_header_tuples):
|
||||||
|
+ accepted_values = []
|
||||||
|
+ # The parser would have parsed a correctly formatted domain-literal
|
||||||
|
+ # The existence of an [ after parsing indicates a parsing failure
|
||||||
|
+ for v in parsed_email_header_tuples:
|
||||||
|
+ if '[' in v[1]:
|
||||||
|
+ v = ('', '')
|
||||||
|
+ accepted_values.append(v)
|
||||||
|
+
|
||||||
|
+ return accepted_values
|
||||||
|
|
||||||
|
|
||||||
|
def _format_timetuple_and_zone(timetuple, zone):
|
||||||
|
@@ -202,16 +318,33 @@ def parsedate_to_datetime(data):
|
||||||
|
tzinfo=datetime.timezone(datetime.timedelta(seconds=tz)))
|
||||||
|
|
||||||
|
|
||||||
|
-def parseaddr(addr):
|
||||||
|
+def parseaddr(addr, *, strict=True):
|
||||||
|
"""
|
||||||
|
Parse addr into its constituent realname and email address parts.
|
||||||
|
|
||||||
|
Return a tuple of realname and email address, unless the parse fails, in
|
||||||
|
which case return a 2-tuple of ('', '').
|
||||||
|
+
|
||||||
|
+ If strict is True, use a strict parser which rejects malformed inputs.
|
||||||
|
"""
|
||||||
|
- addrs = _AddressList(addr).addresslist
|
||||||
|
- if not addrs:
|
||||||
|
- return '', ''
|
||||||
|
+ if not strict:
|
||||||
|
+ addrs = _AddressList(addr).addresslist
|
||||||
|
+ if not addrs:
|
||||||
|
+ return ('', '')
|
||||||
|
+ return addrs[0]
|
||||||
|
+
|
||||||
|
+ if isinstance(addr, list):
|
||||||
|
+ addr = addr[0]
|
||||||
|
+
|
||||||
|
+ if not isinstance(addr, str):
|
||||||
|
+ return ('', '')
|
||||||
|
+
|
||||||
|
+ addr = _pre_parse_validation([addr])[0]
|
||||||
|
+ addrs = _post_parse_validation(_AddressList(addr).addresslist)
|
||||||
|
+
|
||||||
|
+ if not addrs or len(addrs) > 1:
|
||||||
|
+ return ('', '')
|
||||||
|
+
|
||||||
|
return addrs[0]
|
||||||
|
|
||||||
|
|
||||||
|
--- a/Lib/test/test_email/test_email.py
|
||||||
|
+++ b/Lib/test/test_email/test_email.py
|
||||||
|
@@ -16,6 +16,7 @@ from unittest.mock import patch
|
||||||
|
|
||||||
|
import email
|
||||||
|
import email.policy
|
||||||
|
+import email.utils
|
||||||
|
|
||||||
|
from email.charset import Charset
|
||||||
|
from email.header import Header, decode_header, make_header
|
||||||
|
@@ -3248,15 +3249,137 @@ Foo
|
||||||
|
[('Al Person', 'aperson@dom.ain'),
|
||||||
|
('Bud Person', 'bperson@dom.ain')])
|
||||||
|
|
||||||
|
+ def test_parsing_errors(self):
|
||||||
|
+ """Test for parsing errors from CVE-2023-27043 and CVE-2019-16056"""
|
||||||
|
+ alice = 'alice@example.org'
|
||||||
|
+ bob = 'bob@example.com'
|
||||||
|
+ empty = ('', '')
|
||||||
|
+
|
||||||
|
+ # Test utils.getaddresses() and utils.parseaddr() on malformed email
|
||||||
|
+ # addresses: default behavior (strict=True) rejects malformed address,
|
||||||
|
+ # and strict=False which tolerates malformed address.
|
||||||
|
+ for invalid_separator, expected_non_strict in (
|
||||||
|
+ ('(', [(f'<{bob}>', alice)]),
|
||||||
|
+ (')', [('', alice), empty, ('', bob)]),
|
||||||
|
+ ('<', [('', alice), empty, ('', bob), empty]),
|
||||||
|
+ ('>', [('', alice), empty, ('', bob)]),
|
||||||
|
+ ('[', [('', f'{alice}[<{bob}>]')]),
|
||||||
|
+ (']', [('', alice), empty, ('', bob)]),
|
||||||
|
+ ('@', [empty, empty, ('', bob)]),
|
||||||
|
+ (';', [('', alice), empty, ('', bob)]),
|
||||||
|
+ (':', [('', alice), ('', bob)]),
|
||||||
|
+ ('.', [('', alice + '.'), ('', bob)]),
|
||||||
|
+ ('"', [('', alice), ('', f'<{bob}>')]),
|
||||||
|
+ ):
|
||||||
|
+ address = f'{alice}{invalid_separator}<{bob}>'
|
||||||
|
+ with self.subTest(address=address):
|
||||||
|
+ self.assertEqual(utils.getaddresses([address]),
|
||||||
|
+ [empty])
|
||||||
|
+ self.assertEqual(utils.getaddresses([address], strict=False),
|
||||||
|
+ expected_non_strict)
|
||||||
|
+
|
||||||
|
+ self.assertEqual(utils.parseaddr([address]),
|
||||||
|
+ empty)
|
||||||
|
+ self.assertEqual(utils.parseaddr([address], strict=False),
|
||||||
|
+ ('', address))
|
||||||
|
+
|
||||||
|
+ # Comma (',') is treated differently depending on strict parameter.
|
||||||
|
+ # Comma without quotes.
|
||||||
|
+ address = f'{alice},<{bob}>'
|
||||||
|
+ self.assertEqual(utils.getaddresses([address]),
|
||||||
|
+ [('', alice), ('', bob)])
|
||||||
|
+ self.assertEqual(utils.getaddresses([address], strict=False),
|
||||||
|
+ [('', alice), ('', bob)])
|
||||||
|
+ self.assertEqual(utils.parseaddr([address]),
|
||||||
|
+ empty)
|
||||||
|
+ self.assertEqual(utils.parseaddr([address], strict=False),
|
||||||
|
+ ('', address))
|
||||||
|
+
|
||||||
|
+ # Real name between quotes containing comma.
|
||||||
|
+ address = '"Alice, alice@example.org" <bob@example.com>'
|
||||||
|
+ expected_strict = ('Alice, alice@example.org', 'bob@example.com')
|
||||||
|
+ self.assertEqual(utils.getaddresses([address]), [expected_strict])
|
||||||
|
+ self.assertEqual(utils.getaddresses([address], strict=False), [expected_strict])
|
||||||
|
+ self.assertEqual(utils.parseaddr([address]), expected_strict)
|
||||||
|
+ self.assertEqual(utils.parseaddr([address], strict=False),
|
||||||
|
+ ('', address))
|
||||||
|
+
|
||||||
|
+ # Valid parenthesis in comments.
|
||||||
|
+ address = 'alice@example.org (Alice)'
|
||||||
|
+ expected_strict = ('Alice', 'alice@example.org')
|
||||||
|
+ self.assertEqual(utils.getaddresses([address]), [expected_strict])
|
||||||
|
+ self.assertEqual(utils.getaddresses([address], strict=False), [expected_strict])
|
||||||
|
+ self.assertEqual(utils.parseaddr([address]), expected_strict)
|
||||||
|
+ self.assertEqual(utils.parseaddr([address], strict=False),
|
||||||
|
+ ('', address))
|
||||||
|
+
|
||||||
|
+ # Invalid parenthesis in comments.
|
||||||
|
+ address = 'alice@example.org )Alice('
|
||||||
|
+ self.assertEqual(utils.getaddresses([address]), [empty])
|
||||||
|
+ self.assertEqual(utils.getaddresses([address], strict=False),
|
||||||
|
+ [('', 'alice@example.org'), ('', ''), ('', 'Alice')])
|
||||||
|
+ self.assertEqual(utils.parseaddr([address]), empty)
|
||||||
|
+ self.assertEqual(utils.parseaddr([address], strict=False),
|
||||||
|
+ ('', address))
|
||||||
|
+
|
||||||
|
+ # Two addresses with quotes separated by comma.
|
||||||
|
+ address = '"Jane Doe" <jane@example.net>, "John Doe" <john@example.net>'
|
||||||
|
+ self.assertEqual(utils.getaddresses([address]),
|
||||||
|
+ [('Jane Doe', 'jane@example.net'),
|
||||||
|
+ ('John Doe', 'john@example.net')])
|
||||||
|
+ self.assertEqual(utils.getaddresses([address], strict=False),
|
||||||
|
+ [('Jane Doe', 'jane@example.net'),
|
||||||
|
+ ('John Doe', 'john@example.net')])
|
||||||
|
+ self.assertEqual(utils.parseaddr([address]), empty)
|
||||||
|
+ self.assertEqual(utils.parseaddr([address], strict=False),
|
||||||
|
+ ('', address))
|
||||||
|
+
|
||||||
|
+ # Test email.utils.supports_strict_parsing attribute
|
||||||
|
+ self.assertEqual(email.utils.supports_strict_parsing, True)
|
||||||
|
+
|
||||||
|
def test_getaddresses_nasty(self):
|
||||||
|
- eq = self.assertEqual
|
||||||
|
- eq(utils.getaddresses(['foo: ;']), [('', '')])
|
||||||
|
- eq(utils.getaddresses(
|
||||||
|
- ['[]*-- =~$']),
|
||||||
|
- [('', ''), ('', ''), ('', '*--')])
|
||||||
|
- eq(utils.getaddresses(
|
||||||
|
- ['foo: ;', '"Jason R. Mastaler" <jason@dom.ain>']),
|
||||||
|
- [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')])
|
||||||
|
+ for addresses, expected in (
|
||||||
|
+ (['"Sürname, Firstname" <to@example.com>'],
|
||||||
|
+ [('Sürname, Firstname', 'to@example.com')]),
|
||||||
|
+
|
||||||
|
+ (['foo: ;'],
|
||||||
|
+ [('', '')]),
|
||||||
|
+
|
||||||
|
+ (['foo: ;', '"Jason R. Mastaler" <jason@dom.ain>'],
|
||||||
|
+ [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]),
|
||||||
|
+
|
||||||
|
+ ([r'Pete(A nice \) chap) <pete(his account)@silly.test(his host)>'],
|
||||||
|
+ [('Pete (A nice ) chap his account his host)', 'pete@silly.test')]),
|
||||||
|
+
|
||||||
|
+ (['(Empty list)(start)Undisclosed recipients :(nobody(I know))'],
|
||||||
|
+ [('', '')]),
|
||||||
|
+
|
||||||
|
+ (['Mary <@machine.tld:mary@example.net>, , jdoe@test . example'],
|
||||||
|
+ [('Mary', 'mary@example.net'), ('', ''), ('', 'jdoe@test.example')]),
|
||||||
|
+
|
||||||
|
+ (['John Doe <jdoe@machine(comment). example>'],
|
||||||
|
+ [('John Doe (comment)', 'jdoe@machine.example')]),
|
||||||
|
+
|
||||||
|
+ (['"Mary Smith: Personal Account" <smith@home.example>'],
|
||||||
|
+ [('Mary Smith: Personal Account', 'smith@home.example')]),
|
||||||
|
+
|
||||||
|
+ (['Undisclosed recipients:;'],
|
||||||
|
+ [('', '')]),
|
||||||
|
+
|
||||||
|
+ ([r'<boss@nil.test>, "Giant; \"Big\" Box" <bob@example.net>'],
|
||||||
|
+ [('', 'boss@nil.test'), ('Giant; "Big" Box', 'bob@example.net')]),
|
||||||
|
+ ):
|
||||||
|
+ with self.subTest(addresses=addresses):
|
||||||
|
+ self.assertEqual(utils.getaddresses(addresses),
|
||||||
|
+ expected)
|
||||||
|
+ self.assertEqual(utils.getaddresses(addresses, strict=False),
|
||||||
|
+ expected)
|
||||||
|
+
|
||||||
|
+ addresses = ['[]*-- =~$']
|
||||||
|
+ self.assertEqual(utils.getaddresses(addresses),
|
||||||
|
+ [('', '')])
|
||||||
|
+ self.assertEqual(utils.getaddresses(addresses, strict=False),
|
||||||
|
+ [('', ''), ('', ''), ('', '*--')])
|
||||||
|
|
||||||
|
def test_getaddresses_embedded_comment(self):
|
||||||
|
"""Test proper handling of a nested comment"""
|
||||||
|
@@ -3440,6 +3563,54 @@ multipart/report
|
||||||
|
m = cls(*constructor, policy=email.policy.default)
|
||||||
|
self.assertIs(m.policy, email.policy.default)
|
||||||
|
|
||||||
|
+ def test_iter_escaped_chars(self):
|
||||||
|
+ self.assertEqual(list(utils._iter_escaped_chars(r'a\\b\"c\\"d')),
|
||||||
|
+ [(0, 'a'),
|
||||||
|
+ (2, '\\\\'),
|
||||||
|
+ (3, 'b'),
|
||||||
|
+ (5, '\\"'),
|
||||||
|
+ (6, 'c'),
|
||||||
|
+ (8, '\\\\'),
|
||||||
|
+ (9, '"'),
|
||||||
|
+ (10, 'd')])
|
||||||
|
+ self.assertEqual(list(utils._iter_escaped_chars('a\\')),
|
||||||
|
+ [(0, 'a'), (1, '\\')])
|
||||||
|
+
|
||||||
|
+ def test_strip_quoted_realnames(self):
|
||||||
|
+ def check(addr, expected):
|
||||||
|
+ self.assertEqual(utils._strip_quoted_realnames(addr), expected)
|
||||||
|
+
|
||||||
|
+ check('"Jane Doe" <jane@example.net>, "John Doe" <john@example.net>',
|
||||||
|
+ ' <jane@example.net>, <john@example.net>')
|
||||||
|
+ check(r'"Jane \"Doe\"." <jane@example.net>',
|
||||||
|
+ ' <jane@example.net>')
|
||||||
|
+
|
||||||
|
+ # special cases
|
||||||
|
+ check(r'before"name"after', 'beforeafter')
|
||||||
|
+ check(r'before"name"', 'before')
|
||||||
|
+ check(r'b"name"', 'b') # single char
|
||||||
|
+ check(r'"name"after', 'after')
|
||||||
|
+ check(r'"name"a', 'a') # single char
|
||||||
|
+ check(r'"name"', '')
|
||||||
|
+
|
||||||
|
+ # no change
|
||||||
|
+ for addr in (
|
||||||
|
+ 'Jane Doe <jane@example.net>, John Doe <john@example.net>',
|
||||||
|
+ 'lone " quote',
|
||||||
|
+ ):
|
||||||
|
+ self.assertEqual(utils._strip_quoted_realnames(addr), addr)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ def test_check_parenthesis(self):
|
||||||
|
+ addr = 'alice@example.net'
|
||||||
|
+ self.assertTrue(utils._check_parenthesis(f'{addr} (Alice)'))
|
||||||
|
+ self.assertFalse(utils._check_parenthesis(f'{addr} )Alice('))
|
||||||
|
+ self.assertFalse(utils._check_parenthesis(f'{addr} (Alice))'))
|
||||||
|
+ self.assertFalse(utils._check_parenthesis(f'{addr} ((Alice)'))
|
||||||
|
+
|
||||||
|
+ # Ignore real name between quotes
|
||||||
|
+ self.assertTrue(utils._check_parenthesis(f'")Alice((" {addr}'))
|
||||||
|
+
|
||||||
|
|
||||||
|
# Test the iterator/generators
|
||||||
|
class TestIterators(TestEmailBase):
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst
|
||||||
|
@@ -0,0 +1,8 @@
|
||||||
|
+:func:`email.utils.getaddresses` and :func:`email.utils.parseaddr` now
|
||||||
|
+return ``('', '')`` 2-tuples in more situations where invalid email
|
||||||
|
+addresses are encountered instead of potentially inaccurate values. Add
|
||||||
|
+optional *strict* parameter to these two functions: use ``strict=False`` to
|
||||||
|
+get the old behavior, accept malformed inputs.
|
||||||
|
+``getattr(email.utils, 'supports_strict_parsing', False)`` can be use to check
|
||||||
|
+if the *strict* paramater is available. Patch by Thomas Dwyer and Victor
|
||||||
|
+Stinner to improve the CVE-2023-27043 fix.
|
173
CVE-2024-0397-memrace_ssl.SSLContext_cert_store.patch
Normal file
173
CVE-2024-0397-memrace_ssl.SSLContext_cert_store.patch
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
From 732c7d512e7cdf656a3f02a38c329b14a14a8573 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Seth Michael Larson <seth@python.org>
|
||||||
|
Date: Fri, 19 Apr 2024 11:21:40 -0700
|
||||||
|
Subject: [PATCH] [3.9] gh-114572: Fix locking in cert_store_stats and
|
||||||
|
get_ca_certs
|
||||||
|
|
||||||
|
---
|
||||||
|
Misc/NEWS.d/next/Security/2024-04-19-11-21-13.gh-issue-114572.t1QMQD.rst | 4
|
||||||
|
Modules/_ssl.c | 91 +++++++++-
|
||||||
|
2 files changed, 92 insertions(+), 3 deletions(-)
|
||||||
|
create mode 100644 Misc/NEWS.d/next/Security/2024-04-19-11-21-13.gh-issue-114572.t1QMQD.rst
|
||||||
|
|
||||||
|
Index: Python-3.8.19/Misc/NEWS.d/next/Security/2024-04-19-11-21-13.gh-issue-114572.t1QMQD.rst
|
||||||
|
===================================================================
|
||||||
|
--- /dev/null
|
||||||
|
+++ Python-3.8.19/Misc/NEWS.d/next/Security/2024-04-19-11-21-13.gh-issue-114572.t1QMQD.rst
|
||||||
|
@@ -0,0 +1,4 @@
|
||||||
|
+:meth:`ssl.SSLContext.cert_store_stats` and
|
||||||
|
+:meth:`ssl.SSLContext.get_ca_certs` now correctly lock access to the
|
||||||
|
+certificate store, when the :class:`ssl.SSLContext` is shared across
|
||||||
|
+multiple threads.
|
||||||
|
Index: Python-3.8.19/Modules/_ssl.c
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.8.19.orig/Modules/_ssl.c
|
||||||
|
+++ Python-3.8.19/Modules/_ssl.c
|
||||||
|
@@ -168,6 +168,10 @@ extern const SSL_METHOD *TLSv1_2_method(
|
||||||
|
# define PY_OPENSSL_1_1_API 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#if (OPENSSL_VERSION_NUMBER >= 0x30300000L) && !defined(LIBRESSL_VERSION_NUMBER)
|
||||||
|
+# define OPENSSL_VERSION_3_3 1
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* SNI support (client- and server-side) appeared in OpenSSL 1.0.0 and 0.9.8f
|
||||||
|
* This includes the SSL_set_SSL_CTX() function.
|
||||||
|
*/
|
||||||
|
@@ -212,6 +216,16 @@ extern const SSL_METHOD *TLSv1_2_method(
|
||||||
|
#define HAVE_OPENSSL_CRYPTO_LOCK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+/* OpenSSL 1.1+ allows locking X509_STORE, 1.0.2 doesn't. */
|
||||||
|
+#ifdef OPENSSL_VERSION_1_1
|
||||||
|
+#define HAVE_OPENSSL_X509_STORE_LOCK
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+/* OpenSSL 3.3 added the X509_STORE_get1_objects API */
|
||||||
|
+#ifdef OPENSSL_VERSION_3_3
|
||||||
|
+#define HAVE_OPENSSL_X509_STORE_GET1_OBJECTS 1
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
#if defined(OPENSSL_VERSION_1_1) && !defined(OPENSSL_NO_SSL2)
|
||||||
|
#define OPENSSL_NO_SSL2
|
||||||
|
#endif
|
||||||
|
@@ -4678,6 +4692,54 @@ set_sni_callback(PySSLContext *self, PyO
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Shim of X509_STORE_get1_objects API from OpenSSL 3.3
|
||||||
|
+ * Only available with the X509_STORE_lock() API */
|
||||||
|
+#if defined(HAVE_OPENSSL_X509_STORE_LOCK) && !defined(OPENSSL_VERSION_3_3)
|
||||||
|
+#define HAVE_OPENSSL_X509_STORE_GET1_OBJECTS 1
|
||||||
|
+
|
||||||
|
+static X509_OBJECT *x509_object_dup(const X509_OBJECT *obj)
|
||||||
|
+{
|
||||||
|
+ int ok;
|
||||||
|
+ X509_OBJECT *ret = X509_OBJECT_new();
|
||||||
|
+ if (ret == NULL) {
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+ switch (X509_OBJECT_get_type(obj)) {
|
||||||
|
+ case X509_LU_X509:
|
||||||
|
+ ok = X509_OBJECT_set1_X509(ret, X509_OBJECT_get0_X509(obj));
|
||||||
|
+ break;
|
||||||
|
+ case X509_LU_CRL:
|
||||||
|
+ /* X509_OBJECT_get0_X509_CRL was not const-correct prior to 3.0.*/
|
||||||
|
+ ok = X509_OBJECT_set1_X509_CRL(
|
||||||
|
+ ret, X509_OBJECT_get0_X509_CRL((X509_OBJECT *)obj));
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ /* We cannot duplicate unrecognized types in a polyfill, but it is
|
||||||
|
+ * safe to leave an empty object. The caller will ignore it. */
|
||||||
|
+ ok = 1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ if (!ok) {
|
||||||
|
+ X509_OBJECT_free(ret);
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static STACK_OF(X509_OBJECT) *
|
||||||
|
+X509_STORE_get1_objects(X509_STORE *store)
|
||||||
|
+{
|
||||||
|
+ STACK_OF(X509_OBJECT) *ret;
|
||||||
|
+ if (!X509_STORE_lock(store)) {
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+ ret = sk_X509_OBJECT_deep_copy(X509_STORE_get0_objects(store),
|
||||||
|
+ x509_object_dup, X509_OBJECT_free);
|
||||||
|
+ X509_STORE_unlock(store);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
PyDoc_STRVAR(PySSLContext_sni_callback_doc,
|
||||||
|
"Set a callback that will be called when a server name is provided by the SSL/TLS client in the SNI extension.\n\
|
||||||
|
\n\
|
||||||
|
@@ -4707,7 +4769,15 @@ _ssl__SSLContext_cert_store_stats_impl(P
|
||||||
|
int x509 = 0, crl = 0, ca = 0, i;
|
||||||
|
|
||||||
|
store = SSL_CTX_get_cert_store(self->ctx);
|
||||||
|
+#if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
|
||||||
|
+ objs = X509_STORE_get1_objects(store);
|
||||||
|
+ if (objs == NULL) {
|
||||||
|
+ PyErr_SetString(PyExc_MemoryError, "failed to query cert store");
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+#else
|
||||||
|
objs = X509_STORE_get0_objects(store);
|
||||||
|
+#endif
|
||||||
|
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
|
||||||
|
obj = sk_X509_OBJECT_value(objs, i);
|
||||||
|
switch (X509_OBJECT_get_type(obj)) {
|
||||||
|
@@ -4721,12 +4791,13 @@ _ssl__SSLContext_cert_store_stats_impl(P
|
||||||
|
crl++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
- /* Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY.
|
||||||
|
- * As far as I can tell they are internal states and never
|
||||||
|
- * stored in a cert store */
|
||||||
|
+ /* Ignore unrecognized types. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+#if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
|
||||||
|
+ sk_X509_OBJECT_pop_free(objs, X509_OBJECT_free);
|
||||||
|
+#endif
|
||||||
|
return Py_BuildValue("{sisisi}", "x509", x509, "crl", crl,
|
||||||
|
"x509_ca", ca);
|
||||||
|
}
|
||||||
|
@@ -4758,7 +4829,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSL
|
||||||
|
}
|
||||||
|
|
||||||
|
store = SSL_CTX_get_cert_store(self->ctx);
|
||||||
|
+#if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
|
||||||
|
+ objs = X509_STORE_get1_objects(store);
|
||||||
|
+ if (objs == NULL) {
|
||||||
|
+ PyErr_SetString(PyExc_MemoryError, "failed to query cert store");
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+#else
|
||||||
|
objs = X509_STORE_get0_objects(store);
|
||||||
|
+#endif
|
||||||
|
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
|
||||||
|
X509_OBJECT *obj;
|
||||||
|
X509 *cert;
|
||||||
|
@@ -4786,9 +4865,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSL
|
||||||
|
}
|
||||||
|
Py_CLEAR(ci);
|
||||||
|
}
|
||||||
|
+#if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
|
||||||
|
+ sk_X509_OBJECT_pop_free(objs, X509_OBJECT_free);
|
||||||
|
+#endif
|
||||||
|
return rlist;
|
||||||
|
|
||||||
|
error:
|
||||||
|
+#if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
|
||||||
|
+ sk_X509_OBJECT_pop_free(objs, X509_OBJECT_free);
|
||||||
|
+#endif
|
||||||
|
Py_XDECREF(ci);
|
||||||
|
Py_XDECREF(rlist);
|
||||||
|
return NULL;
|
444
CVE-2024-4032-private-IP-addrs.patch
Normal file
444
CVE-2024-4032-private-IP-addrs.patch
Normal file
@ -0,0 +1,444 @@
|
|||||||
|
From 05a14677846ed0a35773cd2ba582f9a65a3dfa48 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Petr Viktorin <encukou@gmail.com>
|
||||||
|
Date: Wed, 24 Apr 2024 14:29:30 +0200
|
||||||
|
Subject: [PATCH 1/3] gh-113171: gh-65056: Fix "private" (non-global) IP
|
||||||
|
address ranges (GH-113179) (GH-113186) (GH-118177)
|
||||||
|
|
||||||
|
* GH-113171: Fix "private" (non-global) IP address ranges (GH-113179)
|
||||||
|
|
||||||
|
The _private_networks variables, used by various is_private
|
||||||
|
implementations, were missing some ranges and at the same time had
|
||||||
|
overly strict ranges (where there are more specific ranges considered
|
||||||
|
globally reachable by the IANA registries).
|
||||||
|
|
||||||
|
This patch updates the ranges with what was missing or otherwise
|
||||||
|
incorrect.
|
||||||
|
|
||||||
|
100.64.0.0/10 is left alone, for now, as it's been made special in [1].
|
||||||
|
|
||||||
|
The _address_exclude_many() call returns 8 networks for IPv4, 121
|
||||||
|
networks for IPv6.
|
||||||
|
|
||||||
|
[1] https://github.com/python/cpython/issues/61602
|
||||||
|
|
||||||
|
* GH-65056: Improve the IP address' is_global/is_private documentation (GH-113186)
|
||||||
|
|
||||||
|
It wasn't clear what the semantics of is_global/is_private are and, when
|
||||||
|
one gets to the bottom of it, it's not quite so simple (hence the
|
||||||
|
exceptions listed).
|
||||||
|
|
||||||
|
(cherry picked from commit 2a4cbf17af19a01d942f9579342f77c39fbd23c4)
|
||||||
|
(cherry picked from commit 40d75c2b7f5c67e254d0a025e0f2e2c7ada7f69f)
|
||||||
|
|
||||||
|
---------
|
||||||
|
|
||||||
|
(cherry picked from commit f86b17ac511e68192ba71f27e752321a3252cee3)
|
||||||
|
|
||||||
|
Co-authored-by: Jakub Stasiak <jakub@stasiak.at>
|
||||||
|
---
|
||||||
|
Doc/library/ipaddress.rst | 43 ++++++++-
|
||||||
|
Doc/whatsnew/3.8.rst | 9 ++
|
||||||
|
Lib/ipaddress.py | 95 +++++++++++++++----
|
||||||
|
Lib/test/test_ipaddress.py | 52 ++++++++++
|
||||||
|
...-03-14-01-38-44.gh-issue-113171.VFnObz.rst | 9 ++
|
||||||
|
5 files changed, 187 insertions(+), 21 deletions(-)
|
||||||
|
create mode 100644 Misc/NEWS.d/next/Library/2024-03-14-01-38-44.gh-issue-113171.VFnObz.rst
|
||||||
|
|
||||||
|
diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst
|
||||||
|
index 5e21d5db2ed9c3..5944e33bb1b339 100644
|
||||||
|
--- a/Doc/library/ipaddress.rst
|
||||||
|
+++ b/Doc/library/ipaddress.rst
|
||||||
|
@@ -179,18 +179,53 @@ write code that handles both IP versions correctly. Address objects are
|
||||||
|
|
||||||
|
.. attribute:: is_private
|
||||||
|
|
||||||
|
- ``True`` if the address is allocated for private networks. See
|
||||||
|
+ ``True`` if the address is defined as not globally reachable by
|
||||||
|
iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
|
||||||
|
- (for IPv6).
|
||||||
|
+ (for IPv6) with the following exceptions:
|
||||||
|
+
|
||||||
|
+ * ``is_private`` is ``False`` for the shared address space (``100.64.0.0/10``)
|
||||||
|
+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
|
||||||
|
+ semantics of the underlying IPv4 addresses and the following condition holds
|
||||||
|
+ (see :attr:`IPv6Address.ipv4_mapped`)::
|
||||||
|
+
|
||||||
|
+ address.is_private == address.ipv4_mapped.is_private
|
||||||
|
+
|
||||||
|
+ ``is_private`` has value opposite to :attr:`is_global`, except for the shared address space
|
||||||
|
+ (``100.64.0.0/10`` range) where they are both ``False``.
|
||||||
|
+
|
||||||
|
+ .. versionchanged:: 3.8.20
|
||||||
|
+
|
||||||
|
+ Fixed some false positives and false negatives.
|
||||||
|
+
|
||||||
|
+ * ``192.0.0.0/24`` is considered private with the exception of ``192.0.0.9/32`` and
|
||||||
|
+ ``192.0.0.10/32`` (previously: only the ``192.0.0.0/29`` sub-range was considered private).
|
||||||
|
+ * ``64:ff9b:1::/48`` is considered private.
|
||||||
|
+ * ``2002::/16`` is considered private.
|
||||||
|
+ * There are exceptions within ``2001::/23`` (otherwise considered private): ``2001:1::1/128``,
|
||||||
|
+ ``2001:1::2/128``, ``2001:3::/32``, ``2001:4:112::/48``, ``2001:20::/28``, ``2001:30::/28``.
|
||||||
|
+ The exceptions are not considered private.
|
||||||
|
|
||||||
|
.. attribute:: is_global
|
||||||
|
|
||||||
|
- ``True`` if the address is allocated for public networks. See
|
||||||
|
+ ``True`` if the address is defined as globally reachable by
|
||||||
|
iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
|
||||||
|
- (for IPv6).
|
||||||
|
+ (for IPv6) with the following exception:
|
||||||
|
+
|
||||||
|
+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
|
||||||
|
+ semantics of the underlying IPv4 addresses and the following condition holds
|
||||||
|
+ (see :attr:`IPv6Address.ipv4_mapped`)::
|
||||||
|
+
|
||||||
|
+ address.is_global == address.ipv4_mapped.is_global
|
||||||
|
+
|
||||||
|
+ ``is_global`` has value opposite to :attr:`is_private`, except for the shared address space
|
||||||
|
+ (``100.64.0.0/10`` range) where they are both ``False``.
|
||||||
|
|
||||||
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
|
+ .. versionchanged:: 3.8.20
|
||||||
|
+
|
||||||
|
+ Fixed some false positives and false negatives, see :attr:`is_private` for details.
|
||||||
|
+
|
||||||
|
.. attribute:: is_unspecified
|
||||||
|
|
||||||
|
``True`` if the address is unspecified. See :RFC:`5735` (for IPv4)
|
||||||
|
diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst
|
||||||
|
index e5278da3f6a5be..de4dd856877543 100644
|
||||||
|
--- a/Doc/whatsnew/3.8.rst
|
||||||
|
+++ b/Doc/whatsnew/3.8.rst
|
||||||
|
@@ -2355,3 +2355,12 @@ tarfile
|
||||||
|
:exc:`DeprecationWarning`.
|
||||||
|
In Python 3.14, the default will switch to ``'data'``.
|
||||||
|
(Contributed by Petr Viktorin in :pep:`706`.)
|
||||||
|
+
|
||||||
|
+Notable changes in 3.8.20
|
||||||
|
+=========================
|
||||||
|
+
|
||||||
|
+ipaddress
|
||||||
|
+---------
|
||||||
|
+
|
||||||
|
+* Fixed ``is_global`` and ``is_private`` behavior in ``IPv4Address``,
|
||||||
|
+ ``IPv6Address``, ``IPv4Network`` and ``IPv6Network``.
|
||||||
|
diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py
|
||||||
|
index d351f07a5bd960..142c3b13b1617e 100644
|
||||||
|
--- a/Lib/ipaddress.py
|
||||||
|
+++ b/Lib/ipaddress.py
|
||||||
|
@@ -1275,18 +1275,41 @@ def is_reserved(self):
|
||||||
|
@property
|
||||||
|
@functools.lru_cache()
|
||||||
|
def is_private(self):
|
||||||
|
- """Test if this address is allocated for private networks.
|
||||||
|
+ """``True`` if the address is defined as not globally reachable by
|
||||||
|
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
|
||||||
|
+ (for IPv6) with the following exceptions:
|
||||||
|
|
||||||
|
- Returns:
|
||||||
|
- A boolean, True if the address is reserved per
|
||||||
|
- iana-ipv4-special-registry.
|
||||||
|
+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
|
||||||
|
+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
|
||||||
|
+ semantics of the underlying IPv4 addresses and the following condition holds
|
||||||
|
+ (see :attr:`IPv6Address.ipv4_mapped`)::
|
||||||
|
+
|
||||||
|
+ address.is_private == address.ipv4_mapped.is_private
|
||||||
|
|
||||||
|
+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
|
||||||
|
+ IPv4 range where they are both ``False``.
|
||||||
|
"""
|
||||||
|
- return any(self in net for net in self._constants._private_networks)
|
||||||
|
+ return (
|
||||||
|
+ any(self in net for net in self._constants._private_networks)
|
||||||
|
+ and all(self not in net for net in self._constants._private_networks_exceptions)
|
||||||
|
+ )
|
||||||
|
|
||||||
|
@property
|
||||||
|
@functools.lru_cache()
|
||||||
|
def is_global(self):
|
||||||
|
+ """``True`` if the address is defined as globally reachable by
|
||||||
|
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
|
||||||
|
+ (for IPv6) with the following exception:
|
||||||
|
+
|
||||||
|
+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
|
||||||
|
+ semantics of the underlying IPv4 addresses and the following condition holds
|
||||||
|
+ (see :attr:`IPv6Address.ipv4_mapped`)::
|
||||||
|
+
|
||||||
|
+ address.is_global == address.ipv4_mapped.is_global
|
||||||
|
+
|
||||||
|
+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
|
||||||
|
+ IPv4 range where they are both ``False``.
|
||||||
|
+ """
|
||||||
|
return self not in self._constants._public_network and not self.is_private
|
||||||
|
|
||||||
|
@property
|
||||||
|
@@ -1490,13 +1513,15 @@ class _IPv4Constants:
|
||||||
|
|
||||||
|
_public_network = IPv4Network('100.64.0.0/10')
|
||||||
|
|
||||||
|
+ # Not globally reachable address blocks listed on
|
||||||
|
+ # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
|
||||||
|
_private_networks = [
|
||||||
|
IPv4Network('0.0.0.0/8'),
|
||||||
|
IPv4Network('10.0.0.0/8'),
|
||||||
|
IPv4Network('127.0.0.0/8'),
|
||||||
|
IPv4Network('169.254.0.0/16'),
|
||||||
|
IPv4Network('172.16.0.0/12'),
|
||||||
|
- IPv4Network('192.0.0.0/29'),
|
||||||
|
+ IPv4Network('192.0.0.0/24'),
|
||||||
|
IPv4Network('192.0.0.170/31'),
|
||||||
|
IPv4Network('192.0.2.0/24'),
|
||||||
|
IPv4Network('192.168.0.0/16'),
|
||||||
|
@@ -1507,6 +1532,11 @@ class _IPv4Constants:
|
||||||
|
IPv4Network('255.255.255.255/32'),
|
||||||
|
]
|
||||||
|
|
||||||
|
+ _private_networks_exceptions = [
|
||||||
|
+ IPv4Network('192.0.0.9/32'),
|
||||||
|
+ IPv4Network('192.0.0.10/32'),
|
||||||
|
+ ]
|
||||||
|
+
|
||||||
|
_reserved_network = IPv4Network('240.0.0.0/4')
|
||||||
|
|
||||||
|
_unspecified_address = IPv4Address('0.0.0.0')
|
||||||
|
@@ -1897,23 +1927,42 @@ def is_site_local(self):
|
||||||
|
@property
|
||||||
|
@functools.lru_cache()
|
||||||
|
def is_private(self):
|
||||||
|
- """Test if this address is allocated for private networks.
|
||||||
|
+ """``True`` if the address is defined as not globally reachable by
|
||||||
|
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
|
||||||
|
+ (for IPv6) with the following exceptions:
|
||||||
|
|
||||||
|
- Returns:
|
||||||
|
- A boolean, True if the address is reserved per
|
||||||
|
- iana-ipv6-special-registry.
|
||||||
|
+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
|
||||||
|
+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
|
||||||
|
+ semantics of the underlying IPv4 addresses and the following condition holds
|
||||||
|
+ (see :attr:`IPv6Address.ipv4_mapped`)::
|
||||||
|
+
|
||||||
|
+ address.is_private == address.ipv4_mapped.is_private
|
||||||
|
|
||||||
|
+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
|
||||||
|
+ IPv4 range where they are both ``False``.
|
||||||
|
"""
|
||||||
|
- return any(self in net for net in self._constants._private_networks)
|
||||||
|
+ ipv4_mapped = self.ipv4_mapped
|
||||||
|
+ if ipv4_mapped is not None:
|
||||||
|
+ return ipv4_mapped.is_private
|
||||||
|
+ return (
|
||||||
|
+ any(self in net for net in self._constants._private_networks)
|
||||||
|
+ and all(self not in net for net in self._constants._private_networks_exceptions)
|
||||||
|
+ )
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_global(self):
|
||||||
|
- """Test if this address is allocated for public networks.
|
||||||
|
+ """``True`` if the address is defined as globally reachable by
|
||||||
|
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
|
||||||
|
+ (for IPv6) with the following exception:
|
||||||
|
|
||||||
|
- Returns:
|
||||||
|
- A boolean, true if the address is not reserved per
|
||||||
|
- iana-ipv6-special-registry.
|
||||||
|
+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
|
||||||
|
+ semantics of the underlying IPv4 addresses and the following condition holds
|
||||||
|
+ (see :attr:`IPv6Address.ipv4_mapped`)::
|
||||||
|
+
|
||||||
|
+ address.is_global == address.ipv4_mapped.is_global
|
||||||
|
|
||||||
|
+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
|
||||||
|
+ IPv4 range where they are both ``False``.
|
||||||
|
"""
|
||||||
|
return not self.is_private
|
||||||
|
|
||||||
|
@@ -2154,19 +2203,31 @@ class _IPv6Constants:
|
||||||
|
|
||||||
|
_multicast_network = IPv6Network('ff00::/8')
|
||||||
|
|
||||||
|
+ # Not globally reachable address blocks listed on
|
||||||
|
+ # https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
|
||||||
|
_private_networks = [
|
||||||
|
IPv6Network('::1/128'),
|
||||||
|
IPv6Network('::/128'),
|
||||||
|
IPv6Network('::ffff:0:0/96'),
|
||||||
|
+ IPv6Network('64:ff9b:1::/48'),
|
||||||
|
IPv6Network('100::/64'),
|
||||||
|
IPv6Network('2001::/23'),
|
||||||
|
- IPv6Network('2001:2::/48'),
|
||||||
|
IPv6Network('2001:db8::/32'),
|
||||||
|
- IPv6Network('2001:10::/28'),
|
||||||
|
+ # IANA says N/A, let's consider it not globally reachable to be safe
|
||||||
|
+ IPv6Network('2002::/16'),
|
||||||
|
IPv6Network('fc00::/7'),
|
||||||
|
IPv6Network('fe80::/10'),
|
||||||
|
]
|
||||||
|
|
||||||
|
+ _private_networks_exceptions = [
|
||||||
|
+ IPv6Network('2001:1::1/128'),
|
||||||
|
+ IPv6Network('2001:1::2/128'),
|
||||||
|
+ IPv6Network('2001:3::/32'),
|
||||||
|
+ IPv6Network('2001:4:112::/48'),
|
||||||
|
+ IPv6Network('2001:20::/28'),
|
||||||
|
+ IPv6Network('2001:30::/28'),
|
||||||
|
+ ]
|
||||||
|
+
|
||||||
|
_reserved_networks = [
|
||||||
|
IPv6Network('::/8'), IPv6Network('100::/8'),
|
||||||
|
IPv6Network('200::/7'), IPv6Network('400::/6'),
|
||||||
|
diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py
|
||||||
|
index 1297b8371d8583..46002111b3270a 100644
|
||||||
|
--- a/Lib/test/test_ipaddress.py
|
||||||
|
+++ b/Lib/test/test_ipaddress.py
|
||||||
|
@@ -1761,6 +1761,10 @@ def testReservedIpv4(self):
|
||||||
|
self.assertEqual(True, ipaddress.ip_address(
|
||||||
|
'172.31.255.255').is_private)
|
||||||
|
self.assertEqual(False, ipaddress.ip_address('172.32.0.0').is_private)
|
||||||
|
+ self.assertFalse(ipaddress.ip_address('192.0.0.0').is_global)
|
||||||
|
+ self.assertTrue(ipaddress.ip_address('192.0.0.9').is_global)
|
||||||
|
+ self.assertTrue(ipaddress.ip_address('192.0.0.10').is_global)
|
||||||
|
+ self.assertFalse(ipaddress.ip_address('192.0.0.255').is_global)
|
||||||
|
|
||||||
|
self.assertEqual(True,
|
||||||
|
ipaddress.ip_address('169.254.100.200').is_link_local)
|
||||||
|
@@ -1776,6 +1780,40 @@ def testReservedIpv4(self):
|
||||||
|
self.assertEqual(False, ipaddress.ip_address('128.0.0.0').is_loopback)
|
||||||
|
self.assertEqual(True, ipaddress.ip_network('0.0.0.0').is_unspecified)
|
||||||
|
|
||||||
|
+ def testPrivateNetworks(self):
|
||||||
|
+ self.assertEqual(False, ipaddress.ip_network("0.0.0.0/0").is_private)
|
||||||
|
+ self.assertEqual(False, ipaddress.ip_network("1.0.0.0/8").is_private)
|
||||||
|
+
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("0.0.0.0/8").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("10.0.0.0/8").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("127.0.0.0/8").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("169.254.0.0/16").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("172.16.0.0/12").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("192.0.0.0/29").is_private)
|
||||||
|
+ self.assertEqual(False, ipaddress.ip_network("192.0.0.9/32").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("192.0.0.170/31").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("192.0.2.0/24").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("192.168.0.0/16").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("198.18.0.0/15").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("198.51.100.0/24").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("203.0.113.0/24").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("240.0.0.0/4").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("255.255.255.255/32").is_private)
|
||||||
|
+
|
||||||
|
+ self.assertEqual(False, ipaddress.ip_network("::/0").is_private)
|
||||||
|
+ self.assertEqual(False, ipaddress.ip_network("::ff/128").is_private)
|
||||||
|
+
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("::1/128").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("::/128").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("::ffff:0:0/96").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("100::/64").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("2001:2::/48").is_private)
|
||||||
|
+ self.assertEqual(False, ipaddress.ip_network("2001:3::/48").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("2001:db8::/32").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("2001:10::/28").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("fc00::/7").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("fe80::/10").is_private)
|
||||||
|
+
|
||||||
|
def testReservedIpv6(self):
|
||||||
|
|
||||||
|
self.assertEqual(True, ipaddress.ip_network('ffff::').is_multicast)
|
||||||
|
@@ -1849,6 +1887,20 @@ def testReservedIpv6(self):
|
||||||
|
self.assertEqual(True, ipaddress.ip_address('0::0').is_unspecified)
|
||||||
|
self.assertEqual(False, ipaddress.ip_address('::1').is_unspecified)
|
||||||
|
|
||||||
|
+ self.assertFalse(ipaddress.ip_address('64:ff9b:1::').is_global)
|
||||||
|
+ self.assertFalse(ipaddress.ip_address('2001::').is_global)
|
||||||
|
+ self.assertTrue(ipaddress.ip_address('2001:1::1').is_global)
|
||||||
|
+ self.assertTrue(ipaddress.ip_address('2001:1::2').is_global)
|
||||||
|
+ self.assertFalse(ipaddress.ip_address('2001:2::').is_global)
|
||||||
|
+ self.assertTrue(ipaddress.ip_address('2001:3::').is_global)
|
||||||
|
+ self.assertFalse(ipaddress.ip_address('2001:4::').is_global)
|
||||||
|
+ self.assertTrue(ipaddress.ip_address('2001:4:112::').is_global)
|
||||||
|
+ self.assertFalse(ipaddress.ip_address('2001:10::').is_global)
|
||||||
|
+ self.assertTrue(ipaddress.ip_address('2001:20::').is_global)
|
||||||
|
+ self.assertTrue(ipaddress.ip_address('2001:30::').is_global)
|
||||||
|
+ self.assertFalse(ipaddress.ip_address('2001:40::').is_global)
|
||||||
|
+ self.assertFalse(ipaddress.ip_address('2002::').is_global)
|
||||||
|
+
|
||||||
|
# some generic IETF reserved addresses
|
||||||
|
self.assertEqual(True, ipaddress.ip_address('100::').is_reserved)
|
||||||
|
self.assertEqual(True, ipaddress.ip_network('4000::1/128').is_reserved)
|
||||||
|
diff --git a/Misc/NEWS.d/next/Library/2024-03-14-01-38-44.gh-issue-113171.VFnObz.rst b/Misc/NEWS.d/next/Library/2024-03-14-01-38-44.gh-issue-113171.VFnObz.rst
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000000000..f9a72473be4e2c
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Misc/NEWS.d/next/Library/2024-03-14-01-38-44.gh-issue-113171.VFnObz.rst
|
||||||
|
@@ -0,0 +1,9 @@
|
||||||
|
+Fixed various false positives and false negatives in
|
||||||
|
+
|
||||||
|
+* :attr:`ipaddress.IPv4Address.is_private` (see these docs for details)
|
||||||
|
+* :attr:`ipaddress.IPv4Address.is_global`
|
||||||
|
+* :attr:`ipaddress.IPv6Address.is_private`
|
||||||
|
+* :attr:`ipaddress.IPv6Address.is_global`
|
||||||
|
+
|
||||||
|
+Also in the corresponding :class:`ipaddress.IPv4Network` and :class:`ipaddress.IPv6Network`
|
||||||
|
+attributes.
|
||||||
|
|
||||||
|
From 2e92223a4298fbf18c1c7f853b6d883943c00c52 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Petr Viktorin <encukou@gmail.com>
|
||||||
|
Date: Wed, 24 Apr 2024 15:16:13 +0200
|
||||||
|
Subject: [PATCH 2/3] Adjust test for 3.10 semantics of is_private on networks
|
||||||
|
|
||||||
|
In 3.10 and below, is_private checks whether the network and broadcast
|
||||||
|
address are both private.
|
||||||
|
In later versions (where the test wss backported from), it checks
|
||||||
|
whether they both are in the same private network.
|
||||||
|
|
||||||
|
For 0.0.0.0/0, both 0.0.0.0 and 255.225.255.255 are private,
|
||||||
|
but one is in 0.0.0.0/8 ("This network") and the other in
|
||||||
|
255.255.255.255/32 ("Limited broadcast").
|
||||||
|
---
|
||||||
|
Lib/test/test_ipaddress.py | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py
|
||||||
|
index 46002111b3270a..fad40334f0d317 100644
|
||||||
|
--- a/Lib/test/test_ipaddress.py
|
||||||
|
+++ b/Lib/test/test_ipaddress.py
|
||||||
|
@@ -1781,7 +1781,7 @@ def testReservedIpv4(self):
|
||||||
|
self.assertEqual(True, ipaddress.ip_network('0.0.0.0').is_unspecified)
|
||||||
|
|
||||||
|
def testPrivateNetworks(self):
|
||||||
|
- self.assertEqual(False, ipaddress.ip_network("0.0.0.0/0").is_private)
|
||||||
|
+ self.assertEqual(True, ipaddress.ip_network("0.0.0.0/0").is_private)
|
||||||
|
self.assertEqual(False, ipaddress.ip_network("1.0.0.0/8").is_private)
|
||||||
|
|
||||||
|
self.assertEqual(True, ipaddress.ip_network("0.0.0.0/8").is_private)
|
||||||
|
|
||||||
|
From e366724f6e290b71ec49005079e8472c3cac2594 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Petr Viktorin <encukou@gmail.com>
|
||||||
|
Date: Wed, 1 May 2024 15:29:13 +0200
|
||||||
|
Subject: [PATCH 3/3] Add IPv6 addresses to suspignore.csv
|
||||||
|
|
||||||
|
That's a lot of semicolons!
|
||||||
|
---
|
||||||
|
Doc/tools/susp-ignored.csv | 8 ++++++++
|
||||||
|
1 file changed, 8 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv
|
||||||
|
index dd6aa38d72adcc..fadeab3f98f2d7 100644
|
||||||
|
--- a/Doc/tools/susp-ignored.csv
|
||||||
|
+++ b/Doc/tools/susp-ignored.csv
|
||||||
|
@@ -158,6 +158,14 @@ library/ipaddress,,:db00,2001:db00::0/24
|
||||||
|
library/ipaddress,,::,2001:db00::0/24
|
||||||
|
library/ipaddress,,:db00,2001:db00::0/ffff:ff00::
|
||||||
|
library/ipaddress,,::,2001:db00::0/ffff:ff00::
|
||||||
|
+library/ipaddress,,:ff9b,64:ff9b:1::/48
|
||||||
|
+library/ipaddress,,::,64:ff9b:1::/48
|
||||||
|
+library/ipaddress,,::,2001::
|
||||||
|
+library/ipaddress,,::,2001:1::
|
||||||
|
+library/ipaddress,,::,2001:3::
|
||||||
|
+library/ipaddress,,::,2001:4:112::
|
||||||
|
+library/ipaddress,,::,2001:20::
|
||||||
|
+library/ipaddress,,::,2001:30::
|
||||||
|
library/itertools,,:step,elements from seq[start:stop:step]
|
||||||
|
library/itertools,,:stop,elements from seq[start:stop:step]
|
||||||
|
library/logging.handlers,,:port,host:port
|
236
F00102-lib64.patch
Normal file
236
F00102-lib64.patch
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
From 81904771db8b112c8617a111e989b68e55af7a9c Mon Sep 17 00:00:00 2001
|
||||||
|
From: David Malcolm <dmalcolm@redhat.com>
|
||||||
|
Date: Wed, 13 Jan 2010 21:25:18 +0000
|
||||||
|
Subject: [PATCH] 00102: Change the various install paths to use /usr/lib64/
|
||||||
|
instead or /usr/lib/
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
Only used when "%{_lib}" == "lib64".
|
||||||
|
|
||||||
|
Co-authored-by: David Malcolm <dmalcolm@redhat.com>
|
||||||
|
Co-authored-by: Thomas Spura <tomspur@fedoraproject.org>
|
||||||
|
Co-authored-by: Slavek Kabrda <bkabrda@redhat.com>
|
||||||
|
Co-authored-by: Matej Stuchlik <mstuchli@redhat.com>
|
||||||
|
Co-authored-by: Tomas Orsava <torsava@redhat.com>
|
||||||
|
Co-authored-by: Charalampos Stratakis <cstratak@redhat.com>
|
||||||
|
Co-authored-by: Petr Viktorin <pviktori@redhat.com>
|
||||||
|
Co-authored-by: Miro Hrončok <miro@hroncok.cz>
|
||||||
|
Co-authored-by: Iryna Shcherbina <shcherbina.iryna@gmail.com>
|
||||||
|
---
|
||||||
|
Lib/distutils/command/install.py | 4 ++--
|
||||||
|
Lib/distutils/sysconfig.py | 6 +++++-
|
||||||
|
Lib/distutils/tests/test_install.py | 3 ++-
|
||||||
|
Lib/site.py | 4 ++++
|
||||||
|
Lib/sysconfig.py | 12 ++++++------
|
||||||
|
Lib/test/test_site.py | 4 ++--
|
||||||
|
Makefile.pre.in | 2 +-
|
||||||
|
Modules/getpath.c | 6 +++---
|
||||||
|
configure | 4 ++--
|
||||||
|
configure.ac | 4 ++--
|
||||||
|
setup.py | 6 +++---
|
||||||
|
11 files changed, 32 insertions(+), 23 deletions(-)
|
||||||
|
|
||||||
|
--- a/Lib/distutils/command/install.py
|
||||||
|
+++ b/Lib/distutils/command/install.py
|
||||||
|
@@ -30,14 +30,14 @@ WINDOWS_SCHEME = {
|
||||||
|
INSTALL_SCHEMES = {
|
||||||
|
'unix_prefix': {
|
||||||
|
'purelib': '$base/lib/python$py_version_short/site-packages',
|
||||||
|
- 'platlib': '$platbase/lib/python$py_version_short/site-packages',
|
||||||
|
+ 'platlib': '$platbase/lib64/python$py_version_short/site-packages',
|
||||||
|
'headers': '$base/include/python$py_version_short$abiflags/$dist_name',
|
||||||
|
'scripts': '$base/bin',
|
||||||
|
'data' : '$base',
|
||||||
|
},
|
||||||
|
'unix_home': {
|
||||||
|
'purelib': '$base/lib/python',
|
||||||
|
- 'platlib': '$base/lib/python',
|
||||||
|
+ 'platlib': '$base/lib64/python',
|
||||||
|
'headers': '$base/include/python/$dist_name',
|
||||||
|
'scripts': '$base/bin',
|
||||||
|
'data' : '$base',
|
||||||
|
--- a/Lib/distutils/sysconfig.py
|
||||||
|
+++ b/Lib/distutils/sysconfig.py
|
||||||
|
@@ -146,8 +146,12 @@ def get_python_lib(plat_specific=0, stan
|
||||||
|
prefix = plat_specific and EXEC_PREFIX or PREFIX
|
||||||
|
|
||||||
|
if os.name == "posix":
|
||||||
|
+ if plat_specific or standard_lib:
|
||||||
|
+ lib = "lib64"
|
||||||
|
+ else:
|
||||||
|
+ lib = "lib"
|
||||||
|
libpython = os.path.join(prefix,
|
||||||
|
- "lib", "python" + get_python_version())
|
||||||
|
+ lib, "python" + get_python_version())
|
||||||
|
if standard_lib:
|
||||||
|
return libpython
|
||||||
|
else:
|
||||||
|
--- a/Lib/distutils/tests/test_install.py
|
||||||
|
+++ b/Lib/distutils/tests/test_install.py
|
||||||
|
@@ -57,8 +57,9 @@ class InstallTestCase(support.TempdirMan
|
||||||
|
self.assertEqual(got, expected)
|
||||||
|
|
||||||
|
libdir = os.path.join(destination, "lib", "python")
|
||||||
|
+ platlibdir = os.path.join(destination, "lib", "python")
|
||||||
|
check_path(cmd.install_lib, libdir)
|
||||||
|
- check_path(cmd.install_platlib, libdir)
|
||||||
|
+ check_path(cmd.install_platlib, platlibdir)
|
||||||
|
check_path(cmd.install_purelib, libdir)
|
||||||
|
check_path(cmd.install_headers,
|
||||||
|
os.path.join(destination, "include", "python", "foopkg"))
|
||||||
|
--- a/Lib/site.py
|
||||||
|
+++ b/Lib/site.py
|
||||||
|
@@ -344,11 +344,15 @@ def getsitepackages(prefixes=None):
|
||||||
|
seen.add(prefix)
|
||||||
|
|
||||||
|
if os.sep == '/':
|
||||||
|
+ sitepackages.append(os.path.join(prefix, "lib64",
|
||||||
|
+ "python" + sys.version[:3],
|
||||||
|
+ "site-packages"))
|
||||||
|
sitepackages.append(os.path.join(prefix, "lib",
|
||||||
|
"python%d.%d" % sys.version_info[:2],
|
||||||
|
"site-packages"))
|
||||||
|
else:
|
||||||
|
sitepackages.append(prefix)
|
||||||
|
+ sitepackages.append(os.path.join(prefix, "lib64", "site-packages"))
|
||||||
|
sitepackages.append(os.path.join(prefix, "lib", "site-packages"))
|
||||||
|
return sitepackages
|
||||||
|
|
||||||
|
--- a/Lib/sysconfig.py
|
||||||
|
+++ b/Lib/sysconfig.py
|
||||||
|
@@ -25,10 +25,10 @@ _ALWAYS_STR = {
|
||||||
|
|
||||||
|
_INSTALL_SCHEMES = {
|
||||||
|
'posix_prefix': {
|
||||||
|
- 'stdlib': '{installed_base}/lib/python{py_version_short}',
|
||||||
|
- 'platstdlib': '{platbase}/lib/python{py_version_short}',
|
||||||
|
+ 'stdlib': '{installed_base}/lib64/python{py_version_short}',
|
||||||
|
+ 'platstdlib': '{platbase}/lib64/python{py_version_short}',
|
||||||
|
'purelib': '{base}/lib/python{py_version_short}/site-packages',
|
||||||
|
- 'platlib': '{platbase}/lib/python{py_version_short}/site-packages',
|
||||||
|
+ 'platlib': '{platbase}/lib64/python{py_version_short}/site-packages',
|
||||||
|
'include':
|
||||||
|
'{installed_base}/include/python{py_version_short}{abiflags}',
|
||||||
|
'platinclude':
|
||||||
|
@@ -67,10 +67,10 @@ _INSTALL_SCHEMES = {
|
||||||
|
'data': '{userbase}',
|
||||||
|
},
|
||||||
|
'posix_user': {
|
||||||
|
- 'stdlib': '{userbase}/lib/python{py_version_short}',
|
||||||
|
- 'platstdlib': '{userbase}/lib/python{py_version_short}',
|
||||||
|
+ 'stdlib': '{userbase}/lib64/python{py_version_short}',
|
||||||
|
+ 'platstdlib': '{userbase}/lib64/python{py_version_short}',
|
||||||
|
'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
|
||||||
|
- 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
|
||||||
|
+ 'platlib': '{userbase}/lib64/python{py_version_short}/site-packages',
|
||||||
|
'include': '{userbase}/include/python{py_version_short}',
|
||||||
|
'scripts': '{userbase}/bin',
|
||||||
|
'data': '{userbase}',
|
||||||
|
--- a/Lib/test/test_site.py
|
||||||
|
+++ b/Lib/test/test_site.py
|
||||||
|
@@ -307,8 +307,8 @@ class HelperFunctionsTests(unittest.Test
|
||||||
|
dirs = site.getsitepackages()
|
||||||
|
if os.sep == '/':
|
||||||
|
# OS X, Linux, FreeBSD, etc
|
||||||
|
- self.assertEqual(len(dirs), 1)
|
||||||
|
- wanted = os.path.join('xoxo', 'lib',
|
||||||
|
+ self.assertEqual(len(dirs), 2)
|
||||||
|
+ wanted = os.path.join('xoxo', 'lib64',
|
||||||
|
'python%d.%d' % sys.version_info[:2],
|
||||||
|
'site-packages')
|
||||||
|
self.assertEqual(dirs[0], wanted)
|
||||||
|
--- a/Makefile.pre.in
|
||||||
|
+++ b/Makefile.pre.in
|
||||||
|
@@ -143,7 +143,7 @@ LIBDIR= @libdir@
|
||||||
|
MANDIR= @mandir@
|
||||||
|
INCLUDEDIR= @includedir@
|
||||||
|
CONFINCLUDEDIR= $(exec_prefix)/include
|
||||||
|
-SCRIPTDIR= $(prefix)/lib
|
||||||
|
+SCRIPTDIR= $(prefix)/lib64
|
||||||
|
ABIFLAGS= @ABIFLAGS@
|
||||||
|
|
||||||
|
# Detailed destination directories
|
||||||
|
--- a/Modules/getpath.c
|
||||||
|
+++ b/Modules/getpath.c
|
||||||
|
@@ -730,7 +730,7 @@ calculate_exec_prefix(PyCalculatePath *c
|
||||||
|
if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
|
||||||
|
return PATHLEN_ERR();
|
||||||
|
}
|
||||||
|
- status = joinpath(exec_prefix, L"lib/lib-dynload", exec_prefix_len);
|
||||||
|
+ status = joinpath(exec_prefix, L"lib64/lib-dynload", exec_prefix_len);
|
||||||
|
if (_PyStatus_EXCEPTION(status)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
@@ -1063,7 +1063,7 @@ calculate_zip_path(PyCalculatePath *calc
|
||||||
|
return PATHLEN_ERR();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- status = joinpath(zip_path, L"lib/python00.zip", zip_path_len);
|
||||||
|
+ status = joinpath(zip_path, L"lib64/python00.zip", zip_path_len);
|
||||||
|
if (_PyStatus_EXCEPTION(status)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
@@ -1193,7 +1193,7 @@ calculate_init(PyCalculatePath *calculat
|
||||||
|
if (!calculate->exec_prefix) {
|
||||||
|
return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
|
||||||
|
}
|
||||||
|
- calculate->lib_python = Py_DecodeLocale("lib/python" VERSION, &len);
|
||||||
|
+ calculate->lib_python = Py_DecodeLocale("lib64/python" VERSION, &len);
|
||||||
|
if (!calculate->lib_python) {
|
||||||
|
return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
|
||||||
|
}
|
||||||
|
--- a/configure
|
||||||
|
+++ b/configure
|
||||||
|
@@ -15276,9 +15276,9 @@ fi
|
||||||
|
|
||||||
|
|
||||||
|
if test x$PLATFORM_TRIPLET = x; then
|
||||||
|
- LIBPL='$(prefix)'"/lib/python${VERSION}/config-${LDVERSION}"
|
||||||
|
+ LIBPL='$(prefix)'"/lib64/python${VERSION}/config-${LDVERSION}"
|
||||||
|
else
|
||||||
|
- LIBPL='$(prefix)'"/lib/python${VERSION}/config-${LDVERSION}-${PLATFORM_TRIPLET}"
|
||||||
|
+ LIBPL='$(prefix)'"/lib64/python${VERSION}/config-${LDVERSION}-${PLATFORM_TRIPLET}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -4722,9 +4722,9 @@ fi
|
||||||
|
dnl define LIBPL after ABIFLAGS and LDVERSION is defined.
|
||||||
|
AC_SUBST(PY_ENABLE_SHARED)
|
||||||
|
if test x$PLATFORM_TRIPLET = x; then
|
||||||
|
- LIBPL='$(prefix)'"/lib/python${VERSION}/config-${LDVERSION}"
|
||||||
|
+ LIBPL='$(prefix)'"/lib64/python${VERSION}/config-${LDVERSION}"
|
||||||
|
else
|
||||||
|
- LIBPL='$(prefix)'"/lib/python${VERSION}/config-${LDVERSION}-${PLATFORM_TRIPLET}"
|
||||||
|
+ LIBPL='$(prefix)'"/lib64/python${VERSION}/config-${LDVERSION}-${PLATFORM_TRIPLET}"
|
||||||
|
fi
|
||||||
|
AC_SUBST(LIBPL)
|
||||||
|
|
||||||
|
--- a/setup.py
|
||||||
|
+++ b/setup.py
|
||||||
|
@@ -634,7 +634,7 @@ class PyBuildExt(build_ext):
|
||||||
|
# directories (i.e. '.' and 'Include') must be first. See issue
|
||||||
|
# 10520.
|
||||||
|
if not CROSS_COMPILING:
|
||||||
|
- add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
|
||||||
|
+ add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib64')
|
||||||
|
add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
|
||||||
|
# only change this for cross builds for 3.3, issues on Mageia
|
||||||
|
if CROSS_COMPILING:
|
||||||
|
@@ -938,11 +938,11 @@ class PyBuildExt(build_ext):
|
||||||
|
elif curses_library:
|
||||||
|
readline_libs.append(curses_library)
|
||||||
|
elif self.compiler.find_library_file(self.lib_dirs +
|
||||||
|
- ['/usr/lib/termcap'],
|
||||||
|
+ ['/usr/lib64/termcap'],
|
||||||
|
'termcap'):
|
||||||
|
readline_libs.append('termcap')
|
||||||
|
self.add(Extension('readline', ['readline.c'],
|
||||||
|
- library_dirs=['/usr/lib/termcap'],
|
||||||
|
+ library_dirs=['/usr/lib64/termcap'],
|
||||||
|
extra_link_args=readline_extra_link_args,
|
||||||
|
libraries=readline_libs))
|
||||||
|
else:
|
57
F00251-change-user-install-location.patch
Normal file
57
F00251-change-user-install-location.patch
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
From 910f38d9768d39d4d31426743ae4081ed1ab66b6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michal Cyprian <m.cyprian@gmail.com>
|
||||||
|
Date: Mon, 26 Jun 2017 16:32:56 +0200
|
||||||
|
Subject: [PATCH] 00251: Change user install location
|
||||||
|
|
||||||
|
Set values of prefix and exec_prefix in distutils install command
|
||||||
|
to /usr/local if executable is /usr/bin/python* and RPM build
|
||||||
|
is not detected to make pip and distutils install into separate location.
|
||||||
|
|
||||||
|
Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
||||||
|
---
|
||||||
|
Lib/distutils/command/install.py | 15 +++++++++++++--
|
||||||
|
Lib/site.py | 9 ++++++++-
|
||||||
|
2 files changed, 21 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
--- a/Lib/distutils/command/install.py
|
||||||
|
+++ b/Lib/distutils/command/install.py
|
||||||
|
@@ -418,8 +418,19 @@ class install(Command):
|
||||||
|
raise DistutilsOptionError(
|
||||||
|
"must not supply exec-prefix without prefix")
|
||||||
|
|
||||||
|
- self.prefix = os.path.normpath(sys.prefix)
|
||||||
|
- self.exec_prefix = os.path.normpath(sys.exec_prefix)
|
||||||
|
+ # self.prefix is set to sys.prefix + /local/
|
||||||
|
+ # if neither RPM build nor virtual environment is
|
||||||
|
+ # detected to make pip and distutils install packages
|
||||||
|
+ # into the separate location.
|
||||||
|
+ if (not (hasattr(sys, 'real_prefix') or
|
||||||
|
+ sys.prefix != sys.base_prefix) and
|
||||||
|
+ 'RPM_BUILD_ROOT' not in os.environ):
|
||||||
|
+ addition = "/local"
|
||||||
|
+ else:
|
||||||
|
+ addition = ""
|
||||||
|
+
|
||||||
|
+ self.prefix = os.path.normpath(sys.prefix) + addition
|
||||||
|
+ self.exec_prefix = os.path.normpath(sys.exec_prefix) + addition
|
||||||
|
|
||||||
|
else:
|
||||||
|
if self.exec_prefix is None:
|
||||||
|
--- a/Lib/site.py
|
||||||
|
+++ b/Lib/site.py
|
||||||
|
@@ -357,7 +357,14 @@ def getsitepackages(prefixes=None):
|
||||||
|
return sitepackages
|
||||||
|
|
||||||
|
def addsitepackages(known_paths, prefixes=None):
|
||||||
|
- """Add site-packages to sys.path"""
|
||||||
|
+ """Add site-packages to sys.path
|
||||||
|
+
|
||||||
|
+ '/usr/local' is included in PREFIXES if RPM build is not detected
|
||||||
|
+ to make packages installed into this location visible.
|
||||||
|
+
|
||||||
|
+ """
|
||||||
|
+ if ENABLE_USER_SITE and 'RPM_BUILD_ROOT' not in os.environ:
|
||||||
|
+ PREFIXES.insert(0, "/usr/local")
|
||||||
|
for sitedir in getsitepackages(prefixes):
|
||||||
|
if os.path.isdir(sitedir):
|
||||||
|
addsitedir(sitedir, known_paths)
|
26
PACKAGING-NOTES
Normal file
26
PACKAGING-NOTES
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Notes for packagers of Python3
|
||||||
|
==============================
|
||||||
|
|
||||||
|
0. Faster build turnaround
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
By default, python builds with profile-guided optimization. This needs
|
||||||
|
an additional run of the test suite and it is generally slow.
|
||||||
|
PGO build takes around 50 minutes.
|
||||||
|
|
||||||
|
For development, use "--without profileopt" option to disable PGO. This
|
||||||
|
shortens the build time to ~5 minutes including test suite.
|
||||||
|
|
||||||
|
1. import_failed.map
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
This is a mechanism installed as part of python3-base, that places shim modules
|
||||||
|
on python's path (through a generated zzzz-import-failed-hooks.pth file, so that
|
||||||
|
it is imported as much at the end as makes sense; and an _import_failed subdir
|
||||||
|
of /usr/lib/pythonX.Y). Then when the user tries to import a module that is part
|
||||||
|
of a subpackage, the ImportError will contain a helpful message telling them
|
||||||
|
which missing subpackage to install.
|
||||||
|
|
||||||
|
This can sometimes cause problems on non-standard configurations, if the pth
|
||||||
|
gets included too early (for instance if you are using a script to include all
|
||||||
|
pths by hand in some strange order). Just something to look out for.
|
3
Python-3.8.19.tar.xz
Normal file
3
Python-3.8.19.tar.xz
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:d2807ac69f69b84fd46a0b93bbd02a4fa48d3e70f4b2835ff0f72a2885040076
|
||||||
|
size 18975156
|
16
Python-3.8.19.tar.xz.asc
Normal file
16
Python-3.8.19.tar.xz.asc
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
-----BEGIN PGP SIGNATURE-----
|
||||||
|
|
||||||
|
iQIzBAABCgAdFiEE4/8oOcBIslwITevpsmmV4xAlBWgFAmX5t/gACgkQsmmV4xAl
|
||||||
|
BWgW0RAAkQYR6L3LNvuAg3OS/wD6Kouv3CnXeAwYY/BHglsHawtz+gM4jZRK8fIo
|
||||||
|
vEKBk6uoZBvXX1yJR+cxLZOxb9K/X7zYJXyBxRav8veBzXePTVhJBNSS/ckE0ARN
|
||||||
|
bD8M2P/7byMlm616aNNE1hrIIaxNoX8/yTEK3DmISQonc8vCW6ygIXm3Vw/6rqG8
|
||||||
|
n16MGG2r4dNEI+pEs8LPj8/VBaHHkbyvK9y2DQ8ywBqsaE459bN4HdzTkMxh28s0
|
||||||
|
scDl33PwTabFgVUTXILs+vBNnHc6ylo6gEd6fAe7Epec5wnvexKykel9ZtidxHwB
|
||||||
|
KQl2YKErJGF97T1Aj/Cru82jBYS/YS2QVy2cX0sYhiTgOXsvB7vOViFESR3IlSEL
|
||||||
|
aQv+f+lBXZp8T4MbDuzz2H7dqNY0sYqmTcqJU9r4H+RGLw43PHLSRVfIDPiaheA+
|
||||||
|
n1ZYzzgfm2uucO+iIpDwAOvTWznj4YcFwX116fn2kJYLtJeI58wVIbtMTDCl/l9U
|
||||||
|
hNY+b5L5JsHlyoRSjDwAtQVBm3fS0YqV4OhWglhvvuEdobRK+F3+hmHvo18YxZyl
|
||||||
|
WXLBUwZy9LQoEyuc1YFemWYw7g3u1ru8WTCFtPm91OeErkKq3QuqwiCjROgUmN9D
|
||||||
|
xUypHTocPhkdF1yEVqG+HMDin9Rw+l2KMgFt5XLNYFvAycGlsk4=
|
||||||
|
=Uo2Y
|
||||||
|
-----END PGP SIGNATURE-----
|
43
README.SUSE
Normal file
43
README.SUSE
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
Python 3 in SUSE
|
||||||
|
==============
|
||||||
|
|
||||||
|
* Subpackages *
|
||||||
|
|
||||||
|
Python 3 is split into several subpackages, based on external dependencies.
|
||||||
|
The main package 'python3' has soft dependencies on all subpackages needed to
|
||||||
|
assemble the standard library; however, these might not all be installed by default.
|
||||||
|
|
||||||
|
If you attempt to import a module that is currently not installed, an ImportError is thrown,
|
||||||
|
with instructions to install the missing subpackage. Installing the subpackage might result
|
||||||
|
in installing libraries that the subpackage requires to function.
|
||||||
|
|
||||||
|
|
||||||
|
* ensurepip *
|
||||||
|
|
||||||
|
The 'ensurepip' module from Python 3 standard library (PEP 453) is supposed to deploy
|
||||||
|
a bundled copy of the pip installer. This makes no sense in a managed distribution like SUSE.
|
||||||
|
Instead, you need to install package 'python3-pip'. Usually this will be installed automatically
|
||||||
|
with 'python3'.
|
||||||
|
|
||||||
|
Using 'ensurepip' when pip is not installed will result in an ImportError with instructions
|
||||||
|
to install 'python3-pip'.
|
||||||
|
|
||||||
|
|
||||||
|
* Documentation *
|
||||||
|
|
||||||
|
You can find documentation in seprarate packages: python3-doc and
|
||||||
|
python3-doc-pdf. These contan following documents:
|
||||||
|
|
||||||
|
Tutorial, What's New in Python, Global Module Index, Library Reference,
|
||||||
|
Macintosh Module Reference, Installing Python Modules, Distributing Python
|
||||||
|
Modules, Language Reference, Extending and Embedding, Python/C API,
|
||||||
|
Documenting Python
|
||||||
|
|
||||||
|
The python3-doc package constains many text files from source tarball.
|
||||||
|
|
||||||
|
|
||||||
|
* Interactive mode *
|
||||||
|
|
||||||
|
Interactive mode is by default enhanced with of history and command completion.
|
||||||
|
If you don't like these features, you can unset the PYTHONSTARTUP variable
|
||||||
|
in your .profile or disable it system wide in /etc/profile.d/python.sh.
|
411
SUSE-FEDORA-multilib.patch
Normal file
411
SUSE-FEDORA-multilib.patch
Normal file
@ -0,0 +1,411 @@
|
|||||||
|
---
|
||||||
|
Lib/distutils/command/install.py | 18 +++++++++---------
|
||||||
|
Lib/distutils/sysconfig.py | 7 ++-----
|
||||||
|
Lib/site.py | 19 +++++++++----------
|
||||||
|
Lib/sysconfig.py | 12 ++++++------
|
||||||
|
Lib/test/test_embed.py | 10 +++++++---
|
||||||
|
Lib/test/test_site.py | 7 +++++--
|
||||||
|
Lib/test/test_sysconfig.py | 14 +++++++++++++-
|
||||||
|
Makefile.pre.in | 6 +++++-
|
||||||
|
Modules/getpath.c | 24 ++++++++++++------------
|
||||||
|
configure | 4 ++--
|
||||||
|
configure.ac | 18 ++++++++++++++++--
|
||||||
|
setup.py | 6 +++---
|
||||||
|
12 files changed, 89 insertions(+), 56 deletions(-)
|
||||||
|
|
||||||
|
--- a/Lib/distutils/command/install.py
|
||||||
|
+++ b/Lib/distutils/command/install.py
|
||||||
|
@@ -30,14 +30,14 @@ WINDOWS_SCHEME = {
|
||||||
|
INSTALL_SCHEMES = {
|
||||||
|
'unix_prefix': {
|
||||||
|
'purelib': '$base/lib/python$py_version_short/site-packages',
|
||||||
|
- 'platlib': '$platbase/lib64/python$py_version_short/site-packages',
|
||||||
|
+ 'platlib': '$platbase/$platsubdir/python$py_version_short/site-packages',
|
||||||
|
'headers': '$base/include/python$py_version_short$abiflags/$dist_name',
|
||||||
|
'scripts': '$base/bin',
|
||||||
|
'data' : '$base',
|
||||||
|
},
|
||||||
|
'unix_home': {
|
||||||
|
'purelib': '$base/lib/python',
|
||||||
|
- 'platlib': '$base/lib64/python',
|
||||||
|
+ 'platlib': '$base/lib/python',
|
||||||
|
'headers': '$base/include/python/$dist_name',
|
||||||
|
'scripts': '$base/bin',
|
||||||
|
'data' : '$base',
|
||||||
|
@@ -281,7 +281,7 @@ class install(Command):
|
||||||
|
# about needing recursive variable expansion (shudder).
|
||||||
|
|
||||||
|
py_version = sys.version.split()[0]
|
||||||
|
- (prefix, exec_prefix) = get_config_vars('prefix', 'exec_prefix')
|
||||||
|
+ (prefix, exec_prefix, platsubdir) = get_config_vars('prefix', 'exec_prefix', 'platsubdir')
|
||||||
|
try:
|
||||||
|
abiflags = sys.abiflags
|
||||||
|
except AttributeError:
|
||||||
|
@@ -298,6 +298,7 @@ class install(Command):
|
||||||
|
'sys_exec_prefix': exec_prefix,
|
||||||
|
'exec_prefix': exec_prefix,
|
||||||
|
'abiflags': abiflags,
|
||||||
|
+ 'platsubdir': platsubdir,
|
||||||
|
}
|
||||||
|
|
||||||
|
if HAS_USER_SITE:
|
||||||
|
@@ -419,12 +420,11 @@ class install(Command):
|
||||||
|
"must not supply exec-prefix without prefix")
|
||||||
|
|
||||||
|
# self.prefix is set to sys.prefix + /local/
|
||||||
|
- # if neither RPM build nor virtual environment is
|
||||||
|
- # detected to make pip and distutils install packages
|
||||||
|
- # into the separate location.
|
||||||
|
- if (not (hasattr(sys, 'real_prefix') or
|
||||||
|
- sys.prefix != sys.base_prefix) and
|
||||||
|
- 'RPM_BUILD_ROOT' not in os.environ):
|
||||||
|
+ # if the executable is /usr/bin/python* and RPM build
|
||||||
|
+ # is not detected to make pip and distutils install into
|
||||||
|
+ # the separate location.
|
||||||
|
+ if (sys.executable.startswith("/usr/bin/python")
|
||||||
|
+ and 'RPM_BUILD_ROOT' not in os.environ):
|
||||||
|
addition = "/local"
|
||||||
|
else:
|
||||||
|
addition = ""
|
||||||
|
--- a/Lib/distutils/sysconfig.py
|
||||||
|
+++ b/Lib/distutils/sysconfig.py
|
||||||
|
@@ -146,12 +146,9 @@ def get_python_lib(plat_specific=0, stan
|
||||||
|
prefix = plat_specific and EXEC_PREFIX or PREFIX
|
||||||
|
|
||||||
|
if os.name == "posix":
|
||||||
|
- if plat_specific or standard_lib:
|
||||||
|
- lib = "lib64"
|
||||||
|
- else:
|
||||||
|
- lib = "lib"
|
||||||
|
+ libdir = plat_specific and get_config_var("platsubdir") or "lib"
|
||||||
|
libpython = os.path.join(prefix,
|
||||||
|
- lib, "python" + get_python_version())
|
||||||
|
+ libdir, "python" + get_python_version())
|
||||||
|
if standard_lib:
|
||||||
|
return libpython
|
||||||
|
else:
|
||||||
|
--- a/Lib/site.py
|
||||||
|
+++ b/Lib/site.py
|
||||||
|
@@ -344,12 +344,18 @@ def getsitepackages(prefixes=None):
|
||||||
|
seen.add(prefix)
|
||||||
|
|
||||||
|
if os.sep == '/':
|
||||||
|
- sitepackages.append(os.path.join(prefix, "lib64",
|
||||||
|
+ from sysconfig import get_config_var
|
||||||
|
+ platsubdir = get_config_var("platsubdir")
|
||||||
|
+ sitepackages.append(os.path.join(prefix, platsubdir,
|
||||||
|
"python" + sys.version[:3],
|
||||||
|
"site-packages"))
|
||||||
|
- sitepackages.append(os.path.join(prefix, "lib",
|
||||||
|
+ sitepackages.append(os.path.join(prefix, platsubdir,
|
||||||
|
"python%d.%d" % sys.version_info[:2],
|
||||||
|
"site-packages"))
|
||||||
|
+ if platsubdir != "lib":
|
||||||
|
+ sitepackages.append(os.path.join(prefix, "lib",
|
||||||
|
+ "python%d.%d" % sys.version_info[:2],
|
||||||
|
+ "site-packages"))
|
||||||
|
else:
|
||||||
|
sitepackages.append(prefix)
|
||||||
|
sitepackages.append(os.path.join(prefix, "lib64", "site-packages"))
|
||||||
|
@@ -357,14 +363,7 @@ def getsitepackages(prefixes=None):
|
||||||
|
return sitepackages
|
||||||
|
|
||||||
|
def addsitepackages(known_paths, prefixes=None):
|
||||||
|
- """Add site-packages to sys.path
|
||||||
|
-
|
||||||
|
- '/usr/local' is included in PREFIXES if RPM build is not detected
|
||||||
|
- to make packages installed into this location visible.
|
||||||
|
-
|
||||||
|
- """
|
||||||
|
- if ENABLE_USER_SITE and 'RPM_BUILD_ROOT' not in os.environ:
|
||||||
|
- PREFIXES.insert(0, "/usr/local")
|
||||||
|
+ """Add site-packages to sys.path"""
|
||||||
|
for sitedir in getsitepackages(prefixes):
|
||||||
|
if os.path.isdir(sitedir):
|
||||||
|
addsitedir(sitedir, known_paths)
|
||||||
|
--- a/Lib/sysconfig.py
|
||||||
|
+++ b/Lib/sysconfig.py
|
||||||
|
@@ -25,10 +25,10 @@ _ALWAYS_STR = {
|
||||||
|
|
||||||
|
_INSTALL_SCHEMES = {
|
||||||
|
'posix_prefix': {
|
||||||
|
- 'stdlib': '{installed_base}/lib64/python{py_version_short}',
|
||||||
|
- 'platstdlib': '{platbase}/lib64/python{py_version_short}',
|
||||||
|
+ 'stdlib': '{installed_base}/{platsubdir}/python{py_version_short}',
|
||||||
|
+ 'platstdlib': '{platbase}/{platsubdir}/python{py_version_short}',
|
||||||
|
'purelib': '{base}/lib/python{py_version_short}/site-packages',
|
||||||
|
- 'platlib': '{platbase}/lib64/python{py_version_short}/site-packages',
|
||||||
|
+ 'platlib': '{platbase}/{platsubdir}/python{py_version_short}/site-packages',
|
||||||
|
'include':
|
||||||
|
'{installed_base}/include/python{py_version_short}{abiflags}',
|
||||||
|
'platinclude':
|
||||||
|
@@ -67,10 +67,10 @@ _INSTALL_SCHEMES = {
|
||||||
|
'data': '{userbase}',
|
||||||
|
},
|
||||||
|
'posix_user': {
|
||||||
|
- 'stdlib': '{userbase}/lib64/python{py_version_short}',
|
||||||
|
- 'platstdlib': '{userbase}/lib64/python{py_version_short}',
|
||||||
|
+ 'stdlib': '{userbase}/lib/python{py_version_short}',
|
||||||
|
+ 'platstdlib': '{userbase}/lib/python{py_version_short}',
|
||||||
|
'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
|
||||||
|
- 'platlib': '{userbase}/lib64/python{py_version_short}/site-packages',
|
||||||
|
+ 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
|
||||||
|
'include': '{userbase}/include/python{py_version_short}',
|
||||||
|
'scripts': '{userbase}/bin',
|
||||||
|
'data': '{userbase}',
|
||||||
|
--- a/Lib/test/test_embed.py
|
||||||
|
+++ b/Lib/test/test_embed.py
|
||||||
|
@@ -10,6 +10,7 @@ import re
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
+import sysconfig
|
||||||
|
import tempfile
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
@@ -1072,12 +1073,13 @@ class InitConfigTests(EmbeddingTestsMixi
|
||||||
|
return config['config']['module_search_paths']
|
||||||
|
else:
|
||||||
|
ver = sys.version_info
|
||||||
|
+ platsubdir = sysconfig.get_config_var('platsubdir')
|
||||||
|
return [
|
||||||
|
os.path.join(prefix, 'lib',
|
||||||
|
f'python{ver.major}{ver.minor}.zip'),
|
||||||
|
- os.path.join(prefix, 'lib',
|
||||||
|
+ os.path.join(prefix, platsubdir,
|
||||||
|
f'python{ver.major}.{ver.minor}'),
|
||||||
|
- os.path.join(exec_prefix, 'lib',
|
||||||
|
+ os.path.join(exec_prefix, platsubdir,
|
||||||
|
f'python{ver.major}.{ver.minor}', 'lib-dynload'),
|
||||||
|
]
|
||||||
|
|
||||||
|
@@ -1188,13 +1190,15 @@ class InitConfigTests(EmbeddingTestsMixi
|
||||||
|
def test_init_pyvenv_cfg(self):
|
||||||
|
# Test path configuration with pyvenv.cfg configuration file
|
||||||
|
|
||||||
|
+ platsubdir = sysconfig.get_config_var('platsubdir')
|
||||||
|
+
|
||||||
|
with self.tmpdir_with_python() as tmpdir, \
|
||||||
|
tempfile.TemporaryDirectory() as pyvenv_home:
|
||||||
|
ver = sys.version_info
|
||||||
|
|
||||||
|
if not MS_WINDOWS:
|
||||||
|
lib_dynload = os.path.join(pyvenv_home,
|
||||||
|
- 'lib',
|
||||||
|
+ platsubdir,
|
||||||
|
f'python{ver.major}.{ver.minor}',
|
||||||
|
'lib-dynload')
|
||||||
|
os.makedirs(lib_dynload)
|
||||||
|
--- a/Lib/test/test_site.py
|
||||||
|
+++ b/Lib/test/test_site.py
|
||||||
|
@@ -307,8 +307,11 @@ class HelperFunctionsTests(unittest.Test
|
||||||
|
dirs = site.getsitepackages()
|
||||||
|
if os.sep == '/':
|
||||||
|
# OS X, Linux, FreeBSD, etc
|
||||||
|
- self.assertEqual(len(dirs), 2)
|
||||||
|
- wanted = os.path.join('xoxo', 'lib64',
|
||||||
|
+ self.assertTrue(len(dirs) in (1,2,3),
|
||||||
|
+ "dirs = {} has len not in (1,2,3).".format(dirs))
|
||||||
|
+
|
||||||
|
+ platsubdir = sysconfig.get_config_var('platsubdir')
|
||||||
|
+ wanted = os.path.join('xoxo', platsubdir,
|
||||||
|
'python%d.%d' % sys.version_info[:2],
|
||||||
|
'site-packages')
|
||||||
|
self.assertEqual(dirs[0], wanted)
|
||||||
|
--- a/Lib/test/test_sysconfig.py
|
||||||
|
+++ b/Lib/test/test_sysconfig.py
|
||||||
|
@@ -243,6 +243,7 @@ class TestSysConfig(unittest.TestCase):
|
||||||
|
# is similar to the global posix_prefix one
|
||||||
|
base = get_config_var('base')
|
||||||
|
user = get_config_var('userbase')
|
||||||
|
+ platsubdir = get_config_var("platsubdir")
|
||||||
|
# the global scheme mirrors the distinction between prefix and
|
||||||
|
# exec-prefix but not the user scheme, so we have to adapt the paths
|
||||||
|
# before comparing (issue #9100)
|
||||||
|
@@ -257,8 +258,19 @@ class TestSysConfig(unittest.TestCase):
|
||||||
|
# before comparing
|
||||||
|
global_path = global_path.replace(sys.base_prefix, sys.prefix)
|
||||||
|
base = base.replace(sys.base_prefix, sys.prefix)
|
||||||
|
+
|
||||||
|
+ if platsubdir != "lib":
|
||||||
|
+ platbase = os.path.join(base, platsubdir)
|
||||||
|
+ purebase = os.path.join(base, "lib")
|
||||||
|
+ userlib = os.path.join(user, "lib")
|
||||||
|
+ # replace platbase first because usually purebase is a prefix of platbase
|
||||||
|
+ # /usr/lib is prefix of /usr/lib64 and would get replaced first
|
||||||
|
+ modified_path = global_path.replace(platbase, userlib, 1).replace(purebase, userlib, 1)
|
||||||
|
+ else:
|
||||||
|
+ modified_path = global_path.replace(base, user, 1)
|
||||||
|
+
|
||||||
|
user_path = get_path(name, 'posix_user')
|
||||||
|
- self.assertEqual(user_path, global_path.replace(base, user, 1))
|
||||||
|
+ self.assertEqual(user_path, modified_path)
|
||||||
|
|
||||||
|
def test_main(self):
|
||||||
|
# just making sure _main() runs and returns things in the stdout
|
||||||
|
--- a/Makefile.pre.in
|
||||||
|
+++ b/Makefile.pre.in
|
||||||
|
@@ -137,13 +137,16 @@ exec_prefix= @exec_prefix@
|
||||||
|
# Install prefix for data files
|
||||||
|
datarootdir= @datarootdir@
|
||||||
|
|
||||||
|
+# Name of "lib" directory under prefix
|
||||||
|
+platsubdir= @platsubdir@
|
||||||
|
+
|
||||||
|
# Expanded directories
|
||||||
|
BINDIR= @bindir@
|
||||||
|
LIBDIR= @libdir@
|
||||||
|
MANDIR= @mandir@
|
||||||
|
INCLUDEDIR= @includedir@
|
||||||
|
CONFINCLUDEDIR= $(exec_prefix)/include
|
||||||
|
-SCRIPTDIR= $(prefix)/lib64
|
||||||
|
+SCRIPTDIR= @libdir@
|
||||||
|
ABIFLAGS= @ABIFLAGS@
|
||||||
|
|
||||||
|
# Detailed destination directories
|
||||||
|
@@ -766,6 +769,7 @@ Modules/getpath.o: $(srcdir)/Modules/get
|
||||||
|
-DEXEC_PREFIX='"$(exec_prefix)"' \
|
||||||
|
-DVERSION='"$(VERSION)"' \
|
||||||
|
-DVPATH='"$(VPATH)"' \
|
||||||
|
+ -DPLATLIBDIR='"$(platsubdir)"' \
|
||||||
|
-o $@ $(srcdir)/Modules/getpath.c
|
||||||
|
|
||||||
|
Programs/python.o: $(srcdir)/Programs/python.c
|
||||||
|
--- a/Modules/getpath.c
|
||||||
|
+++ b/Modules/getpath.c
|
||||||
|
@@ -55,12 +55,12 @@
|
||||||
|
* pybuilddir.txt. If the landmark is found, we're done.
|
||||||
|
*
|
||||||
|
* For the remaining steps, the prefix landmark will always be
|
||||||
|
- * lib/python$VERSION/os.py and the exec_prefix will always be
|
||||||
|
- * lib/python$VERSION/lib-dynload, where $VERSION is Python's version
|
||||||
|
- * number as supplied by the Makefile. Note that this means that no more
|
||||||
|
- * build directory checking is performed; if the first step did not find
|
||||||
|
- * the landmarks, the assumption is that python is running from an
|
||||||
|
- * installed setup.
|
||||||
|
+ * $lib/python$VERSION/os.py and the exec_prefix will always be
|
||||||
|
+ * $lib/python$VERSION/lib-dynload, where $VERSION is Python's version
|
||||||
|
+ * number and $lib is PLATLIBDIR as supplied by the Makefile. Note that
|
||||||
|
+ * this means that no more build directory checking is performed; if the
|
||||||
|
+ * first step did not find the landmarks, the assumption is that python
|
||||||
|
+ * is running from an installed setup.
|
||||||
|
*
|
||||||
|
* Step 2. See if the $PYTHONHOME environment variable points to the
|
||||||
|
* installed location of the Python libraries. If $PYTHONHOME is set, then
|
||||||
|
@@ -86,7 +86,7 @@
|
||||||
|
* containing the shared library modules is appended. The environment
|
||||||
|
* variable $PYTHONPATH is inserted in front of it all. Finally, the
|
||||||
|
* prefix and exec_prefix globals are tweaked so they reflect the values
|
||||||
|
- * expected by other code, by stripping the "lib/python$VERSION/..." stuff
|
||||||
|
+ * expected by other code, by stripping the "$lib/python$VERSION/..." stuff
|
||||||
|
* off. If either points to the build directory, the globals are reset to
|
||||||
|
* the corresponding preprocessor variables (so sys.prefix will reflect the
|
||||||
|
* installation location, even though sys.path points into the build
|
||||||
|
@@ -105,8 +105,8 @@ extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
-#if !defined(PREFIX) || !defined(EXEC_PREFIX) || !defined(VERSION) || !defined(VPATH)
|
||||||
|
-#error "PREFIX, EXEC_PREFIX, VERSION, and VPATH must be constant defined"
|
||||||
|
+#if !defined(PREFIX) || !defined(EXEC_PREFIX) || !defined(VERSION) || !defined(VPATH) || !defined(PLATLIBDIR)
|
||||||
|
+#error "PREFIX, EXEC_PREFIX, VERSION, VPATH, and PLATLIBDIR must be constant defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LANDMARK
|
||||||
|
@@ -730,7 +730,7 @@ calculate_exec_prefix(PyCalculatePath *c
|
||||||
|
if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
|
||||||
|
return PATHLEN_ERR();
|
||||||
|
}
|
||||||
|
- status = joinpath(exec_prefix, L"lib64/lib-dynload", exec_prefix_len);
|
||||||
|
+ status = joinpath(exec_prefix, L"lib/lib-dynload", exec_prefix_len);
|
||||||
|
if (_PyStatus_EXCEPTION(status)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
@@ -1063,7 +1063,7 @@ calculate_zip_path(PyCalculatePath *calc
|
||||||
|
return PATHLEN_ERR();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- status = joinpath(zip_path, L"lib64/python00.zip", zip_path_len);
|
||||||
|
+ status = joinpath(zip_path, L"lib/python00.zip", zip_path_len);
|
||||||
|
if (_PyStatus_EXCEPTION(status)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
@@ -1193,7 +1193,7 @@ calculate_init(PyCalculatePath *calculat
|
||||||
|
if (!calculate->exec_prefix) {
|
||||||
|
return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
|
||||||
|
}
|
||||||
|
- calculate->lib_python = Py_DecodeLocale("lib64/python" VERSION, &len);
|
||||||
|
+ calculate->lib_python = Py_DecodeLocale(PLATLIBDIR "/python" VERSION, &len);
|
||||||
|
if (!calculate->lib_python) {
|
||||||
|
return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
|
||||||
|
}
|
||||||
|
--- a/configure
|
||||||
|
+++ b/configure
|
||||||
|
@@ -15276,9 +15276,9 @@ fi
|
||||||
|
|
||||||
|
|
||||||
|
if test x$PLATFORM_TRIPLET = x; then
|
||||||
|
- LIBPL='$(prefix)'"/lib64/python${VERSION}/config-${LDVERSION}"
|
||||||
|
+ LIBPL='$(prefix)'"/${platsubdir}/python${VERSION}/config-${LDVERSION}"
|
||||||
|
else
|
||||||
|
- LIBPL='$(prefix)'"/lib64/python${VERSION}/config-${LDVERSION}-${PLATFORM_TRIPLET}"
|
||||||
|
+ LIBPL='$(prefix)'"/${platsubdir}/python${VERSION}/config-${LDVERSION}-${PLATFORM_TRIPLET}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -4719,12 +4719,26 @@ else
|
||||||
|
LIBPYTHON=''
|
||||||
|
fi
|
||||||
|
|
||||||
|
+# platsubdir must be defined before LIBPL definition
|
||||||
|
+AC_MSG_CHECKING(for custom platsubdir)
|
||||||
|
+AC_ARG_WITH(custom-platsubdir,
|
||||||
|
+ [AS_HELP_STRING([--with-custom-platsubdir=<libdirname>],
|
||||||
|
+ [set the platsubdir name to a custom string])],
|
||||||
|
+ [],
|
||||||
|
+ [with_custom_platsubdir=yes])
|
||||||
|
+AS_CASE($with_custom_platsubdir,
|
||||||
|
+ [yes],[platsubdir=`basename ${libdir}`],
|
||||||
|
+ [no],[platsubdir=lib],
|
||||||
|
+ [platsubdir=$with_custom_platsubdir])
|
||||||
|
+AC_MSG_RESULT($platsubdir)
|
||||||
|
+AC_SUBST(platsubdir)
|
||||||
|
+
|
||||||
|
dnl define LIBPL after ABIFLAGS and LDVERSION is defined.
|
||||||
|
AC_SUBST(PY_ENABLE_SHARED)
|
||||||
|
if test x$PLATFORM_TRIPLET = x; then
|
||||||
|
- LIBPL='$(prefix)'"/lib64/python${VERSION}/config-${LDVERSION}"
|
||||||
|
+ LIBPL='$(prefix)'"/${platsubdir}/python${VERSION}/config-${LDVERSION}"
|
||||||
|
else
|
||||||
|
- LIBPL='$(prefix)'"/lib64/python${VERSION}/config-${LDVERSION}-${PLATFORM_TRIPLET}"
|
||||||
|
+ LIBPL='$(prefix)'"/${platsubdir}/python${VERSION}/config-${LDVERSION}-${PLATFORM_TRIPLET}"
|
||||||
|
fi
|
||||||
|
AC_SUBST(LIBPL)
|
||||||
|
|
||||||
|
--- a/setup.py
|
||||||
|
+++ b/setup.py
|
||||||
|
@@ -634,7 +634,7 @@ class PyBuildExt(build_ext):
|
||||||
|
# directories (i.e. '.' and 'Include') must be first. See issue
|
||||||
|
# 10520.
|
||||||
|
if not CROSS_COMPILING:
|
||||||
|
- add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib64')
|
||||||
|
+ add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
|
||||||
|
add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
|
||||||
|
# only change this for cross builds for 3.3, issues on Mageia
|
||||||
|
if CROSS_COMPILING:
|
||||||
|
@@ -938,11 +938,11 @@ class PyBuildExt(build_ext):
|
||||||
|
elif curses_library:
|
||||||
|
readline_libs.append(curses_library)
|
||||||
|
elif self.compiler.find_library_file(self.lib_dirs +
|
||||||
|
- ['/usr/lib64/termcap'],
|
||||||
|
+ ['/usr/lib/termcap'],
|
||||||
|
'termcap'):
|
||||||
|
readline_libs.append('termcap')
|
||||||
|
self.add(Extension('readline', ['readline.c'],
|
||||||
|
- library_dirs=['/usr/lib64/termcap'],
|
||||||
|
+ library_dirs=['/usr/lib/termcap'],
|
||||||
|
extra_link_args=readline_extra_link_args,
|
||||||
|
libraries=readline_libs))
|
||||||
|
else:
|
4
_multibuild
Normal file
4
_multibuild
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<multibuild>
|
||||||
|
<package>base</package>
|
||||||
|
<package>doc</package>
|
||||||
|
</multibuild>
|
3
baselibs.conf
Normal file
3
baselibs.conf
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
python38-base
|
||||||
|
python38
|
||||||
|
libpython3_8-1_0
|
163
bpo-31046_ensurepip_honours_prefix.patch
Normal file
163
bpo-31046_ensurepip_honours_prefix.patch
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
From 5754521af1d51aa8e445cba07a093bbc0c88596d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Zackery Spytz <zspytz@gmail.com>
|
||||||
|
Date: Mon, 16 Dec 2019 18:24:08 -0700
|
||||||
|
Subject: [PATCH] bpo-31046: ensurepip does not honour the value of $(prefix)
|
||||||
|
|
||||||
|
Co-Authored-By: Xavier de Gaye <xdegaye@gmail.com>
|
||||||
|
---
|
||||||
|
Doc/library/ensurepip.rst | 9 +++--
|
||||||
|
Lib/ensurepip/__init__.py | 18 +++++++---
|
||||||
|
Lib/test/test_ensurepip.py | 11 ++++++
|
||||||
|
Makefile.pre.in | 4 +-
|
||||||
|
Misc/NEWS.d/next/Build/2019-12-16-17-50-42.bpo-31046.XA-Qfr.rst | 1
|
||||||
|
5 files changed, 34 insertions(+), 9 deletions(-)
|
||||||
|
create mode 100644 Misc/NEWS.d/next/Build/2019-12-16-17-50-42.bpo-31046.XA-Qfr.rst
|
||||||
|
|
||||||
|
--- a/Doc/library/ensurepip.rst
|
||||||
|
+++ b/Doc/library/ensurepip.rst
|
||||||
|
@@ -56,8 +56,9 @@ is at least as recent as the one bundled
|
||||||
|
By default, ``pip`` is installed into the current virtual environment
|
||||||
|
(if one is active) or into the system site packages (if there is no
|
||||||
|
active virtual environment). The installation location can be controlled
|
||||||
|
-through two additional command line options:
|
||||||
|
+through some additional command line options:
|
||||||
|
|
||||||
|
+* ``--prefix <dir>``: Installs ``pip`` using the given directory prefix.
|
||||||
|
* ``--root <dir>``: Installs ``pip`` relative to the given root directory
|
||||||
|
rather than the root of the currently active virtual environment (if any)
|
||||||
|
or the default root for the current Python installation.
|
||||||
|
@@ -89,7 +90,7 @@ Module API
|
||||||
|
Returns a string specifying the bundled version of pip that will be
|
||||||
|
installed when bootstrapping an environment.
|
||||||
|
|
||||||
|
-.. function:: bootstrap(root=None, upgrade=False, user=False, \
|
||||||
|
+.. function:: bootstrap(root=None, prefix=None, upgrade=False, user=False, \
|
||||||
|
altinstall=False, default_pip=False, \
|
||||||
|
verbosity=0)
|
||||||
|
|
||||||
|
@@ -99,6 +100,8 @@ Module API
|
||||||
|
If *root* is ``None``, then installation uses the default install location
|
||||||
|
for the current environment.
|
||||||
|
|
||||||
|
+ *prefix* specifies the directory prefix to use when installing.
|
||||||
|
+
|
||||||
|
*upgrade* indicates whether or not to upgrade an existing installation
|
||||||
|
of an earlier version of ``pip`` to the bundled version.
|
||||||
|
|
||||||
|
@@ -119,6 +122,8 @@ Module API
|
||||||
|
*verbosity* controls the level of output to :data:`sys.stdout` from the
|
||||||
|
bootstrapping operation.
|
||||||
|
|
||||||
|
+ .. versionchanged:: 3.9 the *prefix* parameter was added.
|
||||||
|
+
|
||||||
|
.. audit-event:: ensurepip.bootstrap root ensurepip.bootstrap
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
--- a/Lib/ensurepip/__init__.py
|
||||||
|
+++ b/Lib/ensurepip/__init__.py
|
||||||
|
@@ -55,27 +55,27 @@ def _disable_pip_configuration_settings(
|
||||||
|
os.environ['PIP_CONFIG_FILE'] = os.devnull
|
||||||
|
|
||||||
|
|
||||||
|
-def bootstrap(*, root=None, upgrade=False, user=False,
|
||||||
|
+def bootstrap(*, root=None, prefix=None, upgrade=False, user=False,
|
||||||
|
altinstall=False, default_pip=False,
|
||||||
|
verbosity=0):
|
||||||
|
"""
|
||||||
|
Bootstrap pip into the current Python installation (or the given root
|
||||||
|
- directory).
|
||||||
|
+ and directory prefix).
|
||||||
|
|
||||||
|
Note that calling this function will alter both sys.path and os.environ.
|
||||||
|
"""
|
||||||
|
# Discard the return value
|
||||||
|
- _bootstrap(root=root, upgrade=upgrade, user=user,
|
||||||
|
+ _bootstrap(root=root, prefix=prefix, upgrade=upgrade, user=user,
|
||||||
|
altinstall=altinstall, default_pip=default_pip,
|
||||||
|
verbosity=verbosity)
|
||||||
|
|
||||||
|
|
||||||
|
-def _bootstrap(*, root=None, upgrade=False, user=False,
|
||||||
|
+def _bootstrap(*, root=None, prefix=None, upgrade=False, user=False,
|
||||||
|
altinstall=False, default_pip=False,
|
||||||
|
verbosity=0):
|
||||||
|
"""
|
||||||
|
Bootstrap pip into the current Python installation (or the given root
|
||||||
|
- directory). Returns pip command status code.
|
||||||
|
+ and directory prefix). Returns pip command status code.
|
||||||
|
|
||||||
|
Note that calling this function will alter both sys.path and os.environ.
|
||||||
|
"""
|
||||||
|
@@ -118,6 +118,8 @@ def _bootstrap(*, root=None, upgrade=Fal
|
||||||
|
args = ["install", "--no-cache-dir", "--no-index", "--find-links", tmpdir]
|
||||||
|
if root:
|
||||||
|
args += ["--root", root]
|
||||||
|
+ if prefix:
|
||||||
|
+ args += ["--prefix", prefix]
|
||||||
|
if upgrade:
|
||||||
|
args += ["--upgrade"]
|
||||||
|
if user:
|
||||||
|
@@ -190,6 +192,11 @@ def _main(argv=None):
|
||||||
|
help="Install everything relative to this alternate root directory.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
+ "--prefix",
|
||||||
|
+ default=None,
|
||||||
|
+ help="Install everything using this prefix.",
|
||||||
|
+ )
|
||||||
|
+ parser.add_argument(
|
||||||
|
"--altinstall",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
@@ -208,6 +215,7 @@ def _main(argv=None):
|
||||||
|
|
||||||
|
return _bootstrap(
|
||||||
|
root=args.root,
|
||||||
|
+ prefix=args.prefix,
|
||||||
|
upgrade=args.upgrade,
|
||||||
|
user=args.user,
|
||||||
|
verbosity=args.verbosity,
|
||||||
|
--- a/Lib/test/test_ensurepip.py
|
||||||
|
+++ b/Lib/test/test_ensurepip.py
|
||||||
|
@@ -61,6 +61,17 @@ class TestBootstrap(EnsurepipMixin, unit
|
||||||
|
unittest.mock.ANY,
|
||||||
|
)
|
||||||
|
|
||||||
|
+ def test_bootstrapping_with_prefix(self):
|
||||||
|
+ ensurepip.bootstrap(prefix="/foo/bar/")
|
||||||
|
+ self.run_pip.assert_called_once_with(
|
||||||
|
+ [
|
||||||
|
+ "install", "--no-cache-dir", "--no-index", "--find-links",
|
||||||
|
+ unittest.mock.ANY, "--prefix", "/foo/bar/",
|
||||||
|
+ "setuptools", "pip",
|
||||||
|
+ ],
|
||||||
|
+ unittest.mock.ANY,
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
def test_bootstrapping_with_user(self):
|
||||||
|
ensurepip.bootstrap(user=True)
|
||||||
|
|
||||||
|
--- a/Makefile.pre.in
|
||||||
|
+++ b/Makefile.pre.in
|
||||||
|
@@ -1200,7 +1200,7 @@ install: @FRAMEWORKINSTALLFIRST@ commoni
|
||||||
|
install|*) ensurepip="" ;; \
|
||||||
|
esac; \
|
||||||
|
$(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \
|
||||||
|
- $$ensurepip --root=$(DESTDIR)/ ; \
|
||||||
|
+ $$ensurepip --root=$(DESTDIR)/ --prefix=$(prefix) ; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
altinstall: commoninstall
|
||||||
|
@@ -1210,7 +1210,7 @@ altinstall: commoninstall
|
||||||
|
install|*) ensurepip="--altinstall" ;; \
|
||||||
|
esac; \
|
||||||
|
$(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \
|
||||||
|
- $$ensurepip --root=$(DESTDIR)/ ; \
|
||||||
|
+ $$ensurepip --root=$(DESTDIR)/ --prefix=$(prefix) ; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
commoninstall: check-clean-src @FRAMEWORKALTINSTALLFIRST@ \
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Misc/NEWS.d/next/Build/2019-12-16-17-50-42.bpo-31046.XA-Qfr.rst
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+A directory prefix can now be specified when using :mod:`ensurepip`.
|
152
bpo34022-stop_hash-based_invalidation_w_SOURCE_DATE_EPOCH.patch
Normal file
152
bpo34022-stop_hash-based_invalidation_w_SOURCE_DATE_EPOCH.patch
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
From 2c096b513273a758b446405d9e5efe4860af1036 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Elvis Pranskevichus <elvis@magic.io>
|
||||||
|
Date: Thu, 27 Sep 2018 13:05:14 -0400
|
||||||
|
Subject: [PATCH] bpo-34022: Stop forcing of hash-based invalidation with
|
||||||
|
SOURCE_DATE_EPOCH
|
||||||
|
|
||||||
|
Unconditional forcing of ``CHECKED_HASH`` invalidation was introduced in
|
||||||
|
3.7.0 in bpo-29708. The change is bad, as it unconditionally overrides
|
||||||
|
*invalidation_mode*, even if it was passed as an explicit argument to
|
||||||
|
``py_compile.compile()`` or ``compileall``. An environment variable
|
||||||
|
should *never* override an explicit argument to a library function.
|
||||||
|
That change leads to multiple test failures if the ``SOURCE_DATE_EPOCH``
|
||||||
|
environment variable is set.
|
||||||
|
|
||||||
|
This changes ``py_compile.compile()`` to only look at
|
||||||
|
``SOURCE_DATE_EPOCH`` if no explicit *invalidation_mode* was specified.
|
||||||
|
I also made various relevant tests run with explicit control over the
|
||||||
|
value of ``SOURCE_DATE_EPOCH``.
|
||||||
|
|
||||||
|
While looking at this, I noticed that ``zipimport`` does not work
|
||||||
|
with hash-based .pycs _at all_, though I left the fixes for
|
||||||
|
subsequent commits.
|
||||||
|
---
|
||||||
|
Doc/library/compileall.rst | 11 ++--
|
||||||
|
Doc/library/py_compile.rst | 13 ++--
|
||||||
|
Lib/compileall.py | 20 ++++--
|
||||||
|
Lib/py_compile.py | 13 +++-
|
||||||
|
Lib/test/test_compileall.py | 50 ++++++++++++--
|
||||||
|
.../test_importlib/source/test_file_loader.py | 15 +++++
|
||||||
|
Lib/test/test_py_compile.py | 66 +++++++++++++++++--
|
||||||
|
.../2018-09-27-13-14-15.bpo-34022.E2cl0r.rst | 3 +
|
||||||
|
8 files changed, 161 insertions(+), 30 deletions(-)
|
||||||
|
create mode 100644 Misc/NEWS.d/next/Library/2018-09-27-13-14-15.bpo-34022.E2cl0r.rst
|
||||||
|
|
||||||
|
--- a/Doc/library/py_compile.rst
|
||||||
|
+++ b/Doc/library/py_compile.rst
|
||||||
|
@@ -92,6 +92,11 @@ byte-code cache files in the directory c
|
||||||
|
.. versionchanged:: 3.8
|
||||||
|
The *quiet* parameter was added.
|
||||||
|
|
||||||
|
+ .. versionchanged:: 3.7.2
|
||||||
|
+ The :envvar:`SOURCE_DATE_EPOCH` environment variable no longer
|
||||||
|
+ overrides the value of the *invalidation_mode* argument, and determines
|
||||||
|
+ its default value instead.
|
||||||
|
+
|
||||||
|
|
||||||
|
.. class:: PycInvalidationMode
|
||||||
|
|
||||||
|
--- a/Lib/test/test_compileall.py
|
||||||
|
+++ b/Lib/test/test_compileall.py
|
||||||
|
@@ -209,6 +209,21 @@ class CompileallTestsWithoutSourceEpoch(
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
+
|
||||||
|
+class CompileallTestsWithSourceEpoch(CompileallTestsBase,
|
||||||
|
+ unittest.TestCase,
|
||||||
|
+ metaclass=SourceDateEpochTestMeta,
|
||||||
|
+ source_date_epoch=True):
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class CompileallTestsWithoutSourceEpoch(CompileallTestsBase,
|
||||||
|
+ unittest.TestCase,
|
||||||
|
+ metaclass=SourceDateEpochTestMeta,
|
||||||
|
+ source_date_epoch=False):
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+
|
||||||
|
class EncodingTest(unittest.TestCase):
|
||||||
|
"""Issue 6716: compileall should escape source code when printing errors
|
||||||
|
to stdout."""
|
||||||
|
@@ -620,6 +635,21 @@ class CommandLineTestsBase:
|
||||||
|
|
||||||
|
|
||||||
|
class CommmandLineTestsWithSourceEpoch(CommandLineTestsBase,
|
||||||
|
+ unittest.TestCase,
|
||||||
|
+ metaclass=SourceDateEpochTestMeta,
|
||||||
|
+ source_date_epoch=True):
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class CommmandLineTestsNoSourceEpoch(CommandLineTestsBase,
|
||||||
|
+ unittest.TestCase,
|
||||||
|
+ metaclass=SourceDateEpochTestMeta,
|
||||||
|
+ source_date_epoch=False):
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class CommmandLineTestsWithSourceEpoch(CommandLineTestsBase,
|
||||||
|
unittest.TestCase,
|
||||||
|
metaclass=SourceDateEpochTestMeta,
|
||||||
|
source_date_epoch=True):
|
||||||
|
--- a/Lib/test/test_importlib/source/test_file_loader.py
|
||||||
|
+++ b/Lib/test/test_importlib/source/test_file_loader.py
|
||||||
|
@@ -22,6 +22,9 @@ from test.support import make_legacy_pyc
|
||||||
|
from test.test_py_compile import without_source_date_epoch
|
||||||
|
from test.test_py_compile import SourceDateEpochTestMeta
|
||||||
|
|
||||||
|
+from test.test_py_compile import without_source_date_epoch
|
||||||
|
+from test.test_py_compile import SourceDateEpochTestMeta
|
||||||
|
+
|
||||||
|
|
||||||
|
class SimpleTest(abc.LoaderTests):
|
||||||
|
|
||||||
|
@@ -363,6 +366,17 @@ class SimpleTest(abc.LoaderTests):
|
||||||
|
|
||||||
|
|
||||||
|
class SourceDateEpochTestMeta(SourceDateEpochTestMeta,
|
||||||
|
+ type(Source_SimpleTest)):
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class SourceDateEpoch_SimpleTest(Source_SimpleTest,
|
||||||
|
+ metaclass=SourceDateEpochTestMeta,
|
||||||
|
+ source_date_epoch=True):
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class SourceDateEpochTestMeta(SourceDateEpochTestMeta,
|
||||||
|
type(Source_SimpleTest)):
|
||||||
|
pass
|
||||||
|
|
||||||
|
--- a/Lib/test/test_py_compile.py
|
||||||
|
+++ b/Lib/test/test_py_compile.py
|
||||||
|
@@ -272,5 +272,19 @@ class PyCompileCLITestCase(unittest.Test
|
||||||
|
self.assertIn(b'No such file or directory', stderr)
|
||||||
|
|
||||||
|
|
||||||
|
+class PyCompileTestsWithSourceEpoch(PyCompileTestsBase,
|
||||||
|
+ unittest.TestCase,
|
||||||
|
+ metaclass=SourceDateEpochTestMeta,
|
||||||
|
+ source_date_epoch=True):
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class PyCompileTestsWithoutSourceEpoch(PyCompileTestsBase,
|
||||||
|
+ unittest.TestCase,
|
||||||
|
+ metaclass=SourceDateEpochTestMeta,
|
||||||
|
+ source_date_epoch=False):
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Misc/NEWS.d/next/Library/2018-09-27-13-14-15.bpo-34022.E2cl0r.rst
|
||||||
|
@@ -0,0 +1,3 @@
|
||||||
|
+The :envvar:`SOURCE_DATE_EPOCH` environment variable no longer overrides the
|
||||||
|
+value of the *invalidation_mode* argument to :func:`py_compile.compile`, and
|
||||||
|
+determines its default value instead.
|
115
bpo34990-2038-problem-compileall.patch
Normal file
115
bpo34990-2038-problem-compileall.patch
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
From 9d3b6b2472f7c7ef841e652825de652bc8af85d7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Miss Islington (bot)"
|
||||||
|
<31488909+miss-islington@users.noreply.github.com>
|
||||||
|
Date: Tue, 24 Aug 2021 08:07:31 -0700
|
||||||
|
Subject: [PATCH] [3.9] bpo-34990: Treat the pyc header's mtime in compileall
|
||||||
|
as an unsigned int (GH-19708)
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
(cherry picked from commit bb21e28fd08f894ceff2405544a2f257d42b1354)
|
||||||
|
|
||||||
|
Co-authored-by: Ammar Askar <ammar@ammaraskar.com>
|
||||||
|
Co-authored-by: Stéphane Wirtel <stephane@wirtel.be>
|
||||||
|
---
|
||||||
|
Lib/compileall.py | 4 -
|
||||||
|
Lib/test/test_compileall.py | 23 +++++++++-
|
||||||
|
Lib/test/test_zipimport.py | 17 ++++---
|
||||||
|
Misc/NEWS.d/next/Library/2020-04-24-20-39-38.bpo-34990.3SmL9M.rst | 2
|
||||||
|
4 files changed, 35 insertions(+), 11 deletions(-)
|
||||||
|
create mode 100644 Misc/NEWS.d/next/Library/2020-04-24-20-39-38.bpo-34990.3SmL9M.rst
|
||||||
|
|
||||||
|
--- a/Lib/compileall.py
|
||||||
|
+++ b/Lib/compileall.py
|
||||||
|
@@ -148,8 +148,8 @@ def compile_file(fullname, ddir=None, fo
|
||||||
|
if not force:
|
||||||
|
try:
|
||||||
|
mtime = int(os.stat(fullname).st_mtime)
|
||||||
|
- expect = struct.pack('<4sll', importlib.util.MAGIC_NUMBER,
|
||||||
|
- 0, mtime)
|
||||||
|
+ expect = struct.pack('<4sLL', importlib.util.MAGIC_NUMBER,
|
||||||
|
+ 0, mtime & 0xFFFF_FFFF)
|
||||||
|
with open(cfile, 'rb') as chandle:
|
||||||
|
actual = chandle.read(12)
|
||||||
|
if expect == actual:
|
||||||
|
--- a/Lib/test/test_compileall.py
|
||||||
|
+++ b/Lib/test/test_compileall.py
|
||||||
|
@@ -54,9 +54,28 @@ class CompileallTestsBase:
|
||||||
|
with open(self.bc_path, 'rb') as file:
|
||||||
|
data = file.read(12)
|
||||||
|
mtime = int(os.stat(self.source_path).st_mtime)
|
||||||
|
- compare = struct.pack('<4sll', importlib.util.MAGIC_NUMBER, 0, mtime)
|
||||||
|
+ compare = struct.pack('<4sLL', importlib.util.MAGIC_NUMBER, 0,
|
||||||
|
+ mtime & 0xFFFF_FFFF)
|
||||||
|
return data, compare
|
||||||
|
|
||||||
|
+ def test_year_2038_mtime_compilation(self):
|
||||||
|
+ # Test to make sure we can handle mtimes larger than what a 32-bit
|
||||||
|
+ # signed number can hold as part of bpo-34990
|
||||||
|
+ try:
|
||||||
|
+ os.utime(self.source_path, (2**32 - 1, 2**32 - 1))
|
||||||
|
+ except (OverflowError, OSError):
|
||||||
|
+ self.skipTest("filesystem doesn't support timestamps near 2**32")
|
||||||
|
+ self.assertTrue(compileall.compile_file(self.source_path))
|
||||||
|
+
|
||||||
|
+ def test_larger_than_32_bit_times(self):
|
||||||
|
+ # This is similar to the test above but we skip it if the OS doesn't
|
||||||
|
+ # support modification times larger than 32-bits.
|
||||||
|
+ try:
|
||||||
|
+ os.utime(self.source_path, (2**35, 2**35))
|
||||||
|
+ except (OverflowError, OSError):
|
||||||
|
+ self.skipTest("filesystem doesn't support large timestamps")
|
||||||
|
+ self.assertTrue(compileall.compile_file(self.source_path))
|
||||||
|
+
|
||||||
|
def recreation_check(self, metadata):
|
||||||
|
"""Check that compileall recreates bytecode when the new metadata is
|
||||||
|
used."""
|
||||||
|
@@ -75,7 +94,7 @@ class CompileallTestsBase:
|
||||||
|
|
||||||
|
def test_mtime(self):
|
||||||
|
# Test a change in mtime leads to a new .pyc.
|
||||||
|
- self.recreation_check(struct.pack('<4sll', importlib.util.MAGIC_NUMBER,
|
||||||
|
+ self.recreation_check(struct.pack('<4sLL', importlib.util.MAGIC_NUMBER,
|
||||||
|
0, 1))
|
||||||
|
|
||||||
|
def test_magic_number(self):
|
||||||
|
--- a/Lib/test/test_zipimport.py
|
||||||
|
+++ b/Lib/test/test_zipimport.py
|
||||||
|
@@ -34,14 +34,9 @@ raise_src = 'def do_raise(): raise TypeE
|
||||||
|
|
||||||
|
def make_pyc(co, mtime, size):
|
||||||
|
data = marshal.dumps(co)
|
||||||
|
- if type(mtime) is type(0.0):
|
||||||
|
- # Mac mtimes need a bit of special casing
|
||||||
|
- if mtime < 0x7fffffff:
|
||||||
|
- mtime = int(mtime)
|
||||||
|
- else:
|
||||||
|
- mtime = int(-0x100000000 + int(mtime))
|
||||||
|
pyc = (importlib.util.MAGIC_NUMBER +
|
||||||
|
- struct.pack("<iii", 0, int(mtime), size & 0xFFFFFFFF) + data)
|
||||||
|
+ struct.pack("<iLL", 0,
|
||||||
|
+ int(mtime) & 0xFFFF_FFFF, size & 0xFFFF_FFFF) + data)
|
||||||
|
return pyc
|
||||||
|
|
||||||
|
def module_path_to_dotted_name(path):
|
||||||
|
@@ -253,6 +248,14 @@ class UncompressedZipImportTestCase(Impo
|
||||||
|
TESTMOD + pyc_ext: (NOW, badtime_pyc)}
|
||||||
|
self.doTest(".py", files, TESTMOD)
|
||||||
|
|
||||||
|
+ def test2038MTime(self):
|
||||||
|
+ # Make sure we can handle mtimes larger than what a 32-bit signed number
|
||||||
|
+ # can hold.
|
||||||
|
+ twenty_thirty_eight_pyc = make_pyc(test_co, 2**32 - 1, len(test_src))
|
||||||
|
+ files = {TESTMOD + ".py": (NOW, test_src),
|
||||||
|
+ TESTMOD + pyc_ext: (NOW, twenty_thirty_eight_pyc)}
|
||||||
|
+ self.doTest(".py", files, TESTMOD)
|
||||||
|
+
|
||||||
|
def testPackage(self):
|
||||||
|
packdir = TESTPACK + os.sep
|
||||||
|
files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Misc/NEWS.d/next/Library/2020-04-24-20-39-38.bpo-34990.3SmL9M.rst
|
||||||
|
@@ -0,0 +1,2 @@
|
||||||
|
+Fixed a Y2k38 bug in the compileall module where it would fail to compile
|
||||||
|
+files with a modification time after the year 2038.
|
49
bpo36302-sort-module-sources.patch
Normal file
49
bpo36302-sort-module-sources.patch
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
From ca04974425c84f306ddcebe88d6b31442e34e89d Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Bernhard M. Wiedemann" <bwiedemann@suse.de>
|
||||||
|
Date: Mon, 5 Jun 2017 17:33:33 +0200
|
||||||
|
Subject: [PATCH] bpo-36302: Sort list of sources
|
||||||
|
|
||||||
|
when building packages (e.g. for openSUSE Linux)
|
||||||
|
(random) filesystem order of input files
|
||||||
|
influences ordering of functions in the output .so files.
|
||||||
|
Thus without the patch, builds (in disposable VMs) would usually differ.
|
||||||
|
|
||||||
|
Without this patch, all callers have to be patched individually
|
||||||
|
https://github.com/dugsong/libdnet/pull/42
|
||||||
|
https://github.com/sass/libsass-python/pull/212
|
||||||
|
https://github.com/tahoe-lafs/pycryptopp/pull/41
|
||||||
|
https://github.com/yt-project/yt/pull/2206
|
||||||
|
https://github.com/pyproj4/pyproj/pull/142
|
||||||
|
https://github.com/pytries/datrie/pull/49
|
||||||
|
https://github.com/Roche/pyreadstat/pull/37
|
||||||
|
but that is an infinite effort.
|
||||||
|
|
||||||
|
See https://reproducible-builds.org/ for why this matters.
|
||||||
|
---
|
||||||
|
Lib/distutils/command/build_ext.py | 3 ++-
|
||||||
|
.../next/Library/2019-03-21-19-23-46.bpo-36302.Yc591g.rst | 2 ++
|
||||||
|
2 files changed, 4 insertions(+), 1 deletion(-)
|
||||||
|
create mode 100644 Misc/NEWS.d/next/Library/2019-03-21-19-23-46.bpo-36302.Yc591g.rst
|
||||||
|
|
||||||
|
diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py
|
||||||
|
index 2d7cdf063f01..38bb8fd93c27 100644
|
||||||
|
--- a/Lib/distutils/command/build_ext.py
|
||||||
|
+++ b/Lib/distutils/command/build_ext.py
|
||||||
|
@@ -490,7 +490,8 @@ def build_extension(self, ext):
|
||||||
|
"in 'ext_modules' option (extension '%s'), "
|
||||||
|
"'sources' must be present and must be "
|
||||||
|
"a list of source filenames" % ext.name)
|
||||||
|
- sources = list(sources)
|
||||||
|
+ # sort to make the resulting .so file build reproducible
|
||||||
|
+ sources = sorted(sources)
|
||||||
|
|
||||||
|
ext_path = self.get_ext_fullpath(ext.name)
|
||||||
|
depends = sources + ext.depends
|
||||||
|
diff --git a/Misc/NEWS.d/next/Library/2019-03-21-19-23-46.bpo-36302.Yc591g.rst b/Misc/NEWS.d/next/Library/2019-03-21-19-23-46.bpo-36302.Yc591g.rst
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000000..fe01b5915d5d
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Misc/NEWS.d/next/Library/2019-03-21-19-23-46.bpo-36302.Yc591g.rst
|
||||||
|
@@ -0,0 +1,2 @@
|
||||||
|
+distutils sorts source file lists so that Extension .so files
|
||||||
|
+build more reproducibly by default
|
44
bpo44426-complex-keyword-sphinx.patch
Normal file
44
bpo44426-complex-keyword-sphinx.patch
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
From 29b463879b71a3ade67541c34daafb2929269fc4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mark Dickinson <mdickinson@enthought.com>
|
||||||
|
Date: Wed, 16 Jun 2021 18:43:49 +0100
|
||||||
|
Subject: [PATCH] bpo-44426: Use of 'complex' as a C variable name confuses
|
||||||
|
Sphinx; change it to 'num'. (GH-26744) (cherry picked from commit
|
||||||
|
7247f6f433846c6e37308a550e8e5eb6be379856)
|
||||||
|
|
||||||
|
Co-authored-by: Mark Dickinson <mdickinson@enthought.com>
|
||||||
|
---
|
||||||
|
Doc/c-api/complex.rst | 4 ++--
|
||||||
|
Doc/c-api/object.rst | 4 ++--
|
||||||
|
2 files changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
--- a/Doc/c-api/complex.rst
|
||||||
|
+++ b/Doc/c-api/complex.rst
|
||||||
|
@@ -46,9 +46,9 @@ pointers. This is consistent throughout
|
||||||
|
:c:type:`Py_complex` representation.
|
||||||
|
|
||||||
|
|
||||||
|
-.. c:function:: Py_complex _Py_c_neg(Py_complex complex)
|
||||||
|
+.. c:function:: Py_complex _Py_c_neg(Py_complex num)
|
||||||
|
|
||||||
|
- Return the negation of the complex number *complex*, using the C
|
||||||
|
+ Return the negation of the complex number *num*, using the C
|
||||||
|
:c:type:`Py_complex` representation.
|
||||||
|
|
||||||
|
|
||||||
|
--- a/Doc/c-api/object.rst
|
||||||
|
+++ b/Doc/c-api/object.rst
|
||||||
|
@@ -483,12 +483,12 @@ Object Protocol
|
||||||
|
returned. This is the equivalent to the Python expression ``len(o)``.
|
||||||
|
|
||||||
|
|
||||||
|
-.. c:function:: Py_ssize_t PyObject_LengthHint(PyObject *o, Py_ssize_t default)
|
||||||
|
+.. c:function:: Py_ssize_t PyObject_LengthHint(PyObject *o, Py_ssize_t def_size)
|
||||||
|
|
||||||
|
Return an estimated length for the object *o*. First try to return its
|
||||||
|
actual length, then an estimate using :meth:`~object.__length_hint__`, and
|
||||||
|
finally return the default value. On error return ``-1``. This is the
|
||||||
|
- equivalent to the Python expression ``operator.length_hint(o, default)``.
|
||||||
|
+ equivalent to the Python expression ``operator.length_hint(o, def_size)``.
|
||||||
|
|
||||||
|
.. versionadded:: 3.4
|
||||||
|
|
36
decimal-3.8.patch
Normal file
36
decimal-3.8.patch
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
Modules/_decimal/_decimal.c | 4 ++--
|
||||||
|
setup.py | 2 +-
|
||||||
|
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
--- a/Modules/_decimal/_decimal.c
|
||||||
|
+++ b/Modules/_decimal/_decimal.c
|
||||||
|
@@ -3284,7 +3284,7 @@ dec_format(PyObject *dec, PyObject *args
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
size_t n = strlen(spec.dot);
|
||||||
|
- if (n > 1 || (n == 1 && !isascii((uchar)spec.dot[0]))) {
|
||||||
|
+ if (n > 1 || (n == 1 && !isascii((unsigned char)spec.dot[0]))) {
|
||||||
|
/* fix locale dependent non-ascii characters */
|
||||||
|
dot = dotsep_as_utf8(spec.dot);
|
||||||
|
if (dot == NULL) {
|
||||||
|
@@ -3293,7 +3293,7 @@ dec_format(PyObject *dec, PyObject *args
|
||||||
|
spec.dot = PyBytes_AS_STRING(dot);
|
||||||
|
}
|
||||||
|
n = strlen(spec.sep);
|
||||||
|
- if (n > 1 || (n == 1 && !isascii((uchar)spec.sep[0]))) {
|
||||||
|
+ if (n > 1 || (n == 1 && !isascii((unsigned char)spec.sep[0]))) {
|
||||||
|
/* fix locale dependent non-ascii characters */
|
||||||
|
sep = dotsep_as_utf8(spec.sep);
|
||||||
|
if (sep == NULL) {
|
||||||
|
--- a/setup.py
|
||||||
|
+++ b/setup.py
|
||||||
|
@@ -2055,7 +2055,7 @@ class PyBuildExt(build_ext):
|
||||||
|
undef_macros = []
|
||||||
|
if '--with-system-libmpdec' in sysconfig.get_config_var("CONFIG_ARGS"):
|
||||||
|
include_dirs = []
|
||||||
|
- libraries = [':libmpdec.so.2']
|
||||||
|
+ libraries = ['mpdec']
|
||||||
|
sources = ['_decimal/_decimal.c']
|
||||||
|
depends = ['_decimal/docstrings.h']
|
||||||
|
else:
|
11
distutils-reproducible-compile.patch
Normal file
11
distutils-reproducible-compile.patch
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
--- a/Lib/distutils/util.py
|
||||||
|
+++ b/Lib/distutils/util.py
|
||||||
|
@@ -432,7 +432,7 @@ byte_compile(files, optimize=%r, force=%
|
||||||
|
else:
|
||||||
|
from py_compile import compile
|
||||||
|
|
||||||
|
- for file in py_files:
|
||||||
|
+ for file in sorted(py_files):
|
||||||
|
if file[-3:] != ".py":
|
||||||
|
# This lets us be lazy and not filter filenames in
|
||||||
|
# the "install_lib" command.
|
35
idle3.appdata.xml
Normal file
35
idle3.appdata.xml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!-- Copyright 2017 Zbigniew Jędrzejewski-Szmek -->
|
||||||
|
<application>
|
||||||
|
<id type="desktop">idle3.desktop</id>
|
||||||
|
<name>IDLE3</name>
|
||||||
|
<metadata_licence>CC0</metadata_licence>
|
||||||
|
<project_license>Python-2.0</project_license>
|
||||||
|
<summary>Python 3 Integrated Development and Learning Environment</summary>
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
IDLE is Python’s Integrated Development and Learning Environment.
|
||||||
|
The GUI is uniform between Windows, Unix, and Mac OS X.
|
||||||
|
IDLE provides an easy way to start writing, running, and debugging
|
||||||
|
Python code.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
IDLE is written in pure Python, and uses the tkinter GUI toolkit.
|
||||||
|
It provides:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>a Python shell window (interactive interpreter) with colorizing of code input, output, and error messages,</li>
|
||||||
|
<li>a multi-window text editor with multiple undo, Python colorizing, smart indent, call tips, auto completion, and other features,</li>
|
||||||
|
<li>search within any window, replace within editor windows, and search through multiple files (grep),</li>
|
||||||
|
<li>a debugger with persistent breakpoints, stepping, and viewing of global and local namespaces.</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
<url type="homepage">https://docs.python.org/3/library/idle.html</url>
|
||||||
|
<screenshots>
|
||||||
|
<screenshot type="default">http://in.waw.pl/~zbyszek/fedora/idle3-appdata/idle3-main-window.png</screenshot>
|
||||||
|
<screenshot>http://in.waw.pl/~zbyszek/fedora/idle3-appdata/idle3-class-browser.png</screenshot>
|
||||||
|
<screenshot>http://in.waw.pl/~zbyszek/fedora/idle3-appdata/idle3-code-viewer.png</screenshot>
|
||||||
|
</screenshots>
|
||||||
|
<update_contact>zbyszek@in.waw.pl</update_contact>
|
||||||
|
</application>
|
12
idle3.desktop
Normal file
12
idle3.desktop
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Version=1.0
|
||||||
|
Name=IDLE 3
|
||||||
|
GenericName=Python 3 IDE
|
||||||
|
Comment=Python 3 Integrated Development and Learning Environment
|
||||||
|
Exec=idle3 %F
|
||||||
|
TryExec=idle3
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
Icon=idle3
|
||||||
|
Categories=Development;IDE;
|
||||||
|
MimeType=text/x-python;
|
7
import_failed.map
Normal file
7
import_failed.map
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
python38-curses: curses _curses _curses_panel
|
||||||
|
python38-dbm: dbm _dbm _gdbm
|
||||||
|
python38-idle: idlelib
|
||||||
|
python38-testsuite: test _ctypes_test _testbuffer _testcapi _testinternalcapi _testimportmultiple _testmultiphase xxlimited
|
||||||
|
python38-tk: tkinter _tkinter
|
||||||
|
python38-tools: turtledemo
|
||||||
|
python38: sqlite3 readline _sqlite3 nis
|
23
import_failed.py
Normal file
23
import_failed.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import sys, os
|
||||||
|
from sysconfig import get_path
|
||||||
|
|
||||||
|
failed_map_path = os.path.join(get_path('stdlib'), '_import_failed', 'import_failed.map')
|
||||||
|
|
||||||
|
if __spec__:
|
||||||
|
failed_name = __spec__.name
|
||||||
|
else:
|
||||||
|
failed_name = __name__
|
||||||
|
|
||||||
|
with open(failed_map_path) as fd:
|
||||||
|
for line in fd:
|
||||||
|
package = line.split(':')[0]
|
||||||
|
imports = line.split(':')[1]
|
||||||
|
if failed_name in imports:
|
||||||
|
raise ImportError(f"""Module '{failed_name}' is not installed.
|
||||||
|
Use:
|
||||||
|
sudo zypper install {package}
|
||||||
|
to install it.""")
|
||||||
|
|
||||||
|
raise ImportError(f"""Module '{failed_name}' is not installed.
|
||||||
|
It is supposed to be part of python3 distribution, but missing from failed import map.
|
||||||
|
Please file a bug on the SUSE Bugzilla.""")
|
30
macros.python3
Normal file
30
macros.python3
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# macros for the primary python3 providing python flavor
|
||||||
|
%have_python3 1
|
||||||
|
|
||||||
|
# commented out legacy macro definitions
|
||||||
|
#py3_prefix /usr
|
||||||
|
#py3_incdir /usr/include/python3.5m
|
||||||
|
#py3_ver 3.5
|
||||||
|
|
||||||
|
# these should now be provided by macros.python_all
|
||||||
|
#python3_sitearch /usr/lib64/python3.5/site-packages
|
||||||
|
#python3_sitelib /usr/lib/python3.5/site-packages
|
||||||
|
#python3_version 3.5
|
||||||
|
|
||||||
|
# hard to say if anyone ever used these?
|
||||||
|
#py3_soflags cpython-35m-x86_64-linux-gnu
|
||||||
|
#py3_abiflags m
|
||||||
|
%cpython3_soabi %(python3 -c "import sysconfig; print(sysconfig.get_config_var('SOABI'))")
|
||||||
|
%py3_soflags %cpython3_soabi
|
||||||
|
|
||||||
|
# compilation macros that might be in use somewhere
|
||||||
|
%py3_compile(O) \
|
||||||
|
find %1 -name '*.pyc' -exec rm -f {} ";"\
|
||||||
|
python3 -c "import sys, os, compileall; br='%{buildroot}'; compileall.compile_dir(sys.argv[1], ddir=br and (sys.argv[1][len(os.path.abspath(br)):]+'/') or None)" %1\
|
||||||
|
%{-O:\
|
||||||
|
find %1 -name '*.pyo' -exec rm -f {} ";"\
|
||||||
|
python3 -O -c "import sys, os, compileall; br='%{buildroot}'; compileall.compile_dir(sys.argv[1], ddir=br and (sys.argv[1][len(os.path.abspath(br)):]+'/') or None)" %1\
|
||||||
|
}
|
||||||
|
|
||||||
|
%python3_default %(s=$(rpm -qf /usr/bin/python3); echo ${s%%%%-*})
|
||||||
|
%default_python3 %(s=$(rpm -qf /usr/bin/python3); echo ${s%%%%-*})
|
79
old-libexpat.patch
Normal file
79
old-libexpat.patch
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
---
|
||||||
|
Lib/test/test_sax.py | 10 +++++-----
|
||||||
|
Lib/test/test_xml_etree.py | 17 ++++++++---------
|
||||||
|
2 files changed, 13 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
--- a/Lib/test/test_sax.py
|
||||||
|
+++ b/Lib/test/test_sax.py
|
||||||
|
@@ -1207,10 +1207,9 @@ class ExpatReaderTest(XmlTestBase):
|
||||||
|
|
||||||
|
self.assertEqual(result.getvalue(), start + b"<doc>text</doc>")
|
||||||
|
|
||||||
|
+ @unittest.skipIf(pyexpat.version_info < (2, 6, 0),
|
||||||
|
+ "Reparse deferral not defined for libexpat < 2.6.0")
|
||||||
|
def test_flush_reparse_deferral_enabled(self):
|
||||||
|
- if pyexpat.version_info < (2, 6, 0):
|
||||||
|
- self.skipTest(f'Expat {pyexpat.version_info} does not support reparse deferral')
|
||||||
|
-
|
||||||
|
result = BytesIO()
|
||||||
|
xmlgen = XMLGenerator(result)
|
||||||
|
parser = create_parser()
|
||||||
|
@@ -1232,6 +1231,8 @@ class ExpatReaderTest(XmlTestBase):
|
||||||
|
|
||||||
|
self.assertEqual(result.getvalue(), start + b"<doc></doc>")
|
||||||
|
|
||||||
|
+ @unittest.skipIf(pyexpat.version_info < (2, 6, 0),
|
||||||
|
+ "Reparse deferral not defined for libexpat < 2.6.0")
|
||||||
|
def test_flush_reparse_deferral_disabled(self):
|
||||||
|
result = BytesIO()
|
||||||
|
xmlgen = XMLGenerator(result)
|
||||||
|
@@ -1241,8 +1242,7 @@ class ExpatReaderTest(XmlTestBase):
|
||||||
|
for chunk in ("<doc", ">"):
|
||||||
|
parser.feed(chunk)
|
||||||
|
|
||||||
|
- if pyexpat.version_info >= (2, 6, 0):
|
||||||
|
- parser._parser.SetReparseDeferralEnabled(False)
|
||||||
|
+ parser._parser.SetReparseDeferralEnabled(False)
|
||||||
|
|
||||||
|
self.assertEqual(result.getvalue(), start) # i.e. no elements started
|
||||||
|
self.assertFalse(parser._parser.GetReparseDeferralEnabled())
|
||||||
|
--- a/Lib/test/test_xml_etree.py
|
||||||
|
+++ b/Lib/test/test_xml_etree.py
|
||||||
|
@@ -1494,11 +1494,9 @@ class XMLPullParserTest(unittest.TestCas
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
ET.XMLPullParser(events=('start', 'end', 'bogus'))
|
||||||
|
|
||||||
|
+ @unittest.skipIf(pyexpat.version_info < (2, 6, 0),
|
||||||
|
+ "Reparse deferral not defined for libexpat < 2.6.0")
|
||||||
|
def test_flush_reparse_deferral_enabled(self):
|
||||||
|
- if pyexpat.version_info < (2, 6, 0):
|
||||||
|
- self.skipTest(f'Expat {pyexpat.version_info} does not '
|
||||||
|
- 'support reparse deferral')
|
||||||
|
-
|
||||||
|
parser = ET.XMLPullParser(events=('start', 'end'))
|
||||||
|
|
||||||
|
for chunk in ("<doc", ">"):
|
||||||
|
@@ -1519,17 +1517,18 @@ class XMLPullParserTest(unittest.TestCas
|
||||||
|
|
||||||
|
self.assert_event_tags(parser, [('end', 'doc')])
|
||||||
|
|
||||||
|
+ @unittest.skipIf(pyexpat.version_info < (2, 6, 0),
|
||||||
|
+ "Reparse deferral not defined for libexpat < 2.6.0")
|
||||||
|
def test_flush_reparse_deferral_disabled(self):
|
||||||
|
parser = ET.XMLPullParser(events=('start', 'end'))
|
||||||
|
|
||||||
|
for chunk in ("<doc", ">"):
|
||||||
|
parser.feed(chunk)
|
||||||
|
|
||||||
|
- if pyexpat.version_info >= (2, 6, 0):
|
||||||
|
- if not ET is pyET:
|
||||||
|
- self.skipTest(f'XMLParser.(Get|Set)ReparseDeferralEnabled '
|
||||||
|
- 'methods not available in C')
|
||||||
|
- parser._parser._parser.SetReparseDeferralEnabled(False)
|
||||||
|
+ if not ET is pyET:
|
||||||
|
+ self.skipTest(f'XMLParser.(Get|Set)ReparseDeferralEnabled '
|
||||||
|
+ 'methods not available in C')
|
||||||
|
+ parser._parser._parser.SetReparseDeferralEnabled(False)
|
||||||
|
|
||||||
|
self.assert_event_tags(parser, []) # i.e. no elements started
|
||||||
|
if ET is pyET:
|
124
platlibdir-in-sys.patch
Normal file
124
platlibdir-in-sys.patch
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
---
|
||||||
|
Include/cpython/initconfig.h | 1 +
|
||||||
|
Lib/test/test_embed.py | 1 +
|
||||||
|
Makefile.pre.in | 5 +++++
|
||||||
|
Python/initconfig.c | 21 +++++++++++++++++++++
|
||||||
|
Python/sysmodule.c | 1 +
|
||||||
|
5 files changed, 29 insertions(+)
|
||||||
|
|
||||||
|
--- a/Include/cpython/initconfig.h
|
||||||
|
+++ b/Include/cpython/initconfig.h
|
||||||
|
@@ -381,6 +381,7 @@ typedef struct {
|
||||||
|
wchar_t *base_prefix; /* sys.base_prefix */
|
||||||
|
wchar_t *exec_prefix; /* sys.exec_prefix */
|
||||||
|
wchar_t *base_exec_prefix; /* sys.base_exec_prefix */
|
||||||
|
+ wchar_t *platlibdir; /* sys.platlibdir */
|
||||||
|
|
||||||
|
/* --- Parameter only used by Py_Main() ---------- */
|
||||||
|
|
||||||
|
--- a/Lib/test/test_embed.py
|
||||||
|
+++ b/Lib/test/test_embed.py
|
||||||
|
@@ -382,6 +382,7 @@ class InitConfigTests(EmbeddingTestsMixi
|
||||||
|
'exec_prefix': GET_DEFAULT_CONFIG,
|
||||||
|
'base_exec_prefix': GET_DEFAULT_CONFIG,
|
||||||
|
'module_search_paths': GET_DEFAULT_CONFIG,
|
||||||
|
+ 'platlibdir': sys.platlibdir,
|
||||||
|
|
||||||
|
'site_import': 1,
|
||||||
|
'bytes_warning': 0,
|
||||||
|
--- a/Makefile.pre.in
|
||||||
|
+++ b/Makefile.pre.in
|
||||||
|
@@ -811,6 +811,11 @@ Python/sysmodule.o: $(srcdir)/Python/sys
|
||||||
|
$(MULTIARCH_CPPFLAGS) \
|
||||||
|
-o $@ $(srcdir)/Python/sysmodule.c
|
||||||
|
|
||||||
|
+Python/initconfig.o: $(srcdir)/Python/initconfig.c
|
||||||
|
+ $(CC) -c $(PY_CORE_CFLAGS) \
|
||||||
|
+ -DPLATLIBDIR='"$(platsubdir)"' \
|
||||||
|
+ -o $@ $(srcdir)/Python/initconfig.c
|
||||||
|
+
|
||||||
|
$(IO_OBJS): $(IO_H)
|
||||||
|
|
||||||
|
.PHONY: regen-grammar
|
||||||
|
--- a/Python/initconfig.c
|
||||||
|
+++ b/Python/initconfig.c
|
||||||
|
@@ -596,6 +596,7 @@ PyConfig_Clear(PyConfig *config)
|
||||||
|
CLEAR(config->base_prefix);
|
||||||
|
CLEAR(config->exec_prefix);
|
||||||
|
CLEAR(config->base_exec_prefix);
|
||||||
|
+ CLEAR(config->platlibdir);
|
||||||
|
|
||||||
|
CLEAR(config->filesystem_encoding);
|
||||||
|
CLEAR(config->filesystem_errors);
|
||||||
|
@@ -834,6 +835,7 @@ _PyConfig_Copy(PyConfig *config, const P
|
||||||
|
COPY_WSTR_ATTR(base_prefix);
|
||||||
|
COPY_WSTR_ATTR(exec_prefix);
|
||||||
|
COPY_WSTR_ATTR(base_exec_prefix);
|
||||||
|
+ COPY_WSTR_ATTR(platlibdir);
|
||||||
|
|
||||||
|
COPY_ATTR(site_import);
|
||||||
|
COPY_ATTR(bytes_warning);
|
||||||
|
@@ -935,6 +937,7 @@ config_as_dict(const PyConfig *config)
|
||||||
|
SET_ITEM_WSTR(base_prefix);
|
||||||
|
SET_ITEM_WSTR(exec_prefix);
|
||||||
|
SET_ITEM_WSTR(base_exec_prefix);
|
||||||
|
+ SET_ITEM_WSTR(platlibdir);
|
||||||
|
SET_ITEM_INT(site_import);
|
||||||
|
SET_ITEM_INT(bytes_warning);
|
||||||
|
SET_ITEM_INT(inspect);
|
||||||
|
@@ -1336,6 +1339,14 @@ config_read_env_vars(PyConfig *config)
|
||||||
|
config->malloc_stats = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if(config->platlibdir == NULL) {
|
||||||
|
+ status = CONFIG_GET_ENV_DUP(config, &config->platlibdir,
|
||||||
|
+ L"PYTHONPLATLIBDIR", "PYTHONPLATLIBDIR");
|
||||||
|
+ if (_PyStatus_EXCEPTION(status)) {
|
||||||
|
+ return status;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (config->pythonpath_env == NULL) {
|
||||||
|
status = CONFIG_GET_ENV_DUP(config, &config->pythonpath_env,
|
||||||
|
L"PYTHONPATH", "PYTHONPATH");
|
||||||
|
@@ -1786,6 +1797,14 @@ config_read(PyConfig *config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if(config->platlibdir == NULL) {
|
||||||
|
+ status = CONFIG_SET_BYTES_STR(config, &config->platlibdir, PLATLIBDIR,
|
||||||
|
+ "PLATLIBDIR macro");
|
||||||
|
+ if (_PyStatus_EXCEPTION(status)) {
|
||||||
|
+ return status;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (config->_install_importlib) {
|
||||||
|
status = _PyConfig_InitPathConfig(config);
|
||||||
|
if (_PyStatus_EXCEPTION(status)) {
|
||||||
|
@@ -2565,6 +2584,7 @@ PyConfig_Read(PyConfig *config)
|
||||||
|
assert(config->exec_prefix != NULL);
|
||||||
|
assert(config->base_exec_prefix != NULL);
|
||||||
|
}
|
||||||
|
+ assert(config->platlibdir != NULL);
|
||||||
|
assert(config->filesystem_encoding != NULL);
|
||||||
|
assert(config->filesystem_errors != NULL);
|
||||||
|
assert(config->stdio_encoding != NULL);
|
||||||
|
@@ -2715,6 +2735,7 @@ _Py_DumpPathConfig(PyThreadState *tstate
|
||||||
|
DUMP_SYS(_base_executable);
|
||||||
|
DUMP_SYS(base_prefix);
|
||||||
|
DUMP_SYS(base_exec_prefix);
|
||||||
|
+ DUMP_SYS(platlibdir);
|
||||||
|
DUMP_SYS(executable);
|
||||||
|
DUMP_SYS(prefix);
|
||||||
|
DUMP_SYS(exec_prefix);
|
||||||
|
--- a/Python/sysmodule.c
|
||||||
|
+++ b/Python/sysmodule.c
|
||||||
|
@@ -2981,6 +2981,7 @@ _PySys_InitMain(_PyRuntimeState *runtime
|
||||||
|
SET_SYS_FROM_WSTR("base_prefix", config->base_prefix);
|
||||||
|
SET_SYS_FROM_WSTR("exec_prefix", config->exec_prefix);
|
||||||
|
SET_SYS_FROM_WSTR("base_exec_prefix", config->base_exec_prefix);
|
||||||
|
+ SET_SYS_FROM_WSTR("platlibdir", config->platlibdir);
|
||||||
|
|
||||||
|
if (config->pycache_prefix != NULL) {
|
||||||
|
SET_SYS_FROM_WSTR("pycache_prefix", config->pycache_prefix);
|
78
pre_checkin.sh
Normal file
78
pre_checkin.sh
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export LC_ALL=C
|
||||||
|
|
||||||
|
master=python*.spec
|
||||||
|
|
||||||
|
# create import_failed.map from package definitions
|
||||||
|
pkgname=$(grep python_pkg_name $master |grep define |awk -F' ' '{print $3}')
|
||||||
|
MAPFILE=import_failed.map
|
||||||
|
function new_map_line () {
|
||||||
|
package=$1
|
||||||
|
package=$(echo $1 |sed -e "s:%{python_pkg_name}:$pkgname:")
|
||||||
|
modules=$2
|
||||||
|
if [ -z "$package" -o -z "$modules" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if [[ "$package" =~ "-base" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
echo "$package:$modules" >> $MAPFILE.tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
for spec in *.spec; do
|
||||||
|
basename=${spec%.spec}
|
||||||
|
package=
|
||||||
|
modules=
|
||||||
|
while read line; do
|
||||||
|
case $line in
|
||||||
|
"%files -n "*)
|
||||||
|
new_map_line $package "$modules"
|
||||||
|
package=${line#"%files -n "}
|
||||||
|
modules=
|
||||||
|
;;
|
||||||
|
"%files "*)
|
||||||
|
new_map_line $package "$modules"
|
||||||
|
package=$basename-${line#"%files "}
|
||||||
|
modules=
|
||||||
|
;;
|
||||||
|
"%files")
|
||||||
|
new_map_line $package "$modules"
|
||||||
|
package=$basename
|
||||||
|
modules=
|
||||||
|
;;
|
||||||
|
"%{sitedir}/config-"*)
|
||||||
|
# ignore
|
||||||
|
;;
|
||||||
|
"%{sitedir}/"*)
|
||||||
|
word=${line#"%{sitedir}/"}
|
||||||
|
if ! echo $word | grep -q /; then
|
||||||
|
modules="$modules $word"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
"%{dynlib "*"}")
|
||||||
|
word=${line#"%{dynlib "}
|
||||||
|
word=${word%"}"}
|
||||||
|
modules="$modules $word"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done < $spec
|
||||||
|
new_map_line $package "$modules"
|
||||||
|
done
|
||||||
|
|
||||||
|
cat $MAPFILE.tmp |sort -u > $MAPFILE
|
||||||
|
rm $MAPFILE.tmp
|
||||||
|
|
||||||
|
# run test inclusion check
|
||||||
|
tar xJf Python-*.xz
|
||||||
|
python3 skipped_tests.py
|
||||||
|
|
||||||
|
# generate baselibs.conf
|
||||||
|
VERSION=$(grep ^Version $master|awk -F':' '{print $2}' |sed -e 's/ //g')
|
||||||
|
python_version=${VERSION:0:3} # 3.3
|
||||||
|
python_version_abitag=${python_version//./} # 33
|
||||||
|
python_version_soname=${python_version//./_} # 3_3
|
||||||
|
echo "$pkgname-base" > baselibs.conf
|
||||||
|
echo "$pkgname" >> baselibs.conf
|
||||||
|
echo "libpython$python_version_soname-1_0" >> baselibs.conf
|
||||||
|
|
25
python-3.3.0b1-fix_date_time_compiler.patch
Normal file
25
python-3.3.0b1-fix_date_time_compiler.patch
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
Makefile.pre.in | 7 +++++++
|
||||||
|
1 file changed, 7 insertions(+)
|
||||||
|
|
||||||
|
--- a/Makefile.pre.in
|
||||||
|
+++ b/Makefile.pre.in
|
||||||
|
@@ -758,11 +758,18 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \
|
||||||
|
$(DTRACE_OBJS) \
|
||||||
|
$(srcdir)/Modules/getbuildinfo.c
|
||||||
|
$(CC) -c $(PY_CORE_CFLAGS) \
|
||||||
|
+ -DDATE="\"`date -u -r Makefile.pre.in +"%b %d %Y"`\"" \
|
||||||
|
+ -DTIME="\"`date -u -r Makefile.pre.in +"%T"`\"" \
|
||||||
|
-DGITVERSION="\"`LC_ALL=C $(GITVERSION)`\"" \
|
||||||
|
-DGITTAG="\"`LC_ALL=C $(GITTAG)`\"" \
|
||||||
|
-DGITBRANCH="\"`LC_ALL=C $(GITBRANCH)`\"" \
|
||||||
|
-o $@ $(srcdir)/Modules/getbuildinfo.c
|
||||||
|
|
||||||
|
+Python/getcompiler.o: $(srcdir)/Python/getcompiler.c Makefile
|
||||||
|
+ $(CC) -c $(PY_CORE_CFLAGS) \
|
||||||
|
+ -DCOMPILER='"[GCC]"' \
|
||||||
|
+ -o $@ $(srcdir)/Python/getcompiler.c
|
||||||
|
+
|
||||||
|
Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile
|
||||||
|
$(CC) -c $(PY_CORE_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \
|
||||||
|
-DPREFIX='"$(prefix)"' \
|
15
python-3.3.0b1-localpath.patch
Normal file
15
python-3.3.0b1-localpath.patch
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
Lib/site.py | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/Lib/site.py
|
||||||
|
+++ b/Lib/site.py
|
||||||
|
@@ -77,7 +77,7 @@ import io
|
||||||
|
import stat
|
||||||
|
|
||||||
|
# Prefixes for site-packages; add additional prefixes like /usr/local here
|
||||||
|
-PREFIXES = [sys.prefix, sys.exec_prefix]
|
||||||
|
+PREFIXES = [sys.prefix, sys.exec_prefix, '/usr/local']
|
||||||
|
# Enable per user site-packages directory
|
||||||
|
# set it to False to disable the feature or True to force the feature
|
||||||
|
ENABLE_USER_SITE = None
|
11
python-3.3.0b1-test-posix_fadvise.patch
Normal file
11
python-3.3.0b1-test-posix_fadvise.patch
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
--- a/Lib/test/test_posix.py
|
||||||
|
+++ b/Lib/test/test_posix.py
|
||||||
|
@@ -421,7 +421,7 @@ class PosixTester(unittest.TestCase):
|
||||||
|
def test_posix_fadvise(self):
|
||||||
|
fd = os.open(support.TESTFN, os.O_RDONLY)
|
||||||
|
try:
|
||||||
|
- posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_WILLNEED)
|
||||||
|
+ posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_RANDOM)
|
||||||
|
finally:
|
||||||
|
os.close(fd)
|
||||||
|
|
664
python.keyring
Normal file
664
python.keyring
Normal file
@ -0,0 +1,664 @@
|
|||||||
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
|
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
|
||||||
|
Lrfee+7yz1F9N6mVsuyl21KxQV8PGw==
|
||||||
|
=r/zi
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----
|
53
python3-imp-returntype.patch
Normal file
53
python3-imp-returntype.patch
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
From 7bd6f0e5500f778e940374237b94651f60ae1990 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Miss Islington (bot)"
|
||||||
|
<31488909+miss-islington@users.noreply.github.com>
|
||||||
|
Date: Fri, 6 Jul 2018 21:00:45 -0700
|
||||||
|
Subject: [PATCH] closes bpo-34056: Always return bytes from
|
||||||
|
_HackedGetData.get_data(). (GH-8130)
|
||||||
|
|
||||||
|
* Always return bytes from _HackedGetData.get_data().
|
||||||
|
|
||||||
|
Ensure the imp.load_source shim always returns bytes by reopening the file in
|
||||||
|
binary mode if needed. Hash-based pycs have to receive the source code in bytes.
|
||||||
|
|
||||||
|
It's tempting to change imp.get_suffixes() to always return 'rb' as a mode, but
|
||||||
|
that breaks some stdlib tests and likely 3rdparty code, too.
|
||||||
|
(cherry picked from commit b0274f2cddd36b49fe5080efbe160277ef546471)
|
||||||
|
|
||||||
|
Co-authored-by: Benjamin Peterson <benjamin@python.org>
|
||||||
|
---
|
||||||
|
Lib/imp.py | 13 ++++++-------
|
||||||
|
Lib/test/test_imp.py | 15 +++++++++++++++
|
||||||
|
.../2018-07-05-22-45-46.bpo-34056.86isrU.rst | 3 +++
|
||||||
|
3 files changed, 24 insertions(+), 7 deletions(-)
|
||||||
|
create mode 100644 Misc/NEWS.d/next/Library/2018-07-05-22-45-46.bpo-34056.86isrU.rst
|
||||||
|
|
||||||
|
--- a/Lib/test/test_imp.py
|
||||||
|
+++ b/Lib/test/test_imp.py
|
||||||
|
@@ -376,6 +376,20 @@ class ImportTests(unittest.TestCase):
|
||||||
|
mod = imp.load_module('mymod', file, path, description)
|
||||||
|
self.assertEqual(mod.x, 42)
|
||||||
|
|
||||||
|
+ def test_find_and_load_checked_pyc(self):
|
||||||
|
+ # issue 34056
|
||||||
|
+ with support.temp_cwd():
|
||||||
|
+ with open('mymod.py', 'wb') as fp:
|
||||||
|
+ fp.write(b'x = 42\n')
|
||||||
|
+ py_compile.compile(
|
||||||
|
+ 'mymod.py',
|
||||||
|
+ doraise=True,
|
||||||
|
+ invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH,
|
||||||
|
+ )
|
||||||
|
+ file, path, description = imp.find_module('mymod', path=['.'])
|
||||||
|
+ mod = imp.load_module('mymod', file, path, description)
|
||||||
|
+ self.assertEqual(mod.x, 42)
|
||||||
|
+
|
||||||
|
|
||||||
|
class ReloadTests(unittest.TestCase):
|
||||||
|
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Misc/NEWS.d/next/Library/2018-07-05-22-45-46.bpo-34056.86isrU.rst
|
||||||
|
@@ -0,0 +1,3 @@
|
||||||
|
+Ensure the loader shim created by ``imp.load_module`` always returns bytes
|
||||||
|
+from its ``get_data()`` function. This fixes using ``imp.load_module`` with
|
||||||
|
+:pep:`552` hash-based pycs.
|
2657
python38.changes
Normal file
2657
python38.changes
Normal file
File diff suppressed because it is too large
Load Diff
1043
python38.spec
Normal file
1043
python38.spec
Normal file
File diff suppressed because it is too large
Load Diff
143
skip_random_failing_tests.patch
Normal file
143
skip_random_failing_tests.patch
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
From: Michel Normand <normand@linux.vnet.ibm.com>
|
||||||
|
Subject: skip random failing tests
|
||||||
|
Date: Thu, 18 Jan 2018 15:48:52 +0100
|
||||||
|
|
||||||
|
skip random failing tests:
|
||||||
|
in _test_multiprocessing.py:
|
||||||
|
test_async_timeout
|
||||||
|
test_waitfor_timeout
|
||||||
|
test_wait_integer
|
||||||
|
in test_events.py:
|
||||||
|
test_run_until_complete
|
||||||
|
test_signal_handling_args
|
||||||
|
test_call_later
|
||||||
|
|
||||||
|
Reported to fail on ppc64le host on multiple osc build trials:
|
||||||
|
(all failed for ppc64le, except one for ppc)
|
||||||
|
===
|
||||||
|
[michel@abanc:~/work/home:michel_mno:branches:devel:languages:python:Factory/python3]
|
||||||
|
$idx=1; while test 1; do echo "trial $idx:"; osc build \
|
||||||
|
--vm-type kvm -j 8 --threads 4 openSUSE_Factory_PowerPC ppc64le \
|
||||||
|
>/tmp/python3_trialx_${idx}.log 2>&1 || break; ((idx++)); done
|
||||||
|
===
|
||||||
|
FAIL: test_async_timeout (test.test_multiprocessing_fork.WithProcessesTestPool)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/home/abuild/rpmbuild/BUILD/Python-3.6.4/Lib/test/_test_multiprocessing.py", line 2017, in test_async_timeout
|
||||||
|
self.assertRaises(multiprocessing.TimeoutError, get, timeout=TIMEOUT2)
|
||||||
|
AssertionError: TimeoutError not raised by <test._test_multiprocessing.TimingWrapper object at 0x7fff89b45f28>
|
||||||
|
===
|
||||||
|
FAIL: test_waitfor_timeout (test.test_multiprocessing_spawn.WithManagerTestCondition)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/home/abuild/rpmbuild/BUILD/Python-3.6.4/Lib/test/_test_multiprocessing.py", line 1169, in test_waitfor_timeout
|
||||||
|
self.assertTrue(success.value)
|
||||||
|
AssertionError: False is not true
|
||||||
|
===
|
||||||
|
FAIL: test_run_until_complete (test.test_asyncio.test_events.SelectEventLoopTests)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/home/abuild/rpmbuild/BUILD/Python-3.6.4/Lib/test/test_asyncio/test_events.py", line 285, in test_run_until_complete
|
||||||
|
self.assertTrue(0.08 <= t1-t0 <= 0.8, t1-t0)
|
||||||
|
AssertionError: False is not true : 3.966844968999993
|
||||||
|
===
|
||||||
|
FAIL: test_signal_handling_args (test.test_asyncio.test_events.SelectEventLoopTests)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/home/abuild/rpmbuild/BUILD/Python-3.6.4/Lib/test/test_asyncio/test_events.py", line 566, in test_signal_handling_args
|
||||||
|
self.assertEqual(caught, 1)
|
||||||
|
AssertionError: 0 != 1
|
||||||
|
=== (ppc)
|
||||||
|
FAIL: test_wait_integer (test.test_multiprocessing_spawn.TestWait)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/home/abuild/rpmbuild/BUILD/Python-3.6.4/Lib/test/_test_multiprocessing.py", line 3762, in test_wait_integer
|
||||||
|
self.assertLess(delta, expected + 2)
|
||||||
|
AssertionError: 5.576360702514648 not less than 5
|
||||||
|
===
|
||||||
|
===
|
||||||
|
======================================================================
|
||||||
|
FAIL: test_call_later (test.test_asyncio.test_events.PollEventLoopTests)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/home/abuild/rpmbuild/BUILD/Python-3.6.4/Lib/test/test_asyncio/test_events.py", line 309, in test_call_later
|
||||||
|
self.assertTrue(0.08 <= t1-t0 <= 0.8, t1-t0)
|
||||||
|
AssertionError: False is not true : 2.7154626529999746
|
||||||
|
|
||||||
|
======================================================================
|
||||||
|
FAIL: test_call_later (test.test_asyncio.test_events.SelectEventLoopTests)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/home/abuild/rpmbuild/BUILD/Python-3.6.4/Lib/test/test_asyncio/test_events.py", line 309, in test_call_later
|
||||||
|
self.assertTrue(0.08 <= t1-t0 <= 0.8, t1-t0)
|
||||||
|
AssertionError: False is not true : 4.137590406000015
|
||||||
|
===
|
||||||
|
|
||||||
|
|
||||||
|
Signed-off-by: Michel Normand <normand@linux.vnet.ibm.com>
|
||||||
|
---
|
||||||
|
Lib/test/_test_multiprocessing.py | 3 +++
|
||||||
|
Lib/test/test_asyncio/test_events.py | 4 +++-
|
||||||
|
Lib/test/test_buffer.py | 1 +
|
||||||
|
3 files changed, 7 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/Lib/test/_test_multiprocessing.py
|
||||||
|
+++ b/Lib/test/_test_multiprocessing.py
|
||||||
|
@@ -1542,6 +1542,7 @@ class _TestCondition(BaseTestCase):
|
||||||
|
success.value = True
|
||||||
|
|
||||||
|
@unittest.skipUnless(HAS_SHAREDCTYPES, 'needs sharedctypes')
|
||||||
|
+ @unittest.skip("transient failure on PowerPC")
|
||||||
|
def test_waitfor_timeout(self):
|
||||||
|
# based on test in test/lock_tests.py
|
||||||
|
cond = self.Condition()
|
||||||
|
@@ -2432,6 +2433,7 @@ class _TestPool(BaseTestCase):
|
||||||
|
self.assertEqual(get(), 49)
|
||||||
|
self.assertTimingAlmostEqual(get.elapsed, TIMEOUT1)
|
||||||
|
|
||||||
|
+ @unittest.skip("transient failure on PowerPC")
|
||||||
|
def test_async_timeout(self):
|
||||||
|
res = self.pool.apply_async(sqr, (6, TIMEOUT2 + 1.0))
|
||||||
|
get = TimingWrapper(res.get)
|
||||||
|
@@ -4651,6 +4653,7 @@ class TestWait(unittest.TestCase):
|
||||||
|
sem.release()
|
||||||
|
time.sleep(period)
|
||||||
|
|
||||||
|
+ @unittest.skip("transient failure on PowerPC")
|
||||||
|
def test_wait_integer(self):
|
||||||
|
from multiprocessing.connection import wait
|
||||||
|
|
||||||
|
--- a/Lib/test/test_asyncio/test_events.py
|
||||||
|
+++ b/Lib/test/test_asyncio/test_events.py
|
||||||
|
@@ -268,11 +268,12 @@ class EventLoopTestsMixin:
|
||||||
|
# Note: because of the default Windows timing granularity of
|
||||||
|
# 15.6 msec, we use fairly long sleep times here (~100 msec).
|
||||||
|
|
||||||
|
+ @unittest.skip("transient failure on PowerPC")
|
||||||
|
def test_run_until_complete(self):
|
||||||
|
t0 = self.loop.time()
|
||||||
|
self.loop.run_until_complete(asyncio.sleep(0.1))
|
||||||
|
t1 = self.loop.time()
|
||||||
|
- self.assertTrue(0.08 <= t1-t0 <= 0.8, t1-t0)
|
||||||
|
+ self.assertTrue(0.08 <= t1-t0 <= 5.0, t1-t0)
|
||||||
|
|
||||||
|
def test_run_until_complete_stopped(self):
|
||||||
|
|
||||||
|
@@ -477,6 +478,7 @@ class EventLoopTestsMixin:
|
||||||
|
self.assertEqual(caught, 1)
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(signal, 'SIGALRM'), 'No SIGALRM')
|
||||||
|
+ @unittest.skip("transient failure on PowerPC")
|
||||||
|
def test_signal_handling_args(self):
|
||||||
|
some_args = (42,)
|
||||||
|
caught = 0
|
||||||
|
--- a/Lib/test/test_buffer.py
|
||||||
|
+++ b/Lib/test/test_buffer.py
|
||||||
|
@@ -2506,6 +2506,7 @@ class TestBufferProtocol(unittest.TestCa
|
||||||
|
a = ndarray(items, shape=[2, 2, 2], format="b")
|
||||||
|
check(memoryview(a), vsize(base_struct + 3 * per_dim))
|
||||||
|
|
||||||
|
+ @unittest.skip("transient failure on PowerPC")
|
||||||
|
def test_memoryview_struct_module(self):
|
||||||
|
|
||||||
|
class INT(object):
|
69
skipped_tests.py
Normal file
69
skipped_tests.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""
|
||||||
|
Simple regexp-based skipped test checker.
|
||||||
|
It lists tests that are mentioned (presumably for exclusion)
|
||||||
|
in BASE, and in MAIN (presumably for inclusion)
|
||||||
|
and reports discrepancies.
|
||||||
|
|
||||||
|
This will have a number of
|
||||||
|
"""
|
||||||
|
|
||||||
|
MAIN = "python38.spec"
|
||||||
|
|
||||||
|
import glob
|
||||||
|
import re
|
||||||
|
from os.path import basename
|
||||||
|
|
||||||
|
alltests = set()
|
||||||
|
qemu_exclusions = set()
|
||||||
|
|
||||||
|
for item in glob.glob("Python-*/Lib/test/test_*"):
|
||||||
|
testname = basename(item)
|
||||||
|
if testname.endswith(".py"):
|
||||||
|
testname = testname[:-3]
|
||||||
|
alltests.add(testname)
|
||||||
|
|
||||||
|
testre = re.compile(r'[\s"](test_\w+)\b')
|
||||||
|
|
||||||
|
def find_tests_in_spec(specname):
|
||||||
|
global qemu_exclusions
|
||||||
|
|
||||||
|
found_tests = set()
|
||||||
|
with open(specname) as spec:
|
||||||
|
in_qemu = False
|
||||||
|
for line in spec:
|
||||||
|
line = line.strip()
|
||||||
|
if "#" in line:
|
||||||
|
line = line[:line.index("#")]
|
||||||
|
tests = set(testre.findall(line))
|
||||||
|
found_tests |= tests
|
||||||
|
if line == "%if 0%{?qemu_user_space_build} > 0":
|
||||||
|
in_qemu = True
|
||||||
|
if in_qemu:
|
||||||
|
if line == "%endif":
|
||||||
|
in_qemu = False
|
||||||
|
qemu_exclusions |= tests
|
||||||
|
return found_tests
|
||||||
|
|
||||||
|
excluded = find_tests_in_spec(MAIN)
|
||||||
|
|
||||||
|
#print("--- excluded tests:", " ".join(sorted(excluded)))
|
||||||
|
#print("--- included tests:", " ".join(sorted(included)))
|
||||||
|
|
||||||
|
mentioned = excluded
|
||||||
|
nonexistent = mentioned - alltests
|
||||||
|
missing = excluded - qemu_exclusions
|
||||||
|
|
||||||
|
print("--- the following tests are excluded for QEMU and not tested in python")
|
||||||
|
print("--- (that probably means we don't need to worry about them)")
|
||||||
|
for test in sorted(qemu_exclusions - excluded):
|
||||||
|
print(test)
|
||||||
|
|
||||||
|
print("--- the following tests might be excluded in python:")
|
||||||
|
for test in sorted(missing):
|
||||||
|
print(test)
|
||||||
|
|
||||||
|
if nonexistent:
|
||||||
|
print("--- the following tests don't exist:")
|
||||||
|
for test in sorted(nonexistent):
|
||||||
|
print(test)
|
26
sphinx-update-removed-function.patch
Normal file
26
sphinx-update-removed-function.patch
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
From 960bb883769e5c64a63b014590d75654db87ffb0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pablo Galindo <Pablogsal@gmail.com>
|
||||||
|
Date: Fri, 10 May 2019 22:58:17 +0100
|
||||||
|
Subject: [PATCH] Fix sphinx deprecation warning about env.note_versionchange()
|
||||||
|
(GH-13236)
|
||||||
|
|
||||||
|
---
|
||||||
|
Doc/tools/extensions/pyspecific.py | 7 ++++++-
|
||||||
|
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/Doc/tools/extensions/pyspecific.py
|
||||||
|
+++ b/Doc/tools/extensions/pyspecific.py
|
||||||
|
@@ -384,7 +384,12 @@ class DeprecatedRemoved(Directive):
|
||||||
|
translatable=False)
|
||||||
|
node.append(para)
|
||||||
|
env = self.state.document.settings.env
|
||||||
|
- env.get_domain('changeset').note_changeset(node)
|
||||||
|
+ # new method
|
||||||
|
+ if hasattr(env, 'get_domain'):
|
||||||
|
+ env.get_domain('changeset').note_changeset(node)
|
||||||
|
+ # deprecated pre-Sphinx-2 method
|
||||||
|
+ else:
|
||||||
|
+ env.note_versionchange('deprecated', version[0], node, self.lineno)
|
||||||
|
return [node] + messages
|
||||||
|
|
||||||
|
|
12
subprocess-raise-timeout.patch
Normal file
12
subprocess-raise-timeout.patch
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
--- a/Lib/test/test_subprocess.py
|
||||||
|
+++ b/Lib/test/test_subprocess.py
|
||||||
|
@@ -1147,7 +1147,8 @@ class ProcessTestCase(BaseTestCase):
|
||||||
|
self.assertIn("0.0001", str(c.exception)) # For coverage of __str__.
|
||||||
|
# Some heavily loaded buildbots (sparc Debian 3.x) require this much
|
||||||
|
# time to start.
|
||||||
|
- self.assertEqual(p.wait(timeout=3), 0)
|
||||||
|
+ # OBS might require even more
|
||||||
|
+ self.assertEqual(p.wait(timeout=10), 0)
|
||||||
|
|
||||||
|
def test_invalid_bufsize(self):
|
||||||
|
# an invalid type of the bufsize argument should raise
|
71
support-expat-CVE-2022-25236-patched.patch
Normal file
71
support-expat-CVE-2022-25236-patched.patch
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
From 7da97f61816f3cadaa6788804b22a2434b40e8c5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Miss Islington (bot)"
|
||||||
|
<31488909+miss-islington@users.noreply.github.com>
|
||||||
|
Date: Mon, 21 Feb 2022 08:16:09 -0800
|
||||||
|
Subject: [PATCH] bpo-46811: Make test suite support Expat >=2.4.5 (GH-31453)
|
||||||
|
(GH-31472)
|
||||||
|
|
||||||
|
Curly brackets were never allowed in namespace URIs
|
||||||
|
according to RFC 3986, and so-called namespace-validating
|
||||||
|
XML parsers have the right to reject them a invalid URIs.
|
||||||
|
|
||||||
|
libexpat >=2.4.5 has become strcter in that regard due to
|
||||||
|
related security issues; with ET.XML instantiating a
|
||||||
|
namespace-aware parser under the hood, this test has no
|
||||||
|
future in CPython.
|
||||||
|
|
||||||
|
References:
|
||||||
|
- https://datatracker.ietf.org/doc/html/rfc3968
|
||||||
|
- https://www.w3.org/TR/xml-names/
|
||||||
|
|
||||||
|
Also, test_minidom.py: Support Expat >=2.4.5
|
||||||
|
(cherry picked from commit 2cae93832f46b245847bdc252456ddf7742ef45e)
|
||||||
|
|
||||||
|
Co-authored-by: Sebastian Pipping <sebastian@pipping.org>
|
||||||
|
---
|
||||||
|
Lib/test/test_minidom.py | 25 +++++++++++--------------
|
||||||
|
1 file changed, 11 insertions(+), 14 deletions(-)
|
||||||
|
create mode 100644 Misc/NEWS.d/next/Library/2022-02-20-21-03-31.bpo-46811.8BxgdQ.rst
|
||||||
|
|
||||||
|
--- a/Lib/test/test_minidom.py
|
||||||
|
+++ b/Lib/test/test_minidom.py
|
||||||
|
@@ -1149,14 +1149,12 @@ class MinidomTest(unittest.TestCase):
|
||||||
|
|
||||||
|
# Verify that character decoding errors raise exceptions instead
|
||||||
|
# of crashing
|
||||||
|
- if pyexpat.version_info >= (2, 4, 5):
|
||||||
|
- self.assertRaises(ExpatError, parseString,
|
||||||
|
- b'<fran\xe7ais></fran\xe7ais>')
|
||||||
|
- self.assertRaises(ExpatError, parseString,
|
||||||
|
- b'<franais>Comment \xe7a va ? Tr\xe8s bien ?</franais>')
|
||||||
|
- else:
|
||||||
|
- self.assertRaises(UnicodeDecodeError, parseString,
|
||||||
|
- b'<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
|
||||||
|
+ # It doesn’t make any sense to insist on the exact text of the
|
||||||
|
+ # error message, or even the exact Exception … it is enough that
|
||||||
|
+ # the error has been discovered.
|
||||||
|
+ with self.assertRaises((UnicodeDecodeError, ExpatError)):
|
||||||
|
+ parseString(
|
||||||
|
+ b'<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
|
||||||
|
|
||||||
|
doc.unlink()
|
||||||
|
|
||||||
|
@@ -1601,13 +1599,12 @@ class MinidomTest(unittest.TestCase):
|
||||||
|
self.confirm(doc2.namespaceURI == xml.dom.EMPTY_NAMESPACE)
|
||||||
|
|
||||||
|
def testExceptionOnSpacesInXMLNSValue(self):
|
||||||
|
- if pyexpat.version_info >= (2, 4, 5):
|
||||||
|
- context = self.assertRaisesRegex(ExpatError, 'syntax error')
|
||||||
|
- else:
|
||||||
|
- context = self.assertRaisesRegex(ValueError, 'Unsupported syntax')
|
||||||
|
+ # It doesn’t make any sense to insist on the exact text of the
|
||||||
|
+ # error message, or even the exact Exception … it is enough that
|
||||||
|
+ # the error has been discovered.
|
||||||
|
+ with self.assertRaises((ExpatError, ValueError)):
|
||||||
|
+ parseString('<element xmlns:abc="http:abc.com/de f g/hi/j k"><abc:foo /></element>')
|
||||||
|
|
||||||
|
- with context:
|
||||||
|
- parseString('<element xmlns:abc="http:abc.com/de f g/hi/j k"><abc:foo /></element>')
|
||||||
|
|
||||||
|
def testDocRemoveChild(self):
|
||||||
|
doc = parse(tstfile)
|
Loading…
Reference in New Issue
Block a user