Accepting request 1085253 from home:mcepl:branches:devel:languages:python
- 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. OBS-URL: https://build.opensuse.org/request/show/1085253 OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python39?expand=0&rev=142
This commit is contained in:
parent
7ce77a1280
commit
1079252656
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
|
||||||
|
@@ -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.
|
@ -8,10 +8,8 @@
|
|||||||
Misc/NEWS.d/next/Library/2023-03-23-15-24-38.gh-issue-102953.YR4KaK.rst | 4
|
Misc/NEWS.d/next/Library/2023-03-23-15-24-38.gh-issue-102953.YR4KaK.rst | 4
|
||||||
7 files changed, 1766 insertions(+), 97 deletions(-)
|
7 files changed, 1766 insertions(+), 97 deletions(-)
|
||||||
|
|
||||||
Index: Python-3.9.16/Doc/library/shutil.rst
|
--- a/Doc/library/shutil.rst
|
||||||
===================================================================
|
+++ b/Doc/library/shutil.rst
|
||||||
--- Python-3.9.16.orig/Doc/library/shutil.rst
|
|
||||||
+++ Python-3.9.16/Doc/library/shutil.rst
|
|
||||||
@@ -614,7 +614,7 @@ provided. They rely on the :mod:`zipfil
|
@@ -614,7 +614,7 @@ provided. They rely on the :mod:`zipfil
|
||||||
Remove the archive format *name* from the list of supported formats.
|
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
|
*description* can be provided to describe the format, and will be returned
|
||||||
by the :func:`get_unpack_formats` function.
|
by the :func:`get_unpack_formats` function.
|
||||||
Index: Python-3.9.16/Doc/library/tarfile.rst
|
--- a/Doc/library/tarfile.rst
|
||||||
===================================================================
|
+++ b/Doc/library/tarfile.rst
|
||||||
--- Python-3.9.16.orig/Doc/library/tarfile.rst
|
|
||||||
+++ Python-3.9.16/Doc/library/tarfile.rst
|
|
||||||
@@ -206,6 +206,38 @@ The :mod:`tarfile` module defines the fo
|
@@ -206,6 +206,38 @@ The :mod:`tarfile` module defines the fo
|
||||||
Is raised by :meth:`TarInfo.frombuf` if the buffer it gets is invalid.
|
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:
|
.. _tar-examples:
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
Index: Python-3.9.16/Lib/shutil.py
|
--- a/Lib/shutil.py
|
||||||
===================================================================
|
+++ b/Lib/shutil.py
|
||||||
--- Python-3.9.16.orig/Lib/shutil.py
|
|
||||||
+++ Python-3.9.16/Lib/shutil.py
|
|
||||||
@@ -1191,7 +1191,7 @@ def _unpack_zipfile(filename, extract_di
|
@@ -1191,7 +1191,7 @@ def _unpack_zipfile(filename, extract_di
|
||||||
finally:
|
finally:
|
||||||
zip.close()
|
zip.close()
|
||||||
@ -751,10 +745,8 @@ Index: Python-3.9.16/Lib/shutil.py
|
|||||||
func(filename, extract_dir, **kwargs)
|
func(filename, extract_dir, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
Index: Python-3.9.16/Lib/tarfile.py
|
--- a/Lib/tarfile.py
|
||||||
===================================================================
|
+++ b/Lib/tarfile.py
|
||||||
--- Python-3.9.16.orig/Lib/tarfile.py
|
|
||||||
+++ Python-3.9.16/Lib/tarfile.py
|
|
||||||
@@ -45,6 +45,7 @@ import time
|
@@ -45,6 +45,7 @@ import time
|
||||||
import struct
|
import struct
|
||||||
import copy
|
import copy
|
||||||
@ -1349,10 +1341,8 @@ Index: Python-3.9.16/Lib/tarfile.py
|
|||||||
if args.verbose:
|
if args.verbose:
|
||||||
if curdir == '.':
|
if curdir == '.':
|
||||||
msg = '{!r} file is extracted.'.format(src)
|
msg = '{!r} file is extracted.'.format(src)
|
||||||
Index: Python-3.9.16/Lib/test/test_shutil.py
|
--- a/Lib/test/test_shutil.py
|
||||||
===================================================================
|
+++ b/Lib/test/test_shutil.py
|
||||||
--- Python-3.9.16.orig/Lib/test/test_shutil.py
|
|
||||||
+++ Python-3.9.16/Lib/test/test_shutil.py
|
|
||||||
@@ -31,6 +31,7 @@ except ImportError:
|
@@ -31,6 +31,7 @@ except ImportError:
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
@ -1437,10 +1427,8 @@ Index: Python-3.9.16/Lib/test/test_shutil.py
|
|||||||
|
|
||||||
def test_unpack_registry(self):
|
def test_unpack_registry(self):
|
||||||
|
|
||||||
Index: Python-3.9.16/Lib/test/test_tarfile.py
|
--- a/Lib/test/test_tarfile.py
|
||||||
===================================================================
|
+++ b/Lib/test/test_tarfile.py
|
||||||
--- Python-3.9.16.orig/Lib/test/test_tarfile.py
|
|
||||||
+++ Python-3.9.16/Lib/test/test_tarfile.py
|
|
||||||
@@ -5,6 +5,10 @@ from hashlib import sha256
|
@@ -5,6 +5,10 @@ from hashlib import sha256
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from random import Random
|
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):
|
+ def make_evil_tarfile(self, tar_name):
|
||||||
+ files = [support.findfile('tokenize_tests.txt')]
|
+ 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:
|
+ with tarfile.open(tar_name, 'w') as tf:
|
||||||
+ benign = tarfile.TarInfo('benign')
|
+ benign = tarfile.TarInfo('benign')
|
||||||
+ tf.addfile(benign, fileobj=io.BytesIO(b''))
|
+ 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')
|
+ destdir = os.path.join(tarextdir, 'dest')
|
||||||
+ os.mkdir(tarextdir)
|
+ os.mkdir(tarextdir)
|
||||||
+ try:
|
+ try:
|
||||||
+ with os_helper.temp_cwd(destdir):
|
+ with support.temp_cwd(destdir):
|
||||||
+ self.tarfilecmd_failure('-e', tmpname,
|
+ self.tarfilecmd_failure('-e', tmpname,
|
||||||
+ '-v',
|
+ '-v',
|
||||||
+ '--filter', 'data')
|
+ '--filter', 'data')
|
||||||
@ -1632,7 +1620,7 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py
|
|||||||
+ PYTHONIOENCODING='utf-8')
|
+ PYTHONIOENCODING='utf-8')
|
||||||
+ self.assertIn(b' file is extracted.', out)
|
+ self.assertIn(b' file is extracted.', out)
|
||||||
+ finally:
|
+ finally:
|
||||||
+ os_helper.rmtree(tarextdir)
|
+ support.rmtree(tarextdir)
|
||||||
+
|
+
|
||||||
def test_extract_command_different_directory(self):
|
def test_extract_command_different_directory(self):
|
||||||
self.make_simple_tarfile(tmpname)
|
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 member in self.tar.getmembers():
|
||||||
+ for attr_name in attr_names:
|
+ for attr_name in attr_names:
|
||||||
+ setattr(member, attr_name, None)
|
+ setattr(member, attr_name, None)
|
||||||
+ with os_helper.temp_dir(DIR):
|
+ with support.temp_dir(DIR):
|
||||||
+ self.tar.extractall(DIR, filter='fully_trusted')
|
+ self.tar.extractall(DIR, filter='fully_trusted')
|
||||||
+ self.check_files_present(DIR)
|
+ self.check_files_present(DIR)
|
||||||
+ yield DIR
|
+ yield DIR
|
||||||
@ -2026,7 +2014,7 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py
|
|||||||
+ other files.
|
+ other files.
|
||||||
+ When checking directories, do so before their contents.
|
+ When checking directories, do so before their contents.
|
||||||
+ """
|
+ """
|
||||||
+ with os_helper.temp_dir(self.outerdir):
|
+ with support.temp_dir(self.outerdir):
|
||||||
+ try:
|
+ try:
|
||||||
+ tar.extractall(self.destdir, filter=filter)
|
+ tar.extractall(self.destdir, filter=filter)
|
||||||
+ except Exception as exc:
|
+ 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', symlink_to='current/..')
|
||||||
+ arc.add('parent/evil')
|
+ arc.add('parent/evil')
|
||||||
+
|
+
|
||||||
+ if os_helper.can_symlink():
|
+ if support.can_symlink():
|
||||||
+ with self.check_context(arc.open(), 'fully_trusted'):
|
+ with self.check_context(arc.open(), 'fully_trusted'):
|
||||||
+ if self.raised_exception is not None:
|
+ if self.raised_exception is not None:
|
||||||
+ # Windows will refuse to create a file that's a symlink to itself
|
+ # 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')
|
+ arc.add('parent/evil')
|
||||||
+
|
+
|
||||||
+ with self.check_context(arc.open(), 'fully_trusted'):
|
+ 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('current', symlink_to='.')
|
||||||
+ self.expect_file('parent', symlink_to='..')
|
+ self.expect_file('parent', symlink_to='..')
|
||||||
+ self.expect_file('../evil')
|
+ self.expect_file('../evil')
|
||||||
@ -2175,7 +2163,7 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py
|
|||||||
+ self.expect_file('parent/evil')
|
+ self.expect_file('parent/evil')
|
||||||
+
|
+
|
||||||
+ with self.check_context(arc.open(), 'tar'):
|
+ with self.check_context(arc.open(), 'tar'):
|
||||||
+ if os_helper.can_symlink():
|
+ if support.can_symlink():
|
||||||
+ self.expect_exception(
|
+ self.expect_exception(
|
||||||
+ tarfile.OutsideDestinationError,
|
+ tarfile.OutsideDestinationError,
|
||||||
+ "'parent/evil' would be extracted to "
|
+ "'parent/evil' would be extracted to "
|
||||||
@ -2199,14 +2187,14 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py
|
|||||||
+ arc.add('parent/evil')
|
+ arc.add('parent/evil')
|
||||||
+
|
+
|
||||||
+ with self.check_context(arc.open(), 'fully_trusted'):
|
+ 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('parent', symlink_to=self.outerdir)
|
||||||
+ self.expect_file('../evil')
|
+ self.expect_file('../evil')
|
||||||
+ else:
|
+ else:
|
||||||
+ self.expect_file('parent/evil')
|
+ self.expect_file('parent/evil')
|
||||||
+
|
+
|
||||||
+ with self.check_context(arc.open(), 'tar'):
|
+ with self.check_context(arc.open(), 'tar'):
|
||||||
+ if os_helper.can_symlink():
|
+ if support.can_symlink():
|
||||||
+ self.expect_exception(
|
+ self.expect_exception(
|
||||||
+ tarfile.OutsideDestinationError,
|
+ tarfile.OutsideDestinationError,
|
||||||
+ "'parent/evil' would be extracted to "
|
+ "'parent/evil' would be extracted to "
|
||||||
@ -2227,7 +2215,7 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py
|
|||||||
+
|
+
|
||||||
+ try:
|
+ try:
|
||||||
+ with self.check_context(arc.open(), filter='fully_trusted'):
|
+ with self.check_context(arc.open(), filter='fully_trusted'):
|
||||||
+ if os_helper.can_symlink():
|
+ if support.can_symlink():
|
||||||
+ if isinstance(self.raised_exception, FileExistsError):
|
+ if isinstance(self.raised_exception, FileExistsError):
|
||||||
+ # XXX TarFile happens to fail creating a parent
|
+ # XXX TarFile happens to fail creating a parent
|
||||||
+ # directory.
|
+ # directory.
|
||||||
@ -2261,7 +2249,7 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py
|
|||||||
+
|
+
|
||||||
+ with self.check_context(arc.open(), 'fully_trusted'):
|
+ with self.check_context(arc.open(), 'fully_trusted'):
|
||||||
+ self.expect_file('tmp', type=tarfile.DIRTYPE)
|
+ 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')
|
+ self.expect_file('../moo', symlink_to='tmp/../../tmp/moo')
|
||||||
+
|
+
|
||||||
+ for filter in 'tar', 'data':
|
+ for filter in 'tar', 'data':
|
||||||
@ -2568,10 +2556,8 @@ Index: Python-3.9.16/Lib/test/test_tarfile.py
|
|||||||
def setUpModule():
|
def setUpModule():
|
||||||
support.unlink(TEMPDIR)
|
support.unlink(TEMPDIR)
|
||||||
os.makedirs(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
|
--- /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 @@
|
@@ -0,0 +1,4 @@
|
||||||
+The extraction methods in :mod:`tarfile`, and :func:`shutil.unpack_archive`,
|
+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
|
+have a new a *filter* argument that allows limiting tar features than may be
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Sat May 6 17:31:35 UTC 2023 - Matej Cepl <mcepl@suse.com>
|
||||||
|
|
||||||
|
- 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 <mcepl@suse.com>
|
Wed May 3 14:09:37 UTC 2023 - Matej Cepl <mcepl@suse.com>
|
||||||
|
|
||||||
|
@ -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
|
# 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
|
# Implement PEP-706 to filter outcome of the tarball extracing
|
||||||
Patch39: CVE-2007-4559-filter-tarfile_extractall.patch
|
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: autoconf-archive
|
||||||
BuildRequires: automake
|
BuildRequires: automake
|
||||||
BuildRequires: fdupes
|
BuildRequires: fdupes
|
||||||
@ -428,6 +431,7 @@ other applications.
|
|||||||
%patch37 -p1
|
%patch37 -p1
|
||||||
%patch38 -p1
|
%patch38 -p1
|
||||||
%patch39 -p1
|
%patch39 -p1
|
||||||
|
%patch40 -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
|
||||||
|
Loading…
Reference in New Issue
Block a user