Skip to content

Missing documentation for calver #725

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
kasium opened this issue Jun 22, 2022 · 18 comments
Open

Missing documentation for calver #725

kasium opened this issue Jun 22, 2022 · 18 comments

Comments

@kasium
Copy link

kasium commented Jun 22, 2022

I found out that this project supports calver (e.g. calver-by-date) but these options are not documented

@huxuan
Copy link
Member

huxuan commented Jul 28, 2023

Hi buddies, any quick start for how to use it?

@RonnyPfannschmidt
Copy link
Contributor

Starting point is to use one of the Calver named Version shemes as per the readme

The documentation rework in #880 will eventually provide better examples

@huxuan
Copy link
Member

huxuan commented Jul 28, 2023

I tried to change the version_scheme to calver-by-date, but seems it will still use the git tag when the repo is clean. So maybe the problem is what is the best practice to use calver. It might also including how to manage git tags or even the migration from normal semver to calver.

@RonnyPfannschmidt
Copy link
Contributor

Current behavior is that on exact tags The Tag wins

@jziolkowski
Copy link

I'm either blind or the docs are still missing for this?

Basically I wonder if/how can I achieve this:

vYYYY.MM.<sequence>[.devX]

@RonnyPfannschmidt
Copy link
Contributor

@jziolkowski this would be something called "calver-by-month" its currently not implemented

_DATE_REGEX = re.compile(
r"""
^(?P<date>
(?P<prefix>[vV]?)
(?P<year>\d{2}|\d{4})(?:\.\d{1,2}){2})
(?:\.(?P<patch>\d*))?$
""",
re.VERBOSE,
)
def date_ver_match(ver: str) -> Match[str] | None:
return _DATE_REGEX.match(ver)
def guess_next_date_ver(
version: ScmVersion,
node_date: date | None = None,
date_fmt: str | None = None,
version_cls: type | None = None,
) -> str:
"""
same-day -> patch +1
other-day -> today
distance is always added as .devX
"""
match = date_ver_match(str(version.tag))
if match is None:
warnings.warn(
f"{version} does not correspond to a valid versioning date, "
"assuming legacy version"
)
if date_fmt is None:
date_fmt = "%y.%m.%d"
else:
# deduct date format if not provided
if date_fmt is None:
date_fmt = "%Y.%m.%d" if len(match.group("year")) == 4 else "%y.%m.%d"
if prefix := match.group("prefix"):
if not date_fmt.startswith(prefix):
date_fmt = prefix + date_fmt
today = version.time.date()
head_date = node_date or today
# compute patch
if match is None:
tag_date = today
else:
tag_date = (
datetime.strptime(match.group("date"), date_fmt)
.replace(tzinfo=timezone.utc)
.date()
)
if tag_date == head_date:
patch = "0" if match is None else (match.group("patch") or "0")
patch = int(patch) + 1
else:
if tag_date > head_date and match is not None:
# warn on future times
warnings.warn(
f"your previous tag ({tag_date})"
f" is ahead your node date ({head_date})"
)
patch = 0
next_version = "{node_date:{date_fmt}}.{patch}".format(
node_date=head_date, date_fmt=date_fmt, patch=patch
)
# rely on the Version object to ensure consistency (e.g. remove leading 0s)
if version_cls is None:
version_cls = PkgVersion
next_version = str(version_cls(next_version))
return next_version
def calver_by_date(version: ScmVersion) -> str:
if version.exact and not version.dirty:
return version.format_with("{tag}")
# TODO: move the release-X check to a new scheme
if version.branch is not None and version.branch.startswith("release-"):
branch_ver = _parse_version_tag(version.branch.split("-")[-1], version.config)
if branch_ver is not None:
ver = branch_ver["version"]
match = date_ver_match(ver)
if match:
return ver
return version.format_next_version(
guess_next_date_ver,
node_date=version.node_date,
version_cls=version.config.version_cls,
)
implements it for `vYYYY.MM.DD.{sequence}[.devX]

im open to adoption it to support calver-by-month but i cant implement it myself soon

@lebrice
Copy link

lebrice commented Feb 26, 2025

Hey there @RonnyPfannschmidt , I wasn't able to find instructions on setting up setuptools-csm with calver versions like you described (vYYYY.MM.DD.{sequence}.[devX]). Is it possible to set this up using only configuration options in a pyproject.toml, or would I need to do some runtime stuff in a setup.py script?

@RonnyPfannschmidt
Copy link
Contributor

[tool.setuptools_scm]
version_scheme = "calver-by-date"

https://github.com/pypa/setuptools-scm/blob/main/pyproject.toml#L103

i need to add the docs

@WojciechMigda
Copy link

I tried using calver-by-date today (2025-03-10) and the version produced for package being built has 25.3.9 string in it.
If possible, how can I configure setuptools_scm:
1). to give patch number which equals current day, 10, instead of 9?
2). to have month and day numbers 0-padded, e.g. 03.10, to facilitate sorting?
3). have year value as 2025 instead of 25?
In setuptools_scm source code I can see mentions of date_fmt and same-day / other-day, but it is not obvious if I can (and how) use these options in my pyproject.toml.
Thank you!

@RonnyPfannschmidt
Copy link
Contributor

The commit date is used else artifacts from archives/checkouts of old commits would report the wrong date

It's necessary to disable version normalization to get padding as by default the python ecosystem strips leading zeroes

@WojciechMigda
Copy link

Oh, I see. As for date format, is it possible to customize it?

@WojciechMigda
Copy link

WojciechMigda commented Mar 11, 2025

As for date format, is it possible to customize it?

I figured it out myself! I followed docs/examples/version_scheme_code:

in setup.py

def myversion_func(version: ScmVersion) -> str:
    from setuptools_scm.version import guess_next_date_ver

    return version.format_next_version(
        guess_next_date_ver,
        node_date=version.node_date,
        date_fmt='%Y.1%m.1%d',
        version_cls=version.config.version_cls,
    )

if __name__ == "__main__":
    setup(use_scm_version={"version_scheme": myversion_func})

in pyproject.toml

[tool.setuptools_scm]
local_scheme = "node-and-timestamp"
#version_scheme = "calver-by-date"
root = "../../"

@WojciechMigda
Copy link

I am afraid 8.2.1 release has regression which breaks the above code of mine. I just ran into package build problems manifested by:

$ python3 -m build .
* Creating isolated environment: venv+pip...
* Installing packages in isolated environment:
  - setuptools>=61.0
  - setuptools_scm>=7.1
* Getting build dependencies for sdist...
/tmp/build-env-iixu5wsj/lib/python3.12/site-packages/setuptools_scm/_integration/setuptools.py:92: UserWarning: version of None already set
  warnings.warn(f"version of {dist_name} already set")

This manifests itself in the package version being overriden and set to 0.1.

When I pin setuptools_scm version to 8.2.0 everything works as expected and the version is set to the one calculated by code in my previous post.

@RonnyPfannschmidt
Copy link
Contributor

what version of setuptools is in use there?

@RonnyPfannschmidt
Copy link
Contributor

the output with SETUPTOOLS_SCM_DEBUG woudl help

@WojciechMigda
Copy link

python3.12, built from source
setuptools installed: 75.6.0
setuptools pulled during package build: 77.0.3

@WojciechMigda
Copy link

As for SETUPTOOLS_SCM_DEBUG do you need something specific from the output? It is much more verbose.

@WojciechMigda
Copy link

The first significant difference between the two outputs is in this fragment:

8.2.0:

DEBUG setuptools_scm.version config Configuration(relative_to='pyproject.toml', root='../../', version_scheme=<function calver_func at 0x7f8c4e299120>, local_scheme='node-and-timestamp', tag_regex=re.compile('^(?:[\\w-]+-)?(?P<version>[vV]?\\d+(?:\\.\\d+){0,2}[^\\+]*)(?:\\+.*)?$'), parentdir_prefix_version=None, fallback_version=None, fallback_root='.', write_to=None, write_to_template=None, version_file=None, version_file_template=None, parse=None, git_describe_command=None, dist_name='REDACTED', version_cls=<class 'packaging.version.Version'>, search_parent_directories=False, parent=PosixPath('/repo/REDACTED'))
/tmp/build-env-k155emaw/lib/python3.12/site-packages/setuptools_scm/version.py:352: UserWarning: <ScmVersion 0.0 dist=792 node=g80bd93c dirty=False branch=main> does not correspond to a valid versioning date, assuming legacy version
  warnings.warn(
DEBUG setuptools_scm.version version 2025.103.120.1.dev792
DEBUG setuptools_scm.entrypoints ep found: node-and-timestamp
DEBUG setuptools_scm.version local_version +g80bd93c
DEBUG setuptools_scm._integration.setuptools infer_version {'name': None, 'version': '2025.103.120.1.dev792+g80bd93c', 'author': None, 'author_email': None, 'maintainer': None, 'maintainer_email': None, 'url': None, 'license': None, 'description': None, 'long_description': None, 'keywords': None, 'platforms': None, 'classifiers': None, 'download_url': None, 'provides': None, 'requires': None, 'obsoletes': None}

8.2.1:

DEBUG setuptools_scm.version config Configuration(relative_to='pyproject.toml', root='../../', version_scheme='guess-next-dev', local_scheme='node-and-timestamp', tag_regex=re.compile('^(?:[\\w-]+-)?(?P<version>[vV]?\\d+(?:\\.\\d+){0,2}[^\\+]*)(?:\\+.*)?$'), parentdir_prefix_version=None, fallback_version=None, fallback_root='.', write_to=None, write_to_template=None, version_file=None, version_file_template=None, parse=None, git_describe_command=None, dist_name='REDACTED', version_cls=<class 'packaging.version.Version'>, search_parent_directories=False, parent=PosixPath('/repo/REDACTED'))
DEBUG setuptools_scm.entrypoints ep found: guess-next-dev
DEBUG setuptools_scm.version version 0.1.dev792
DEBUG setuptools_scm.entrypoints ep found: node-and-timestamp
DEBUG setuptools_scm.version local_version +g80bd93c.d20250320212736
DEBUG setuptools_scm._integration.setuptools version_keyword {'name': None, 'version': '0.1.dev792+g80bd93c.d20250320212736', 'author': None, 'author_email': None, 'maintainer': None, 'maintainer_email': None, 'url': None, 'license': None, 'description': None, 'long_description': None, 'keywords': None, 'platforms': None, 'classifiers': None, 'download_url': None, 'provides': None, 'requires': None, 'obsoletes': None}

So with 8.2.0 user-provided function is used for version_scheme (calver_func), while 8.2.1 uses guess-next-dev.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants