From d9ccc30eb674d87fc6b913ec527fa1cf68216711 Mon Sep 17 00:00:00 2001 From: mcalabkova <> Date: Jan 17 2025 23:27:08 +0000 Subject: Update python-pytest-shutil to version 1.8.0 / rev 13 via SR 1238531 https://build.opensuse.org/request/show/1238531 by user mcalabkova + anag+factory --- diff --git a/.files b/.files index d6df137..75385f3 100644 Binary files a/.files and b/.files differ diff --git a/.rev b/.rev index a0a641f..8f70a12 100644 --- a/.rev +++ b/.rev @@ -108,4 +108,12 @@ <comment>- Remove not needed dep python-setuptools-git</comment> <requestid>1220541</requestid> </revision> + <revision rev="13" vrev="3"> + <srcmd5>ee7f372fbfa9f0300092ef925cd2ada7</srcmd5> + <version>1.8.0</version> + <time>1737135833</time> + <user>anag+factory</user> + <comment></comment> + <requestid>1238531</requestid> + </revision> </revisionlist> diff --git a/python-pytest-shutil-no-six.patch b/python-pytest-shutil-no-six.patch new file mode 100644 index 0000000..8837bd3 --- /dev/null +++ b/python-pytest-shutil-no-six.patch @@ -0,0 +1,437 @@ +Index: pytest-shutil-1.8.0/pytest_shutil/cmdline.py +=================================================================== +--- pytest-shutil-1.8.0.orig/pytest_shutil/cmdline.py ++++ pytest-shutil-1.8.0/pytest_shutil/cmdline.py +@@ -10,12 +10,6 @@ from contextlib import contextmanager + from tempfile import mkdtemp + + +-try: # Python 2 +- str_type = basestring +-except NameError: # Python 3 +- str_type = str +- +- + def get_log(): + return logging.getLogger(__name__) + +Index: pytest-shutil-1.8.0/pytest_shutil/run.py +=================================================================== +--- pytest-shutil-1.8.0.orig/pytest_shutil/run.py ++++ pytest-shutil-1.8.0/pytest_shutil/run.py +@@ -3,36 +3,20 @@ + """ + import sys + import os ++import pickle + import importlib.util + import logging + from functools import update_wrapper + import inspect + import textwrap +-from contextlib import closing ++from contextlib import closing, ExitStack + import subprocess +- +-try: +- from unittest.mock import patch +-except ImportError: +- # python 2 +- from mock import patch ++from unittest.mock import patch + + import execnet +-from six.moves import cPickle # @UnresolvedImport + + from . import cmdline + +-try: +- # Python 3 +- from contextlib import ExitStack +-except ImportError: +- from contextlib2 import ExitStack +- +-try: # Python 2 +- str_type = basestring +-except NameError: # Python 3 +- str_type = str +- + + log = logging.getLogger(__name__) + +@@ -68,7 +52,7 @@ def run(cmd, stdin=None, capture_stdout= + + (out, _) = p.communicate(stdin) + +- if out is not None and not isinstance(out, str_type): ++ if out is not None and not isinstance(out, str): + try: + out = out.decode('utf-8') + except: +@@ -143,22 +127,20 @@ def _make_pickleable(fn): + # return a pickleable function followed by a tuple of initial arguments + # could use partial but this is more efficient + try: +- cPickle.dumps(fn, protocol=0) +- except (TypeError, cPickle.PickleError, AttributeError): ++ pickle.dumps(fn, protocol=0) ++ except (TypeError, pickle.PickleError, AttributeError): + pass + else: + return fn, () + if inspect.ismethod(fn): + name, self_ = fn.__name__, fn.__self__ +- if self_ is None: # Python 2 unbound method +- self_ = fn.im_class + return _invoke_method, (self_, name) + elif inspect.isfunction(fn) and fn.__module__ in sys.modules: + cls, name = _find_class_from_staticmethod(fn) + if (cls, name) != (None, None): + try: +- cPickle.dumps((cls, name), protocol=0) +- except cPickle.PicklingError: ++ pickle.dumps((cls, name), protocol=0) ++ except pickle.PicklingError: + pass + else: + return _invoke_method, (cls, name) +@@ -176,9 +158,9 @@ def _run_in_subprocess_redirect_stdout(f + + + def _run_in_subprocess_remote_fn(channel): +- from six.moves import cPickle # @UnresolvedImport @Reimport # NOQA +- fn, args, kwargs = cPickle.loads(channel.receive(None)) +- channel.send(cPickle.dumps(fn(*args, **kwargs), protocol=0)) ++ import pickle ++ fn, args, kwargs = pickle.loads(channel.receive(None)) ++ channel.send(pickle.dumps(fn(*args, **kwargs), protocol=0)) + + + def run_in_subprocess(fn, python=sys.executable, cd=None, timeout=None): +@@ -204,12 +186,12 @@ def run_in_subprocess(fn, python=sys.exe + stack.callback(gw.exit) + if fix_stdout: + with closing(gw.remote_exec(_run_in_subprocess_remote_fn)) as chan: +- chan.send(cPickle.dumps((_run_in_subprocess_redirect_stdout, (fd,), {}), protocol=0)) ++ chan.send(pickle.dumps((_run_in_subprocess_redirect_stdout, (fd,), {}), protocol=0)) + chan.receive(None) + with closing(gw.remote_exec(_run_in_subprocess_remote_fn)) as chan: + payload = (pkl_fn, tuple(i for t in (preargs, args) for i in t), kwargs) +- chan.send(cPickle.dumps(payload, protocol=0)) +- return cPickle.loads(chan.receive(timeout)) ++ chan.send(pickle.dumps(payload, protocol=0)) ++ return pickle.loads(chan.receive(timeout)) + return inner if isinstance(fn, str) else update_wrapper(inner, fn) + + +Index: pytest-shutil-1.8.0/pytest_shutil/workspace.py +=================================================================== +--- pytest-shutil-1.8.0.orig/pytest_shutil/workspace.py ++++ pytest-shutil-1.8.0/pytest_shutil/workspace.py +@@ -1,6 +1,5 @@ + """ Temporary directory fixtures + """ +-from __future__ import absolute_import + import os + import tempfile + import shutil +Index: pytest-shutil-1.8.0/setup.py +=================================================================== +--- pytest-shutil-1.8.0.orig/setup.py ++++ pytest-shutil-1.8.0/setup.py +@@ -17,7 +17,7 @@ classifiers = [ + 'Programming Language :: Python :: 3.7', + ] + +-install_requires = ['six', ++install_requires = [ + 'execnet', + 'pytest', + 'termcolor' +Index: pytest-shutil-1.8.0/tests/integration/test_run_integration.py +=================================================================== +--- pytest-shutil-1.8.0.orig/tests/integration/test_run_integration.py ++++ pytest-shutil-1.8.0/tests/integration/test_run_integration.py +@@ -6,13 +6,9 @@ import pytest + import execnet + import inspect + import textwrap ++from unittest import mock + from uuid import uuid4 + +-try: +- from unittest import mock +-except ImportError: +- import mock +- + from pytest_shutil import run, workspace + from pytest_shutil.env import no_cov + +Index: pytest-shutil-1.8.0/tests/unit/test_run.py +=================================================================== +--- pytest-shutil-1.8.0.orig/tests/unit/test_run.py ++++ pytest-shutil-1.8.0/tests/unit/test_run.py +@@ -1,17 +1,11 @@ ++import pickle + import sys + from uuid import uuid4 + from subprocess import PIPE, STDOUT ++from unittest.mock import Mock, patch, sentinel, DEFAULT, call + + import pytest + +-try: +- from unittest.mock import Mock, patch, sentinel, DEFAULT, call +-except ImportError: +- # python 2 +- from mock import Mock, patch, sentinel, DEFAULT, call +- +-from six.moves import cPickle +- + from pytest_shutil import run + + ARG = str(uuid4()) +@@ -50,41 +44,41 @@ def test_run_as_main(): + + + def test_run_in_subprocess(): +- with patch.multiple('pytest_shutil.run', cPickle=DEFAULT, execnet=DEFAULT) as mocks: ++ with patch.multiple('pytest_shutil.run', pickle=DEFAULT, execnet=DEFAULT) as mocks: + fn = Mock(__name__='fn') + res = run.run_in_subprocess(fn, python='sentinel.python')(sentinel.arg, kw=sentinel.kw) + mocks['execnet'].makegateway.assert_called_once_with('popen//python=sentinel.python') + gw = mocks['execnet'].makegateway.return_value + ((remote_fn,), _) = gw.remote_exec.call_args + chan = gw.remote_exec.return_value +- mocks['cPickle'].dumps.assert_called_with((fn, (sentinel.arg,), {'kw': sentinel.kw}), protocol=0) +- chan.send.assert_called_with(mocks['cPickle'].dumps.return_value) ++ mocks['pickle'].dumps.assert_called_with((fn, (sentinel.arg,), {'kw': sentinel.kw}), protocol=0) ++ chan.send.assert_called_with(mocks['pickle'].dumps.return_value) + chan.receive.assert_has_calls([call(None) for _i in range(gw.remote_exec.call_count)]) +- mocks['cPickle'].loads.assert_called_once_with(chan.receive.return_value) +- assert res is mocks['cPickle'].loads.return_value ++ mocks['pickle'].loads.assert_called_once_with(chan.receive.return_value) ++ assert res is mocks['pickle'].loads.return_value + chan.close.assert_has_calls([call() for _i in range(gw.remote_exec.call_count)]) + gw.exit.assert_called_once_with() + +- with patch('six.moves.cPickle') as cPickle: ++ with patch('pickle.loads') as loads, patch('pickle.dumps') as dumps: + channel, fn = Mock(), Mock() +- cPickle.loads.return_value = (fn, (sentinel.arg,), {'kw': sentinel.kw}) ++ loads.return_value = (fn, (sentinel.arg,), {'kw': sentinel.kw}) + remote_fn(channel) + channel.receive.assert_called_once_with(None) +- cPickle.loads.assert_called_once_with(channel.receive.return_value) ++ loads.assert_called_once_with(channel.receive.return_value) + fn.assert_called_once_with(sentinel.arg, kw=sentinel.kw) +- cPickle.dumps.assert_called_once_with(fn.return_value, protocol=0) +- channel.send.assert_called_once_with(cPickle.dumps.return_value) ++ dumps.assert_called_once_with(fn.return_value, protocol=0) ++ channel.send.assert_called_once_with(dumps.return_value) + + + def test_run_in_runcd(): +- with patch.multiple('pytest_shutil.run', cPickle=DEFAULT, execnet=DEFAULT) as mocks: ++ with patch.multiple('pytest_shutil.run', pickle=DEFAULT, execnet=DEFAULT) as mocks: + run.run_in_subprocess(Mock(__name__='fn'), python='sentinel.python', + cd='sentinel.cd')(sentinel.arg, kw=sentinel.kw) + mocks['execnet'].makegateway.assert_called_once_with('popen//python=sentinel.python//chdir=sentinel.cd') + + + def test_run_in_runtimeout(): +- with patch.multiple('pytest_shutil.run', cPickle=DEFAULT, execnet=DEFAULT) as mocks: ++ with patch.multiple('pytest_shutil.run', pickle=DEFAULT, execnet=DEFAULT) as mocks: + run.run_in_subprocess(Mock(__name__='fn'), python='sentinel.python', + timeout=sentinel.timeout)(sentinel.arg, kw=sentinel.kw) + gw = mocks['execnet'].makegateway.return_value +@@ -100,15 +94,15 @@ def test_run_in_runpickleable_function() + with patch('pytest_shutil.run.execnet') as execnet: + gw = execnet.makegateway.return_value + chan = gw.remote_exec.return_value +- chan.receive.return_value = cPickle.dumps(sentinel.ret) ++ chan.receive.return_value = pickle.dumps(sentinel.ret) + with patch.object(run, fn.__name__, fn, create=True): + run.run_in_subprocess(fn, python='sentinel.python')(ARG, kw=KW) + ((s,), _) = chan.send.call_args +- assert cPickle.loads(s) == (fn, (ARG,), {'kw': KW}) ++ assert pickle.loads(s) == (fn, (ARG,), {'kw': KW}) + ((remote_fn,), _) = gw.remote_exec.call_args + ((chan.receive.return_value,), _) = chan.send.call_args + remote_fn(chan) +- chan.send.assert_called_with(cPickle.dumps(((ARG,), {'kw': KW}), protocol=0)) ++ chan.send.assert_called_with(pickle.dumps(((ARG,), {'kw': KW}), protocol=0)) + + + def test_run_in_runstr(): +@@ -118,14 +112,14 @@ def test_run_in_runstr(): + with patch('pytest_shutil.run.execnet') as execnet: + gw = execnet.makegateway.return_value + chan = gw.remote_exec.return_value +- chan.receive.return_value = cPickle.dumps(sentinel.ret) ++ chan.receive.return_value = pickle.dumps(sentinel.ret) + run.run_in_subprocess(source, python='sentinel.python')(ARG, kw=KW) + ((s,), _) = chan.send.call_args +- assert cPickle.loads(s) == (run._evaluate_fn_source, (source, ARG,), {'kw': KW}) ++ assert pickle.loads(s) == (run._evaluate_fn_source, (source, ARG,), {'kw': KW}) + ((remote_fn,), _) = gw.remote_exec.call_args + ((chan.receive.return_value,), _) = chan.send.call_args + remote_fn(chan) +- chan.send.assert_called_with(cPickle.dumps(((ARG,), {'kw': KW}), protocol=0)) ++ chan.send.assert_called_with(pickle.dumps(((ARG,), {'kw': KW}), protocol=0)) + + + def test_run_in_runnested_function(): +@@ -137,14 +131,14 @@ def test_run_in_runnested_function(): + with patch('pytest_shutil.run.execnet') as execnet: + gw = execnet.makegateway.return_value + chan = gw.remote_exec.return_value +- chan.receive.return_value = cPickle.dumps(sentinel.ret) ++ chan.receive.return_value = pickle.dumps(sentinel.ret) + run.run_in_subprocess(fn, python='sentinel.python')(ARG, kw=KW) + ((s,), _) = chan.send.call_args +- assert cPickle.loads(s) == (run._evaluate_fn_source, (source, ARG,), {'kw': KW}) ++ assert pickle.loads(s) == (run._evaluate_fn_source, (source, ARG,), {'kw': KW}) + ((remote_fn,), _) = gw.remote_exec.call_args + ((chan.receive.return_value,), _) = chan.send.call_args + remote_fn(chan) +- chan.send.assert_called_with(cPickle.dumps(((ARG,), {'kw': KW}), protocol=0)) ++ chan.send.assert_called_with(pickle.dumps(((ARG,), {'kw': KW}), protocol=0)) + + + @pytest.mark.xfail(sys.version_info >= (3,5), reason="python3.5 api changes") +@@ -157,23 +151,18 @@ def test_run_in_runbound_method(): + with patch('pytest_shutil.run.execnet') as execnet: + gw = execnet.makegateway.return_value + chan = gw.remote_exec.return_value +- chan.receive.return_value = cPickle.dumps(sentinel.ret) ++ chan.receive.return_value = pickle.dumps(sentinel.ret) + c = C() + with patch.object(run, C.__name__, C, create=True): + run.run_in_subprocess(c.fn, python='sentinel.python')(ARG, kw=KW) + ((s,), _) = chan.send.call_args + +- if sys.version_info < (3, 0, 0): +- # Bound methods are not pickleable in Python 2. +- assert cPickle.loads(s) == (run._invoke_method, (c, 'fn', ARG,), {'kw': KW}) +- else: +- # Bound methods are pickleable in Python 3. +- assert cPickle.loads(s) == (c.fn, (ARG,), {'kw': KW}) ++ assert pickle.loads(s) == (c.fn, (ARG,), {'kw': KW}) + + ((remote_fn,), _) = gw.remote_exec.call_args + ((chan.receive.return_value,), _) = chan.send.call_args + remote_fn(chan) +- chan.send.assert_called_with(cPickle.dumps((c, (ARG,), {'kw': KW}), protocol=0)) ++ chan.send.assert_called_with(pickle.dumps((c, (ARG,), {'kw': KW}), protocol=0)) + + + @pytest.mark.xfail(sys.version_info >= (3,5), reason="python3.5 api changes") +@@ -182,7 +171,7 @@ def test_run_in_runbound_method_on_unpic + def fn(self, *args, **kwargs): + return self, args, kwargs + with patch('pytest_shutil.run.execnet'): +- with pytest.raises(cPickle.PicklingError): ++ with pytest.raises(pickle.PicklingError): + run.run_in_subprocess(C().fn, python='sentinel.python')(ARG, kw=KW) + + +@@ -196,16 +185,16 @@ def test_run_in_rununbound_method(): + with patch('pytest_shutil.run.execnet') as execnet: + gw = execnet.makegateway.return_value + chan = gw.remote_exec.return_value +- chan.receive.return_value = cPickle.dumps(sentinel.ret) ++ chan.receive.return_value = pickle.dumps(sentinel.ret) + c = C() + with patch.object(run, C.__name__, C, create=True): + run.run_in_subprocess(C.fn, python='sentinel.python')(c, ARG, kw=KW) + ((s,), _) = chan.send.call_args +- assert cPickle.loads(s) == (run._invoke_method, (C, 'fn', c, ARG,), {'kw': KW}) ++ assert pickle.loads(s) == (run._invoke_method, (C, 'fn', c, ARG,), {'kw': KW}) + ((remote_fn,), _) = gw.remote_exec.call_args + ((chan.receive.return_value,), _) = chan.send.call_args + remote_fn(chan) +- chan.send.assert_called_with(cPickle.dumps((c, (ARG,), {'kw': KW}), protocol=0)) ++ chan.send.assert_called_with(pickle.dumps((c, (ARG,), {'kw': KW}), protocol=0)) + + + @pytest.mark.xfail(sys.version_info >= (3,5), reason="python3.5 api changes") +@@ -214,7 +203,7 @@ def test_run_in_rununbound_method_on_unp + def fn(self, *args, **kwargs): + return self, args, kwargs + with patch('pytest_shutil.run.execnet'): +- with pytest.raises(cPickle.PicklingError): ++ with pytest.raises(pickle.PicklingError): + run.run_in_subprocess(C.fn, python='sentinel.python')(C(), ARG, kw=KW) + + +@@ -229,15 +218,15 @@ def test_run_in_runstaticmethod(): + with patch('pytest_shutil.run.execnet') as execnet: + gw = execnet.makegateway.return_value + chan = gw.remote_exec.return_value +- chan.receive.return_value = cPickle.dumps(sentinel.ret) ++ chan.receive.return_value = pickle.dumps(sentinel.ret) + with patch.object(run, C.__name__, C, create=True): + run.run_in_subprocess(C.fn, python='sentinel.python')(ARG, kw=KW) + ((s,), _) = chan.send.call_args +- assert cPickle.loads(s) == (run._invoke_method, (C, 'fn', ARG,), {'kw': KW}) ++ assert pickle.loads(s) == (run._invoke_method, (C, 'fn', ARG,), {'kw': KW}) + ((remote_fn,), _) = gw.remote_exec.call_args + ((chan.receive.return_value,), _) = chan.send.call_args + remote_fn(chan) +- chan.send.assert_called_with(cPickle.dumps(((ARG,), {'kw': KW}), protocol=0)) ++ chan.send.assert_called_with(pickle.dumps(((ARG,), {'kw': KW}), protocol=0)) + + + @pytest.mark.xfail(sys.version_info >= (3,5), reason="python3.5 api changes") +@@ -255,15 +244,15 @@ def fn(*args, **kwargs): + with patch('pytest_shutil.run.execnet') as execnet: + gw = execnet.makegateway.return_value + chan = gw.remote_exec.return_value +- chan.receive.return_value = cPickle.dumps(sentinel.ret) ++ chan.receive.return_value = pickle.dumps(sentinel.ret) + with patch.object(run, C.__name__, C, create=True): + run.run_in_subprocess(C.fn, python='sentinel.python')(ARG, kw=KW) + ((s,), _) = chan.send.call_args +- assert cPickle.loads(s) == (run._evaluate_fn_source, (source, ARG,), {'kw': KW}) ++ assert pickle.loads(s) == (run._evaluate_fn_source, (source, ARG,), {'kw': KW}) + ((remote_fn,), _) = gw.remote_exec.call_args + ((chan.receive.return_value,), _) = chan.send.call_args + remote_fn(chan) +- chan.send.assert_called_with(cPickle.dumps(((ARG,), {'kw': KW}), protocol=0)) ++ chan.send.assert_called_with(pickle.dumps(((ARG,), {'kw': KW}), protocol=0)) + + + @pytest.mark.xfail(sys.version_info >= (3,5), reason="python3.5 api changes") +@@ -277,21 +266,16 @@ def test_run_in_runclassmethod(): + with patch('pytest_shutil.run.execnet') as execnet: + gw = execnet.makegateway.return_value + chan = gw.remote_exec.return_value +- chan.receive.return_value = cPickle.dumps(sentinel.ret) ++ chan.receive.return_value = pickle.dumps(sentinel.ret) + c = C() + with patch.object(run, C.__name__, C, create=True): + run.run_in_subprocess(c.fn, python='sentinel.python')(ARG, kw=KW) + ((s,), _) = chan.send.call_args +- if sys.version_info < (3, 0, 0): +- # Class methods are not pickleable in Python 2. +- assert cPickle.loads(s) == (run._invoke_method, (C, 'fn', ARG), {'kw': KW}) +- else: +- # Class methods are pickleable in Python 3. +- assert cPickle.loads(s) == (c.fn, (ARG,), {'kw': KW}) ++ assert pickle.loads(s) == (c.fn, (ARG,), {'kw': KW}) + ((remote_fn,), _) = gw.remote_exec.call_args + ((chan.receive.return_value,), _) = chan.send.call_args + remote_fn(chan) +- chan.send.assert_called_with(cPickle.dumps((C, (ARG,), {'kw': KW}), protocol=0)) ++ chan.send.assert_called_with(pickle.dumps((C, (ARG,), {'kw': KW}), protocol=0)) + + + @pytest.mark.xfail(sys.version_info >= (3,5), reason="python3.5 api changes") +@@ -301,5 +285,5 @@ def test_run_in_runclassmethod_on_unpick + def fn(cls, *args, **kwargs): + return cls, args, kwargs + with patch('pytest_shutil.run.execnet'): +- with pytest.raises(cPickle.PicklingError): ++ with pytest.raises(pickle.PicklingError): + run.run_in_subprocess(C.fn, python='sentinel.python')(ARG, kw=KW) diff --git a/python-pytest-shutil.changes b/python-pytest-shutil.changes index 3ac3c04..798bc79 100644 --- a/python-pytest-shutil.changes +++ b/python-pytest-shutil.changes @@ -1,4 +1,17 @@ ------------------------------------------------------------------- +Fri Jan 17 15:01:51 UTC 2025 - pgajdos@suse.com + +- really remove six requirements + +------------------------------------------------------------------- +Fri Jan 17 14:21:10 UTC 2025 - pgajdos@suse.com + +- do not require six +- added patches + fix https://github.com/man-group/pytest-plugins/commit/0018cc543229732b9c04fad909d2b7ee6167fa40 + + python-pytest-shutil-no-six.patch + +------------------------------------------------------------------- Mon Nov 4 11:05:21 UTC 2024 - Daniel Garcia <daniel.garcia@suse.com> - Remove not needed dep python-setuptools-git diff --git a/python-pytest-shutil.spec b/python-pytest-shutil.spec index 636177e..2300e86 100644 --- a/python-pytest-shutil.spec +++ b/python-pytest-shutil.spec @@ -1,7 +1,7 @@ # # spec file for package python-pytest-shutil # -# Copyright (c) 2024 SUSE LLC +# Copyright (c) 2025 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -24,18 +24,18 @@ Summary: A goodie-bag of unix shell and environment tools for pytest License: MIT URL: https://github.com/man-group/pytest-plugins Source: https://files.pythonhosted.org/packages/source/p/pytest-shutil/pytest-shutil-%{version}.tar.gz +# https://github.com/man-group/pytest-plugins/commit/0018cc543229732b9c04fad909d2b7ee6167fa40 +Patch0: python-pytest-shutil-no-six.patch BuildRequires: %{python_module execnet} BuildRequires: %{python_module pip} BuildRequires: %{python_module pytest} BuildRequires: %{python_module setuptools} -BuildRequires: %{python_module six} BuildRequires: %{python_module termcolor} BuildRequires: %{python_module wheel} BuildRequires: fdupes BuildRequires: python-rpm-macros Requires: python-execnet Requires: python-pytest -Requires: python-six Requires: python-termcolor BuildArch: noarch @@ -46,7 +46,7 @@ This library is a goodie-bag of Unix shell and environment management tools for automated tests. %prep -%autosetup -p2 -n pytest-shutil-%{version} +%autosetup -p1 -n pytest-shutil-%{version} %build %pyproject_wheel