diff --git a/src/setuptools_scm/__init__.py b/src/setuptools_scm/__init__.py index 47b9e44b..c9626573 100644 --- a/src/setuptools_scm/__init__.py +++ b/src/setuptools_scm/__init__.py @@ -157,6 +157,7 @@ def get_version( parse=None, git_describe_command=None, dist_name=None, + version_cls=None, # or name it version_factory ? ): """ If supplied, relative_to should be a file from which root may diff --git a/src/setuptools_scm/config.py b/src/setuptools_scm/config.py index fe1eb984..b2440350 100644 --- a/src/setuptools_scm/config.py +++ b/src/setuptools_scm/config.py @@ -66,6 +66,7 @@ def __init__( parse=None, git_describe_command=None, dist_name=None, + version_cls=None, ): # TODO: self._relative_to = relative_to @@ -83,6 +84,7 @@ def __init__( self.tag_regex = tag_regex self.git_describe_command = git_describe_command self.dist_name = dist_name + self.version_cls = version_cls @property def fallback_root(self): diff --git a/src/setuptools_scm/version.py b/src/setuptools_scm/version.py index f97dca5e..73148369 100644 --- a/src/setuptools_scm/version.py +++ b/src/setuptools_scm/version.py @@ -98,7 +98,11 @@ def tag_to_version(tag, config=None): ) ) - if VERSION_CLASS is not None: + # use custom version class if provided + if config.version_cls is not None: + version = config.version_cls(version) + trace("version", repr(version)) + elif VERSION_CLASS is not None: version = pkg_parse_version(version) trace("version", repr(version)) @@ -187,7 +191,9 @@ def format_next_version(self, guess_next, fmt="{guessed}.dev{distance}", **kw): def _parse_tag(tag, preformatted, config): if preformatted: return tag - if VERSION_CLASS is None or not isinstance(tag, VERSION_CLASS): + # use custom version class if provided + version_cls = config.version_cls or VERSION_CLASS + if version_cls is None or not isinstance(tag, version_cls): tag = tag_to_version(tag, config) return tag diff --git a/testing/test_basic_api.py b/testing/test_basic_api.py index 5e35a9ec..d3cc4ba3 100644 --- a/testing/test_basic_api.py +++ b/testing/test_basic_api.py @@ -123,3 +123,17 @@ def parse(root): with pytest.raises(TypeError): setuptools_scm.get_version(parse=parse) + + +# def test_custom_version_cls(monkeypatch): +# +# monkeypatch.setenv(setuptools_scm.PRETEND_KEY, "1.0.1") +# +# class MyVersion: +# def __init__(self, tag_str: str): +# # todo +# pass +# +# # TODO unfortunately with PRETEND_KEY the preformatted flag becomes True which bypasses our class. +# # which other mechanism would be ok to use ? +# assert setuptools_scm.get_version(version_cls=MyVersion) == "1" diff --git a/testing/test_version.py b/testing/test_version.py index ee138014..d8a0118d 100644 --- a/testing/test_version.py +++ b/testing/test_version.py @@ -170,3 +170,19 @@ def test_version_bump_bad(): ): guess_next_version(tag_version="2.0.0-alpha.5-PMC") + + +def test_custom_version_cls(): + """Test that we can pass our own version class instead of pkg_resources""" + + class MyVersion: + def __init__(self, tag_str: str): + self.tag = tag_str + + def __repr__(self): + return "Custom %s" % self.tag + + scm_version = meta("1.0.0-foo", config=Configuration(version_cls=MyVersion)) + + assert isinstance(scm_version.tag, MyVersion) + assert repr(scm_version.tag) == "Custom 1.0.0-foo"