Skip to content

Commit

Permalink
remove deprecated docs and add version_file argument
Browse files Browse the repository at this point in the history
  • Loading branch information
RonnyPfannschmidt committed Jul 9, 2023
1 parent 0c9c125 commit 4e4aa28
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 124 deletions.
114 changes: 14 additions & 100 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ to be supplied to ``get_version()``. For example:
# pyproject.toml
[tool.setuptools_scm]
write_to = "pkg/_version.py"
version_file = "pkg/_version.py"
Where ``pkg`` is the name of your package.

Expand All @@ -93,72 +93,7 @@ directly in your working environment and run:
$ python -m setuptools_scm --help
``setup.py`` usage (deprecated)
-------------------------------
.. warning::

``setup_requires`` has been deprecated in favor of ``pyproject.toml``

The following settings are considered legacy behavior and
superseded by the ``pyproject.toml`` usage, but for maximal
compatibility, projects may also supply the configuration in
this older form.

To use ``setuptools_scm`` just modify your project's ``setup.py`` file
like this:

* Add ``setuptools_scm`` to the ``setup_requires`` parameter.
* Add the ``use_scm_version`` parameter and set it to ``True``.

For example:

.. code:: python
from setuptools import setup
setup(
...,
use_scm_version=True,
setup_requires=['setuptools_scm'],
...,
)
Arguments to ``get_version()`` (see below) may be passed as a dictionary to
``use_scm_version``. For example:

.. code:: python
from setuptools import setup
setup(
...,
use_scm_version = {
"root": "..",
"relative_to": __file__,
"local_scheme": "node-and-timestamp"
},
setup_requires=['setuptools_scm'],
...,
)
You can confirm the version number locally via ``setup.py``:

.. code-block:: shell
$ python setup.py --version
.. note::

If you see unusual version numbers for packages but ``python setup.py
--version`` reports the expected version number, ensure ``[egg_info]`` is
not defined in ``setup.cfg``.


``setup.cfg`` usage (deprecated)
------------------------------------

as ``setup_requires`` is deprecated in favour of ``pyproject.toml``
usage in ``setup.cfg`` is considered deprecated,
please use ``pyproject.toml`` whenever possible.
Programmatic usage
Expand All @@ -172,8 +107,6 @@ than the project's root, you can use:
from setuptools_scm import get_version
version = get_version(root='..', relative_to=__file__)
See `setup.py Usage (deprecated)`_ above for how to use this within ``setup.py``.

Retrieving package version at runtime
-------------------------------------
Expand All @@ -193,21 +126,6 @@ or the `importlib_metadata`_ backport:
# package is not installed
pass
Alternatively, you can use ``pkg_resources`` which is included in
``setuptools`` (but has a significant runtime cost):

.. code:: python
from pkg_resources import get_distribution, DistributionNotFound
try:
__version__ = get_distribution("package-name").version
except DistributionNotFound:
# package is not installed
pass
However, this does place a runtime dependency on ``setuptools`` and can add up to
a few 100ms overhead for the package import time.
.. _PEP-0566: https://www.python.org/dev/peps/pep-0566/
.. _importlib_metadata: https://pypi.org/project/importlib-metadata/
Expand Down Expand Up @@ -392,7 +310,7 @@ The currently supported configuration keys are:
Configures how the local component of the version is constructed; either an
entrypoint name or a callable.

:write_to:
:version_file:
A path to a file that gets replaced with a file containing the current
version. It is ideal for creating a ``_version.py`` file within the
package, typically used to avoid using `pkg_resources.get_distribution`
Expand All @@ -404,10 +322,14 @@ The currently supported configuration keys are:
templates, for other file types it is necessary to provide
:code:`write_to_template`.

:write_to_template:
:version_file_template_template:
A newstyle format string that is given the current version as
the ``version`` keyword argument for formatting.

:write_to:
(deprecated) legacy option to create a version file relative to the scm root
its broken for usage from a sdist and fixing it would be a fatal breaking change,
use ``version_file`` instead
:relative_to:
A file from which the root can be resolved.
Typically called by a script or module that is not in the root of the
Expand Down Expand Up @@ -488,28 +410,20 @@ function:
It optionally accepts the keys of the ``use_scm_version`` parameter as
keyword arguments.

Example configuration in ``setup.py`` format:

.. code:: python
from setuptools import setup
setup(
use_scm_version={
'write_to': '_version.py',
'write_to_template': '__version__ = "{version}"',
'tag_regex': r'^(?P<prefix>v)?(?P<version>[^\+]+)(?P<suffix>.*)?$',
}
)

Environment variables
---------------------

:SETUPTOOLS_SCM_PRETEND_VERSION:
when defined and not empty,
its used as the primary source for the version number
in which case it will be an unparsed string
in which case it will be an string

.. warning::

its strongly recommended to use use distribution name specific pretend versions



:SETUPTOOLS_SCM_PRETEND_VERSION_FOR_${NORMALIZED_DIST_NAME}:
when defined and not empty,
Expand Down
2 changes: 2 additions & 0 deletions src/setuptools_scm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ def get_version(
local_scheme: _t.VERSION_SCHEME = _config.DEFAULT_LOCAL_SCHEME,
write_to: _t.PathT | None = None,
write_to_template: str | None = None,
version_file: _t.PathT | None = None,
version_file_template: str | None = None,
relative_to: _t.PathT | None = None,
tag_regex: str | Pattern[str] = _config.DEFAULT_TAG_REGEX,
parentdir_prefix_version: str | None = None,
Expand Down
2 changes: 2 additions & 0 deletions src/setuptools_scm/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ class Configuration:
fallback_root: _t.PathT = "."
write_to: _t.PathT | None = None
write_to_template: str | None = None
version_file: _t.PathT | None = None
version_file_template: str | None = None
parse: ParseFunction | None = None
git_describe_command: _t.CMD_TYPE | None = None
dist_name: str | None = None
Expand Down
50 changes: 38 additions & 12 deletions src/setuptools_scm/_get_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import re
import warnings
from pathlib import Path
from typing import Any
from typing import NoReturn
from typing import Pattern
Expand Down Expand Up @@ -41,25 +42,48 @@ def _do_parse(config: Configuration) -> ScmVersion | None:
)


def _get_version(config: Configuration) -> str | None:
parsed_version = _do_parse(config)
if parsed_version is None:
return None
version_string = _format_version(
parsed_version,
version_scheme=config.version_scheme,
local_scheme=config.local_scheme,
)
def write_version_files(
config: Configuration, version: str, scm_version: ScmVersion
) -> None:
if config.write_to is not None:
from ._integration.dump_version import dump_version

dump_version(
root=config.root,
version=version_string,
scm_version=parsed_version,
version=version,
scm_version=scm_version,
write_to=config.write_to,
template=config.write_to_template,
)
if config.version_file:
from ._integration.dump_version import write_version_to_path

version_file = Path(config.version_file)
assert not version_file.is_absolute(), f"{version_file=}"
# todo: use a better name than fallback root
assert config.relative_to is not None
target = Path(config.relative_to).parent.joinpath(version_file)
write_version_to_path(
target,
template=config.version_file_template,
version=version,
scm_version=scm_version,
)


def _get_version(
config: Configuration, force_write_version_files: bool = False
) -> str | None:
parsed_version = _do_parse(config)
if parsed_version is None:
return None
version_string = _format_version(
parsed_version,
version_scheme=config.version_scheme,
local_scheme=config.local_scheme,
)
if force_write_version_files:
write_version_files(config, version=version_string, scm_version=parsed_version)

return version_string

Expand All @@ -83,6 +107,8 @@ def get_version(
local_scheme: _t.VERSION_SCHEME = _config.DEFAULT_LOCAL_SCHEME,
write_to: _t.PathT | None = None,
write_to_template: str | None = None,
version_file: _t.PathT | None = None,
version_file_template: str | None = None,
relative_to: _t.PathT | None = None,
tag_regex: str | Pattern[str] = _config.DEFAULT_TAG_REGEX,
parentdir_prefix_version: str | None = None,
Expand All @@ -106,7 +132,7 @@ def get_version(
del normalize
tag_regex = parse_tag_regex(tag_regex)
config = Configuration(**locals())
maybe_version = _get_version(config)
maybe_version = _get_version(config, force_write_version_files=True)

if maybe_version is None:
_version_missing(config)
Expand Down
40 changes: 31 additions & 9 deletions src/setuptools_scm/_integration/dump_version.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
from __future__ import annotations

import warnings
from pathlib import Path

from .. import _types as _t
from .._log import log as parent_log
from .._version_cls import _version_as_tuple
from ..version import ScmVersion


log = parent_log.getChild("dump_version")

TEMPLATES = {
".py": """\
# file generated by setuptools_scm
Expand All @@ -25,27 +30,44 @@ def dump_version(
scm_version: ScmVersion | None = None,
) -> None:
assert isinstance(version, str)
# todo: assert write_to doesnt escape
write_to = Path(write_to)
assert not write_to.is_absolute(), f"{write_to=}"
target = Path(root).joinpath(write_to)
template = template or TEMPLATES.get(target.suffix)
from .._log import log
write_version_to_path(
target, template=template, version=version, scm_version=scm_version
)


def _validate_template(target: Path, template: str | None) -> str:
if template == "":
warnings.warn(f"{template=} looks like a error, using default instead")
template = None
if template is None:
template = TEMPLATES.get(target.suffix)

log.debug("dump %s into %s", version, write_to)
if template is None:
raise ValueError(
f"bad file format: {target.suffix!r} (of {target})\n"
"only *.txt and *.py have a default template"
)
version_tuple = _version_as_tuple(version)
else:
return template


def write_version_to_path(
target: Path, template: str | None, version: str, scm_version: ScmVersion | None
) -> None:
final_template = _validate_template(target, template)
log.debug("dump %s into %s", version, target)
version_tuple = _version_as_tuple(version)
if scm_version is not None:
content = template.format(
content = final_template.format(
version=version,
version_tuple=version_tuple,
scm_version=scm_version,
)

else:
content = template.format(version=version, version_tuple=version_tuple)
content = final_template.format(version=version, version_tuple=version_tuple)

with open(target, "w", encoding="utf-8") as fp:
fp.write(content)
target.write_text(content, encoding="utf-8")
3 changes: 2 additions & 1 deletion src/setuptools_scm/_integration/setuptools.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ def _assign_version(
) -> None:
from .._get_version import _get_version, _version_missing

maybe_version = _get_version(config)
# todo: build time plugin
maybe_version = _get_version(config, force_write_version_files=True)

if maybe_version is None:
_version_missing(config)
Expand Down
18 changes: 16 additions & 2 deletions testing/test_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,22 @@ def test_dump_version_works_with_pretend(
version: str, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv(PRETEND_KEY, version)
target = tmp_path.joinpath("VERSION.txt")
get_version(write_to=target)
name = "VERSION.txt"
target = tmp_path.joinpath(name)
get_version(root=tmp_path, write_to=name)
assert target.read_text() == version


def test_dump_version_modern(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
version = "1.2.3"
monkeypatch.setenv(PRETEND_KEY, version)
name = "VERSION.txt"

project = tmp_path.joinpath("project")
target = project.joinpath(name)
project.mkdir()

get_version(root="..", relative_to=target, version_file=name)
assert target.read_text() == version


Expand Down

0 comments on commit 4e4aa28

Please sign in to comment.