Skip to content

Commit

Permalink
Merge pull request #616 from RonnyPfannschmidt/fix-regressions
Browse files Browse the repository at this point in the history
combined preparation for the 6.3.0 release and a regression resolution
  • Loading branch information
RonnyPfannschmidt authored Sep 3, 2021
2 parents 410011b + 7b65699 commit 682d669
Show file tree
Hide file tree
Showing 20 changed files with 400 additions and 155 deletions.
17 changes: 14 additions & 3 deletions .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
update: true
- run: pip install -U setuptools
if: matrix.python_version != 'msys2'
- run: pip install -e .[toml] pytest
- run: pip install -e .[toml] pytest virtualenv
# pip2 is needed because Mercurial uses python2 on Ubuntu 20.04
- run: |
curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py
Expand All @@ -49,6 +49,17 @@ jobs:
if: matrix.os == 'ubuntu-latest'
- run: pytest

test_legacy_setuptools:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Setup python
uses: actions/setup-python@v2
with:
python-version: "3.6"
architecture: x64
- run: pip install -e .[toml] pytest virtualenv
- run: pytest --test-legacy testing/test_setuptools_support.py || true # ignore fail flaky on ci
check_selfinstall:
runs-on: ubuntu-latest
strategy:
Expand All @@ -66,8 +77,8 @@ jobs:
architecture: x64
# self install testing needs some clarity
# so its being executed without any other tools running
# setuptools smaller 52 is needed too di easy_install
- run: pip install -U "setuptools<52" tomli
# setuptools smaller 52 is needed to do easy_install
- run: pip install -U "setuptools<52" tomli packaging
- run: python setup.py egg_info
- run: python setup.py sdist
- run: ${{ matrix.installer }} dist/*
Expand Down
24 changes: 24 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@

6.3.0
=======

.. warning::

This release explicitly warns on unsupported setuptools.
This unfortunately has to happen as the legacy ``setup_requires`` mechanism
incorrectly configures the setuptools working-set when a more recent setuptools
version than available is required.

As all releases of setuptools are affected as the historic mechanism
for ensuring a working setuptools setup was shipping a ``ez_setup`` file
next to ``setup.py``, which would install the required version of setuptools.

This mechanism has long since been deprecated and removed
as most people haven't been using it


* fix #612: depend on packaging to ensure version parsing parts
* fix #611: correct the typo that hid away the toml extra and add it in ``setup.py`` as well
* fix #615: restore support for the git_archive plugin which doesn't pass over the config
* restore the ability to run on old setuptools while to avoid breaking pipelines

v6.2.0
=======

Expand Down
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ include *.rst
include LICENSE
include *.toml
include mypy.ini
include testing/Dockerfile.busted-buster
recursive-include testing *.bash
7 changes: 6 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
[build-system]
requires = ["setuptools>=45", "wheel", "tomli"]
requires = [
"setuptools>=45",
"wheel",
"tomli>=1.0",
"packaging>=20.0"
]
build-backend = "setuptools.build_meta"
10 changes: 6 additions & 4 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ classifiers =
[options]
packages = find:
install_requires =
setuptools>=45
tomli>=1.0
packaging>=20.0
setuptools
python_requires = >=3.6
package_dir =
=src
Expand Down Expand Up @@ -68,5 +68,7 @@ setuptools_scm.version_scheme =
no-guess-dev = setuptools_scm.version:no_guess_dev_version
calver-by-date = setuptools_scm.version:calver_by_date

[option.extras_require]
toml = # empty
[options.extras_require]
toml =
setuptools>=42
tomli>=1.0.0
60 changes: 31 additions & 29 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,54 +13,56 @@
import sys

import setuptools
from setuptools.command.bdist_egg import bdist_egg as original_bdist_egg


def scm_config():
class bdist_egg(original_bdist_egg):
def run(self):
raise SystemExit(
f"{type(self).__name__} is forbidden, "
"please update to setuptools>=45 which uses pip"
)


def scm_version():

if sys.version_info < (3, 6):
raise RuntimeError(
"support for python < 3.6 has been removed in setuptools_scm>=6.0.0"
)

here = os.path.dirname(os.path.abspath(__file__))
src = os.path.join(here, "src")
egg_info = os.path.join(src, "setuptools_scm.egg-info")
has_entrypoints = os.path.isdir(egg_info)
import pkg_resources

sys.path.insert(0, src)
pkg_resources.working_set.add_entry(src)

from setuptools_scm import get_version
from setuptools_scm.hacks import parse_pkginfo
from setuptools_scm.git import parse as parse_git
from setuptools_scm import git
from setuptools_scm.version import guess_next_dev_version, get_local_node_and_date

def parse(root):
def parse(root, config):
try:
return parse_pkginfo(root)
return parse_pkginfo(root, config)
except OSError:
return parse_git(root)
return git.parse(root, config=config)

config = dict(
version_scheme=guess_next_dev_version, local_scheme=get_local_node_and_date
return get_version(
root=here,
parse=parse,
version_scheme=guess_next_dev_version,
local_scheme=get_local_node_and_date,
)

from setuptools.command.bdist_egg import bdist_egg as original_bdist_egg

class bdist_egg(original_bdist_egg):
def run(self):
raise SystemExit("bdist_egg is forbidden, please update to setuptools>=45")

if has_entrypoints:
return dict(use_scm_version=config, cmdclass={"bdist_egg": bdist_egg})
else:
from setuptools_scm import get_version

return dict(
version=get_version(root=here, parse=parse, **config),
cmdclass={"bdist_egg": bdist_egg},
)


if __name__ == "__main__":
setuptools.setup(setup_requires=["setuptools>=45", "tomli"], **scm_config())
setuptools.setup(
setup_requires=["setuptools"],
version=scm_version(),
extras_require={
"toml": [
"setuptools>=42",
"tomli>=1.0.0",
],
},
cmdclass={"bdist_egg": bdist_egg},
)
44 changes: 21 additions & 23 deletions src/setuptools_scm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,17 @@
import os
import warnings

try:
from packaging.version import parse
except ImportError:
from pkg_resources import parse_version as parse

from .config import (
Configuration,
DEFAULT_VERSION_SCHEME,
DEFAULT_LOCAL_SCHEME,
DEFAULT_TAG_REGEX,
NonNormalizedVersion,
)
from .utils import function_has_arg, trace
from .version import format_version, meta
from ._version_cls import NonNormalizedVersion
from ._version_cls import Version
from .config import Configuration
from .config import DEFAULT_LOCAL_SCHEME
from .config import DEFAULT_TAG_REGEX
from .config import DEFAULT_VERSION_SCHEME
from .discover import iter_matching_entrypoints
from .utils import function_has_arg
from .utils import trace
from .version import format_version
from .version import meta

PRETEND_KEY = "SETUPTOOLS_SCM_PRETEND_VERSION"
PRETEND_KEY_NAMED = PRETEND_KEY + "_FOR_{name}"
Expand All @@ -40,9 +36,9 @@ def version_from_scm(root):
warnings.warn(
"version_from_scm is deprecated please use get_version",
category=DeprecationWarning,
stacklevel=2,
)
config = Configuration()
config.root = root
config = Configuration(root=root)
# TODO: Is it API?
return _version_from_entrypoints(config)

Expand All @@ -52,15 +48,16 @@ def _call_entrypoint_fn(root, config, fn):
return fn(root, config=config)
else:
warnings.warn(
"parse functions are required to provide a named argument"
" 'config' in the future.",
category=PendingDeprecationWarning,
f"parse function {fn.__module__}.{fn.__name__}"
" are required to provide a named argument"
" 'config', setuptools_scm>=8.0 will remove support.",
category=DeprecationWarning,
stacklevel=2,
)
return fn(root)


def _version_from_entrypoints(config, fallback=False):
def _version_from_entrypoints(config: Configuration, fallback=False):
if fallback:
entrypoint = "setuptools_scm.parse_scm_fallback"
root = config.fallback_root
Expand All @@ -70,7 +67,7 @@ def _version_from_entrypoints(config, fallback=False):

for ep in iter_matching_entrypoints(root, entrypoint, config):
version = _call_entrypoint_fn(root, config, ep.load())

trace(ep, version)
if version:
return version

Expand All @@ -90,7 +87,7 @@ def dump_version(root, version, write_to, template=None):
)
)

parsed_version = parse(version)
parsed_version = Version(version)
version_fields = parsed_version.release
if parsed_version.dev is not None:
version_fields += (f"dev{parsed_version.dev}",)
Expand Down Expand Up @@ -201,10 +198,11 @@ def _get_version(config):
"dump_version",
"version_from_scm",
"Configuration",
"NonNormalizedVersion",
"DEFAULT_VERSION_SCHEME",
"DEFAULT_LOCAL_SCHEME",
"DEFAULT_TAG_REGEX",
"Version",
"NonNormalizedVersion",
# TODO: are the symbols below part of public API ?
"function_has_arg",
"trace",
Expand Down
49 changes: 49 additions & 0 deletions src/setuptools_scm/_version_cls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
try:
from packaging.version import Version

assert hasattr(Version, "release")
except ImportError:
from pkg_resources._vendor.packaging.version import Version as SetuptoolsVersion

try:
SetuptoolsVersion.release
Version = SetuptoolsVersion
except AttributeError:

class Version(SetuptoolsVersion): # type: ignore
@property
def release(self):
return self._version.release

@property
def dev(self):
return self._version.dev

@property
def local(self):
return self._version.local


class NonNormalizedVersion(Version):
"""A non-normalizing version handler.
You can use this class to preserve version verification but skip normalization.
For example you can use this to avoid git release candidate version tags
("1.0.0-rc1") to be normalized to "1.0.0rc1". Only use this if you fully
trust the version tags.
"""

def __init__(self, version):
# parse and validate using parent
super().__init__(version)

# store raw for str
self._raw_version = version

def __str__(self):
# return the non-normalized version (parent returns the normalized)
return self._raw_version

def __repr__(self):
# same pattern as parent
return f"<NonNormalizedVersion({self._raw_version!r})>"
Loading

0 comments on commit 682d669

Please sign in to comment.