diff --git a/.bumpversion.cfg b/.bumpversion.cfg deleted file mode 100644 index 16058d4c24..0000000000 --- a/.bumpversion.cfg +++ /dev/null @@ -1,6 +0,0 @@ -[bumpversion] -current_version = 78.1.0 -commit = True -tag = True - -[bumpversion:file:pyproject.toml] diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 14f3151d34..0475d29f5d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -71,6 +71,8 @@ jobs: timeout-minutes: 75 steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Install build dependencies # Install dependencies for building packages on pre-release Pythons # jaraco/skeleton#161 @@ -183,6 +185,8 @@ jobs: timeout-minutes: 75 steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Install Cygwin with Python uses: cygwin/cygwin-install-action@v4 with: @@ -244,6 +248,8 @@ jobs: timeout-minutes: 75 steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Install OS-level dependencies run: | sudo apt-get update @@ -269,6 +275,8 @@ jobs: timeout-minutes: 75 steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup Python uses: actions/setup-python@v5 with: diff --git a/MANIFEST.in b/MANIFEST.in index 0643e7ee2d..1ed43fda06 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -16,6 +16,7 @@ include msvc-build-launcher.cmd include mypy.ini include pytest.ini include tox.ini +include NEWS.rst include setuptools/tests/config/setupcfg_examples.txt include setuptools/config/*.schema.json global-exclude *.py[cod] __pycache__ diff --git a/newsfragments/4948.misc.rst b/newsfragments/4948.misc.rst new file mode 100644 index 0000000000..31fa413053 --- /dev/null +++ b/newsfragments/4948.misc.rst @@ -0,0 +1,4 @@ +Setuptools stopped using ``egg_info --tag-build --tag-date`` for its own build +process. Instead version is now inferred from git tag history. +To ensure the proper version is considered, please make sure to fetch the git tags. +Local development tags are added to the latest version if the latest commit is not tagged. diff --git a/pyproject.toml b/pyproject.toml index e4d0441317..5241456f95 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,6 @@ backend-path = ["."] [project] name = "setuptools" -version = "78.1.0" authors = [ { name = "Python Packaging Authority", email = "distutils-sig@python.org" }, ] @@ -26,6 +25,7 @@ requires-python = ">=3.9" dependencies = [ ] keywords = ["CPAN PyPI distutils eggs package management"] +dynamic = ["version"] [project.urls] Source = "https://github.com/pypa/setuptools" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 38922089ad..0000000000 --- a/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[egg_info] -tag_build = .post -tag_date = 1 diff --git a/setup.py b/setup.py index c28a14e722..c726434bd2 100755 --- a/setup.py +++ b/setup.py @@ -1,10 +1,14 @@ #!/usr/bin/env python import os +import re +import subprocess import sys import textwrap +import time import setuptools +from setuptools import _normalization from setuptools.command.install import install here = os.path.dirname(__file__) @@ -26,6 +30,21 @@ package_data.setdefault('setuptools.command', []).extend(['*.xml']) +def _get_version() -> str: + cmd = ["git", "describe", "--abbrev", "--match", "v?[0-9]*", "--dirty"] + try: + version = subprocess.check_output(cmd, encoding="utf-8") + return _normalization.best_effort_version(version, "{safe}.dev+{sanitized}") + except subprocess.CalledProcessError: # e.g.: git not installed or history missing + if os.path.exists("PKG-INFO"): # building wheel from sdist + with open("PKG-INFO", encoding="utf-8") as fp: + if match := re.search(r"^Version: (\d+\.\d+\.\d+.*)$", fp.read(), re.M): + return match[1] + with open("NEWS.rst", encoding="utf-8") as fp: + match = re.search(r"v\d+\.\d+\.\d+", fp.read()) # latest version + return f"{match[0] if match else '0.0.0'}.dev+{time.strftime('%Y%m%d')}" + + def pypi_link(pkg_filename): """ Given the filename, including md5 fragment, construct the @@ -83,6 +102,7 @@ def _restore_install_lib(self): setup_params = dict( + version=_get_version(), cmdclass={'install': install_with_pth}, package_data=package_data, ) diff --git a/setuptools/_normalization.py b/setuptools/_normalization.py index 0937a4faf8..06c29afa0c 100644 --- a/setuptools/_normalization.py +++ b/setuptools/_normalization.py @@ -12,7 +12,7 @@ _VALID_NAME = re.compile(r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.I) _UNSAFE_NAME_CHARS = re.compile(r"[^A-Z0-9._-]+", re.I) _NON_ALPHANUMERIC = re.compile(r"[^A-Z0-9]+", re.I) -_PEP440_FALLBACK = re.compile(r"^v?(?P(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.I) +_PEP440_FALLBACK = re.compile(r"^(?Pv?(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.I) def safe_identifier(name: str) -> str: @@ -65,7 +65,10 @@ def safe_version(version: str) -> str: return str(packaging.version.Version(attempt)) -def best_effort_version(version: str) -> str: +def best_effort_version( + version: str, + template: str = "{safe}.dev0+sanitized.{sanitized}", +) -> str: """Convert an arbitrary string into a version-like string. Fallback when ``safe_version`` is not safe enough. >>> best_effort_version("v0.2 beta") @@ -80,6 +83,8 @@ def best_effort_version(version: str) -> str: '0.dev0+sanitized' >>> best_effort_version("42.+?1") '42.dev0+sanitized.1' + >>> best_effort_version("v78.1.0-2-g3a3144f0d") + '78.1.0.dev0+sanitized.2.g3a3144f0d' """ # See pkg_resources._forgiving_version try: @@ -94,8 +99,8 @@ def best_effort_version(version: str) -> str: safe = "0" rest = version safe_rest = _NON_ALPHANUMERIC.sub(".", rest).strip(".") - local = f"sanitized.{safe_rest}".strip(".") - return safe_version(f"{safe}.dev0+{local}") + fallback = template.format(safe=safe, sanitized=safe_rest).strip(".") + return safe_version(fallback) def safe_extra(extra: str) -> str: diff --git a/setuptools/tests/test_setuptools.py b/setuptools/tests/test_setuptools.py index 1d56e1a8a4..39d49f4fcd 100644 --- a/setuptools/tests/test_setuptools.py +++ b/setuptools/tests/test_setuptools.py @@ -265,6 +265,15 @@ def test_findall_missing_symlink(tmpdir): assert found == [] +def test_setuptools_own_dists_infers_version(setuptools_sdist, setuptools_wheel): + # Sanity check + # Validates that `setup.py:_get_version` works as expected + assert "0.0.0" not in setuptools_sdist.name + # Validates that `setup.py:_get_version` guarantees the fallback + # code path is finding something in PKG-INFO: + assert "0.0.0" not in setuptools_wheel.name + + @pytest.mark.xfail(reason="unable to exclude tests; #4475 #3260") def test_its_own_wheel_does_not_contain_tests(setuptools_wheel): with ZipFile(setuptools_wheel) as zipfile: diff --git a/tools/finalize.py b/tools/finalize.py deleted file mode 100644 index d646e67cd0..0000000000 --- a/tools/finalize.py +++ /dev/null @@ -1,62 +0,0 @@ -""" -Finalize the repo for a release. Invokes towncrier and bumpversion. -""" - -__requires__ = ['bump2version', 'towncrier', 'jaraco.develop>=7.21'] - - -import pathlib -import re -import subprocess -import sys - -from jaraco.develop import towncrier - -bump_version_command = [ - sys.executable, - '-m', - 'bumpversion', - towncrier.release_kind(), -] - - -def get_version(): - cmd = bump_version_command + ['--dry-run', '--verbose'] - out = subprocess.check_output(cmd, text=True, encoding='utf-8') - return re.search('^new_version=(.*)', out, re.MULTILINE).group(1) - - -def update_changelog(): - towncrier.run('build', '--yes') - _repair_changelog() - - -def _repair_changelog(): - """ - Workaround for #2666 - """ - changelog_fn = pathlib.Path('NEWS.rst') - changelog = changelog_fn.read_text(encoding='utf-8') - fixed = re.sub(r'^(v[0-9.]+)v[0-9.]+$', r'\1', changelog, flags=re.M) - changelog_fn.write_text(fixed, encoding='utf-8') - subprocess.check_output(['git', 'add', changelog_fn]) - - -def bump_version(): - cmd = bump_version_command + ['--allow-dirty'] - subprocess.check_call(cmd) - - -def ensure_config(): - """ - Double-check that Git has an e-mail configured. - """ - subprocess.check_output(['git', 'config', 'user.email']) - - -if __name__ == '__main__': - print("Cutting release at", get_version()) - ensure_config() - towncrier.check_changes() - update_changelog() - bump_version() diff --git a/tox.ini b/tox.ini index 942e2b9835..7df82a64b9 100644 --- a/tox.ini +++ b/tox.ini @@ -63,11 +63,10 @@ description = assemble changelog and tag a release skip_install = True deps = towncrier - bump2version jaraco.develop >= 7.23 pass_env = * commands = - python tools/finalize.py + python -m jaraco.develop.finalize [testenv:vendor] skip_install = True @@ -102,8 +101,6 @@ setenv = TWINE_USERNAME = {env:TWINE_USERNAME:__token__} commands = python -c "import shutil; shutil.rmtree('dist', ignore_errors=True)" - # unset tag_build and tag_date pypa/setuptools#2500 - python setup.py egg_info -Db "" saveopts python -m build python -m twine upload dist/* python -m jaraco.develop.create-github-release