Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-setuptools for openSUSE:Factory checked in at 2023-06-08 21:41:51 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-setuptools (Old) and /work/SRC/openSUSE:Factory/.python-setuptools.new.15902 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-setuptools" Thu Jun 8 21:41:51 2023 rev:77 rq:1091248 version:67.8.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-setuptools/python-setuptools.changes 2023-05-30 22:02:02.042865890 +0200 +++ /work/SRC/openSUSE:Factory/.python-setuptools.new.15902/python-setuptools.changes 2023-06-08 21:41:54.241758337 +0200 @@ -1,0 +2,9 @@ +Wed Jun 7 09:07:45 UTC 2023 - Daniel Garcia <daniel.gar...@suse.com> + +- Update to 67.8.0: + * #3128: In deprecated easy_install, reload and merge the pth file + before saving. + * #3915: Adequate tests to the latest changes in virtualenv for + Python 3.12. + +------------------------------------------------------------------- Old: ---- setuptools-67.7.2.tar.gz New: ---- setuptools-67.8.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-setuptools.spec ++++++ --- /var/tmp/diff_new_pack.j7FMeQ/_old 2023-06-08 21:41:54.857761968 +0200 +++ /var/tmp/diff_new_pack.j7FMeQ/_new 2023-06-08 21:41:54.861761991 +0200 @@ -38,7 +38,7 @@ %define mypython python %{?sle15_python_module_pythons} Name: python-setuptools%{psuffix} -Version: 67.7.2 +Version: 67.8.0 Release: 0 Summary: Download, build, install, upgrade, and uninstall Python packages License: Apache-2.0 AND MIT AND BSD-2-Clause AND Python-2.0 ++++++ setuptools-67.7.2.tar.gz -> setuptools-67.8.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/setuptools-67.7.2/CHANGES.rst new/setuptools-67.8.0/CHANGES.rst --- old/setuptools-67.7.2/CHANGES.rst 2023-04-24 13:36:34.000000000 +0200 +++ new/setuptools-67.8.0/CHANGES.rst 2023-05-19 21:38:04.000000000 +0200 @@ -1,3 +1,16 @@ +v67.8.0 +------- + + +Changes +^^^^^^^ +* #3128: In deprecated easy_install, reload and merge the pth file before saving. + +Misc +^^^^ +* #3915: Adequate tests to the latest changes in ``virtualenv`` for Python 3.12. + + v67.7.2 ------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/setuptools-67.7.2/LICENSE new/setuptools-67.8.0/LICENSE --- old/setuptools-67.7.2/LICENSE 2023-04-24 13:36:34.000000000 +0200 +++ new/setuptools-67.8.0/LICENSE 2023-05-19 21:38:04.000000000 +0200 @@ -1,5 +1,3 @@ -Copyright Jason R. Coombs - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/setuptools-67.7.2/PKG-INFO new/setuptools-67.8.0/PKG-INFO --- old/setuptools-67.7.2/PKG-INFO 2023-04-24 13:36:54.237340200 +0200 +++ new/setuptools-67.8.0/PKG-INFO 2023-05-19 21:38:26.308272800 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: setuptools -Version: 67.7.2 +Version: 67.8.0 Summary: Easily download, build, install, upgrade, and uninstall Python packages Home-page: https://github.com/pypa/setuptools Author: Python Packaging Authority diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/setuptools-67.7.2/docs/userguide/ext_modules.rst new/setuptools-67.8.0/docs/userguide/ext_modules.rst --- old/setuptools-67.7.2/docs/userguide/ext_modules.rst 2023-04-24 13:36:34.000000000 +0200 +++ new/setuptools-67.8.0/docs/userguide/ext_modules.rst 2023-05-19 21:38:04.000000000 +0200 @@ -46,7 +46,7 @@ .. seealso:: You can find more information on the `Python docs about C/C++ extensions`_. - Alternatively, you might also be interested in learn about `Cython`_. + Alternatively, you might also be interested in learning about `Cython`_. If you plan to distribute a package that uses extensions across multiple platforms, :pypi:`cibuildwheel` can also be helpful. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/setuptools-67.7.2/pyproject.toml new/setuptools-67.8.0/pyproject.toml --- old/setuptools-67.7.2/pyproject.toml 2023-04-24 13:36:34.000000000 +0200 +++ new/setuptools-67.8.0/pyproject.toml 2023-05-19 21:38:04.000000000 +0200 @@ -14,12 +14,12 @@ [tool.pytest-enabler.mypy] #addopts = "--mypy" -[tool.pytest-enabler.flake8] -addopts = "--flake8" - [tool.pytest-enabler.cov] addopts = "--cov" +[tool.pytest-enabler.ruff] +addopts = "--ruff" + [tool.pytest-enabler.xdist] addopts = "-n auto" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/setuptools-67.7.2/pytest.ini new/setuptools-67.8.0/pytest.ini --- old/setuptools-67.7.2/pytest.ini 2023-04-24 13:36:34.000000000 +0200 +++ new/setuptools-67.8.0/pytest.ini 2023-05-19 21:38:04.000000000 +0200 @@ -14,19 +14,11 @@ # Ensure ResourceWarnings are emitted default::ResourceWarning - # Suppress deprecation warning in flake8 - ignore:SelectableGroups dict interface is deprecated::flake8 - # shopkeep/pytest-black#55 ignore:<class 'pytest_black.BlackItem'> is not using a cooperative constructor:pytest.PytestDeprecationWarning ignore:The \(fspath. py.path.local\) argument to BlackItem is deprecated.:pytest.PytestDeprecationWarning ignore:BlackItem is an Item subclass and should not be a collector:pytest.PytestWarning - # tholo/pytest-flake8#83 - ignore:<class 'pytest_flake8.Flake8Item'> is not using a cooperative constructor:pytest.PytestDeprecationWarning - ignore:The \(fspath. py.path.local\) argument to Flake8Item is deprecated.:pytest.PytestDeprecationWarning - ignore:Flake8Item is an Item subclass and should not be a collector:pytest.PytestWarning - # shopkeep/pytest-black#67 ignore:'encoding' argument not specified::pytest_black diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/setuptools-67.7.2/setup.cfg new/setuptools-67.8.0/setup.cfg --- old/setuptools-67.7.2/setup.cfg 2023-04-24 13:36:54.237340200 +0200 +++ new/setuptools-67.8.0/setup.cfg 2023-05-19 21:38:26.308272800 +0200 @@ -1,6 +1,6 @@ [metadata] name = setuptools -version = 67.7.2 +version = 67.8.0 author = Python Packaging Authority author_email = distutils-...@python.org description = Easily download, build, install, upgrade, and uninstall Python packages @@ -40,9 +40,6 @@ testing = pytest >= 6 pytest-checkdocs >= 2.4 - pytest-flake8; \ - python_version < "3.12" - flake8 < 5 pytest-black >= 0.3.7; \ python_implementation != "PyPy" pytest-cov; \ @@ -50,7 +47,7 @@ pytest-mypy >= 0.9.1; \ python_implementation != "PyPy" pytest-enabler >= 1.3 - pytest-perf + pytest-ruff; sys_platform != "cygwin" flake8-2020 virtualenv>=13.0.0 @@ -65,6 +62,7 @@ ini2toml[lite]>=0.9 tomli-w>=1.0.0 pytest-timeout + pytest-perf testing-integration = pytest pytest-xdist diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/setuptools-67.7.2/setuptools/command/easy_install.py new/setuptools-67.8.0/setuptools/command/easy_install.py --- old/setuptools-67.7.2/setuptools/command/easy_install.py 2023-04-24 13:36:34.000000000 +0200 +++ new/setuptools-67.8.0/setuptools/command/easy_install.py 2023-05-19 21:38:04.000000000 +0200 @@ -1567,50 +1567,79 @@ class PthDistributions(Environment): """A .pth file with Distribution paths in it""" - dirty = False - def __init__(self, filename, sitedirs=()): self.filename = filename self.sitedirs = list(map(normalize_path, sitedirs)) self.basedir = normalize_path(os.path.dirname(self.filename)) - self._load() + self.paths, self.dirty = self._load() + # keep a copy if someone manually updates the paths attribute on the instance + self._init_paths = self.paths[:] super().__init__([], None, None) for path in yield_lines(self.paths): list(map(self.add, find_distributions(path, True))) - def _load(self): - self.paths = [] - saw_import = False + def _load_raw(self): + paths = [] + dirty = saw_import = False seen = dict.fromkeys(self.sitedirs) + f = open(self.filename, 'rt') + for line in f: + path = line.rstrip() + # still keep imports and empty/commented lines for formatting + paths.append(path) + if line.startswith(('import ', 'from ')): + saw_import = True + continue + stripped_path = path.strip() + if not stripped_path or stripped_path.startswith('#'): + continue + # skip non-existent paths, in case somebody deleted a package + # manually, and duplicate paths as well + normalized_path = normalize_path(os.path.join(self.basedir, path)) + if normalized_path in seen or not os.path.exists(normalized_path): + log.debug("cleaned up dirty or duplicated %r", path) + dirty = True + paths.pop() + continue + seen[normalized_path] = 1 + f.close() + # remove any trailing empty/blank line + while paths and not paths[-1].strip(): + paths.pop() + dirty = True + return paths, dirty or (paths and saw_import) + + def _load(self): if os.path.isfile(self.filename): - f = open(self.filename, 'rt') - for line in f: - if line.startswith('import'): - saw_import = True - continue - path = line.rstrip() - self.paths.append(path) - if not path.strip() or path.strip().startswith('#'): - continue - # skip non-existent paths, in case somebody deleted a package - # manually, and duplicate paths as well - path = self.paths[-1] = normalize_path( - os.path.join(self.basedir, path) - ) - if not os.path.exists(path) or path in seen: - self.paths.pop() # skip it - self.dirty = True # we cleaned up, so we're dirty now :) - continue - seen[path] = 1 - f.close() - - if self.paths and not saw_import: - self.dirty = True # ensure anything we touch has import wrappers - while self.paths and not self.paths[-1].strip(): - self.paths.pop() + return self._load_raw() + return [], False def save(self): """Write changed .pth file back to disk""" + # first reload the file + last_paths, last_dirty = self._load() + # and check that there are no difference with what we have. + # there can be difference if someone else has written to the file + # since we first loaded it. + # we don't want to lose the eventual new paths added since then. + for path in last_paths[:]: + if path not in self.paths: + self.paths.append(path) + log.info("detected new path %r", path) + last_dirty = True + else: + last_paths.remove(path) + # also, re-check that all paths are still valid before saving them + for path in self.paths[:]: + if path not in last_paths \ + and not path.startswith(('import ', 'from ', '#')): + absolute_path = os.path.join(self.basedir, path) + if not os.path.exists(absolute_path): + self.paths.remove(path) + log.info("removing now non-existent path %r", path) + last_dirty = True + + self.dirty |= last_dirty or self.paths != self._init_paths if not self.dirty: return @@ -1619,17 +1648,16 @@ log.debug("Saving %s", self.filename) lines = self._wrap_lines(rel_paths) data = '\n'.join(lines) + '\n' - if os.path.islink(self.filename): os.unlink(self.filename) with open(self.filename, 'wt') as f: f.write(data) - elif os.path.exists(self.filename): log.debug("Deleting empty %s", self.filename) os.unlink(self.filename) self.dirty = False + self._init_paths[:] = self.paths[:] @staticmethod def _wrap_lines(lines): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/setuptools-67.7.2/setuptools/tests/fixtures.py new/setuptools-67.8.0/setuptools/tests/fixtures.py --- old/setuptools-67.7.2/setuptools/tests/fixtures.py 2023-04-24 13:36:34.000000000 +0200 +++ new/setuptools-67.8.0/setuptools/tests/fixtures.py 2023-05-19 21:38:04.000000000 +0200 @@ -105,6 +105,8 @@ """Virtual env with the version of setuptools under test installed""" env = environment.VirtualEnv() env.root = path.Path(tmp_path / 'venv') + env.create_opts = ['--no-setuptools', '--wheel=bundle'] + # TODO: Use `--no-wheel` when setuptools implements its own bdist_wheel env.req = str(setuptools_wheel) # In some environments (eg. downstream distro packaging), # where tox isn't used to run tests and PYTHONPATH is set to point to @@ -125,7 +127,7 @@ """Virtual env without any version of setuptools installed""" env = environment.VirtualEnv() env.root = path.Path(tmp_path / 'venv_without_setuptools') - env.create_opts = ['--no-setuptools'] + env.create_opts = ['--no-setuptools', '--no-wheel'] env.ensure_env() return env diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/setuptools-67.7.2/setuptools/tests/test_easy_install.py new/setuptools-67.8.0/setuptools/tests/test_easy_install.py --- old/setuptools-67.7.2/setuptools/tests/test_easy_install.py 2023-04-24 13:36:34.000000000 +0200 +++ new/setuptools-67.8.0/setuptools/tests/test_easy_install.py 2023-05-19 21:38:04.000000000 +0200 @@ -28,7 +28,9 @@ from setuptools.sandbox import run_setup import setuptools.command.easy_install as ei from setuptools.command.easy_install import ( - EasyInstallDeprecationWarning, ScriptWriter, PthDistributions, + EasyInstallDeprecationWarning, + ScriptWriter, + PthDistributions, WindowsScriptWriter, ) from setuptools.dist import Distribution @@ -62,11 +64,13 @@ return 'spec' -SETUP_PY = DALS(""" +SETUP_PY = DALS( + """ from setuptools import setup setup() - """) + """ +) class TestEasyInstallTest: @@ -79,8 +83,7 @@ assert "'spec'" in script assert "'console_scripts'" in script assert "'name'" in script - assert re.search( - '^# EASY-INSTALL-ENTRY-SCRIPT', script, flags=re.MULTILINE) + assert re.search('^# EASY-INSTALL-ENTRY-SCRIPT', script, flags=re.MULTILINE) def test_no_find_links(self): # new option '--no-find-links', that blocks find-links added at @@ -124,6 +127,7 @@ def mock_gsp(): return [path] + monkeypatch.setattr(site, 'getsitepackages', mock_gsp, raising=False) assert path in ei.get_site_dirs() @@ -136,7 +140,8 @@ files = [ ( 'setup.py', - DALS(""" + DALS( + """ import setuptools setuptools.setup( name="setuptools-test-unicode", @@ -144,7 +149,8 @@ packages=["mypkg"], include_package_data=True, ) - """), + """ + ), ), ( 'mypkg/__init__.py', @@ -166,8 +172,7 @@ return str(sdist) @fail_on_ascii - def test_unicode_filename_in_sdist( - self, sdist_unicode, tmpdir, monkeypatch): + def test_unicode_filename_in_sdist(self, sdist_unicode, tmpdir, monkeypatch): """ The install command should execute correctly even if the package has unicode filenames. @@ -188,7 +193,8 @@ files = [ ( "setup.py", - DALS(""" + DALS( + """ import setuptools setuptools.setup( name="setuptools-test-unicode", @@ -197,7 +203,8 @@ include_package_data=True, scripts=['mypkg/unicode_in_script'], ) - """), + """ + ), ), ("mypkg/__init__.py", ""), ( @@ -209,7 +216,8 @@ non_python_fn() { } - """), + """ + ), ), ] sdist_name = "setuptools-test-unicode-script-1.0.zip" @@ -224,7 +232,8 @@ @fail_on_ascii def test_unicode_content_in_sdist( - self, sdist_unicode_in_script, tmpdir, monkeypatch): + self, sdist_unicode_in_script, tmpdir, monkeypatch + ): """ The install command should execute correctly even if the package has unicode in scripts. @@ -241,21 +250,25 @@ files = [ ( 'setup.py', - DALS(""" + DALS( + """ import setuptools setuptools.setup( name="setuptools-test-script", version="1.0", scripts=["mypkg_script"], ) - """), + """ + ), ), ( 'mypkg_script', - DALS(""" + DALS( + """ #/usr/bin/python print('mypkg_script') - """), + """ + ), ), ] sdist_name = 'setuptools-test-script-1.0.zip' @@ -263,8 +276,9 @@ make_sdist(sdist, files) return sdist - @pytest.mark.skipif(not sys.platform.startswith('linux'), - reason="Test can only be run on Linux") + @pytest.mark.skipif( + not sys.platform.startswith('linux'), reason="Test can only be run on Linux" + ) def test_script_install(self, sdist_script, tmpdir, monkeypatch): """ Check scripts are installed. @@ -313,11 +327,59 @@ location = '/test/location/does-not-have-to-exist' # PthDistributions expects all locations to be normalized location = pkg_resources.normalize_path(location) - pth = PthDistributions('does-not_exist', [location, ]) + pth = PthDistributions( + 'does-not_exist', + [ + location, + ], + ) assert not pth.dirty pth.add(PRDistribution(location)) assert not pth.dirty + def test_many_pth_distributions_merge_together(self, tmpdir): + """ + If the pth file is modified under the hood, then PthDistribution + will refresh its content before saving, merging contents when + necessary. + """ + # putting the pth file in a dedicated sub-folder, + pth_subdir = tmpdir.join("pth_subdir") + pth_subdir.mkdir() + pth_path = str(pth_subdir.join("file1.pth")) + pth1 = PthDistributions(pth_path) + pth2 = PthDistributions(pth_path) + assert ( + pth1.paths == pth2.paths == [] + ), "unless there would be some default added at some point" + # and so putting the src_subdir in folder distinct than the pth one, + # so to keep it absolute by PthDistributions + new_src_path = tmpdir.join("src_subdir") + new_src_path.mkdir() # must exist to be accounted + new_src_path_str = str(new_src_path) + pth1.paths.append(new_src_path_str) + pth1.save() + assert ( + pth1.paths + ), "the new_src_path added must still be present/valid in pth1 after save" + # now, + assert ( + new_src_path_str not in pth2.paths + ), "right before we save the entry should still not be present" + pth2.save() + assert ( + new_src_path_str in pth2.paths + ), "the new_src_path entry should have been added by pth2 with its save() call" + assert pth2.paths[-1] == new_src_path, ( + "and it should match exactly on the last entry actually " + "given we append to it in save()" + ) + # finally, + assert PthDistributions(pth_path).paths == pth2.paths, ( + "and we should have the exact same list at the end " + "with a fresh PthDistributions instance" + ) + @pytest.fixture def setup_context(tmpdir): @@ -330,7 +392,6 @@ @pytest.mark.usefixtures("user_override") @pytest.mark.usefixtures("setup_context") class TestUserInstallTest: - # prevent check that site-packages is writable. easy_install # shouldn't be writing to system site-packages during finalize # options, but while it does, bypass the behavior. @@ -408,6 +469,7 @@ """ with self.orig_context(*args, **kwargs): import setuptools.command.easy_install as ei + ei.__file__ = site.USER_SITE yield @@ -464,15 +526,23 @@ self.create_project(project_root) cmd = [ sys.executable, - '-c', '__import__("setuptools").setup()', + '-c', + '__import__("setuptools").setup()', 'install', - '--install-base', str(install_root), - '--install-lib', str(install_root), - '--install-headers', str(install_root), - '--install-scripts', str(install_root), - '--install-data', str(install_root), - '--install-purelib', str(install_root), - '--install-platlib', str(install_root), + '--install-base', + str(install_root), + '--install-lib', + str(install_root), + '--install-headers', + str(install_root), + '--install-scripts', + str(install_root), + '--install-data', + str(install_root), + '--install-purelib', + str(install_root), + '--install-platlib', + str(install_root), ] env = {**os.environ, "__EASYINSTALL_INDEX": mock_index.url} cp = subprocess.run( @@ -512,7 +582,6 @@ class TestSetupRequires: - def test_setup_requires_honors_fetch_params(self, mock_index, monkeypatch): """ When easy_install installs a source distribution which specifies @@ -529,11 +598,14 @@ with contexts.environment(PYTHONPATH=temp_install_dir): cmd = [ sys.executable, - '-c', '__import__("setuptools").setup()', + '-c', + '__import__("setuptools").setup()', 'easy_install', - '--index-url', mock_index.url, + '--index-url', + mock_index.url, '--exclude-scripts', - '--install-dir', temp_install_dir, + '--install-dir', + temp_install_dir, dist_file, ] subprocess.Popen(cmd).wait() @@ -549,17 +621,25 @@ """ with contexts.tempdir() as dir: dist_path = os.path.join(dir, 'setuptools-test-fetcher-1.0.tar.gz') - make_sdist(dist_path, [ - ('setup.py', DALS(""" + make_sdist( + dist_path, + [ + ( + 'setup.py', + DALS( + """ import setuptools setuptools.setup( name="setuptools-test-fetcher", version="1.0", setup_requires = ['does-not-exist'], ) - """)), - ('setup.cfg', ''), - ]) + """ + ), + ), + ('setup.cfg', ''), + ], + ) yield dist_path use_setup_cfg = ( @@ -580,14 +660,16 @@ requirement is already on the path. """ - fake_dist = PRDistribution('does-not-matter', project_name='foobar', - version='0.0') + fake_dist = PRDistribution( + 'does-not-matter', project_name='foobar', version='0.0' + ) working_set.add(fake_dist) with contexts.save_pkg_resources_state(): with contexts.tempdir() as temp_dir: test_pkg = create_setup_requires_package( - temp_dir, use_setup_cfg=use_setup_cfg) + temp_dir, use_setup_cfg=use_setup_cfg + ) test_setup_py = os.path.join(test_pkg, 'setup.py') with contexts.quiet() as (stdout, stderr): # Don't even need to install the package, just @@ -618,11 +700,13 @@ tf.extractall(foobar_1_dir) sys.path.insert(1, foobar_1_dir) - dist = PRDistribution(foobar_1_dir, project_name='foo.bar', - version='0.1') + dist = PRDistribution( + foobar_1_dir, project_name='foo.bar', version='0.1' + ) working_set.add(dist) - template = DALS("""\ + template = DALS( + """\ import foo # Even with foo imported first the # setup_requires package should override import setuptools @@ -634,11 +718,17 @@ if 'foo.bar-0.2' not in foo.__path__[0]: print('FAIL') - """) + """ + ) test_pkg = create_setup_requires_package( - temp_dir, 'foo.bar', '0.2', make_nspkg_sdist, template, - use_setup_cfg=use_setup_cfg) + temp_dir, + 'foo.bar', + '0.2', + make_nspkg_sdist, + template, + use_setup_cfg=use_setup_cfg, + ) test_setup_py = os.path.join(test_pkg, 'setup.py') @@ -650,7 +740,8 @@ except pkg_resources.VersionConflict: self.fail( 'Installing setup.py requirements ' - 'caused a VersionConflict') + 'caused a VersionConflict' + ) assert 'FAIL' not in stdout.getvalue() lines = stdout.readlines() @@ -660,27 +751,38 @@ @pytest.mark.parametrize('use_setup_cfg', use_setup_cfg) def test_setup_requires_with_attr_version(self, use_setup_cfg): def make_dependency_sdist(dist_path, distname, version): - files = [( - 'setup.py', - DALS(""" + files = [ + ( + 'setup.py', + DALS( + """ import setuptools setuptools.setup( name={name!r}, version={version!r}, py_modules=[{name!r}], ) - """.format(name=distname, version=version)), - ), ( - distname + '.py', - DALS(""" + """.format( + name=distname, version=version + ) + ), + ), + ( + distname + '.py', + DALS( + """ version = 42 - """), - )] + """ + ), + ), + ] make_sdist(dist_path, files) + with contexts.save_pkg_resources_state(): with contexts.tempdir() as temp_dir: test_pkg = create_setup_requires_package( - temp_dir, setup_attrs=dict(version='attr: foobar.version'), + temp_dir, + setup_attrs=dict(version='attr: foobar.version'), make_package=make_dependency_sdist, use_setup_cfg=use_setup_cfg + ('version',), ) @@ -699,15 +801,21 @@ with contexts.save_pkg_resources_state(): with contexts.tempdir() as temp_dir: test_pkg = create_setup_requires_package( - temp_dir, 'python-xlib', '0.19', - setup_attrs=dict(dependency_links=[])) + temp_dir, + 'python-xlib', + '0.19', + setup_attrs=dict(dependency_links=[]), + ) test_setup_cfg = os.path.join(test_pkg, 'setup.cfg') with open(test_setup_cfg, 'w') as fp: - fp.write(DALS( - ''' + fp.write( + DALS( + ''' [easy_install] index_url = https://pypi.org/legacy/ - ''')) + ''' + ) + ) test_setup_py = os.path.join(test_pkg, 'setup.py') with pytest.raises(distutils.errors.DistutilsError): run_setup(test_setup_py, [str('--version')]) @@ -726,25 +834,30 @@ test_pkg = create_setup_requires_package( temp_dir, # Ignored (overridden by setup_attrs) - 'python-xlib', '0.19', - setup_attrs=dict( - setup_requires='dependency @ %s' % dep_url)) + 'python-xlib', + '0.19', + setup_attrs=dict(setup_requires='dependency @ %s' % dep_url), + ) test_setup_py = os.path.join(test_pkg, 'setup.py') run_setup(test_setup_py, [str('--version')]) assert len(mock_index.requests) == 0 def test_setup_requires_with_allow_hosts(self, mock_index): - ''' The `allow-hosts` option in not supported anymore. ''' + '''The `allow-hosts` option in not supported anymore.''' files = { 'test_pkg': { - 'setup.py': DALS(''' + 'setup.py': DALS( + ''' from setuptools import setup setup(setup_requires='python-xlib') - '''), - 'setup.cfg': DALS(''' + ''' + ), + 'setup.cfg': DALS( + ''' [easy_install] allow_hosts = * - '''), + ''' + ), } } with contexts.save_pkg_resources_state(): @@ -756,7 +869,7 @@ assert len(mock_index.requests) == 0 def test_setup_requires_with_python_requires(self, monkeypatch, tmpdir): - ''' Check `python_requires` is honored. ''' + '''Check `python_requires` is honored.''' monkeypatch.setenv(str('PIP_RETRIES'), str('0')) monkeypatch.setenv(str('PIP_TIMEOUT'), str('0')) monkeypatch.setenv(str('PIP_NO_INDEX'), str('1')) @@ -765,59 +878,65 @@ dep_1_0_url = path_to_url(str(tmpdir / dep_1_0_sdist)) dep_1_0_python_requires = '>=2.7' make_python_requires_sdist( - str(tmpdir / dep_1_0_sdist), 'dep', '1.0', dep_1_0_python_requires) + str(tmpdir / dep_1_0_sdist), 'dep', '1.0', dep_1_0_python_requires + ) dep_2_0_sdist = 'dep-2.0.tar.gz' dep_2_0_url = path_to_url(str(tmpdir / dep_2_0_sdist)) - dep_2_0_python_requires = '!=' + '.'.join( - map(str, sys.version_info[:2])) + '.*' + dep_2_0_python_requires = '!=' + '.'.join(map(str, sys.version_info[:2])) + '.*' make_python_requires_sdist( - str(tmpdir / dep_2_0_sdist), 'dep', '2.0', dep_2_0_python_requires) + str(tmpdir / dep_2_0_sdist), 'dep', '2.0', dep_2_0_python_requires + ) index = tmpdir / 'index.html' - index.write_text(DALS( - ''' + index.write_text( + DALS( + ''' <!DOCTYPE html> <html><head><title>Links for dep</title></head> <body> <h1>Links for dep</h1> - <a href="{dep_1_0_url}" data-requires-python="{dep_1_0_python_requires}">{dep_1_0_sdist}</a><br/> - <a href="{dep_2_0_url}" data-requires-python="{dep_2_0_python_requires}">{dep_2_0_sdist}</a><br/> + <a href="{dep_1_0_url}"\ +data-requires-python="{dep_1_0_python_requires}">{dep_1_0_sdist}</a><br/> + <a href="{dep_2_0_url}"\ +data-requires-python="{dep_2_0_python_requires}">{dep_2_0_sdist}</a><br/> </body> </html> - ''').format( # noqa + ''' + ).format( dep_1_0_url=dep_1_0_url, dep_1_0_sdist=dep_1_0_sdist, dep_1_0_python_requires=dep_1_0_python_requires, dep_2_0_url=dep_2_0_url, dep_2_0_sdist=dep_2_0_sdist, dep_2_0_python_requires=dep_2_0_python_requires, - ), 'utf-8') + ), + 'utf-8', + ) index_url = path_to_url(str(index)) with contexts.save_pkg_resources_state(): test_pkg = create_setup_requires_package( str(tmpdir), - 'python-xlib', '0.19', # Ignored (overridden by setup_attrs). - setup_attrs=dict( - setup_requires='dep', dependency_links=[index_url])) + 'python-xlib', + '0.19', # Ignored (overridden by setup_attrs). + setup_attrs=dict(setup_requires='dep', dependency_links=[index_url]), + ) test_setup_py = os.path.join(test_pkg, 'setup.py') run_setup(test_setup_py, [str('--version')]) - eggs = list(map(str, pkg_resources.find_distributions( - os.path.join(test_pkg, '.eggs')))) + eggs = list( + map(str, pkg_resources.find_distributions(os.path.join(test_pkg, '.eggs'))) + ) assert eggs == ['dep 1.0'] - @pytest.mark.parametrize( - 'with_dependency_links_in_setup_py', - (False, True)) + @pytest.mark.parametrize('with_dependency_links_in_setup_py', (False, True)) def test_setup_requires_with_find_links_in_setup_cfg( - self, monkeypatch, - with_dependency_links_in_setup_py): + self, monkeypatch, with_dependency_links_in_setup_py + ): monkeypatch.setenv(str('PIP_RETRIES'), str('0')) monkeypatch.setenv(str('PIP_TIMEOUT'), str('0')) with contexts.save_pkg_resources_state(): with contexts.tempdir() as temp_dir: make_trivial_sdist( - os.path.join(temp_dir, 'python-xlib-42.tar.gz'), - 'python-xlib', - '42') + os.path.join(temp_dir, 'python-xlib-42.tar.gz'), 'python-xlib', '42' + ) test_pkg = os.path.join(temp_dir, 'test_pkg') test_setup_py = os.path.join(test_pkg, 'setup.py') test_setup_cfg = os.path.join(test_pkg, 'setup.cfg') @@ -827,25 +946,31 @@ dependency_links = [os.path.join(temp_dir, 'links')] else: dependency_links = [] - fp.write(DALS( - ''' + fp.write( + DALS( + ''' from setuptools import installer, setup setup(setup_requires='python-xlib==42', dependency_links={dependency_links!r}) - ''').format( - dependency_links=dependency_links)) - with open(test_setup_cfg, 'w') as fp: - fp.write(DALS( ''' + ).format(dependency_links=dependency_links) + ) + with open(test_setup_cfg, 'w') as fp: + fp.write( + DALS( + ''' [easy_install] index_url = {index_url} find_links = {find_links} - ''').format(index_url=os.path.join(temp_dir, 'index'), - find_links=temp_dir)) + ''' + ).format( + index_url=os.path.join(temp_dir, 'index'), + find_links=temp_dir, + ) + ) run_setup(test_setup_py, [str('--version')]) - def test_setup_requires_with_transitive_extra_dependency( - self, monkeypatch): + def test_setup_requires_with_transitive_extra_dependency(self, monkeypatch): ''' Use case: installing a package with a build dependency on an already installed `dep[extra]`, which in turn depends @@ -855,36 +980,42 @@ with contexts.tempdir() as temp_dir: # Create source distribution for `extra_dep`. make_trivial_sdist( - os.path.join(temp_dir, 'extra_dep-1.0.tar.gz'), - 'extra_dep', '1.0') + os.path.join(temp_dir, 'extra_dep-1.0.tar.gz'), 'extra_dep', '1.0' + ) # Create source tree for `dep`. dep_pkg = os.path.join(temp_dir, 'dep') os.mkdir(dep_pkg) - path.build({ - 'setup.py': - DALS(""" + path.build( + { + 'setup.py': DALS( + """ import setuptools setuptools.setup( name='dep', version='2.0', extras_require={'extra': ['extra_dep']}, ) - """), - 'setup.cfg': '', - }, prefix=dep_pkg) + """ + ), + 'setup.cfg': '', + }, + prefix=dep_pkg, + ) # "Install" dep. - run_setup( - os.path.join(dep_pkg, 'setup.py'), [str('dist_info')]) + run_setup(os.path.join(dep_pkg, 'setup.py'), [str('dist_info')]) working_set.add_entry(dep_pkg) # Create source tree for test package. test_pkg = os.path.join(temp_dir, 'test_pkg') test_setup_py = os.path.join(test_pkg, 'setup.py') os.mkdir(test_pkg) with open(test_setup_py, 'w') as fp: - fp.write(DALS( - ''' + fp.write( + DALS( + ''' from setuptools import installer, setup setup(setup_requires='dep[extra]') - ''')) + ''' + ) + ) # Check... monkeypatch.setenv(str('PIP_FIND_LINKS'), str(temp_dir)) monkeypatch.setenv(str('PIP_NO_INDEX'), str('1')) @@ -900,25 +1031,33 @@ with contexts.save_pkg_resources_state(): with contexts.tempdir() as temp_dir: # Create source distribution for `extra_dep`. - make_sdist(os.path.join(temp_dir, 'extra_dep-1.0.tar.gz'), [ - ('setup.py', - DALS(""" + make_sdist( + os.path.join(temp_dir, 'extra_dep-1.0.tar.gz'), + [ + ( + 'setup.py', + DALS( + """ import setuptools setuptools.setup( name='extra_dep', version='1.0', py_modules=['extra_dep'], ) - """)), - ('setup.cfg', ''), - ('extra_dep.py', ''), - ]) + """ + ), + ), + ('setup.cfg', ''), + ('extra_dep.py', ''), + ], + ) # Create source tree for `epdep`. dep_pkg = os.path.join(temp_dir, 'epdep') os.mkdir(dep_pkg) - path.build({ - 'setup.py': - DALS(""" + path.build( + { + 'setup.py': DALS( + """ import setuptools setuptools.setup( name='dep', version='2.0', @@ -929,31 +1068,38 @@ epcmd = epcmd:epcmd [extra] ''', ) - """), - 'setup.cfg': '', - 'epcmd.py': DALS(""" + """ + ), + 'setup.cfg': '', + 'epcmd.py': DALS( + """ from distutils.command.build_py import build_py import extra_dep class epcmd(build_py): pass - """), - }, prefix=dep_pkg) + """ + ), + }, + prefix=dep_pkg, + ) # "Install" dep. - run_setup( - os.path.join(dep_pkg, 'setup.py'), [str('dist_info')]) + run_setup(os.path.join(dep_pkg, 'setup.py'), [str('dist_info')]) working_set.add_entry(dep_pkg) # Create source tree for test package. test_pkg = os.path.join(temp_dir, 'test_pkg') test_setup_py = os.path.join(test_pkg, 'setup.py') os.mkdir(test_pkg) with open(test_setup_py, 'w') as fp: - fp.write(DALS( - ''' + fp.write( + DALS( + ''' from setuptools import installer, setup setup(setup_requires='dep[extra]') - ''')) + ''' + ) + ) # Check... monkeypatch.setenv(str('PIP_FIND_LINKS'), str(temp_dir)) monkeypatch.setenv(str('PIP_NO_INDEX'), str('1')) @@ -968,17 +1114,25 @@ setup.py. """ - make_sdist(dist_path, [ - ('setup.py', - DALS("""\ + make_sdist( + dist_path, + [ + ( + 'setup.py', + DALS( + """\ import setuptools setuptools.setup( name=%r, version=%r ) - """ % (distname, version))), - ('setup.cfg', ''), - ]) + """ + % (distname, version) + ), + ), + ('setup.cfg', ''), + ], + ) def make_nspkg_sdist(dist_path, distname, version): @@ -993,7 +1147,8 @@ packages = ['.'.join(parts[:idx]) for idx in range(1, len(parts) + 1)] - setup_py = DALS("""\ + setup_py = DALS( + """\ import setuptools setuptools.setup( name=%r, @@ -1001,12 +1156,13 @@ packages=%r, namespace_packages=[%r] ) - """ % (distname, version, packages, nspackage)) + """ + % (distname, version, packages, nspackage) + ) init = "__import__('pkg_resources').declare_namespace(__name__)" - files = [('setup.py', setup_py), - (os.path.join(nspackage, '__init__.py'), init)] + files = [('setup.py', setup_py), (os.path.join(nspackage, '__init__.py'), init)] for package in packages[1:]: filename = os.path.join(*(package.split('.') + ['__init__.py'])) files.append((filename, '')) @@ -1015,21 +1171,27 @@ def make_python_requires_sdist(dist_path, distname, version, python_requires): - make_sdist(dist_path, [ - ( - 'setup.py', - DALS("""\ + make_sdist( + dist_path, + [ + ( + 'setup.py', + DALS( + """\ import setuptools setuptools.setup( name={name!r}, version={version!r}, python_requires={python_requires!r}, ) - """).format( - name=distname, version=version, - python_requires=python_requires)), - ('setup.cfg', ''), - ]) + """ + ).format( + name=distname, version=version, python_requires=python_requires + ), + ), + ('setup.cfg', ''), + ], + ) def make_sdist(dist_path, files): @@ -1049,10 +1211,15 @@ dist.addfile(file_info, fileobj=file_bytes) -def create_setup_requires_package(path, distname='foobar', version='0.1', - make_package=make_trivial_sdist, - setup_py_template=None, setup_attrs={}, - use_setup_cfg=()): +def create_setup_requires_package( + path, + distname='foobar', + version='0.1', + make_package=make_trivial_sdist, + setup_py_template=None, + setup_attrs={}, + use_setup_cfg=(), +): """Creates a source tree under path for a trivial test package that has a single requirement in setup_requires--a tarball for that requirement is also created and added to the dependency_links argument. @@ -1063,9 +1230,10 @@ """ test_setup_attrs = { - 'name': 'test_pkg', 'version': '0.0', + 'name': 'test_pkg', + 'version': '0.0', 'setup_requires': ['%s==%s' % (distname, version)], - 'dependency_links': [os.path.abspath(path)] + 'dependency_links': [os.path.abspath(path)], } test_setup_attrs.update(setup_attrs) @@ -1103,10 +1271,12 @@ # setup.py if setup_py_template is None: - setup_py_template = DALS("""\ + setup_py_template = DALS( + """\ import setuptools setuptools.setup(**%r) - """) + """ + ) with open(os.path.join(test_pkg, 'setup.py'), 'w') as f: f.write(setup_py_template % test_setup_attrs) @@ -1118,7 +1288,7 @@ @pytest.mark.skipif( sys.platform.startswith('java') and ei.is_sh(sys.executable), - reason="Test cannot run under java when executable is sh" + reason="Test cannot run under java when executable is sh", ) class TestScriptHeader: non_ascii_exe = '/Users/José/bin/python' @@ -1130,22 +1300,21 @@ assert actual == expected def test_get_script_header_args(self): - expected = '#!%s -x\n' % ei.nt_quote_arg( - os.path.normpath(sys.executable)) + expected = '#!%s -x\n' % ei.nt_quote_arg(os.path.normpath(sys.executable)) actual = ei.ScriptWriter.get_header('#!/usr/bin/python -x') assert actual == expected def test_get_script_header_non_ascii_exe(self): actual = ei.ScriptWriter.get_header( - '#!/usr/bin/python', - executable=self.non_ascii_exe) + '#!/usr/bin/python', executable=self.non_ascii_exe + ) expected = str('#!%s -x\n') % self.non_ascii_exe assert actual == expected def test_get_script_header_exe_with_spaces(self): actual = ei.ScriptWriter.get_header( - '#!/usr/bin/python', - executable='"' + self.exe_with_spaces + '"') + '#!/usr/bin/python', executable='"' + self.exe_with_spaces + '"' + ) expected = '#!"%s"\n' % self.exe_with_spaces assert actual == expected @@ -1246,7 +1415,7 @@ def test_editable_user_and_build_isolation(setup_context, monkeypatch, tmp_path): - ''' `setup.py develop` should honor `--user` even under build isolation''' + '''`setup.py develop` should honor `--user` even under build isolation''' # == Arrange == # Pretend that build isolation was enabled @@ -1255,9 +1424,20 @@ # Patching $HOME for 2 reasons: # 1. setuptools/command/easy_install.py:create_home_path - # tries creating directories in $HOME - # given `self.config_vars['DESTDIRS'] = "/home/user/.pyenv/versions/3.9.10 /home/user/.pyenv/versions/3.9.10/lib /home/user/.pyenv/versions/3.9.10/lib/python3.9 /home/user/.pyenv/versions/3.9.10/lib/python3.9/lib-dynload"`` # noqa: E501 - # it will `makedirs("/home/user/.pyenv/versions/3.9.10 /home/user/.pyenv/versions/3.9.10/lib /home/user/.pyenv/versions/3.9.10/lib/python3.9 /home/user/.pyenv/versions/3.9.10/lib/python3.9/lib-dynload")`` # noqa: E501 + # tries creating directories in $HOME. + # Given:: + # self.config_vars['DESTDIRS'] = ( + # "/home/user/.pyenv/versions/3.9.10 " + # "/home/user/.pyenv/versions/3.9.10/lib " + # "/home/user/.pyenv/versions/3.9.10/lib/python3.9 " + # "/home/user/.pyenv/versions/3.9.10/lib/python3.9/lib-dynload") + # `create_home_path` will:: + # makedirs( + # "/home/user/.pyenv/versions/3.9.10 " + # "/home/user/.pyenv/versions/3.9.10/lib " + # "/home/user/.pyenv/versions/3.9.10/lib/python3.9 " + # "/home/user/.pyenv/versions/3.9.10/lib/python3.9/lib-dynload") + # # 2. We are going to force `site` to update site.USER_BASE and site.USER_SITE # To point inside our new home monkeypatch.setenv('HOME', str(tmp_path / '.home')) @@ -1268,7 +1448,7 @@ user_site = Path(site.getusersitepackages()) user_site.mkdir(parents=True, exist_ok=True) - sys_prefix = (tmp_path / '.sys_prefix') + sys_prefix = tmp_path / '.sys_prefix' sys_prefix.mkdir(parents=True, exist_ok=True) monkeypatch.setattr('sys.prefix', str(sys_prefix)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/setuptools-67.7.2/setuptools/tests/test_virtualenv.py new/setuptools-67.8.0/setuptools/tests/test_virtualenv.py --- old/setuptools-67.7.2/setuptools/tests/test_virtualenv.py 2023-04-24 13:36:34.000000000 +0200 +++ new/setuptools-67.8.0/setuptools/tests/test_virtualenv.py 2023-05-19 21:38:04.000000000 +0200 @@ -174,8 +174,8 @@ def test_test_command_install_requirements(venv, tmpdir, tmpdir_cwd): - # Ensure pip/wheel packages are installed. - venv.run(["python", "-c", "__import__('pkg_resources').require(['pip', 'wheel'])"]) + # Ensure pip is installed. + venv.run(["python", "-c", "import pip"]) # disable index URL so bits and bobs aren't requested from PyPI with contexts.environment(PYTHONPATH=None, PIP_NO_INDEX="1"): _check_test_command_install_requirements(venv, tmpdir) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/setuptools-67.7.2/setuptools/version.py new/setuptools-67.8.0/setuptools/version.py --- old/setuptools-67.7.2/setuptools/version.py 2023-04-24 13:36:34.000000000 +0200 +++ new/setuptools-67.8.0/setuptools/version.py 2023-05-19 21:38:04.000000000 +0200 @@ -1,6 +1,6 @@ from ._importlib import metadata try: - __version__ = metadata.version('setuptools') + __version__ = metadata.version('setuptools') or '0.dev0+unknown' except Exception: - __version__ = 'unknown' + __version__ = '0.dev0+unknown' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/setuptools-67.7.2/setuptools.egg-info/PKG-INFO new/setuptools-67.8.0/setuptools.egg-info/PKG-INFO --- old/setuptools-67.7.2/setuptools.egg-info/PKG-INFO 2023-04-24 13:36:53.000000000 +0200 +++ new/setuptools-67.8.0/setuptools.egg-info/PKG-INFO 2023-05-19 21:38:26.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: setuptools -Version: 67.7.2 +Version: 67.8.0 Summary: Easily download, build, install, upgrade, and uninstall Python packages Home-page: https://github.com/pypa/setuptools Author: Python Packaging Authority diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/setuptools-67.7.2/setuptools.egg-info/requires.txt new/setuptools-67.8.0/setuptools.egg-info/requires.txt --- old/setuptools-67.7.2/setuptools.egg-info/requires.txt 2023-04-24 13:36:53.000000000 +0200 +++ new/setuptools-67.8.0/setuptools.egg-info/requires.txt 2023-05-19 21:38:26.000000000 +0200 @@ -21,9 +21,7 @@ [testing] pytest>=6 pytest-checkdocs>=2.4 -flake8<5 pytest-enabler>=1.3 -pytest-perf flake8-2020 virtualenv>=13.0.0 wheel @@ -37,6 +35,7 @@ ini2toml[lite]>=0.9 tomli-w>=1.0.0 pytest-timeout +pytest-perf [testing-integration] pytest @@ -55,5 +54,5 @@ pytest-cov pytest-mypy>=0.9.1 -[testing:python_version < "3.12"] -pytest-flake8 +[testing:sys_platform != "cygwin"] +pytest-ruff