summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2021-01-16 16:48:54 -0500
committerGitHub <noreply@github.com>2021-01-16 16:48:54 -0500
commitef457b2e4eb215ab9d730afbd61a10ed3b118d3c (patch)
tree8e7c5e2dabfeff4097dd1589ce633a8ee0b13179
parentd2b1f7ebd6ebd57b4a50bc6660e93b31129bacb4 (diff)
parented07f8b124f75b43e27e5d636484898476a0be4f (diff)
downloadpython-setuptools-git-ef457b2e4eb215ab9d730afbd61a10ed3b118d3c.tar.gz
Merge pull request #2533 from pypa/fix/2529
Fix/2529
-rw-r--r--changelog.d/2529.change.rst1
-rw-r--r--setuptools/command/egg_info.py10
-rw-r--r--setuptools/tests/test_egg_info.py84
3 files changed, 57 insertions, 38 deletions
diff --git a/changelog.d/2529.change.rst b/changelog.d/2529.change.rst
new file mode 100644
index 00000000..10c41518
--- /dev/null
+++ b/changelog.d/2529.change.rst
@@ -0,0 +1 @@
+Fixed an issue where version tags may be added multiple times
diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py
index 0b7ad677..066c2488 100644
--- a/setuptools/command/egg_info.py
+++ b/setuptools/command/egg_info.py
@@ -130,10 +130,12 @@ class InfoCommon:
egg_info may be called more than once for a distribution,
in which case the version string already contains all tags.
"""
- return (
- version if self.vtags and version.endswith(self.vtags)
- else version + self.vtags
- )
+ # Remove the tags if they exist. The tags maybe have been normalized
+ # (e.g. turning .dev into .dev0) so we can't just compare strings
+ base_version = parse_version(version).base_version
+
+ # Add the tags
+ return base_version + self.vtags
def tags(self):
version = ''
diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py
index 1047468b..1d0f07e3 100644
--- a/setuptools/tests/test_egg_info.py
+++ b/setuptools/tests/test_egg_info.py
@@ -6,6 +6,7 @@ import re
import stat
import time
+from setuptools.build_meta import prepare_metadata_for_build_wheel
from setuptools.command.egg_info import (
egg_info, manifest_maker, EggInfoDeprecationWarning, get_pkg_info_revision,
)
@@ -19,6 +20,26 @@ from .textwrap import DALS
from . import contexts
+def _run_egg_info_command(tmpdir_cwd, env, cmd=None, output=None):
+ environ = os.environ.copy().update(
+ HOME=env.paths['home'],
+ )
+ if cmd is None:
+ cmd = [
+ 'egg_info',
+ ]
+ code, data = environment.run_setup_py(
+ cmd=cmd,
+ pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]),
+ data_stream=1,
+ env=environ,
+ )
+ assert not code, data
+
+ if output:
+ assert output in data
+
+
class Environment(str):
pass
@@ -132,7 +153,7 @@ class TestEggInfo:
def test_expected_files_produced(self, tmpdir_cwd, env):
self._create_project()
- self._run_egg_info_command(tmpdir_cwd, env)
+ _run_egg_info_command(tmpdir_cwd, env)
actual = os.listdir('foo.egg-info')
expected = [
@@ -166,7 +187,7 @@ class TestEggInfo:
# currently configured to use a subprocess, the actual traceback
# object is lost and we need to parse it from stderr
with pytest.raises(AssertionError) as exc:
- self._run_egg_info_command(tmpdir_cwd, env)
+ _run_egg_info_command(tmpdir_cwd, env)
# Hopefully this is not too fragile: the only argument to the
# assertion error should be a traceback, ending with:
@@ -180,13 +201,13 @@ class TestEggInfo:
"""Ensure timestamps are updated when the command is re-run."""
self._create_project()
- self._run_egg_info_command(tmpdir_cwd, env)
+ _run_egg_info_command(tmpdir_cwd, env)
timestamp_a = os.path.getmtime('foo.egg-info')
# arbitrary sleep just to handle *really* fast systems
time.sleep(.001)
- self._run_egg_info_command(tmpdir_cwd, env)
+ _run_egg_info_command(tmpdir_cwd, env)
timestamp_b = os.path.getmtime('foo.egg-info')
assert timestamp_a != timestamp_b
@@ -201,7 +222,7 @@ class TestEggInfo:
'usage.rst': "Run 'hi'",
}
})
- self._run_egg_info_command(tmpdir_cwd, env)
+ _run_egg_info_command(tmpdir_cwd, env)
egg_info_dir = os.path.join('.', 'foo.egg-info')
sources_txt = os.path.join(egg_info_dir, 'SOURCES.txt')
with open(sources_txt) as f:
@@ -441,7 +462,7 @@ class TestEggInfo:
self, tmpdir_cwd, env, requires, use_setup_cfg,
expected_requires, install_cmd_kwargs):
self._setup_script_with_requires(requires, use_setup_cfg)
- self._run_egg_info_command(tmpdir_cwd, env, **install_cmd_kwargs)
+ _run_egg_info_command(tmpdir_cwd, env, **install_cmd_kwargs)
egg_info_dir = os.path.join('.', 'foo.egg-info')
requires_txt = os.path.join(egg_info_dir, 'requires.txt')
if os.path.exists(requires_txt):
@@ -461,14 +482,14 @@ class TestEggInfo:
req = 'install_requires={"fake-factory==0.5.2", "pytz"}'
self._setup_script_with_requires(req)
with pytest.raises(AssertionError):
- self._run_egg_info_command(tmpdir_cwd, env)
+ _run_egg_info_command(tmpdir_cwd, env)
def test_extras_require_with_invalid_marker(self, tmpdir_cwd, env):
tmpl = 'extras_require={{":{marker}": ["barbazquux"]}},'
req = tmpl.format(marker=self.invalid_marker)
self._setup_script_with_requires(req)
with pytest.raises(AssertionError):
- self._run_egg_info_command(tmpdir_cwd, env)
+ _run_egg_info_command(tmpdir_cwd, env)
assert glob.glob(os.path.join(env.paths['lib'], 'barbazquux*')) == []
def test_extras_require_with_invalid_marker_in_req(self, tmpdir_cwd, env):
@@ -476,7 +497,7 @@ class TestEggInfo:
req = tmpl.format(marker=self.invalid_marker)
self._setup_script_with_requires(req)
with pytest.raises(AssertionError):
- self._run_egg_info_command(tmpdir_cwd, env)
+ _run_egg_info_command(tmpdir_cwd, env)
assert glob.glob(os.path.join(env.paths['lib'], 'barbazquux*')) == []
def test_provides_extra(self, tmpdir_cwd, env):
@@ -865,26 +886,22 @@ class TestEggInfo:
sources = f.read().split('\n')
assert 'setup.py' in sources
- def _run_egg_info_command(self, tmpdir_cwd, env, cmd=None, output=None):
- environ = os.environ.copy().update(
- HOME=env.paths['home'],
- )
- if cmd is None:
- cmd = [
- 'egg_info',
- ]
- code, data = environment.run_setup_py(
- cmd=cmd,
- pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]),
- data_stream=1,
- env=environ,
- )
- assert not code, data
-
- if output:
- assert output in data
-
- def test_egg_info_tag_only_once(self, tmpdir_cwd, env):
+ @pytest.mark.parametrize(
+ ('make_metadata_path', 'run_command'),
+ [
+ (
+ lambda env: os.path.join('.', 'foo.egg-info', 'PKG-INFO'),
+ lambda tmpdir_cwd, env: _run_egg_info_command(tmpdir_cwd, env)
+ ),
+ (
+ lambda env: os.path.join(env, 'foo.dist-info', 'METADATA'),
+ lambda tmpdir_cwd, env: prepare_metadata_for_build_wheel(env)
+ )
+ ]
+ )
+ def test_egg_info_tag_only_once(
+ self, tmpdir_cwd, env, make_metadata_path, run_command
+ ):
self._create_project()
build_files({
'setup.cfg': DALS("""
@@ -894,11 +911,10 @@ class TestEggInfo:
tag_svn_revision = 0
"""),
})
- self._run_egg_info_command(tmpdir_cwd, env)
- 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')
- assert 'Version: 0.0.0.dev0' in pkg_info_lines
+ run_command(tmpdir_cwd, env)
+ with open(make_metadata_path(env)) as metadata_file:
+ metadata_lines = metadata_file.read().split('\n')
+ assert 'Version: 0.0.0.dev0' in metadata_lines
def test_get_pkg_info_revision_deprecated(self):
pytest.warns(EggInfoDeprecationWarning, get_pkg_info_revision)