Compare commits

...

No commits in common. 'c9' and 'c8' have entirely different histories.
c9 ... c8

2
.gitignore vendored

@ -1 +1 @@
SOURCES/setuptools-53.0.0.tar.gz
SOURCES/setuptools-39.2.0.zip

@ -1 +1 @@
878b8c351cac940e0b9fd1ba3ad49665dfc2889c SOURCES/setuptools-53.0.0.tar.gz
83e75ec6b04423735e0a9a384b465c68f5206bcf SOURCES/setuptools-39.2.0.zip

@ -1,170 +0,0 @@
From 21b122e06969a9d85c65ce8276519d34da7dc747 Mon Sep 17 00:00:00 2001
From: Melissa Li <li.melissa.kun@gmail.com>
Date: Tue, 23 Feb 2021 21:23:35 -0500
Subject: [PATCH 1/6] Preserve case-sensitive keys in setup.cfg
---
setuptools/dist.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/setuptools/dist.py b/setuptools/dist.py
index 050388de16..c31020f0c4 100644
--- a/setuptools/dist.py
+++ b/setuptools/dist.py
@@ -583,6 +583,7 @@ def _parse_config_files(self, filenames=None): # noqa: C901
self.announce("Distribution.parse_config_files():")
parser = ConfigParser()
+ parser.optionxform = str
for filename in filenames:
with io.open(filename, encoding='utf-8') as reader:
if DEBUG:
From 90d8740c353ddf20c1c76d8c06cd923c19b8cc84 Mon Sep 17 00:00:00 2001
From: Melissa Li <li.melissa.kun@gmail.com>
Date: Tue, 23 Feb 2021 21:06:55 -0500
Subject: [PATCH 2/6] Add case-sensitive entry point name test
---
setuptools/tests/test_config.py | 34 +++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/setuptools/tests/test_config.py b/setuptools/tests/test_config.py
index 1dee12718f..6cc1d0a46b 100644
--- a/setuptools/tests/test_config.py
+++ b/setuptools/tests/test_config.py
@@ -802,6 +802,40 @@ def test_entry_points(self, tmpdir):
with get_dist(tmpdir) as dist:
assert dist.entry_points == expected
+ def test_case_sensitive_entry_points(self, tmpdir):
+ _, config = fake_env(
+ tmpdir,
+ '[options.entry_points]\n'
+ 'GROUP1 = point1 = pack.module:func, '
+ '.point2 = pack.module2:func_rest [rest]\n'
+ 'group2 = point3 = pack.module:func2\n'
+ )
+
+ with get_dist(tmpdir) as dist:
+ assert dist.entry_points == {
+ 'GROUP1': [
+ 'point1 = pack.module:func',
+ '.point2 = pack.module2:func_rest [rest]',
+ ],
+ 'group2': ['point3 = pack.module:func2']
+ }
+
+ expected = (
+ '[blogtool.parsers]\n'
+ '.rst = some.nested.module:SomeClass.some_classmethod[reST]\n'
+ )
+
+ tmpdir.join('entry_points').write(expected)
+
+ # From file.
+ config.write(
+ '[options]\n'
+ 'entry_points = file: entry_points\n'
+ )
+
+ with get_dist(tmpdir) as dist:
+ assert dist.entry_points == expected
+
def test_data_files(self, tmpdir):
fake_env(
tmpdir,
From 39659040bda0664ee08588ecd2faa41b4ea406a1 Mon Sep 17 00:00:00 2001
From: Melissa Li <li.melissa.kun@gmail.com>
Date: Wed, 24 Feb 2021 00:31:16 -0500
Subject: [PATCH 3/6] Add change note
---
changelog.d/1937.breaking.rst | 1 +
1 file changed, 1 insertion(+)
create mode 100644 changelog.d/1937.breaking.rst
diff --git a/changelog.d/1937.breaking.rst b/changelog.d/1937.breaking.rst
new file mode 100644
index 0000000000..94dc739ab6
--- /dev/null
+++ b/changelog.d/1937.breaking.rst
@@ -0,0 +1 @@
+Preserved case-sensitivity of keys in setup.cfg so that entry point names are case-sensitive. Changed sensitivity of configparser -- by :user:`melissa-kun-li`
\ No newline at end of file
From 7f3e6d688e5ff080ee6bd7ccc6bd81a87c05cfd7 Mon Sep 17 00:00:00 2001
From: Melissa Li <li.melissa.kun@gmail.com>
Date: Wed, 24 Feb 2021 23:57:59 -0500
Subject: [PATCH 4/6] Update test for case-sensitive entry point names
---
setuptools/tests/test_config.py | 16 ----------------
1 file changed, 16 deletions(-)
diff --git a/setuptools/tests/test_config.py b/setuptools/tests/test_config.py
index 6cc1d0a46b..649075609a 100644
--- a/setuptools/tests/test_config.py
+++ b/setuptools/tests/test_config.py
@@ -820,22 +820,6 @@ def test_case_sensitive_entry_points(self, tmpdir):
'group2': ['point3 = pack.module:func2']
}
- expected = (
- '[blogtool.parsers]\n'
- '.rst = some.nested.module:SomeClass.some_classmethod[reST]\n'
- )
-
- tmpdir.join('entry_points').write(expected)
-
- # From file.
- config.write(
- '[options]\n'
- 'entry_points = file: entry_points\n'
- )
-
- with get_dist(tmpdir) as dist:
- assert dist.entry_points == expected
-
def test_data_files(self, tmpdir):
fake_env(
tmpdir,
From 11529db0de4081404b37fab17711660faa85abb8 Mon Sep 17 00:00:00 2001
From: Melissa Li <li.melissa.kun@gmail.com>
Date: Thu, 25 Feb 2021 00:00:23 -0500
Subject: [PATCH 5/6] Update change log
---
changelog.d/1937.change.rst | 1 +
1 file changed, 1 insertion(+)
create mode 100644 changelog.d/1937.change.rst
diff --git a/changelog.d/1937.change.rst b/changelog.d/1937.change.rst
new file mode 100644
index 0000000000..acd4305968
--- /dev/null
+++ b/changelog.d/1937.change.rst
@@ -0,0 +1 @@
+Preserved case-sensitivity of keys in setup.cfg so that entry point names are case-sensitive. Changed sensitivity of configparser. NOTE: Any projects relying on case-insensitivity will need to adapt to accept the original case as published. -- by :user:`melissa-kun-li`
\ No newline at end of file
From 898a0b59427f143efe0bcc0cabf69007fb3ee439 Mon Sep 17 00:00:00 2001
From: "Jason R. Coombs" <jaraco@jaraco.com>
Date: Thu, 25 Feb 2021 08:57:04 -0500
Subject: [PATCH 6/6] Remove 'breaking' changelog, superseded by 'change'.
---
changelog.d/1937.breaking.rst | 1 -
1 file changed, 1 deletion(-)
delete mode 100644 changelog.d/1937.breaking.rst
diff --git a/changelog.d/1937.breaking.rst b/changelog.d/1937.breaking.rst
deleted file mode 100644
index 94dc739ab6..0000000000
--- a/changelog.d/1937.breaking.rst
+++ /dev/null
@@ -1 +0,0 @@
-Preserved case-sensitivity of keys in setup.cfg so that entry point names are case-sensitive. Changed sensitivity of configparser -- by :user:`melissa-kun-li`
\ No newline at end of file

@ -1,8 +1,8 @@
diff --git a/setuptools/package_index.py b/setuptools/package_index.py
index 123e958..a90b810 100644
index b6407be..bdcf4a6 100755
--- a/setuptools/package_index.py
+++ b/setuptools/package_index.py
@@ -215,7 +215,7 @@ def unique_values(func):
@@ -212,7 +212,7 @@ def unique_values(func):
return wrapper
@ -12,17 +12,19 @@ index 123e958..a90b810 100644
diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py
index 8e9435e..bc1e373 100644
index 63b9294..49bd819 100644
--- a/setuptools/tests/test_packageindex.py
+++ b/setuptools/tests/test_packageindex.py
@@ -308,3 +308,10 @@ class TestPyPIConfig:
cred = cfg.creds_by_repository['https://pypi.org']
assert cred.username == 'jaraco'
assert cred.password == 'pity%'
+
+@pytest.mark.timeout(1)
+def test_REL_DoS():
@@ -223,6 +223,12 @@ class TestPackageIndex:
assert dists[0].version == ''
assert dists[1].version == vc
+ def test_REL_DoS(self):
+ """
+ REL should not hang on a contrived attack string.
+ """
+ setuptools.package_index.REL.search('< rel=' + ' ' * 2**12)
+
class TestContentCheckers:
def test_md5(self):

@ -1,15 +1,14 @@
From 39a1aa65fb4163d917131b4814d4c2dd2bf19677 Mon Sep 17 00:00:00 2001
From 8af1b3e03edc8a38565558aff3bf1689c1ca3545 Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Wed, 24 Jul 2024 12:43:20 +0200
Date: Fri, 26 Jul 2024 13:49:11 +0200
Subject: [PATCH] CVE-2024-6345
---
setuptools/package_index.py | 23 +++++++++-------------
setuptools/tests/test_packageindex.py | 28 +++++++++++++--------------
2 files changed, 23 insertions(+), 28 deletions(-)
setuptools/package_index.py | 23 +++++++++--------------
1 file changed, 9 insertions(+), 14 deletions(-)
diff --git a/setuptools/package_index.py b/setuptools/package_index.py
index 123e9582b..07cc8924b 100644
index bdcf4a6..1d3e5b4 100755
--- a/setuptools/package_index.py
+++ b/setuptools/package_index.py
@@ -1,4 +1,5 @@
@ -18,24 +17,24 @@ index 123e9582b..07cc8924b 100644
import sys
import os
import re
@@ -860,7 +861,7 @@ class PackageIndex(Environment):
@@ -848,7 +849,7 @@ class PackageIndex(Environment):
def _download_svn(self, url, filename):
warnings.warn("SVN download support is deprecated", UserWarning)
url = url.split('#', 1)[0] # remove any fragment for svn's sake
- creds = ''
+ creds = []
if url.lower().startswith('svn:') and '@' in url:
scheme, netloc, path, p, q, f = urllib.parse.urlparse(url)
if not netloc and path.startswith('//') and '/' in path[2:]:
@@ -869,14 +870,14 @@ class PackageIndex(Environment):
@@ -857,14 +858,14 @@ class PackageIndex(Environment):
if auth:
if ':' in auth:
user, pw = auth.split(':', 1)
- creds = " --username=%s --password=%s" % (user, pw)
+ creds = [f"--username={user}", f"--password={pw}"]
+ creds = ["--username=" + user, "--password=" + pw]
else:
- creds = " --username=" + auth
+ creds = [f"--username={auth}"]
+ creds = ["--username=" + auth]
netloc = host
parts = scheme, netloc, url, p, q, f
url = urllib.parse.urlunparse(parts)
@ -45,7 +44,7 @@ index 123e9582b..07cc8924b 100644
return filename
@staticmethod
@@ -902,14 +903,11 @@ class PackageIndex(Environment):
@@ -890,14 +891,11 @@ class PackageIndex(Environment):
url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True)
self.info("Doing git clone from %s to %s", url, filename)
@ -54,7 +53,7 @@ index 123e9582b..07cc8924b 100644
if rev is not None:
self.info("Checking out %s", rev)
- os.system("git -C %s checkout --quiet %s" % (
- os.system("(cd %s && git checkout --quiet %s)" % (
- filename,
- rev,
- ))
@ -62,7 +61,7 @@ index 123e9582b..07cc8924b 100644
return filename
@@ -918,14 +916,11 @@ class PackageIndex(Environment):
@@ -906,14 +904,11 @@ class PackageIndex(Environment):
url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True)
self.info("Doing hg clone from %s to %s", url, filename)
@ -71,7 +70,7 @@ index 123e9582b..07cc8924b 100644
if rev is not None:
self.info("Updating to %s", rev)
- os.system("hg --cwd %s up -C -r %s -q" % (
- os.system("(cd %s && hg up -C -r %s -q)" % (
- filename,
- rev,
- ))
@ -79,81 +78,6 @@ index 123e9582b..07cc8924b 100644
return filename
diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py
index 8e9435efe..9289b9032 100644
--- a/setuptools/tests/test_packageindex.py
+++ b/setuptools/tests/test_packageindex.py
@@ -197,56 +197,56 @@ class TestPackageIndex:
url = 'git+https://github.example/group/project@master#egg=foo'
index = setuptools.package_index.PackageIndex()
- with mock.patch("os.system") as os_system_mock:
+ with mock.patch("subprocess.check_call") as subprocess_check_call_mock:
result = index.download(url, str(tmpdir))
- os_system_mock.assert_called()
+ subprocess_check_call_mock.assert_called()
expected_dir = str(tmpdir / 'project@master')
expected = (
'git clone --quiet '
'https://github.example/group/project {expected_dir}'
- ).format(**locals())
- first_call_args = os_system_mock.call_args_list[0][0]
+ ).format(**locals()).split()
+ first_call_args = subprocess_check_call_mock.call_args_list[0][0]
assert first_call_args == (expected,)
tmpl = 'git -C {expected_dir} checkout --quiet master'
- expected = tmpl.format(**locals())
- assert os_system_mock.call_args_list[1][0] == (expected,)
+ expected = tmpl.format(**locals()).split()
+ assert subprocess_check_call_mock.call_args_list[1][0] == (expected,)
assert result == expected_dir
def test_download_git_no_rev(self, tmpdir):
url = 'git+https://github.example/group/project#egg=foo'
index = setuptools.package_index.PackageIndex()
- with mock.patch("os.system") as os_system_mock:
+ with mock.patch("subprocess.check_call") as subprocess_check_call_mock:
result = index.download(url, str(tmpdir))
- os_system_mock.assert_called()
+ subprocess_check_call_mock.assert_called()
expected_dir = str(tmpdir / 'project')
expected = (
'git clone --quiet '
'https://github.example/group/project {expected_dir}'
- ).format(**locals())
- os_system_mock.assert_called_once_with(expected)
+ ).format(**locals()).split()
+ subprocess_check_call_mock.assert_called_once_with(expected)
def test_download_svn(self, tmpdir):
url = 'svn+https://svn.example/project#egg=foo'
index = setuptools.package_index.PackageIndex()
with pytest.warns(UserWarning):
- with mock.patch("os.system") as os_system_mock:
+ with mock.patch("subprocess.check_call") as subprocess_check_call_mock:
result = index.download(url, str(tmpdir))
- os_system_mock.assert_called()
+ subprocess_check_call_mock.assert_called()
expected_dir = str(tmpdir / 'project')
expected = (
'svn checkout -q '
'svn+https://svn.example/project {expected_dir}'
- ).format(**locals())
- os_system_mock.assert_called_once_with(expected)
+ ).format(**locals()).split()
+ subprocess_check_call_mock.assert_called_once_with(expected)
class TestContentCheckers:
--
2.45.2

@ -0,0 +1,17 @@
diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py
index 91c48b3..0c9b0f4 100755
--- a/setuptools/command/easy_install.py
+++ b/setuptools/command/easy_install.py
@@ -446,6 +446,12 @@ class easy_install(Command):
instdir = normalize_path(self.install_dir)
pth_file = os.path.join(instdir, 'easy-install.pth')
+ if not os.path.exists(instdir):
+ try:
+ os.makedirs(instdir)
+ except (OSError, IOError):
+ self.cant_write_to_target()
+
# Is it a configured, PYTHONPATH, implicit, or explicit site dir?
is_site_dir = instdir in self.all_site_dirs

@ -1,650 +0,0 @@
From 490a2b28fa2325f9929261aa2ee398fbb4c715dd Mon Sep 17 00:00:00 2001
From: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
Date: Sat, 3 Apr 2021 16:12:19 -0400
Subject: [PATCH 1/2] license_files - Add support for glob patterns + add
default patterns
https://github.com/pypa/setuptools/pull/2620
---
changelog.d/2620.breaking.rst | 4 ++
changelog.d/2620.change.rst | 1 +
changelog.d/2620.deprecation.rst | 2 +
changelog.d/2620.doc.rst | 1 +
docs/references/keywords.rst | 11 +++++
docs/userguide/declarative_config.rst | 2 +-
setuptools/command/sdist.py | 55 +++++++++++++---------
setuptools/tests/test_egg_info.py | 68 +++++++++++++++++++++++++--
setuptools/tests/test_manifest.py | 1 +
9 files changed, 118 insertions(+), 27 deletions(-)
create mode 100644 changelog.d/2620.breaking.rst
create mode 100644 changelog.d/2620.change.rst
create mode 100644 changelog.d/2620.deprecation.rst
create mode 100644 changelog.d/2620.doc.rst
diff --git a/changelog.d/2620.breaking.rst b/changelog.d/2620.breaking.rst
new file mode 100644
index 00000000..431e7105
--- /dev/null
+++ b/changelog.d/2620.breaking.rst
@@ -0,0 +1,4 @@
+If neither ``license_file`` nor ``license_files`` is specified, the ``sdist``
+option will now auto-include files that match the following patterns:
+``LICEN[CS]E*``, ``COPYING*``, ``NOTICE*``, ``AUTHORS*``.
+This matches the behavior of ``bdist_wheel``. -- by :user:`cdce8p`
diff --git a/changelog.d/2620.change.rst b/changelog.d/2620.change.rst
new file mode 100644
index 00000000..5470592d
--- /dev/null
+++ b/changelog.d/2620.change.rst
@@ -0,0 +1 @@
+The ``license_file`` and ``license_files`` options now support glob patterns. -- by :user:`cdce8p`
diff --git a/changelog.d/2620.deprecation.rst b/changelog.d/2620.deprecation.rst
new file mode 100644
index 00000000..1af5f246
--- /dev/null
+++ b/changelog.d/2620.deprecation.rst
@@ -0,0 +1,2 @@
+The ``license_file`` option is now marked as deprecated.
+Use ``license_files`` instead. -- by :user:`cdce8p`
diff --git a/changelog.d/2620.doc.rst b/changelog.d/2620.doc.rst
new file mode 100644
index 00000000..7564adac
--- /dev/null
+++ b/changelog.d/2620.doc.rst
@@ -0,0 +1 @@
+Added documentation for the ``license_files`` option. -- by :user:`cdce8p`
diff --git a/docs/references/keywords.rst b/docs/references/keywords.rst
index 03ce9fa2..619b2d14 100644
--- a/docs/references/keywords.rst
+++ b/docs/references/keywords.rst
@@ -76,6 +76,17 @@ Keywords
``license``
A string specifying the license of the package.
+``license_file``
+
+ .. warning::
+ ``license_file`` is deprecated. Use ``license_files`` instead.
+
+``license_files``
+
+ A list of glob patterns for license related files that should be included.
+ If neither ``license_file`` nor ``license_files`` is specified, this option
+ defaults to ``LICEN[CS]E*``, ``COPYING*``, ``NOTICE*``, and ``AUTHORS*``.
+
``keywords``
A list of strings or a comma-separated string providing descriptive
meta-data. See: `PEP 0314`_.
diff --git a/docs/userguide/declarative_config.rst b/docs/userguide/declarative_config.rst
index bc66869b..1d2d66e2 100644
--- a/docs/userguide/declarative_config.rst
+++ b/docs/userguide/declarative_config.rst
@@ -184,7 +184,7 @@ maintainer_email maintainer-email str
classifiers classifier file:, list-comma
license str
license_file str
-license_files list-comma
+license_files list-comma 42.0.0
description summary file:, str
long_description long-description file:, str
long_description_content_type str 38.6.0
diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py
index 887b7efa..a6ea814a 100644
--- a/setuptools/command/sdist.py
+++ b/setuptools/command/sdist.py
@@ -4,6 +4,7 @@ import os
import sys
import io
import contextlib
+from glob import iglob
from setuptools.extern import ordered_set
@@ -194,29 +195,41 @@ class sdist(sdist_add_defaults, orig.sdist):
"""Checks if license_file' or 'license_files' is configured and adds any
valid paths to 'self.filelist'.
"""
-
- files = ordered_set.OrderedSet()
-
opts = self.distribution.get_option_dict('metadata')
- # ignore the source of the value
- _, license_file = opts.get('license_file', (None, None))
-
- if license_file is None:
- log.debug("'license_file' option was not specified")
- else:
- files.add(license_file)
-
+ files = ordered_set.OrderedSet()
try:
- files.update(self.distribution.metadata.license_files)
+ license_files = self.distribution.metadata.license_files
except TypeError:
log.warn("warning: 'license_files' option is malformed")
-
- for f in files:
- if not os.path.exists(f):
- log.warn(
- "warning: Failed to find the configured license file '%s'",
- f)
- files.remove(f)
-
- self.filelist.extend(files)
+ license_files = ordered_set.OrderedSet()
+ patterns = license_files if isinstance(license_files, ordered_set.OrderedSet) \
+ else ordered_set.OrderedSet(license_files)
+
+ if 'license_file' in opts:
+ log.warn(
+ "warning: the 'license_file' option is deprecated, "
+ "use 'license_files' instead")
+ patterns.append(opts['license_file'][1])
+
+ if 'license_file' not in opts and 'license_files' not in opts:
+ # Default patterns match the ones wheel uses
+ # See https://wheel.readthedocs.io/en/stable/user_guide.html
+ # -> 'Including license files in the generated wheel file'
+ patterns = ('LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*')
+
+ for pattern in patterns:
+ for path in iglob(pattern):
+ if path.endswith('~'):
+ log.debug(
+ "ignoring license file '%s' as it looks like a backup",
+ path)
+ continue
+
+ if path not in files and os.path.isfile(path):
+ log.info(
+ "adding license file '%s' (matched pattern '%s')",
+ path, pattern)
+ files.add(path)
+
+ self.filelist.extend(sorted(files))
diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py
index 1047468b..c93ed020 100644
--- a/setuptools/tests/test_egg_info.py
+++ b/setuptools/tests/test_egg_info.py
@@ -533,7 +533,7 @@ class TestEggInfo:
'setup.cfg': DALS("""
"""),
'LICENSE': "Test license"
- }, False), # no license_file attribute
+ }, True), # no license_file attribute, LICENSE auto-included
({
'setup.cfg': DALS("""
[metadata]
@@ -541,7 +541,15 @@ class TestEggInfo:
"""),
'MANIFEST.in': "exclude LICENSE",
'LICENSE': "Test license"
- }, False) # license file is manually excluded
+ }, False), # license file is manually excluded
+ pytest.param({
+ 'setup.cfg': DALS("""
+ [metadata]
+ license_file = LICEN[CS]E*
+ """),
+ 'LICENSE': "Test license",
+ }, True,
+ id="glob_pattern"),
])
def test_setup_cfg_license_file(
self, tmpdir_cwd, env, files, license_in_sources):
@@ -621,7 +629,7 @@ class TestEggInfo:
'setup.cfg': DALS("""
"""),
'LICENSE': "Test license"
- }, [], ['LICENSE']), # no license_files attribute
+ }, ['LICENSE'], []), # no license_files attribute, LICENSE auto-included
({
'setup.cfg': DALS("""
[metadata]
@@ -640,7 +648,36 @@ class TestEggInfo:
'MANIFEST.in': "exclude LICENSE-XYZ",
'LICENSE-ABC': "ABC license",
'LICENSE-XYZ': "XYZ license"
- }, ['LICENSE-ABC'], ['LICENSE-XYZ']) # subset is manually excluded
+ }, ['LICENSE-ABC'], ['LICENSE-XYZ']), # subset is manually excluded
+ pytest.param({
+ 'setup.cfg': "",
+ 'LICENSE-ABC': "ABC license",
+ 'COPYING-ABC': "ABC copying",
+ 'NOTICE-ABC': "ABC notice",
+ 'AUTHORS-ABC': "ABC authors",
+ 'LICENCE-XYZ': "XYZ license",
+ 'LICENSE': "License",
+ 'INVALID-LICENSE': "Invalid license",
+ }, [
+ 'LICENSE-ABC',
+ 'COPYING-ABC',
+ 'NOTICE-ABC',
+ 'AUTHORS-ABC',
+ 'LICENCE-XYZ',
+ 'LICENSE',
+ ], ['INVALID-LICENSE'],
+ # ('LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*')
+ id="default_glob_patterns"),
+ pytest.param({
+ 'setup.cfg': DALS("""
+ [metadata]
+ license_files =
+ LICENSE*
+ """),
+ 'LICENSE-ABC': "ABC license",
+ 'NOTICE-XYZ': "XYZ notice",
+ }, ['LICENSE-ABC'], ['NOTICE-XYZ'],
+ id="no_default_glob_patterns"),
])
def test_setup_cfg_license_files(
self, tmpdir_cwd, env, files, incl_licenses, excl_licenses):
@@ -745,7 +782,28 @@ class TestEggInfo:
'LICENSE-PQR': "PQR license",
'LICENSE-XYZ': "XYZ license"
# manually excluded
- }, ['LICENSE-XYZ'], ['LICENSE-ABC', 'LICENSE-PQR'])
+ }, ['LICENSE-XYZ'], ['LICENSE-ABC', 'LICENSE-PQR']),
+ pytest.param({
+ 'setup.cfg': DALS("""
+ [metadata]
+ license_file = LICENSE*
+ """),
+ 'LICENSE-ABC': "ABC license",
+ 'NOTICE-XYZ': "XYZ notice",
+ }, ['LICENSE-ABC'], ['NOTICE-XYZ'],
+ id="no_default_glob_patterns"),
+ pytest.param({
+ 'setup.cfg': DALS("""
+ [metadata]
+ license_file = LICENSE*
+ license_files =
+ NOTICE*
+ """),
+ 'LICENSE-ABC': "ABC license",
+ 'NOTICE-ABC': "ABC notice",
+ 'AUTHORS-ABC': "ABC authors",
+ }, ['LICENSE-ABC', 'NOTICE-ABC'], ['AUTHORS-ABC'],
+ id="combined_glob_patterrns"),
])
def test_setup_cfg_license_file_license_files(
self, tmpdir_cwd, env, files, incl_licenses, excl_licenses):
diff --git a/setuptools/tests/test_manifest.py b/setuptools/tests/test_manifest.py
index 82bdb9c6..589cefb2 100644
--- a/setuptools/tests/test_manifest.py
+++ b/setuptools/tests/test_manifest.py
@@ -55,6 +55,7 @@ def touch(filename):
default_files = frozenset(map(make_local_path, [
'README.rst',
'MANIFEST.in',
+ 'LICENSE',
'setup.py',
'app.egg-info/PKG-INFO',
'app.egg-info/SOURCES.txt',
From e1aa3949d2b0d610f6d83bc3c85d96c5c4cabd3a Mon Sep 17 00:00:00 2001
From: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
Date: Sat, 22 May 2021 20:00:24 -0400
Subject: [PATCH 2/2] Add License-File field to package metadata
https://github.com/pypa/setuptools/pull/2645
---
changelog.d/2645.breaking.rst | 3 ++
changelog.d/2645.change.rst | 4 +++
setuptools/command/egg_info.py | 9 +++++-
setuptools/command/sdist.py | 46 --------------------------
setuptools/config.py | 5 +++
setuptools/dist.py | 54 ++++++++++++++++++++++++++++++-
setuptools/tests/test_egg_info.py | 54 ++++++++++++++++++++++++++++---
setuptools/tests/test_manifest.py | 1 -
8 files changed, 122 insertions(+), 54 deletions(-)
create mode 100644 changelog.d/2645.breaking.rst
create mode 100644 changelog.d/2645.change.rst
diff --git a/changelog.d/2645.breaking.rst b/changelog.d/2645.breaking.rst
new file mode 100644
index 00000000..b96b492a
--- /dev/null
+++ b/changelog.d/2645.breaking.rst
@@ -0,0 +1,3 @@
+License files excluded via the ``MANIFEST.in`` but matched by either
+the ``license_file`` (deprecated) or ``license_files`` options,
+will be nevertheless included in the source distribution. - by :user:`cdce8p`
diff --git a/changelog.d/2645.change.rst b/changelog.d/2645.change.rst
new file mode 100644
index 00000000..b22385c1
--- /dev/null
+++ b/changelog.d/2645.change.rst
@@ -0,0 +1,4 @@
+Added ``License-File`` (multiple) to the output package metadata.
+The field will contain the path of a license file, matched by the
+``license_file`` (deprecated) and ``license_files`` options,
+relative to ``.dist-info``. - by :user:`cdce8p`
diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py
index 1f120b67..18b81340 100644
--- a/setuptools/command/egg_info.py
+++ b/setuptools/command/egg_info.py
@@ -541,6 +541,7 @@ class manifest_maker(sdist):
self.add_defaults()
if os.path.exists(self.template):
self.read_template()
+ self.add_license_files()
self.prune_file_list()
self.filelist.sort()
self.filelist.remove_duplicates()
@@ -575,7 +576,6 @@ class manifest_maker(sdist):
def add_defaults(self):
sdist.add_defaults(self)
- self.check_license()
self.filelist.append(self.template)
self.filelist.append(self.manifest)
rcfiles = list(walk_revctrl())
@@ -592,6 +592,13 @@ class manifest_maker(sdist):
ei_cmd = self.get_finalized_command('egg_info')
self.filelist.graft(ei_cmd.egg_info)
+ def add_license_files(self):
+ license_files = self.distribution.metadata.license_files or []
+ for lf in license_files:
+ log.info("adding license file '%s'", lf)
+ pass
+ self.filelist.extend(license_files)
+
def prune_file_list(self):
build = self.get_finalized_command('build')
base_dir = self.distribution.get_fullname()
diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py
index a6ea814a..4a014283 100644
--- a/setuptools/command/sdist.py
+++ b/setuptools/command/sdist.py
@@ -4,9 +4,6 @@ import os
import sys
import io
import contextlib
-from glob import iglob
-
-from setuptools.extern import ordered_set
from .py36compat import sdist_add_defaults
@@ -190,46 +187,3 @@ class sdist(sdist_add_defaults, orig.sdist):
continue
self.filelist.append(line)
manifest.close()
-
- def check_license(self):
- """Checks if license_file' or 'license_files' is configured and adds any
- valid paths to 'self.filelist'.
- """
- opts = self.distribution.get_option_dict('metadata')
-
- files = ordered_set.OrderedSet()
- try:
- license_files = self.distribution.metadata.license_files
- except TypeError:
- log.warn("warning: 'license_files' option is malformed")
- license_files = ordered_set.OrderedSet()
- patterns = license_files if isinstance(license_files, ordered_set.OrderedSet) \
- else ordered_set.OrderedSet(license_files)
-
- if 'license_file' in opts:
- log.warn(
- "warning: the 'license_file' option is deprecated, "
- "use 'license_files' instead")
- patterns.append(opts['license_file'][1])
-
- if 'license_file' not in opts and 'license_files' not in opts:
- # Default patterns match the ones wheel uses
- # See https://wheel.readthedocs.io/en/stable/user_guide.html
- # -> 'Including license files in the generated wheel file'
- patterns = ('LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*')
-
- for pattern in patterns:
- for path in iglob(pattern):
- if path.endswith('~'):
- log.debug(
- "ignoring license file '%s' as it looks like a backup",
- path)
- continue
-
- if path not in files and os.path.isfile(path):
- log.info(
- "adding license file '%s' (matched pattern '%s')",
- path, pattern)
- files.add(path)
-
- self.filelist.extend(sorted(files))
diff --git a/setuptools/config.py b/setuptools/config.py
index af3a3bcb..ece325e2 100644
--- a/setuptools/config.py
+++ b/setuptools/config.py
@@ -520,6 +520,11 @@ class ConfigMetadataHandler(ConfigHandler):
'obsoletes': parse_list,
'classifiers': self._get_parser_compound(parse_file, parse_list),
'license': exclude_files_parser('license'),
+ 'license_file': self._deprecated_config_handler(
+ exclude_files_parser('license_file'),
+ "The license_file parameter is deprecated, "
+ "use license_files instead.",
+ DeprecationWarning),
'license_files': parse_list,
'description': parse_file,
'long_description': parse_file,
diff --git a/setuptools/dist.py b/setuptools/dist.py
index 050388de..bc663e63 100644
--- a/setuptools/dist.py
+++ b/setuptools/dist.py
@@ -14,6 +14,7 @@ import distutils.dist
from distutils.util import strtobool
from distutils.debug import DEBUG
from distutils.fancy_getopt import translate_longopt
+from glob import iglob
import itertools
from collections import defaultdict
@@ -117,6 +118,8 @@ def read_pkg_file(self, file):
self.provides = None
self.obsoletes = None
+ self.license_files = _read_list('license-file')
+
def single_line(val):
# quick and dirty validation for description pypa/setuptools#1390
@@ -199,6 +202,7 @@ def write_pkg_file(self, file): # noqa: C901 # is too complex (14) # FIXME
for extra in self.provides_extras:
write_field('Provides-Extra', extra)
+ self._write_list(file, 'License-File', self.license_files or [])
sequence = tuple, list
@@ -398,7 +402,8 @@ class Distribution(_Distribution):
'long_description_content_type': None,
'project_urls': dict,
'provides_extras': ordered_set.OrderedSet,
- 'license_files': ordered_set.OrderedSet,
+ 'license_file': lambda: None,
+ 'license_files': lambda: None,
}
_patched_dist = None
@@ -557,6 +562,34 @@ class Distribution(_Distribution):
req.marker = None
return req
+ def _finalize_license_files(self):
+ """Compute names of all license files which should be included."""
+ license_files: Optional[List[str]] = self.metadata.license_files
+ patterns: List[str] = license_files if license_files else []
+
+ license_file: Optional[str] = self.metadata.license_file
+ if license_file and license_file not in patterns:
+ patterns.append(license_file)
+
+ if license_files is None and license_file is None:
+ # Default patterns match the ones wheel uses
+ # See https://wheel.readthedocs.io/en/stable/user_guide.html
+ # -> 'Including license files in the generated wheel file'
+ patterns = ('LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*')
+
+ self.metadata.license_files = list(
+ unique_everseen(self._expand_patterns(patterns)))
+
+ @staticmethod
+ def _expand_patterns(patterns):
+ return (
+ path
+ for pattern in patterns
+ for path in iglob(pattern)
+ if not path.endswith('~')
+ and os.path.isfile(path)
+ )
+
# FIXME: 'Distribution._parse_config_files' is too complex (14)
def _parse_config_files(self, filenames=None): # noqa: C901
"""
@@ -680,6 +713,7 @@ class Distribution(_Distribution):
parse_configuration(self, self.command_options,
ignore_option_errors=ignore_option_errors)
self._finalize_requires()
+ self._finalize_license_files()
def fetch_build_eggs(self, requires):
"""Resolve pre-setup requirements"""
@@ -1020,3 +1054,21 @@ class Distribution(_Distribution):
class DistDeprecationWarning(SetuptoolsDeprecationWarning):
"""Class for warning about deprecations in dist in
setuptools. Not ignored by default, unlike DeprecationWarning."""
+
+
+def unique_everseen(iterable, key=None):
+ "List unique elements, preserving order. Remember all elements ever seen."
+ # unique_everseen('AAAABBBCCDAABBB') --> A B C D
+ # unique_everseen('ABBCcAD', str.lower) --> A B C D
+ seen = set()
+ seen_add = seen.add
+ if key is None:
+ for element in itertools.filterfalse(seen.__contains__, iterable):
+ seen_add(element)
+ yield element
+ else:
+ for element in iterable:
+ k = key(element)
+ if k not in seen:
+ seen_add(k)
+ yield element
diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py
index c93ed020..e8b49732 100644
--- a/setuptools/tests/test_egg_info.py
+++ b/setuptools/tests/test_egg_info.py
@@ -541,7 +541,7 @@ class TestEggInfo:
"""),
'MANIFEST.in': "exclude LICENSE",
'LICENSE': "Test license"
- }, False), # license file is manually excluded
+ }, True), # manifest is overwritten by license_file
pytest.param({
'setup.cfg': DALS("""
[metadata]
@@ -637,7 +637,7 @@ class TestEggInfo:
"""),
'MANIFEST.in': "exclude LICENSE",
'LICENSE': "Test license"
- }, [], ['LICENSE']), # license file is manually excluded
+ }, ['LICENSE'], []), # manifest is overwritten by license_files
({
'setup.cfg': DALS("""
[metadata]
@@ -648,7 +648,8 @@ class TestEggInfo:
'MANIFEST.in': "exclude LICENSE-XYZ",
'LICENSE-ABC': "ABC license",
'LICENSE-XYZ': "XYZ license"
- }, ['LICENSE-ABC'], ['LICENSE-XYZ']), # subset is manually excluded
+ # manifest is overwritten by license_files
+ }, ['LICENSE-ABC', 'LICENSE-XYZ'], []),
pytest.param({
'setup.cfg': "",
'LICENSE-ABC': "ABC license",
@@ -678,6 +679,17 @@ class TestEggInfo:
'NOTICE-XYZ': "XYZ notice",
}, ['LICENSE-ABC'], ['NOTICE-XYZ'],
id="no_default_glob_patterns"),
+ pytest.param({
+ 'setup.cfg': DALS("""
+ [metadata]
+ license_files =
+ LICENSE-ABC
+ LICENSE*
+ """),
+ 'LICENSE-ABC': "ABC license",
+ }, ['LICENSE-ABC'], [],
+ id="files_only_added_once",
+ ),
])
def test_setup_cfg_license_files(
self, tmpdir_cwd, env, files, incl_licenses, excl_licenses):
@@ -781,8 +793,8 @@ class TestEggInfo:
'LICENSE-ABC': "ABC license",
'LICENSE-PQR': "PQR license",
'LICENSE-XYZ': "XYZ license"
- # manually excluded
- }, ['LICENSE-XYZ'], ['LICENSE-ABC', 'LICENSE-PQR']),
+ # manifest is overwritten
+ }, ['LICENSE-ABC', 'LICENSE-PQR', 'LICENSE-XYZ'], []),
pytest.param({
'setup.cfg': DALS("""
[metadata]
@@ -825,6 +837,38 @@ class TestEggInfo:
for lf in excl_licenses:
assert sources_lines.count(lf) == 0
+ def test_license_file_attr_pkg_info(self, tmpdir_cwd, env):
+ """All matched license files should have a corresponding License-File."""
+ self._create_project()
+ build_files({
+ "setup.cfg": DALS("""
+ [metadata]
+ license_files =
+ NOTICE*
+ LICENSE*
+ """),
+ "LICENSE-ABC": "ABC license",
+ "LICENSE-XYZ": "XYZ license",
+ "NOTICE": "included",
+ "IGNORE": "not include",
+ })
+
+ environment.run_setup_py(
+ cmd=['egg_info'],
+ pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)])
+ )
+ egg_info_dir = os.path.join('.', 'foo.egg-info')
+ with open(os.path.join(egg_info_dir, 'PKG-INFO')) as pkginfo_file:
+ pkg_info_lines = pkginfo_file.read().split('\n')
+ license_file_lines = [
+ line for line in pkg_info_lines if line.startswith('License-File:')]
+
+ # Only 'NOTICE', LICENSE-ABC', and 'LICENSE-XYZ' should have been matched
+ # Also assert that order from license_files is keeped
+ assert "License-File: NOTICE" == license_file_lines[0]
+ assert "License-File: LICENSE-ABC" in license_file_lines[1:]
+ assert "License-File: LICENSE-XYZ" in license_file_lines[1:]
+
def test_long_description_content_type(self, tmpdir_cwd, env):
# Test that specifying a `long_description_content_type` keyword arg to
# the `setup` function results in writing a `Description-Content-Type`
diff --git a/setuptools/tests/test_manifest.py b/setuptools/tests/test_manifest.py
index 589cefb2..82bdb9c6 100644
--- a/setuptools/tests/test_manifest.py
+++ b/setuptools/tests/test_manifest.py
@@ -55,7 +55,6 @@ def touch(filename):
default_files = frozenset(map(make_local_path, [
'README.rst',
'MANIFEST.in',
- 'LICENSE',
'setup.py',
'app.egg-info/PKG-INFO',
'app.egg-info/SOURCES.txt',

@ -1,471 +1,357 @@
%global srcname setuptools
# The original RHEL 9 content set is defined by (build)dependencies
# of the packages in Fedora ELN. Hence we disable tests here
# to prevent pulling many unwanted packages in.
# Once the RHEL 9 content set is defined and/or RHEL 9 forks from ELN,
# the conditional can be removed from the Fedora spec file.
# We intentionally keep this enabled on EPEL.
%if 0%{?rhel} >= 9 && !0%{?epel}
%bcond_with tests
%else
%bcond_without tests
%endif
# WARNING When bootstrapping, disable tests as well,
# because tests need pip.
%bcond_with bootstrap
# Similar to what we have in pythonX.Y.spec files.
# If enabled, provides unversioned executables and other stuff.
# Disable it if you build this package in an alternative stack.
%bcond_without main_python
%bcond_without tests
%bcond_with py2_wheel
%if 0%{?rhel} && 0%{?rhel} <= 7
%global _without_python3 1
# define some macros for RHEL 6
%global __python2 %__python
%global python2_sitelib %python_sitelib
%endif
# Note(hguemar): overrides must be placed *before* those
# Otherwise it doesn't work
%bcond_without python2
%bcond_without python3
%if %{without bootstrap}
%global python_wheel_name %{srcname}-%{version}-py3-none-any.whl
%global python_wheelname %{srcname}-%{version}-py2.py3-none-any.whl
%if %{with python2}
%global python2_wheelname %python_wheelname
%global python2_record %{python2_sitelib}/%{srcname}-%{version}.dist-info/RECORD
%global python2_wheeldir %{_datadir}/python2-wheels
%endif # with python2
%if %{with python3}
%global python3_wheelname %python_wheelname
%global python3_record %{python3_sitelib}/%{srcname}-%{version}.dist-info/RECORD
%endif
%global python3_wheeldir %{_datadir}/python3-wheels
%endif # with python3
%endif # without bootstrap
Name: python-setuptools
# When updating, update the bundled libraries versions bellow!
Version: 53.0.0
Release: 12%{?dist}.1
Version: 39.2.0
Release: 8%{?dist}
Summary: Easily build and distribute Python packages
# setuptools is MIT
# appdirs is MIT
# ordered-set is MIT
# packaging is BSD or ASL 2.0
# pyparsing is MIT
# the setuptools logo has unknown license and possible TM problems,
# but the sdist **does not** contain it,
# see https://github.com/pypa/setuptools/issues/2227
License: MIT and (BSD or ASL 2.0)
Group: Applications/System
License: MIT
URL: https://pypi.python.org/pypi/%{srcname}
Source0: %{pypi_source %{srcname} %{version}}
# Two backports related to the License-File metadata field
# Fixes https://bugzilla.redhat.com/2033994
#
# license_files - Add support for glob patterns + add default patterns
# https://github.com/pypa/setuptools/pull/2620
# included in setuptools 56+
#
# Add License-File field to package metadata
# https://github.com/pypa/setuptools/pull/2645
# included in setuptools 57+
# depends on the previous one
Patch1: license-file-metadata.patch
# Fix case sensitivity of entry point names and keys in setup.cfg
# Fixes https://bugzilla.redhat.com/2124281
Patch2: https://github.com/pypa/setuptools/pull/2580.patch
Source0: https://files.pythonhosted.org/packages/source/s/%{srcname}/%{srcname}-%{version}.zip
# In Fedora, sudo setup.py install installs to /usr/local/lib/pythonX.Y/site-packages
# But pythonX doesn't own that dir, that would be against FHS
# We need to create it if it doesn't exist
# https://bugzilla.redhat.com/show_bug.cgi?id=1576924
Patch0: create-site-packages.patch
# Security fix for CVE-2022-40897
# Regular Expression Denial of Service (ReDoS) in package_index.py
# Resolved upstream: https://github.com/pypa/setuptools/commit/43a9c9bfa6aa626ec2a22540bea28d2ca77964be
Patch3: CVE-2022-40897.patch
Patch1: CVE-2022-40897.patch
# Security fix for CVE-2024-6345
# Remote code execution via download functions in the package_index module
# Tracking bug: https://bugzilla.redhat.com/show_bug.cgi?id=2297771
# Upstream solution: https://github.com/pypa/setuptools/pull/4332
# Patch simplified because upstream doesn't support SVN anymore.
Patch4: CVE-2024-6345.patch
Patch2: CVE-2024-6345.patch
BuildArch: noarch
BuildRequires: python%{python3_pkgversion}-devel
%if %{with tests}
BuildRequires: gcc
BuildRequires: python%{python3_pkgversion}-pip
BuildRequires: python%{python3_pkgversion}-pytest
BuildRequires: python%{python3_pkgversion}-mock
BuildRequires: python%{python3_pkgversion}-pytest-fixture-config
BuildRequires: python%{python3_pkgversion}-pytest-virtualenv
BuildRequires: python%{python3_pkgversion}-jaraco-envs
%if %{with python2}
BuildRequires: python2-devel
%if %{with py2_wheel}
BuildRequires: python2-pip
BuildRequires: python2-wheel
%endif # with py2_wheel
%endif # with python2
%if %{with python3}
BuildRequires: python3-devel
%if %{with tests}
BuildRequires: python3-pip
BuildRequires: python3-pytest
BuildRequires: python3-mock
%endif # with tests
%if %{without bootstrap}
BuildRequires: python%{python3_pkgversion}-pip
BuildRequires: python%{python3_pkgversion}-wheel
BuildRequires: python%{python3_pkgversion}-setuptools
# python3 bootstrap: this is built before the final build of python3, which
# adds the dependency on python3-rpm-generators, so we require it manually
# The minimal version is for bundled provides verification script
BuildRequires: python3-rpm-generators >= 11-8
BuildRequires: python3-pip
BuildRequires: python3-wheel
%endif # without bootstrap
%description
Setuptools is a collection of enhancements to the Python distutils that allow
you to more easily build and distribute Python packages, especially ones that
have dependencies on other packages.
This package also contains the runtime components of setuptools, necessary to
execute the software that requires pkg_resources.
# Virtual provides for the packages bundled by setuptools.
# Bundled packages are defined in two files:
# - pkg_resources/_vendor/vendored.txt, and
# - setuptools/_vendor/vendored.txt
# Merge them to one and then generate the list with:
# %%{_rpmconfigdir}/pythonbundles.py --namespace 'python%%{python3_pkgversion}dist' allvendor.txt
%global bundled %{expand:
Provides: bundled(python%{python3_pkgversion}dist(appdirs)) = 1.4.3
Provides: bundled(python%{python3_pkgversion}dist(ordered-set)) = 3.1.1
Provides: bundled(python%{python3_pkgversion}dist(packaging)) = 20.4
Provides: bundled(python%{python3_pkgversion}dist(pyparsing)) = 2.2.1
}
%package -n python%{python3_pkgversion}-setuptools
%endif # with python3
# We're now back to setuptools as the package.
# Keep the python-distribute name active for a few releases. Eventually we'll
# want to get rid of the Provides and just keep the Obsoletes
Provides: python-distribute = %{version}-%{release}
Obsoletes: python-distribute < 0.6.36-2
%global _description \
Setuptools is a collection of enhancements to the Python distutils that allow \
you to more easily build and distribute Python packages, especially ones that \
have dependencies on other packages. \
\
This package also contains the runtime components of setuptools, necessary to \
execute the software that requires pkg_resources.py.
%description %_description
%if %{with python3}
%package -n platform-python-setuptools
Summary: Easily build and distribute Python 3 packages
%{bundled}
Group: Applications/System
Conflicts: python3-setuptools < 39.2.0-4%{?dist}
%if %{with bootstrap}
Provides: python%{python3_pkgversion}dist(setuptools) = %{version}
Provides: python%{python3_version}dist(setuptools) = %{version}
%endif
%description -n platform-python-setuptools %_description
# For users who might see ModuleNotFoundError: No module named 'pkg_resoureces'
%py_provides python%{python3_pkgversion}-pkg_resources
%py_provides python%{python3_pkgversion}-pkg-resources
%endif # with python3
# Provide platform-python-setuptools for backwards compatibility with RHEL 8
Provides: platform-python-setuptools = %{version}-%{release}
%description -n python%{python3_pkgversion}-setuptools
Setuptools is a collection of enhancements to the Python 3 distutils that allow
you to more easily build and distribute Python 3 packages, especially ones that
have dependencies on other packages.
%if %{with python2}
%package -n python2-setuptools
Summary: Easily build and distribute Python packages
%{?python_provide:%python_provide python2-setuptools}
This package also contains the runtime components of setuptools, necessary to
execute the software that requires pkg_resources.
%description -n python2-setuptools %_description
%endif # with python2
%if %{with python3}
%package -n python3-setuptools
Summary: Easily build and distribute Python 3 packages
Group: Applications/System
Requires: platform-python-setuptools = %{version}-%{release}
%{?python_provide:%python_provide python3-setuptools}
%description -n python3-setuptools %_description
%endif # with python3
%if %{without bootstrap}
%package -n %{python_wheel_pkg_prefix}-%{srcname}-wheel
%if %{with py2_wheel}
%if %{with python2}
%package -n python2-setuptools-wheel
Summary: The setuptools wheel
%{bundled}
Provides: %{name}-wheel = %{version}-%{release}
Obsoletes: %{name}-wheel < %{version}-%{release}
# Older versions of python3-libs expect Python wheels at the old unversioned
# location, so we conflict with the old Python versions that wouldn't work with
# the new wheel location.
Conflicts: python3-libs < 3.9.9-2
%description -n %{python_wheel_pkg_prefix}-%{srcname}-wheel
%description -n python2-setuptools-wheel
A Python wheel of setuptools to use with venv.
%endif
%endif #with python2
%endif #with py2_wheel
%if %{with python3}
%package -n python3-setuptools-wheel
Summary: The setuptools wheel
%description -n python3-setuptools-wheel
A Python wheel of setuptools to use with venv.
%endif #with python3
%endif #with bootstrap
%prep
%autosetup -p1 -n %{srcname}-%{version}
%if %{without bootstrap}
# If we don't have setuptools installed yet, we use the pre-generated .egg-info
# See https://github.com/pypa/setuptools/pull/2543
# And https://github.com/pypa/setuptools/issues/2550
rm -r %{srcname}.egg-info
%endif
# We can't remove .egg-info (but it doesn't matter, since it'll be rebuilt):
# The problem is that to properly execute setuptools' setup.py,
# it is needed for setuptools to be loaded as a Distribution
# (with egg-info or .dist-info dir), it's not sufficient
# to just have them on PYTHONPATH
# Running "setup.py install" without having setuptools installed
# as a distribution gives warnings such as
# ... distutils/dist.py:267: UserWarning: Unknown distribution option: 'entry_points'
# and doesn't create "easy_install" and .egg-info directory
# Note: this is only a problem if bootstrapping wheel or building on RHEL,
# otherwise setuptools are installed as dependency into buildroot
# Strip shbang
find setuptools pkg_resources -name \*.py | xargs sed -i -e '1 {/^#!\//d}'
find setuptools -name \*.py | xargs sed -i -e '1 {/^#!\//d}'
# Remove bundled exes
rm -f setuptools/*.exe
# These tests require internet connection
rm setuptools/tests/test_integration.py
# We don't do linting or coverage here
sed -i pytest.ini -e 's/ --flake8//' \
-e 's/ --cov//'
%build
%if %{with python2}
%if %{with py2_wheel} && %{without bootstrap}
export RHEL_ALLOW_PYTHON2_FOR_BUILD=1
%py2_build_wheel
%else
export RHEL_ALLOW_PYTHON2_FOR_BUILD=1
%py2_build
%endif # without bootstrap + py2_wheel
%endif # with python2
%if %{with python3}
%if %{without bootstrap}
%py3_build_wheel
%else
%py3_build
%endif
%endif # without bootstrap
%endif # with python3
%install
# Must do the python3 install first because the scripts in /usr/bin are
# overwritten with every setup.py install (and we want the python2 version to
# be the default for now).
%if %{with python3}
%if %{without bootstrap}
%py3_install_wheel %{python_wheel_name}
%py3_install_wheel %{python3_wheelname}
# Remove /usr/bin/easy_install from the record as later on we delete the file
sed -i '/\/usr\/bin\/easy_install,/d' %{buildroot}%{python3_record}
%else
%py3_install
%endif
# This is not installed (in 45.2.0 anyway), but better be safe than sorry
rm -rf %{buildroot}%{python3_sitelib}/{setuptools,pkg_resources}/tests
# TODO: we have to remove this by hand now, but it'd be nice if we wouldn't have to
# (pip install wheel doesn't overwrite)
rm %{buildroot}%{_bindir}/easy_install
rm -rf %{buildroot}%{python3_sitelib}/setuptools/tests
%if %{without bootstrap}
sed -i '/^setuptools\/tests\//d' %{buildroot}%{python3_record}
%endif
find %{buildroot}%{python3_sitelib} -name '*.exe' | xargs rm -f
%endif # with python3
%if %{with python2}
export RHEL_ALLOW_PYTHON2_FOR_BUILD=1
%if %{with py2_wheel}
%py2_install_wheel %{python2_wheelname}
%else
%py2_install
%endif #with py2_wheel
rm -rf %{buildroot}%{python2_sitelib}/setuptools/tests
%if %{with py2_wheel}
sed -i '/^setuptools\/tests\//d' %{buildroot}%{python2_record}
%endif # with py2_wheel
find %{buildroot}%{python2_sitelib} -name '*.exe' | xargs rm -f
%endif # with python2
# Don't ship these
rm -r docs/{conf.py,_*}
rm -r docs/{Makefile,conf.py,_*}
%if %{without bootstrap}
mkdir -p %{buildroot}%{python_wheel_dir}
install -p dist/%{python_wheel_name} -t %{buildroot}%{python_wheel_dir}
%endif
%if %{with py2_wheel}
%if %{with python2}
mkdir -p %{buildroot}%{python2_wheeldir}
install -p dist/%{python2_wheelname} -t %{buildroot}%{python2_wheeldir}
%endif #with python2
%endif #with py2_wheel
%if %{with python3}
mkdir -p %{buildroot}%{python3_wheeldir}
install -p dist/%{python3_wheelname} -t %{buildroot}%{python3_wheeldir}
%endif #with python3
%endif #with bootstrap
%if %{with tests}
%check
# Verify bundled provides are up to date
cat pkg_resources/_vendor/vendored.txt setuptools/_vendor/vendored.txt > allvendor.txt
%{_rpmconfigdir}/pythonbundles.py allvendor.txt --namespace 'python%{python3_pkgversion}dist' --compare-with '%{bundled}'
# Regression test, the wheel should not be larger than 600 KiB
# https://bugzilla.redhat.com/show_bug.cgi?id=1914481#c3
test $(du dist/%{python_wheel_name} | cut -f1) -lt 600
# Upstream tests
# --ignore=pavement.py:
# pavement.py is only used by upstream to do releases and vendoring, we don't ship it
PYTHONPATH=$(pwd) %pytest --ignore=pavement.py
%if %{with python3}
# --ignore=setuptools/tests/test_virtualenv.py: because virtualenv executable
# is configured only for Python 2 version of virtualenv—this needs to be fixed
# in the `python-pytest-virtualenv` package
PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$(pwd) py.test-%{python3_version} --ignore=setuptools/tests/test_virtualenv.py
%endif # with python3
%endif # with tests
%files -n python%{python3_pkgversion}-setuptools
%if %{with python2}
%files -n python2-setuptools
%license LICENSE
%doc docs/* CHANGES.rst README.rst
%{python2_sitelib}/*
%{_bindir}/easy_install
%{_bindir}/easy_install-2.*
%endif # with python2
%if %{with python3}
%files -n python3-setuptools
%license LICENSE
%doc docs/* CHANGES.rst README.rst
# The easy_install-3 binary is created using alternatives
# defined in the python36 package
%{_bindir}/easy_install-3.*
%files -n platform-python-setuptools
%license LICENSE
%doc docs/* CHANGES.rst README.rst
%{python3_sitelib}/easy_install.py
%{python3_sitelib}/pkg_resources/
%{python3_sitelib}/setuptools*/
%{python3_sitelib}/_distutils_hack/
%{python3_sitelib}/distutils-precedence.pth
%{python3_sitelib}/__pycache__/*
%endif # with python3
%if %{without bootstrap}
%files -n %{python_wheel_pkg_prefix}-%{srcname}-wheel
%if %{with py2_wheel}
%if %{with python2}
%files -n python2-setuptools-wheel
%license LICENSE
# we own the dir for simplicity
%dir %{python_wheel_dir}/
%{python_wheel_dir}/%{python_wheel_name}
%endif
%dir %{python2_wheeldir}/
%{python2_wheeldir}/%{python2_wheelname}
%endif #with python2
%endif #with py2_wheel
%if %{with python3}
%files -n python3-setuptools-wheel
%license LICENSE
# we own the dir for simplicity
%dir %{python3_wheeldir}/
%{python3_wheeldir}/%{python3_wheelname}
%endif #with python3
%endif #with bootstrap
%changelog
* Wed Jul 24 2024 Lumír Balhar <lbalhar@redhat.com> - 53.0.0-12.1
* Wed Jul 24 2024 Lumír Balhar <lbalhar@redhat.com> - 39.2.0-8
- Security fix for CVE-2024-6345
Resolves: RHEL-50466
Resolves: RHEL-50470
* Wed Jan 11 2023 Charalampos Stratakis <cstratak@redhat.com> - 53.0.0-12
* Wed Jan 11 2023 Charalampos Stratakis <cstratak@redhat.com> - 39.2.0-7
- Security fix for CVE-2022-40897
Resolves: rhbz#2158559
* Wed Sep 07 2022 Miro Hrončok <mhroncok@redhat.com> - 53.0.0-11
- Fix case sensitivity of entry point names and keys in setup.cfg
- Resolves: rhbz#2124281
* Tue Feb 08 2022 Tomas Orsava <torsava@redhat.com> - 53.0.0-10
- Add automatically generated Obsoletes tag with the python39- prefix
for smoother upgrade from RHEL8
- Related: rhbz#1990421
* Wed Jan 12 2022 Miro Hrončok <mhroncok@redhat.com> - 53.0.0-9
- Add License-File field to package metadata
- Resolves: rhbz#2033994
* Wed Nov 24 2021 Tomas Orsava <torsava@redhat.com> - 53.0.0-8
- Conflict with old Python versions that use the old unversioned wheel location
- Resolves: rhbz#1982668
* Wed Sep 22 2021 Tomas Orsava <torsava@redhat.com> - 53.0.0-7
- Make the python-setuptools-wheel subpackage versioned (python3-setuptools-wheel),
and move its contents to a versioned directory /usr/share/python3-wheels
- Resolves: rhbz#1982668
* Tue Aug 10 2021 Mohan Boddu <mboddu@redhat.com>
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Wed Jul 28 2021 Tomas Orsava <torsava@redhat.com> - 53.0.0-5
- Provide the platform-python-setuptools name for backwards compatibility
with RHEL 8
- Related: rhbz#1891487
* Mon Jun 21 2021 Lumír Balhar <lbalhar@redhat.com> - 53.0.0-4
- Add missing bundled provide - ordered-set
Related: rhbz#1950291
* Thu Apr 22 2021 Miro Hrončok <mhroncok@redhat.com> - 53.0.0-3
- Provide python3-pkg_resources
- Provide python3-pkg-resources
Resolves: rhbz#1947857
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 53.0.0-2
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Tue Feb 02 2021 Miro Hrončok <mhroncok@redhat.com> - 53.0.0-1
- Update to 53.0.0
- https://setuptools.readthedocs.io/en/latest/history.html#v53-0-0
- Fixes: rhbz#1923249
* Tue Jan 26 2021 Lumír Balhar <lbalhar@redhat.com> - 52.0.0-1
- Update to 52.0.0 (#1917060)
- Removes easy_install module and executable
* Mon Jan 11 2021 Miro Hrončok <mhroncok@redhat.com> - 51.1.2-1
- Update to 51.1.2
- Removes tests from the wheel
- https://setuptools.readthedocs.io/en/latest/history.html#v51-1-2
- Fixes: rhbz#1914481
* Tue Dec 29 2020 Miro Hrončok <mhroncok@redhat.com> - 51.1.1-1
- Update to 51.1.1
- Fixes test failures with pip 20.3 as well as with pytest 6.2+
- Fixes: rhbz#1909575
* Fri Dec 4 2020 Miro Hrončok <mhroncok@redhat.com> - 50.3.2-2
- Disable tests in Fedora ELN (and RHEL)
* Tue Oct 20 2020 Tomas Hrnciar <thrnciar@redhat.com> - 50.3.2-1
- Update to 50.3.2 (#1889093)
* Fri Sep 04 2020 Tomas Hrnciar <thrnciar@redhat.com> - 50.1.0-1
- Update to 50.1.0 (#1873889)
* Fri Aug 21 2020 Petr Viktorin <pviktori@redhat.com> - 49.6.0-1
- Update to 49.6.0 (#1862791)
* Wed Jul 29 2020 Miro Hrončok <mhroncok@redhat.com> - 49.1.3-1
- Update to 49.1.3 (#1853597)
- https://setuptools.readthedocs.io/en/latest/history.html#v49-1-3
* Wed Jul 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 47.3.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Fri Jun 26 2020 Miro Hrončok <mhroncok@redhat.com> - 47.3.1-1
- Update to 47.3.1 (#1847049)
- https://setuptools.readthedocs.io/en/latest/history.html#v47-3-1
* Mon Jun 01 2020 Charalampos Stratakis <cstratak@redhat.com> - 47.1.1-1
- Update to 47.1.1 (#1841123)
- https://setuptools.readthedocs.io/en/latest/history.html#v47-1-1
* Sun May 24 2020 Miro Hrončok <mhroncok@redhat.com> - 46.4.0-4
- Rebuilt for Python 3.9
* Thu May 21 2020 Miro Hrončok <mhroncok@redhat.com> - 46.4.0-3
- Bootstrap for Python 3.9
* Thu May 21 2020 Miro Hrončok <mhroncok@redhat.com> - 46.4.0-2
- Bootstrap for Python 3.9
* Mon May 18 2020 Tomas Hrnciar <thrnciar@redhat.com> - 46.4.0-1
- Update to 46.4.0 (#1835411)
- https://setuptools.readthedocs.io/en/latest/history.html#v46-4-0
* Wed Mar 25 2020 Charalampos Stratakis <cstratak@redhat.com> - 39.2.0-6
- Create /usr/local/lib/pythonX.Y when needed
Resolves: rhbz#1808301
* Tue May 12 2020 Tomas Hrnciar <thrnciar@redhat.com> - 46.2.0-1
- Update to 46.2.0 (#1833826)
- https://setuptools.readthedocs.io/en/latest/history.html#v46-2-0
* Wed Apr 17 2019 Petr Viktorin <pviktori@redhat.com> - 39.2.0-5
- Add subpackages with wheels
Resolves: rhbz#1718032
* Thu Mar 26 2020 Miro Hrončok <mhroncok@redhat.com> - 46.1.3-1
- Upgrade to 46.1.3 (#1817189)
- https://setuptools.readthedocs.io/en/latest/history.html#v46-1-3
* Mon Oct 22 2018 Lumír Balhar <lbalhar@redhat.com> - 39.2.0-4
- New subpackage platform-python-setuptools without files from /usr/bin/*
- python3-setuptools contains only files from /usr/bin/* and depends
on platform-python-setuptools
- Resolves: rhbz#1641973
* Tue Mar 10 2020 Miro Hrončok <mhroncok@redhat.com> - 46.0.0-1
- Upgrade to 46.0.0 (#1811340)
- https://setuptools.readthedocs.io/en/latest/history.html#v46-0-0
* Mon Jun 25 2018 Petr Viktorin <pviktori@redhat.com> - 39.2.0-3
- Allow Python 2 for build
see https://hurl.corp.redhat.com/rhel8-py2
* Tue Feb 11 2020 Miro Hrončok <mhroncok@redhat.com> - 45.2.0-1
- Upgrade to 45.2.0 (#1775943)
- https://setuptools.readthedocs.io/en/latest/history.html#v45-2-0
- No longer supports Python 2
* Fri Jun 22 2018 Petr Viktorin <pviktori@redhat.com> - 39.2.0-2
- Do not use wheel on Python 2
* Thu Jan 30 2020 Fedora Release Engineering <releng@fedoraproject.org> - 41.6.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Mon Nov 04 2019 Tomas Orsava <torsava@redhat.com> - 41.6.0-1
- Upgrade to 41.6.0 (#1758945).
- https://setuptools.readthedocs.io/en/latest/history.html#v41-6-0
- Disabled a failing upstream test: https://github.com/pypa/setuptools/issues/1896
* Tue Sep 03 2019 Randy Barlow <bowlofeggs@fedoraproject.org> - 41.2.0-1
- Upgrade to 41.2.0 (#1742718).
- https://setuptools.readthedocs.io/en/latest/history.html#v41-2-0
* Mon Aug 26 2019 Miro Hrončok <mhroncok@redhat.com> - 41.0.1-9
- Move python2-setuptools to a separate package
* Sun Aug 18 2019 Miro Hrončok <mhroncok@redhat.com> - 41.0.1-8
- Rebuilt for Python 3.8
* Wed Aug 14 2019 Miro Hrončok <mhroncok@redhat.com> - 41.0.1-7
- Bootstrap for Python 3.8
* Wed Aug 14 2019 Miro Hrončok <mhroncok@redhat.com> - 41.0.1-6
- Provide pythonXdist(setuptools) when bootstrapping
* Wed Aug 14 2019 Miro Hrončok <mhroncok@redhat.com> - 41.0.1-5
- Bootstrap for Python 3.8
* Fri Jul 26 2019 Fedora Release Engineering <releng@fedoraproject.org> - 41.0.1-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Tue Jul 16 2019 Miro Hrončok <mhroncok@redhat.com> - 41.0.1-3
- Make /usr/bin/easy_install Python 3
- Drop obsoleted Obsoletes
* Fri Jun 21 2019 Petr Viktorin <pviktori@redhat.com> - 41.0.1-2
- Remove optional test dependencies for Python 2
- Skip test_virtualenv on Python 2
* Thu Apr 25 2019 Miro Hrončok <mhroncok@redhat.com> - 41.0.1-1
- Update to 41.0.1 (#1695846)
- https://github.com/pypa/setuptools/blob/v41.0.1/CHANGES.rst
* Tue Feb 05 2019 Miro Hrončok <mhroncok@redhat.com> - 40.8.0-1
- Update to 40.8.0 (#1672756)
- https://github.com/pypa/setuptools/blob/v40.8.0/CHANGES.rst
* Sun Feb 03 2019 Miro Hrončok <mhroncok@redhat.com> - 40.7.3-1
- Hotfix update to 40.7.3 (#1672084)
- https://github.com/pypa/setuptools/blob/v40.7.3/CHANGES.rst
* Sat Feb 02 2019 Miro Hrončok <mhroncok@redhat.com> - 40.7.2-1
- Hotfix update to 40.7.2 (#1671608)
- https://github.com/pypa/setuptools/blob/v40.7.2/CHANGES.rst
* Sat Feb 02 2019 Fedora Release Engineering <releng@fedoraproject.org> - 40.7.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Tue Jan 29 2019 Miro Hrončok <mhroncok@redhat.com> - 40.7.1-1
- Hotfix update to 40.7.1 (#1670243)
- https://github.com/pypa/setuptools/blob/v40.7.1/CHANGES.rst
* Mon Jan 28 2019 Miro Hrončok <mhroncok@redhat.com> - 40.7.0-1
- Update to 40.7.0 (#1669876)
- https://github.com/pypa/setuptools/blob/v40.7.0/CHANGES.rst
* Mon Sep 24 2018 Miro Hrončok <mhroncok@redhat.com> - 40.4.3-1
- Update to 40.4.3 to fix dire DeprecationWarnings (#1627071)
- List vendored libraries
- https://github.com/pypa/setuptools/blob/v40.4.3/CHANGES.rst
* Wed Sep 19 2018 Randy Barlow <bowlofeggs@fedoraproject.org> - 40.4.1-1
- Update to 40.4.1 (#1599307).
- https://github.com/pypa/setuptools/blob/v40.4.1/CHANGES.rst
* Wed Aug 15 2018 Petr Viktorin <pviktori@redhat.com> - 39.2.0-7
- Add a subpackage with wheels
- Remove the python3 bcond
- Remove macros for RHEL 6
* Thu Jul 19 2018 Miro Hrončok <mhroncok@redhat.com> - 39.2.0-6
- Create /usr/local/lib/pythonX.Y when needed (#1576924)
* Sat Jul 14 2018 Fedora Release Engineering <releng@fedoraproject.org> - 39.2.0-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Mon Jun 18 2018 Miro Hrončok <mhroncok@redhat.com> - 39.2.0-4
- Rebuilt for Python 3.7
* Wed Jun 13 2018 Miro Hrončok <mhroncok@redhat.com> - 39.2.0-3
- Bootstrap for Python 3.7
* Wed Jun 13 2018 Miro Hrončok <mhroncok@redhat.com> - 39.2.0-2
- Bootstrap for Python 3.7
* Wed May 23 2018 Charalampos Stratakis <cstratak@redhat.com> - 39.2.0-1
* Tue Jun 19 2018 Charalampos Stratakis <cstratak@redhat.com> - 39.2.0-1
- update to 39.2.0 Fixes bug #1572889
* Thu Jun 07 2018 Petr Viktorin <pviktori@redhat.com> - 39.0.1-2
- Remove test requirements on python2 packages and some exotic packages
- Skip tests on Python 2
* Tue Mar 20 2018 Charalampos Stratakis <cstratak@redhat.com> - 39.0.1-1
- update to 39.0.1 Fixes bug #1531527

Loading…
Cancel
Save