diff --git a/99366-patch.dict-can-decorate-async.patch b/99366-patch.dict-can-decorate-async.patch new file mode 100644 index 0000000..b1e5c02 --- /dev/null +++ b/99366-patch.dict-can-decorate-async.patch @@ -0,0 +1,79 @@ +From c0dea0309b9a0a7cbc87727c9957f0a388fb9b0f Mon Sep 17 00:00:00 2001 +From: Nikita Sobolev +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 +--- + 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 +@@ -1761,6 +1761,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() +@@ -1769,6 +1775,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 +@@ -146,6 +146,23 @@ class AsyncPatchCMTest(unittest.TestCase + + 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(iscoroutinefunction(test_async)) ++ 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') ++ ++ 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. diff --git a/CVE-2007-4559-filter-tarfile_extractall.patch b/CVE-2007-4559-filter-tarfile_extractall.patch index d4717dc..3c439d2 100644 --- a/CVE-2007-4559-filter-tarfile_extractall.patch +++ b/CVE-2007-4559-filter-tarfile_extractall.patch @@ -8,10 +8,8 @@ Misc/NEWS.d/next/Library/2023-03-23-15-24-38.gh-issue-102953.YR4KaK.rst | 4 7 files changed, 1766 insertions(+), 97 deletions(-) -Index: Python-3.9.16/Doc/library/shutil.rst -=================================================================== ---- Python-3.9.16.orig/Doc/library/shutil.rst -+++ Python-3.9.16/Doc/library/shutil.rst +--- a/Doc/library/shutil.rst ++++ b/Doc/library/shutil.rst @@ -614,7 +614,7 @@ provided. They rely on the :mod:`zipfil Remove the archive format *name* from the list of supported formats. @@ -66,10 +64,8 @@ Index: Python-3.9.16/Doc/library/shutil.rst *description* can be provided to describe the format, and will be returned by the :func:`get_unpack_formats` function. -Index: Python-3.9.16/Doc/library/tarfile.rst -=================================================================== ---- Python-3.9.16.orig/Doc/library/tarfile.rst -+++ Python-3.9.16/Doc/library/tarfile.rst +--- a/Doc/library/tarfile.rst ++++ b/Doc/library/tarfile.rst @@ -206,6 +206,38 @@ The :mod:`tarfile` module defines the fo Is raised by :meth:`TarInfo.frombuf` if the buffer it gets is invalid. @@ -681,10 +677,8 @@ Index: Python-3.9.16/Doc/library/tarfile.rst .. _tar-examples: Examples -Index: Python-3.9.16/Lib/shutil.py -=================================================================== ---- Python-3.9.16.orig/Lib/shutil.py -+++ Python-3.9.16/Lib/shutil.py +--- a/Lib/shutil.py ++++ b/Lib/shutil.py @@ -1191,7 +1191,7 @@ def _unpack_zipfile(filename, extract_di finally: zip.close() @@ -751,10 +745,8 @@ Index: Python-3.9.16/Lib/shutil.py func(filename, extract_dir, **kwargs) -Index: Python-3.9.16/Lib/tarfile.py -=================================================================== ---- Python-3.9.16.orig/Lib/tarfile.py -+++ Python-3.9.16/Lib/tarfile.py +--- a/Lib/tarfile.py ++++ b/Lib/tarfile.py @@ -45,6 +45,7 @@ import time import struct import copy @@ -1349,10 +1341,8 @@ Index: Python-3.9.16/Lib/tarfile.py if args.verbose: if curdir == '.': msg = '{!r} file is extracted.'.format(src) -Index: Python-3.9.16/Lib/test/test_shutil.py -=================================================================== ---- Python-3.9.16.orig/Lib/test/test_shutil.py -+++ Python-3.9.16/Lib/test/test_shutil.py +--- a/Lib/test/test_shutil.py ++++ b/Lib/test/test_shutil.py @@ -31,6 +31,7 @@ except ImportError: from test import support @@ -1437,10 +1427,8 @@ Index: Python-3.9.16/Lib/test/test_shutil.py def test_unpack_registry(self): -Index: Python-3.9.16/Lib/test/test_tarfile.py -=================================================================== ---- Python-3.9.16.orig/Lib/test/test_tarfile.py -+++ Python-3.9.16/Lib/test/test_tarfile.py +--- a/Lib/test/test_tarfile.py ++++ b/Lib/test/test_tarfile.py @@ -5,6 +5,10 @@ from hashlib import sha256 from contextlib import contextmanager from random import Random @@ -1601,7 +1589,7 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py + def make_evil_tarfile(self, tar_name): + files = [support.findfile('tokenize_tests.txt')] -+ self.addCleanup(os_helper.unlink, tar_name) ++ self.addCleanup(support.unlink, tar_name) + with tarfile.open(tar_name, 'w') as tf: + benign = tarfile.TarInfo('benign') + tf.addfile(benign, fileobj=io.BytesIO(b'')) @@ -1622,7 +1610,7 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py + destdir = os.path.join(tarextdir, 'dest') + os.mkdir(tarextdir) + try: -+ with os_helper.temp_cwd(destdir): ++ with support.temp_cwd(destdir): + self.tarfilecmd_failure('-e', tmpname, + '-v', + '--filter', 'data') @@ -1632,7 +1620,7 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py + PYTHONIOENCODING='utf-8') + self.assertIn(b' file is extracted.', out) + finally: -+ os_helper.rmtree(tarextdir) ++ support.rmtree(tarextdir) + def test_extract_command_different_directory(self): self.make_simple_tarfile(tmpname) @@ -1760,7 +1748,7 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py + for member in self.tar.getmembers(): + for attr_name in attr_names: + setattr(member, attr_name, None) -+ with os_helper.temp_dir(DIR): ++ with support.temp_dir(DIR): + self.tar.extractall(DIR, filter='fully_trusted') + self.check_files_present(DIR) + yield DIR @@ -2026,7 +2014,7 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py + other files. + When checking directories, do so before their contents. + """ -+ with os_helper.temp_dir(self.outerdir): ++ with support.temp_dir(self.outerdir): + try: + tar.extractall(self.destdir, filter=filter) + except Exception as exc: @@ -2122,7 +2110,7 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py + arc.add('parent', symlink_to='current/..') + arc.add('parent/evil') + -+ if os_helper.can_symlink(): ++ if support.can_symlink(): + with self.check_context(arc.open(), 'fully_trusted'): + if self.raised_exception is not None: + # Windows will refuse to create a file that's a symlink to itself @@ -2166,7 +2154,7 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py + arc.add('parent/evil') + + with self.check_context(arc.open(), 'fully_trusted'): -+ if os_helper.can_symlink(): ++ if support.can_symlink(): + self.expect_file('current', symlink_to='.') + self.expect_file('parent', symlink_to='..') + self.expect_file('../evil') @@ -2175,7 +2163,7 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py + self.expect_file('parent/evil') + + with self.check_context(arc.open(), 'tar'): -+ if os_helper.can_symlink(): ++ if support.can_symlink(): + self.expect_exception( + tarfile.OutsideDestinationError, + "'parent/evil' would be extracted to " @@ -2199,14 +2187,14 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py + arc.add('parent/evil') + + with self.check_context(arc.open(), 'fully_trusted'): -+ if os_helper.can_symlink(): ++ if support.can_symlink(): + self.expect_file('parent', symlink_to=self.outerdir) + self.expect_file('../evil') + else: + self.expect_file('parent/evil') + + with self.check_context(arc.open(), 'tar'): -+ if os_helper.can_symlink(): ++ if support.can_symlink(): + self.expect_exception( + tarfile.OutsideDestinationError, + "'parent/evil' would be extracted to " @@ -2227,7 +2215,7 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py + + try: + with self.check_context(arc.open(), filter='fully_trusted'): -+ if os_helper.can_symlink(): ++ if support.can_symlink(): + if isinstance(self.raised_exception, FileExistsError): + # XXX TarFile happens to fail creating a parent + # directory. @@ -2261,7 +2249,7 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py + + with self.check_context(arc.open(), 'fully_trusted'): + self.expect_file('tmp', type=tarfile.DIRTYPE) -+ if os_helper.can_symlink(): ++ if support.can_symlink(): + self.expect_file('../moo', symlink_to='tmp/../../tmp/moo') + + for filter in 'tar', 'data': @@ -2568,10 +2556,8 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py def setUpModule(): support.unlink(TEMPDIR) os.makedirs(TEMPDIR) -Index: Python-3.9.16/Misc/NEWS.d/next/Library/2023-03-23-15-24-38.gh-issue-102953.YR4KaK.rst -=================================================================== --- /dev/null -+++ Python-3.9.16/Misc/NEWS.d/next/Library/2023-03-23-15-24-38.gh-issue-102953.YR4KaK.rst ++++ b/Misc/NEWS.d/next/Library/2023-03-23-15-24-38.gh-issue-102953.YR4KaK.rst @@ -0,0 +1,4 @@ +The extraction methods in :mod:`tarfile`, and :func:`shutil.unpack_archive`, +have a new a *filter* argument that allows limiting tar features than may be diff --git a/python39.changes b/python39.changes index d7abcd7..31d1ec2 100644 --- a/python39.changes +++ b/python39.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Sat May 6 17:31:35 UTC 2023 - Matej Cepl + +- Add 99366-patch.dict-can-decorate-async.patch fixing + gh#python/cpython#98086 (backport from Python 3.10 patch in + gh#python/cpython!99366), fixing bsc#1211158. + ------------------------------------------------------------------- Wed May 3 14:09:37 UTC 2023 - Matej Cepl diff --git a/python39.spec b/python39.spec index 958dd0d..8785262 100644 --- a/python39.spec +++ b/python39.spec @@ -168,6 +168,9 @@ Patch38: CVE-2023-24329-blank-URL-bypass.patch # PATCH-FIX-UPSTREAM CVE-2007-4559-filter-tarfile_extractall.patch bsc#1203750 mcepl@suse.com # Implement PEP-706 to filter outcome of the tarball extracing Patch39: CVE-2007-4559-filter-tarfile_extractall.patch +# PATCH-FIX-UPSTREAM 99366-patch.dict-can-decorate-async.patch bsc#[0-9]+ mcepl@suse.com +# Patch for gh#python/cpython#98086 +Patch40: 99366-patch.dict-can-decorate-async.patch BuildRequires: autoconf-archive BuildRequires: automake BuildRequires: fdupes @@ -428,6 +431,7 @@ other applications. %patch37 -p1 %patch38 -p1 %patch39 -p1 +%patch40 -p1 # drop Autoconf version requirement sed -i 's/^AC_PREREQ/dnl AC_PREREQ/' configure.ac