forked from pool/python39
Compare commits
No commits in common. "devel" and "devel" have entirely different histories.
97
CVE-2024-11168-validation-IPv6-addrs.patch
Normal file
97
CVE-2024-11168-validation-IPv6-addrs.patch
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
From 37bc08c699f48461be5e000b2da9212237a1ca0f Mon Sep 17 00:00:00 2001
|
||||||
|
From: JohnJamesUtley <jjutley231@gmail.com>
|
||||||
|
Date: Tue, 25 Apr 2023 16:01:03 -0400
|
||||||
|
Subject: [PATCH 1/4] Adds checks to ensure that bracketed hosts found by
|
||||||
|
urlsplit are of IPv6 or IPvFuture format
|
||||||
|
|
||||||
|
---
|
||||||
|
Lib/test/test_urlparse.py | 26 ++++++++++
|
||||||
|
Lib/urllib/parse.py | 16 +++++-
|
||||||
|
Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst | 2
|
||||||
|
3 files changed, 43 insertions(+), 1 deletion(-)
|
||||||
|
create mode 100644 Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst
|
||||||
|
|
||||||
|
--- a/Lib/test/test_urlparse.py
|
||||||
|
+++ b/Lib/test/test_urlparse.py
|
||||||
|
@@ -1135,6 +1135,32 @@ class UrlParseTestCase(unittest.TestCase
|
||||||
|
self.assertEqual(p2.scheme, 'tel')
|
||||||
|
self.assertEqual(p2.path, '+31641044153')
|
||||||
|
|
||||||
|
+ def test_invalid_bracketed_hosts(self):
|
||||||
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[192.0.2.146]/Path?Query')
|
||||||
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[important.com:8000]/Path?Query')
|
||||||
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v123r.IP]/Path?Query')
|
||||||
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v12ae]/Path?Query')
|
||||||
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v.IP]/Path?Query')
|
||||||
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v123.]/Path?Query')
|
||||||
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v]/Path?Query')
|
||||||
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af::2309::fae7:1234]/Path?Query')
|
||||||
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af:2309::fae7:1234:2342:438e:192.0.2.146]/Path?Query')
|
||||||
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@]v6a.ip[/Path')
|
||||||
|
+
|
||||||
|
+ def test_splitting_bracketed_hosts(self):
|
||||||
|
+ p1 = urllib.parse.urlsplit('scheme://user@[v6a.ip]/path?query')
|
||||||
|
+ self.assertEqual(p1.hostname, 'v6a.ip')
|
||||||
|
+ self.assertEqual(p1.username, 'user')
|
||||||
|
+ self.assertEqual(p1.path, '/path')
|
||||||
|
+ p2 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7%test]/path?query')
|
||||||
|
+ self.assertEqual(p2.hostname, '0439:23af:2309::fae7%test')
|
||||||
|
+ self.assertEqual(p2.username, 'user')
|
||||||
|
+ self.assertEqual(p2.path, '/path')
|
||||||
|
+ p3 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7:1234:192.0.2.146%test]/path?query')
|
||||||
|
+ self.assertEqual(p3.hostname, '0439:23af:2309::fae7:1234:192.0.2.146%test')
|
||||||
|
+ self.assertEqual(p3.username, 'user')
|
||||||
|
+ self.assertEqual(p3.path, '/path')
|
||||||
|
+
|
||||||
|
def test_port_casting_failure_message(self):
|
||||||
|
message = "Port could not be cast to integer value as 'oracle'"
|
||||||
|
p1 = urllib.parse.urlparse('http://Server=sde; Service=sde:oracle')
|
||||||
|
--- a/Lib/urllib/parse.py
|
||||||
|
+++ b/Lib/urllib/parse.py
|
||||||
|
@@ -36,6 +36,7 @@ import sys
|
||||||
|
import types
|
||||||
|
import collections
|
||||||
|
import warnings
|
||||||
|
+import ipaddress
|
||||||
|
|
||||||
|
__all__ = ["urlparse", "urlunparse", "urljoin", "urldefrag",
|
||||||
|
"urlsplit", "urlunsplit", "urlencode", "parse_qs",
|
||||||
|
@@ -442,6 +443,17 @@ def _checknetloc(netloc):
|
||||||
|
raise ValueError("netloc '" + netloc + "' contains invalid " +
|
||||||
|
"characters under NFKC normalization")
|
||||||
|
|
||||||
|
+# Valid bracketed hosts are defined in
|
||||||
|
+# https://www.rfc-editor.org/rfc/rfc3986#page-49 and https://url.spec.whatwg.org/
|
||||||
|
+def _check_bracketed_host(hostname):
|
||||||
|
+ if hostname.startswith('v'):
|
||||||
|
+ if not re.match(r"\Av[a-fA-F0-9]+\..+\Z", hostname):
|
||||||
|
+ raise ValueError(f"IPvFuture address is invalid")
|
||||||
|
+ else:
|
||||||
|
+ ip = ipaddress.ip_address(hostname) # Throws Value Error if not IPv6 or IPv4
|
||||||
|
+ if isinstance(ip, ipaddress.IPv4Address):
|
||||||
|
+ raise ValueError(f"An IPv4 address cannot be in brackets")
|
||||||
|
+
|
||||||
|
def urlsplit(url, scheme='', allow_fragments=True):
|
||||||
|
"""Parse a URL into 5 components:
|
||||||
|
<scheme>://<netloc>/<path>?<query>#<fragment>
|
||||||
|
@@ -488,12 +500,14 @@ def urlsplit(url, scheme='', allow_fragm
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
scheme, url = url[:i].lower(), url[i+1:]
|
||||||
|
-
|
||||||
|
if url[:2] == '//':
|
||||||
|
netloc, url = _splitnetloc(url, 2)
|
||||||
|
if (('[' in netloc and ']' not in netloc) or
|
||||||
|
(']' in netloc and '[' not in netloc)):
|
||||||
|
raise ValueError("Invalid IPv6 URL")
|
||||||
|
+ if '[' in netloc and ']' in netloc:
|
||||||
|
+ bracketed_host = netloc.partition('[')[2].partition(']')[0]
|
||||||
|
+ _check_bracketed_host(bracketed_host)
|
||||||
|
if allow_fragments and '#' in url:
|
||||||
|
url, fragment = url.split('#', 1)
|
||||||
|
if '?' in url:
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst
|
||||||
|
@@ -0,0 +1,2 @@
|
||||||
|
+Add checks to ensure that ``[`` bracketed ``]`` hosts found by
|
||||||
|
+:func:`urllib.parse.urlsplit` are of IPv6 or IPvFuture format.
|
282
CVE-2024-9287-venv_path_unquoted.patch
Normal file
282
CVE-2024-9287-venv_path_unquoted.patch
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
From ae0d64cb185900712c40a65d7d8aa118f9903d57 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Victor Stinner <vstinner@python.org>
|
||||||
|
Date: Fri, 1 Nov 2024 14:11:47 +0100
|
||||||
|
Subject: [PATCH] [3.11] gh-124651: Quote template strings in `venv` activation
|
||||||
|
scripts (GH-124712) (GH-126185) (#126269)
|
||||||
|
|
||||||
|
(cherry picked from commit ae961ae94bf19c8f8c7fbea3d1c25cc55ce8ae97)
|
||||||
|
---
|
||||||
|
Lib/test/test_venv.py | 81 ++++++++++
|
||||||
|
Lib/venv/__init__.py | 42 ++++-
|
||||||
|
Lib/venv/scripts/common/activate | 6
|
||||||
|
Lib/venv/scripts/nt/activate.bat | 4
|
||||||
|
Lib/venv/scripts/posix/activate.csh | 6
|
||||||
|
Lib/venv/scripts/posix/activate.fish | 6
|
||||||
|
Misc/NEWS.d/next/Library/2024-09-28-02-03-04.gh-issue-124651.bLBGtH.rst | 1
|
||||||
|
7 files changed, 130 insertions(+), 16 deletions(-)
|
||||||
|
create mode 100644 Misc/NEWS.d/next/Library/2024-09-28-02-03-04.gh-issue-124651.bLBGtH.rst
|
||||||
|
|
||||||
|
--- a/Lib/test/test_venv.py
|
||||||
|
+++ b/Lib/test/test_venv.py
|
||||||
|
@@ -14,6 +14,7 @@ import struct
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
+import shlex
|
||||||
|
from test.support import (captured_stdout, captured_stderr, requires_zlib,
|
||||||
|
can_symlink, EnvironmentVarGuard, rmtree,
|
||||||
|
import_module,
|
||||||
|
@@ -85,6 +86,10 @@ class BaseTest(unittest.TestCase):
|
||||||
|
result = f.read()
|
||||||
|
return result
|
||||||
|
|
||||||
|
+ def assertEndsWith(self, string, tail):
|
||||||
|
+ if not string.endswith(tail):
|
||||||
|
+ self.fail(f"String {string!r} does not end with {tail!r}")
|
||||||
|
+
|
||||||
|
class BasicTest(BaseTest):
|
||||||
|
"""Test venv module functionality."""
|
||||||
|
|
||||||
|
@@ -342,6 +347,82 @@ class BasicTest(BaseTest):
|
||||||
|
'import sys; print(sys.executable)'])
|
||||||
|
self.assertEqual(out.strip(), envpy.encode())
|
||||||
|
|
||||||
|
+ # gh-124651: test quoted strings
|
||||||
|
+ @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows')
|
||||||
|
+ def test_special_chars_bash(self):
|
||||||
|
+ """
|
||||||
|
+ Test that the template strings are quoted properly (bash)
|
||||||
|
+ """
|
||||||
|
+ rmtree(self.env_dir)
|
||||||
|
+ bash = shutil.which('bash')
|
||||||
|
+ if bash is None:
|
||||||
|
+ self.skipTest('bash required for this test')
|
||||||
|
+ env_name = '"\';&&$e|\'"'
|
||||||
|
+ env_dir = os.path.join(os.path.realpath(self.env_dir), env_name)
|
||||||
|
+ builder = venv.EnvBuilder(clear=True)
|
||||||
|
+ builder.create(env_dir)
|
||||||
|
+ activate = os.path.join(env_dir, self.bindir, 'activate')
|
||||||
|
+ test_script = os.path.join(self.env_dir, 'test_special_chars.sh')
|
||||||
|
+ with open(test_script, "w") as f:
|
||||||
|
+ f.write(f'source {shlex.quote(activate)}\n'
|
||||||
|
+ 'python -c \'import sys; print(sys.executable)\'\n'
|
||||||
|
+ 'python -c \'import os; print(os.environ["VIRTUAL_ENV"])\'\n'
|
||||||
|
+ 'deactivate\n')
|
||||||
|
+ out, err = check_output([bash, test_script])
|
||||||
|
+ lines = out.splitlines()
|
||||||
|
+ self.assertTrue(env_name.encode() in lines[0])
|
||||||
|
+ self.assertEndsWith(lines[1], env_name.encode())
|
||||||
|
+
|
||||||
|
+ # gh-124651: test quoted strings
|
||||||
|
+ @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows')
|
||||||
|
+ def test_special_chars_csh(self):
|
||||||
|
+ """
|
||||||
|
+ Test that the template strings are quoted properly (csh)
|
||||||
|
+ """
|
||||||
|
+ rmtree(self.env_dir)
|
||||||
|
+ csh = shutil.which('tcsh') or shutil.which('csh')
|
||||||
|
+ if csh is None:
|
||||||
|
+ self.skipTest('csh required for this test')
|
||||||
|
+ env_name = '"\';&&$e|\'"'
|
||||||
|
+ env_dir = os.path.join(os.path.realpath(self.env_dir), env_name)
|
||||||
|
+ builder = venv.EnvBuilder(clear=True)
|
||||||
|
+ builder.create(env_dir)
|
||||||
|
+ activate = os.path.join(env_dir, self.bindir, 'activate.csh')
|
||||||
|
+ test_script = os.path.join(self.env_dir, 'test_special_chars.csh')
|
||||||
|
+ with open(test_script, "w") as f:
|
||||||
|
+ f.write(f'source {shlex.quote(activate)}\n'
|
||||||
|
+ 'python -c \'import sys; print(sys.executable)\'\n'
|
||||||
|
+ 'python -c \'import os; print(os.environ["VIRTUAL_ENV"])\'\n'
|
||||||
|
+ 'deactivate\n')
|
||||||
|
+ out, err = check_output([csh, test_script])
|
||||||
|
+ lines = out.splitlines()
|
||||||
|
+ self.assertTrue(env_name.encode() in lines[0])
|
||||||
|
+ self.assertEndsWith(lines[1], env_name.encode())
|
||||||
|
+
|
||||||
|
+ # gh-124651: test quoted strings on Windows
|
||||||
|
+ @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows')
|
||||||
|
+ def test_special_chars_windows(self):
|
||||||
|
+ """
|
||||||
|
+ Test that the template strings are quoted properly on Windows
|
||||||
|
+ """
|
||||||
|
+ rmtree(self.env_dir)
|
||||||
|
+ env_name = "'&&^$e"
|
||||||
|
+ env_dir = os.path.join(os.path.realpath(self.env_dir), env_name)
|
||||||
|
+ builder = venv.EnvBuilder(clear=True)
|
||||||
|
+ builder.create(env_dir)
|
||||||
|
+ activate = os.path.join(env_dir, self.bindir, 'activate.bat')
|
||||||
|
+ test_batch = os.path.join(self.env_dir, 'test_special_chars.bat')
|
||||||
|
+ with open(test_batch, "w") as f:
|
||||||
|
+ f.write('@echo off\n'
|
||||||
|
+ f'"{activate}" & '
|
||||||
|
+ f'{self.exe} -c "import sys; print(sys.executable)" & '
|
||||||
|
+ f'{self.exe} -c "import os; print(os.environ[\'VIRTUAL_ENV\'])" & '
|
||||||
|
+ 'deactivate')
|
||||||
|
+ out, err = check_output([test_batch])
|
||||||
|
+ lines = out.splitlines()
|
||||||
|
+ self.assertTrue(env_name.encode() in lines[0])
|
||||||
|
+ self.assertEndsWith(lines[1], env_name.encode())
|
||||||
|
+
|
||||||
|
@unittest.skipUnless(os.name == 'nt', 'only relevant on Windows')
|
||||||
|
def test_unicode_in_batch_file(self):
|
||||||
|
"""
|
||||||
|
--- a/Lib/venv/__init__.py
|
||||||
|
+++ b/Lib/venv/__init__.py
|
||||||
|
@@ -11,6 +11,7 @@ import subprocess
|
||||||
|
import sys
|
||||||
|
import sysconfig
|
||||||
|
import types
|
||||||
|
+import shlex
|
||||||
|
|
||||||
|
|
||||||
|
CORE_VENV_DEPS = ('pip', 'setuptools')
|
||||||
|
@@ -348,11 +349,41 @@ class EnvBuilder:
|
||||||
|
:param context: The information for the environment creation request
|
||||||
|
being processed.
|
||||||
|
"""
|
||||||
|
- text = text.replace('__VENV_DIR__', context.env_dir)
|
||||||
|
- text = text.replace('__VENV_NAME__', context.env_name)
|
||||||
|
- text = text.replace('__VENV_PROMPT__', context.prompt)
|
||||||
|
- text = text.replace('__VENV_BIN_NAME__', context.bin_name)
|
||||||
|
- text = text.replace('__VENV_PYTHON__', context.env_exe)
|
||||||
|
+ replacements = {
|
||||||
|
+ '__VENV_DIR__': context.env_dir,
|
||||||
|
+ '__VENV_NAME__': context.env_name,
|
||||||
|
+ '__VENV_PROMPT__': context.prompt,
|
||||||
|
+ '__VENV_BIN_NAME__': context.bin_name,
|
||||||
|
+ '__VENV_PYTHON__': context.env_exe,
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ def quote_ps1(s):
|
||||||
|
+ """
|
||||||
|
+ This should satisfy PowerShell quoting rules [1], unless the quoted
|
||||||
|
+ string is passed directly to Windows native commands [2].
|
||||||
|
+ [1]: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules
|
||||||
|
+ [2]: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_parsing#passing-arguments-that-contain-quote-characters
|
||||||
|
+ """
|
||||||
|
+ s = s.replace("'", "''")
|
||||||
|
+ return f"'{s}'"
|
||||||
|
+
|
||||||
|
+ def quote_bat(s):
|
||||||
|
+ return s
|
||||||
|
+
|
||||||
|
+ # gh-124651: need to quote the template strings properly
|
||||||
|
+ quote = shlex.quote
|
||||||
|
+ script_path = context.script_path
|
||||||
|
+ if script_path.endswith('.ps1'):
|
||||||
|
+ quote = quote_ps1
|
||||||
|
+ elif script_path.endswith('.bat'):
|
||||||
|
+ quote = quote_bat
|
||||||
|
+ else:
|
||||||
|
+ # fallbacks to POSIX shell compliant quote
|
||||||
|
+ quote = shlex.quote
|
||||||
|
+
|
||||||
|
+ replacements = {key: quote(s) for key, s in replacements.items()}
|
||||||
|
+ for key, quoted in replacements.items():
|
||||||
|
+ text = text.replace(key, quoted)
|
||||||
|
return text
|
||||||
|
|
||||||
|
def install_scripts(self, context, path):
|
||||||
|
@@ -392,6 +423,7 @@ class EnvBuilder:
|
||||||
|
with open(srcfile, 'rb') as f:
|
||||||
|
data = f.read()
|
||||||
|
if not srcfile.endswith(('.exe', '.pdb')):
|
||||||
|
+ context.script_path = srcfile
|
||||||
|
try:
|
||||||
|
data = data.decode('utf-8')
|
||||||
|
data = self.replace_variables(data, context)
|
||||||
|
--- a/Lib/venv/scripts/common/activate
|
||||||
|
+++ b/Lib/venv/scripts/common/activate
|
||||||
|
@@ -37,11 +37,11 @@ deactivate () {
|
||||||
|
# unset irrelevant variables
|
||||||
|
deactivate nondestructive
|
||||||
|
|
||||||
|
-VIRTUAL_ENV="__VENV_DIR__"
|
||||||
|
+VIRTUAL_ENV=__VENV_DIR__
|
||||||
|
export VIRTUAL_ENV
|
||||||
|
|
||||||
|
_OLD_VIRTUAL_PATH="$PATH"
|
||||||
|
-PATH="$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH"
|
||||||
|
+PATH="$VIRTUAL_ENV/"__VENV_BIN_NAME__":$PATH"
|
||||||
|
export PATH
|
||||||
|
|
||||||
|
# unset PYTHONHOME if set
|
||||||
|
@@ -54,7 +54,7 @@ fi
|
||||||
|
|
||||||
|
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
|
||||||
|
_OLD_VIRTUAL_PS1="${PS1:-}"
|
||||||
|
- PS1="__VENV_PROMPT__${PS1:-}"
|
||||||
|
+ PS1=__VENV_PROMPT__"${PS1:-}"
|
||||||
|
export PS1
|
||||||
|
fi
|
||||||
|
|
||||||
|
--- a/Lib/venv/scripts/nt/activate.bat
|
||||||
|
+++ b/Lib/venv/scripts/nt/activate.bat
|
||||||
|
@@ -8,7 +8,7 @@ if defined _OLD_CODEPAGE (
|
||||||
|
"%SystemRoot%\System32\chcp.com" 65001 > nul
|
||||||
|
)
|
||||||
|
|
||||||
|
-set VIRTUAL_ENV=__VENV_DIR__
|
||||||
|
+set "VIRTUAL_ENV=__VENV_DIR__"
|
||||||
|
|
||||||
|
if not defined PROMPT set PROMPT=$P$G
|
||||||
|
|
||||||
|
@@ -24,7 +24,7 @@ set PYTHONHOME=
|
||||||
|
if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH%
|
||||||
|
if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH%
|
||||||
|
|
||||||
|
-set PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%
|
||||||
|
+set "PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%"
|
||||||
|
|
||||||
|
:END
|
||||||
|
if defined _OLD_CODEPAGE (
|
||||||
|
--- a/Lib/venv/scripts/posix/activate.csh
|
||||||
|
+++ b/Lib/venv/scripts/posix/activate.csh
|
||||||
|
@@ -8,16 +8,16 @@ alias deactivate 'test $?_OLD_VIRTUAL_PA
|
||||||
|
# Unset irrelevant variables.
|
||||||
|
deactivate nondestructive
|
||||||
|
|
||||||
|
-setenv VIRTUAL_ENV "__VENV_DIR__"
|
||||||
|
+setenv VIRTUAL_ENV __VENV_DIR__
|
||||||
|
|
||||||
|
set _OLD_VIRTUAL_PATH="$PATH"
|
||||||
|
-setenv PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH"
|
||||||
|
+setenv PATH "$VIRTUAL_ENV/"__VENV_BIN_NAME__":$PATH"
|
||||||
|
|
||||||
|
|
||||||
|
set _OLD_VIRTUAL_PROMPT="$prompt"
|
||||||
|
|
||||||
|
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
|
||||||
|
- set prompt = "__VENV_PROMPT__$prompt"
|
||||||
|
+ set prompt = __VENV_PROMPT__"$prompt"
|
||||||
|
endif
|
||||||
|
|
||||||
|
alias pydoc python -m pydoc
|
||||||
|
--- a/Lib/venv/scripts/posix/activate.fish
|
||||||
|
+++ b/Lib/venv/scripts/posix/activate.fish
|
||||||
|
@@ -29,10 +29,10 @@ end
|
||||||
|
# Unset irrelevant variables.
|
||||||
|
deactivate nondestructive
|
||||||
|
|
||||||
|
-set -gx VIRTUAL_ENV "__VENV_DIR__"
|
||||||
|
+set -gx VIRTUAL_ENV __VENV_DIR__
|
||||||
|
|
||||||
|
set -gx _OLD_VIRTUAL_PATH $PATH
|
||||||
|
-set -gx PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__" $PATH
|
||||||
|
+set -gx PATH "$VIRTUAL_ENV/"__VENV_BIN_NAME__ $PATH
|
||||||
|
|
||||||
|
# Unset PYTHONHOME if set.
|
||||||
|
if set -q PYTHONHOME
|
||||||
|
@@ -52,7 +52,7 @@ if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
|
||||||
|
set -l old_status $status
|
||||||
|
|
||||||
|
# Output the venv prompt; color taken from the blue of the Python logo.
|
||||||
|
- printf "%s%s%s" (set_color 4B8BBE) "__VENV_PROMPT__" (set_color normal)
|
||||||
|
+ printf "%s%s%s" (set_color 4B8BBE) __VENV_PROMPT__ (set_color normal)
|
||||||
|
|
||||||
|
# Restore the return status of the previous command.
|
||||||
|
echo "exit $old_status" | .
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Misc/NEWS.d/next/Library/2024-09-28-02-03-04.gh-issue-124651.bLBGtH.rst
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+Properly quote template strings in :mod:`venv` activation scripts.
|
3
Python-3.9.21.tar.xz
Normal file
3
Python-3.9.21.tar.xz
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:3126f59592c9b0d798584755f2bf7b081fa1ca35ce7a6fea980108d752a05bb1
|
||||||
|
size 19647056
|
1
Python-3.9.21.tar.xz.sigstore
Normal file
1
Python-3.9.21.tar.xz.sigstore
Normal file
File diff suppressed because one or more lines are too long
@ -1,3 +1,80 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Dec 4 19:51:41 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Update to 3.9.21:
|
||||||
|
- Tests
|
||||||
|
- gh-125041: Re-enable skipped tests for zlib on the
|
||||||
|
s390x architecture: only skip checks of the compressed
|
||||||
|
bytes, which can be different between zlib’s software
|
||||||
|
implementation and the hardware-accelerated implementation.
|
||||||
|
- gh-109396: Fix test_socket.test_hmac_sha1() in FIPS
|
||||||
|
mode. Use a longer key: FIPS mode requires at least of at
|
||||||
|
least 112 bits. The previous key was only 32 bits. Patch by
|
||||||
|
Victor Stinner.
|
||||||
|
- gh-100454: Fix SSL tests CI for OpenSSL 3.1+
|
||||||
|
- Security
|
||||||
|
- gh-126623: Upgrade libexpat to 2.6.4
|
||||||
|
- gh-122792: Changed IPv4-mapped ipaddress.IPv6Address to
|
||||||
|
consistently use the mapped IPv4 address value for deciding
|
||||||
|
properties. Properties which have their behavior fixed are
|
||||||
|
is_multicast, is_reserved, is_link_local, is_global, and
|
||||||
|
is_unspecified (bsc#1233307, CVE-2024-11168).
|
||||||
|
- Library
|
||||||
|
- gh-124651: Properly quote template strings in venv
|
||||||
|
activation scripts (bsc#1232241, CVE-2024-9287).
|
||||||
|
- gh-103848: Add checks to ensure that [ bracketed ] hosts
|
||||||
|
found by urllib.parse.urlsplit() are of IPv6 or IPvFuture
|
||||||
|
format.
|
||||||
|
- Documentation
|
||||||
|
- gh-95588: Clarified the conflicting advice given in the ast
|
||||||
|
documentation about ast.literal_eval() being “safe” for use
|
||||||
|
on untrusted input while at the same time warning that it
|
||||||
|
can crash the process. The latter statement is true and is
|
||||||
|
deemed unfixable without a large amount of work unsuitable
|
||||||
|
for a bugfix. So we keep the warning and no longer claim
|
||||||
|
that literal_eval is safe.
|
||||||
|
- Remove upstreamed patches:
|
||||||
|
- CVE-2024-11168-validation-IPv6-addrs.patch
|
||||||
|
- CVE-2024-9287-venv_path_unquoted.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Nov 14 07:06:20 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Remove -IVendor/ from python-config boo#1231795
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Nov 13 13:25:01 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Add CVE-2024-11168-validation-IPv6-addrs.patch
|
||||||
|
fixing bsc#1233307 (CVE-2024-11168,
|
||||||
|
gh#python/cpython#103848): Improper validation of IPv6 and
|
||||||
|
IPvFuture addresses.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Fri Nov 1 21:16:32 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Update CVE-2024-9287-venv_path_unquoted.patch according to the
|
||||||
|
upstream PR gh#python/cpython!126301.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Oct 24 16:09:00 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Add CVE-2024-9287-venv_path_unquoted.patch to properly quote
|
||||||
|
path names provided when creating a virtual environment
|
||||||
|
(bsc#1232241, CVE-2024-9287)
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Oct 2 16:18:29 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Drop .pyc files from docdir for reproducible builds
|
||||||
|
(bsc#1230906).
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Fri Sep 20 14:57:10 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Add sphinx-802.patch to overcome working both with the most
|
||||||
|
recent and older Sphinx versions.
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Mon Sep 9 18:02:59 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
Mon Sep 9 18:02:59 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
@ -34,7 +111,7 @@ Mon Sep 9 18:02:59 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
|||||||
:class:`zipfile.Path` causing infinite loops (gh-122905) without breaking
|
:class:`zipfile.Path` causing infinite loops (gh-122905) without breaking
|
||||||
contents using legitimate characters (bsc#1229704, CVE-2024-8088).
|
contents using legitimate characters (bsc#1229704, CVE-2024-8088).
|
||||||
- gh-123067: Fix quadratic complexity in parsing ``"``-quoted cookie values
|
- gh-123067: Fix quadratic complexity in parsing ``"``-quoted cookie values
|
||||||
with backslashes by :mod:`http.cookies`.
|
with backslashes by :mod:`http.cookies` (bsc#1229596, CVE-2024-7592).
|
||||||
- gh-121650: :mod:`email` headers with embedded newlines are now quoted on
|
- gh-121650: :mod:`email` headers with embedded newlines are now quoted on
|
||||||
output. The :mod:`~email.generator` will now refuse to serialize (write)
|
output. The :mod:`~email.generator` will now refuse to serialize (write)
|
||||||
headers that are unsafely folded or delimited; see
|
headers that are unsafely folded or delimited; see
|
||||||
@ -76,8 +153,7 @@ Mon Sep 9 18:02:59 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
|||||||
Thu Sep 5 13:44:48 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
Thu Sep 5 13:44:48 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
- Add CVE-2024-6232-cookies-quad-complex.patch to avoid quadratic
|
- Add CVE-2024-6232-cookies-quad-complex.patch to avoid quadratic
|
||||||
complexity in parsing "-quoted cookie values with backslashes
|
complexity in parsing tarfile headers (bsc#1230227, CVE-2024-6232).
|
||||||
(bsc#1229596, CVE-2024-6232).
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Thu Sep 5 08:11:45 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
Thu Sep 5 08:11:45 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
@ -99,13 +99,13 @@
|
|||||||
%define dynlib() %{sitedir}/lib-dynload/%{1}.cpython-%{abi_tag}-%{archname}-%{_os}%{?_gnu}%{?armsuffix}.so
|
%define dynlib() %{sitedir}/lib-dynload/%{1}.cpython-%{abi_tag}-%{archname}-%{_os}%{?_gnu}%{?armsuffix}.so
|
||||||
%bcond_without profileopt
|
%bcond_without profileopt
|
||||||
Name: %{python_pkg_name}%{psuffix}
|
Name: %{python_pkg_name}%{psuffix}
|
||||||
Version: 3.9.20
|
Version: 3.9.21
|
||||||
Release: 0
|
Release: 0
|
||||||
Summary: Python 3 Interpreter
|
Summary: Python 3 Interpreter
|
||||||
License: Python-2.0
|
License: Python-2.0
|
||||||
URL: https://www.python.org/
|
URL: https://www.python.org/
|
||||||
Source0: https://www.python.org/ftp/python/%{folderversion}/%{tarname}.tar.xz
|
Source0: https://www.python.org/ftp/python/%{folderversion}/%{tarname}.tar.xz
|
||||||
Source1: https://www.python.org/ftp/python/%{folderversion}/%{tarname}.tar.xz.asc
|
Source1: https://www.python.org/ftp/python/%{folderversion}/%{tarname}.tar.xz.sigstore
|
||||||
Source2: baselibs.conf
|
Source2: baselibs.conf
|
||||||
Source3: README.SUSE
|
Source3: README.SUSE
|
||||||
Source7: macros.python3
|
Source7: macros.python3
|
||||||
@ -134,10 +134,6 @@ Source100: PACKAGING-NOTES
|
|||||||
# to /usr/local if executable is /usr/bin/python* and RPM build
|
# to /usr/local if executable is /usr/bin/python* and RPM build
|
||||||
# is not detected to make pip and distutils install into separate location
|
# is not detected to make pip and distutils install into separate location
|
||||||
Patch02: F00251-change-user-install-location.patch
|
Patch02: F00251-change-user-install-location.patch
|
||||||
# PATCH-FEATURE-UPSTREAM decimal.patch bsc#1189356 mcepl@suse.com
|
|
||||||
# fix building with mpdecimal
|
|
||||||
# https://www.bytereef.org/contrib/decimal.diff
|
|
||||||
Patch05: decimal.patch
|
|
||||||
# PATCH-FEATURE-UPSTREAM distutils-reproducible-compile.patch gh#python/cpython#8057 mcepl@suse.com
|
# PATCH-FEATURE-UPSTREAM distutils-reproducible-compile.patch gh#python/cpython#8057 mcepl@suse.com
|
||||||
# Improve reproduceability
|
# Improve reproduceability
|
||||||
Patch06: distutils-reproducible-compile.patch
|
Patch06: distutils-reproducible-compile.patch
|
||||||
@ -161,37 +157,43 @@ Patch33: no-skipif-doctests.patch
|
|||||||
# PATCH-FIX-SLE skip-test_pyobject_freed_is_freed.patch mcepl@suse.com
|
# PATCH-FIX-SLE skip-test_pyobject_freed_is_freed.patch mcepl@suse.com
|
||||||
# skip a test failing on SLE-15
|
# skip a test failing on SLE-15
|
||||||
Patch34: skip-test_pyobject_freed_is_freed.patch
|
Patch34: skip-test_pyobject_freed_is_freed.patch
|
||||||
|
# PATCH-FEATURE-UPSTREAM decimal.patch bsc#1189356 mcepl@suse.com
|
||||||
|
# fix building with mpdecimal
|
||||||
|
# https://www.bytereef.org/contrib/decimal.diff
|
||||||
|
Patch35: decimal.patch
|
||||||
# PATCH-FIX-UPSTREAM support-expat-CVE-2022-25236-patched.patch jsc#SLE-21253 mcepl@suse.com
|
# PATCH-FIX-UPSTREAM support-expat-CVE-2022-25236-patched.patch jsc#SLE-21253 mcepl@suse.com
|
||||||
# Makes Python resilient to changes of API of libexpat
|
# Makes Python resilient to changes of API of libexpat
|
||||||
Patch35: support-expat-CVE-2022-25236-patched.patch
|
Patch40: support-expat-CVE-2022-25236-patched.patch
|
||||||
# PATCH-FIX-UPSTREAM CVE-2023-52425-libexpat-2.6.0-backport.patch gh#python/cpython#117187 mcepl@suse.com
|
# PATCH-FIX-UPSTREAM CVE-2023-52425-libexpat-2.6.0-backport.patch gh#python/cpython#117187 mcepl@suse.com
|
||||||
# Make the test suite work with libexpat < 2.6.0
|
# Make the test suite work with libexpat < 2.6.0
|
||||||
Patch36: CVE-2023-52425-libexpat-2.6.0-backport.patch
|
Patch41: CVE-2023-52425-libexpat-2.6.0-backport.patch
|
||||||
# PATCH-FIX-UPSTREAM 98437-sphinx.locale._-as-gettext-in-pyspecific.patch gh#python/cpython#98366 mcepl@suse.com
|
# PATCH-FIX-UPSTREAM 98437-sphinx.locale._-as-gettext-in-pyspecific.patch gh#python/cpython#98366 mcepl@suse.com
|
||||||
# this patch makes things totally awesome
|
# this patch makes things totally awesome
|
||||||
Patch37: 98437-sphinx.locale._-as-gettext-in-pyspecific.patch
|
Patch42: 98437-sphinx.locale._-as-gettext-in-pyspecific.patch
|
||||||
# PATCH-FIX-UPSTREAM bpo-37596-make-set-marshalling.patch bsc#1211765 mcepl@suse.com
|
# PATCH-FIX-UPSTREAM bpo-37596-make-set-marshalling.patch bsc#1211765 mcepl@suse.com
|
||||||
# Make `set` and `frozenset` marshalling deterministic
|
# Make `set` and `frozenset` marshalling deterministic
|
||||||
Patch38: bpo-37596-make-set-marshalling.patch
|
Patch43: bpo-37596-make-set-marshalling.patch
|
||||||
# PATCH-FIX-UPSTREAM gh-78214-marshal_stabilize_FLAG_REF.patch bsc#1213463 mcepl@suse.com
|
# PATCH-FIX-UPSTREAM gh-78214-marshal_stabilize_FLAG_REF.patch bsc#1213463 mcepl@suse.com
|
||||||
# marshal: Stabilize FLAG_REF usage
|
# marshal: Stabilize FLAG_REF usage
|
||||||
Patch39: gh-78214-marshal_stabilize_FLAG_REF.patch
|
Patch44: gh-78214-marshal_stabilize_FLAG_REF.patch
|
||||||
# PATCH-FIX-UPSTREAM 99366-patch.dict-can-decorate-async.patch bsc#[0-9]+ mcepl@suse.com
|
# PATCH-FIX-UPSTREAM 99366-patch.dict-can-decorate-async.patch bsc#[0-9]+ mcepl@suse.com
|
||||||
# Patch for gh#python/cpython#98086
|
# Patch for gh#python/cpython#98086
|
||||||
Patch40: 99366-patch.dict-can-decorate-async.patch
|
Patch45: 99366-patch.dict-can-decorate-async.patch
|
||||||
# PATCH-FIX-OPENSUSE downport-Sphinx-features.patch mcepl@suse.com
|
# PATCH-FIX-OPENSUSE downport-Sphinx-features.patch mcepl@suse.com
|
||||||
# Make documentation build with older Sphinx
|
# Make documentation build with older Sphinx
|
||||||
Patch41: downport-Sphinx-features.patch
|
Patch46: downport-Sphinx-features.patch
|
||||||
# PATCH-FIX-UPSTREAM bso1227999-reproducible-builds.patch bsc#1227999 mcepl@suse.com
|
# PATCH-FIX-UPSTREAM bso1227999-reproducible-builds.patch bsc#1227999 mcepl@suse.com
|
||||||
# reproducibility patches
|
# reproducibility patches
|
||||||
Patch46: bso1227999-reproducible-builds.patch
|
Patch47: bso1227999-reproducible-builds.patch
|
||||||
# PATCH-FIX-UPSTREAM CVE-2024-5642-OpenSSL-API-buf-overread-NPN.patch bsc#1227233 mcepl@suse.com
|
# PATCH-FIX-UPSTREAM CVE-2024-5642-OpenSSL-API-buf-overread-NPN.patch bsc#1227233 mcepl@suse.com
|
||||||
# Remove for support for anything but OpenSSL 1.1.1 or newer
|
# Remove for support for anything but OpenSSL 1.1.1 or newer
|
||||||
Patch48: CVE-2024-5642-OpenSSL-API-buf-overread-NPN.patch
|
Patch48: CVE-2024-5642-OpenSSL-API-buf-overread-NPN.patch
|
||||||
# PATCH-FIX-UPSTREAM gh120226-fix-sendfile-test-kernel-610.patch gh#python/cpython#120226 mcepl@suse.com
|
# PATCH-FIX-UPSTREAM gh120226-fix-sendfile-test-kernel-610.patch gh#python/cpython#120226 mcepl@suse.com
|
||||||
# Fix test_sendfile_close_peer_in_the_middle_of_receiving on Linux >= 6.10 (GH-120227)
|
# Fix test_sendfile_close_peer_in_the_middle_of_receiving on Linux >= 6.10 (GH-120227)
|
||||||
Patch50: gh120226-fix-sendfile-test-kernel-610.patch
|
Patch50: gh120226-fix-sendfile-test-kernel-610.patch
|
||||||
|
# PATCH-FIX-UPSTREAM sphinx-802.patch mcepl@suse.com
|
||||||
|
# status_iterator method moved between the Sphinx versions
|
||||||
|
Patch51: sphinx-802.patch
|
||||||
BuildRequires: autoconf-archive
|
BuildRequires: autoconf-archive
|
||||||
BuildRequires: automake
|
BuildRequires: automake
|
||||||
BuildRequires: fdupes
|
BuildRequires: fdupes
|
||||||
@ -430,6 +432,7 @@ other applications.
|
|||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q -n %{tarname}
|
%setup -q -n %{tarname}
|
||||||
|
|
||||||
%patch -P 02 -p1
|
%patch -P 02 -p1
|
||||||
%patch -P 06 -p1
|
%patch -P 06 -p1
|
||||||
%patch -P 07 -p1
|
%patch -P 07 -p1
|
||||||
@ -439,25 +442,30 @@ other applications.
|
|||||||
%patch -P 25 -p1
|
%patch -P 25 -p1
|
||||||
%patch -P 29 -p1
|
%patch -P 29 -p1
|
||||||
%patch -P 32 -p1
|
%patch -P 32 -p1
|
||||||
|
|
||||||
%if 0%{?sle_version}
|
%if 0%{?sle_version}
|
||||||
%patch -P 33 -p1
|
%patch -P 33 -p1
|
||||||
%patch -P 34 -p1
|
%patch -P 34 -p1
|
||||||
%endif
|
%endif
|
||||||
%if %{with mpdecimal}
|
%if %{with mpdecimal}
|
||||||
%patch -P 05 -p1
|
|
||||||
%endif
|
|
||||||
%patch -P 35 -p1
|
%patch -P 35 -p1
|
||||||
%patch -P 36 -p1
|
|
||||||
%patch -P 37 -p1
|
|
||||||
%patch -P 38 -p1
|
|
||||||
%patch -P 39 -p1
|
|
||||||
%patch -P 40 -p1
|
|
||||||
%if 0%{?sle_version} && 0%{?sle_version} <= 150500
|
|
||||||
%patch -p1 -P 41
|
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
%patch -P 40 -p1
|
||||||
|
%patch -P 41 -p1
|
||||||
|
%patch -P 42 -p1
|
||||||
|
%patch -P 43 -p1
|
||||||
|
%patch -P 44 -p1
|
||||||
|
%patch -P 45 -p1
|
||||||
|
|
||||||
|
%if 0%{?sle_version} && 0%{?sle_version} <= 150500
|
||||||
%patch -p1 -P 46
|
%patch -p1 -P 46
|
||||||
%patch -p1 -P 48
|
%endif
|
||||||
%patch -p1 -P 50
|
|
||||||
|
%patch -P 47 -p1
|
||||||
|
%patch -P 48 -p1
|
||||||
|
%patch -P 50 -p1
|
||||||
|
%patch -P 51 -p1
|
||||||
|
|
||||||
# drop Autoconf version requirement
|
# drop Autoconf version requirement
|
||||||
sed -i 's/^AC_PREREQ/dnl AC_PREREQ/' configure.ac
|
sed -i 's/^AC_PREREQ/dnl AC_PREREQ/' configure.ac
|
||||||
@ -764,6 +772,9 @@ install -m 755 -D Tools/gdb/libpython.py %{buildroot}%{_datadir}/gdb/auto-load/%
|
|||||||
# install devel files to /config
|
# install devel files to /config
|
||||||
#cp Makefile Makefile.pre.in Makefile.pre $RPM_BUILD_ROOT%{sitedir}/config-%{python_abi}/
|
#cp Makefile Makefile.pre.in Makefile.pre $RPM_BUILD_ROOT%{sitedir}/config-%{python_abi}/
|
||||||
|
|
||||||
|
# Remove -IVendor/ from python-config boo#1231795
|
||||||
|
sed -i 's/-IVendor\///' %{buildroot}%{_bindir}/python%{python_abi}-config
|
||||||
|
|
||||||
# RPM macros
|
# RPM macros
|
||||||
%if %{primary_interpreter}
|
%if %{primary_interpreter}
|
||||||
mkdir -p %{buildroot}%{_rpmconfigdir}/macros.d/
|
mkdir -p %{buildroot}%{_rpmconfigdir}/macros.d/
|
||||||
@ -792,6 +803,11 @@ LD_LIBRARY_PATH=. ./python -O -c "from py_compile import compile; compile('$FAIL
|
|||||||
echo %{sitedir}/_import_failed > %{buildroot}/%{sitedir}/site-packages/zzzz-import-failed-hooks.pth
|
echo %{sitedir}/_import_failed > %{buildroot}/%{sitedir}/site-packages/zzzz-import-failed-hooks.pth
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
# For the purposes of reproducibility, it is necessary to eliminate any *.pyc files inside documentation dirs
|
||||||
|
if [ -d %{buildroot}%{_defaultdocdir} ] ; then
|
||||||
|
find %{buildroot}%{_defaultdocdir} -type f -name \*.pyc -ls -exec rm -vf '{}' \;
|
||||||
|
fi
|
||||||
|
|
||||||
%if %{with general}
|
%if %{with general}
|
||||||
%files -n %{python_pkg_name}-tk
|
%files -n %{python_pkg_name}-tk
|
||||||
%{sitedir}/tkinter
|
%{sitedir}/tkinter
|
||||||
|
21
sphinx-802.patch
Normal file
21
sphinx-802.patch
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
Doc/tools/extensions/pyspecific.py | 8 +++++++-
|
||||||
|
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/Doc/tools/extensions/pyspecific.py
|
||||||
|
+++ b/Doc/tools/extensions/pyspecific.py
|
||||||
|
@@ -27,7 +27,13 @@ try:
|
||||||
|
except ImportError:
|
||||||
|
from sphinx.environment import NoUri
|
||||||
|
from sphinx.locale import _ as sphinx_gettext
|
||||||
|
-from sphinx.util import status_iterator, logging
|
||||||
|
+try:
|
||||||
|
+ from sphinx.util.display import status_iterator
|
||||||
|
+except ImportError:
|
||||||
|
+ # This method was moved into sphinx.util.display in Sphinx 6.1.0. Before
|
||||||
|
+ # that it resided in sphinx.util.
|
||||||
|
+ from sphinx.util import status_iterator
|
||||||
|
+from sphinx.util import logging
|
||||||
|
from sphinx.util.nodes import split_explicit_title
|
||||||
|
from sphinx.writers.text import TextWriter, TextTranslator
|
||||||
|
from sphinx.writers.latex import LaTeXTranslator
|
Loading…
Reference in New Issue
Block a user