Giter Site home page Giter Site logo

mtkennerly / dunamai Goto Github PK

View Code? Open in Web Editor NEW
300.0 3.0 25.0 405 KB

Dynamic versioning library and CLI

Home Page: https://dunamai.readthedocs.io/en/latest

License: MIT License

Python 100.00%
python versioning cli git mercurial darcs semantic-versioning subversion bazaar fossil

dunamai's People

Contributors

dbrattli avatar fabaff avatar flying-sheep avatar jonathangreen avatar jpc4242 avatar jstriebel avatar legendof-selda avatar mariusvniekerk avatar marnikow avatar mtkennerly avatar pdecat avatar riton avatar spirotot avatar wwuck avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

dunamai's Issues

Tag lookup fails when git refs contain commas

Since dunamai parses git tags by running git log --simplify-by-decoration --topo-order --decorate=full HEAD "--format=%H%d" and splitting on commas, it will fail with an unhelpful error if any tag contains a comma. For example, with the following tag list:

b8847fb838aa45b474537e0c3f8aa5f385cd3ed0 (HEAD -> refs/heads/master, tag: refs/tags/0.0.1,, tag: refs/tags/0.0.1)

Running poetry version with any poetry-dynamic-versioning config results in this error:


  RuntimeError

  Unable to determine commit offset for ref refs/tags/0.0.1, in data: {'refs/tags/0.0.1': 0}

  at ~/.local/pipx/venvs/poetry/lib/python3.6/site-packages/dunamai/__init__.py:233 in commit_offset
       229│             return self.tag_topo_lookup[self.fullref]
       230│         except KeyError:
       231│             raise RuntimeError(
       232│                 "Unable to determine commit offset for ref {} in data: {}".format(
    →  233│                     self.fullref, self.tag_topo_lookup
       234│                 )
       235│             )
       236│
       237│     @property

It's unclear what the issue is from a user perspective, and it's not obvious that the comma is a part of the tag here. It might be tricky to parse tags containing commas properly, but it would be nice if the error message at least was more helpful since we know that commas can trip things up with the way parsing is currently done.

(it seems that this behavior started happening in 1.5.1)

Style is overwritten which causes validation of format regardless if user passed parameter

style = Style.Pep440

if style == Style.Pep440:

check_version(out, style)

def check_version(version: str, style: Style = Style.Pep440) -> None:

Currently using poetry to generate version dynamically(poetry-dynamic-versioning). If Format is configured but style isn't, Format is still validated due to being overwritten on both line 678 and during method on 1788 parameter initialization. Method call on 738 never gets called as value is set before if statement on 699.

I suggest you either remove 678 to allow 699 to be called and set default value of style parameter in 1788 to None.
Or you could add an additional conditional to 678 to check if format is set to then configure the style and then set default value of style parameter in 1788 to None.

Hopefully no upstream issues by value being none.
Love the plugin
Thanks

Get rid of pkg_resources dependency

It has known performance problems and is in the process of being deprecated: pypa/setuptools_scm#513 (comment)

The time spent when importing dunamai is almost exclusively invested into pkg_resources:

$ PYTHONPROFILEIMPORTTIME=1 python -c 'import dunamai' 2>! importprofile.log
$ tuna importprofile.log

import-times

Alternatives

Detect untracked files as dirty (for git)

Hi Mathhew , first of all, thanks for for dunamai and poetry_dynamic_versioning.

One question: When working with git, have you considered detecting if untracked files are present? Or are you purposely ignoring them?

I think it would be as easy as adding this to __init__.py

       code, msg = _run_cmd("git describe --always --dirty")
       dirty = msg.endswith("-dirty")
       # above lines already in your code, just for context
       if not dirty:
         code, msg = _run_cmd("git status --porcelain=v1")
         if msg.strip() == "" #strip probably never needed but just in case
           dirty = True
       # end of my suggested changes

I can fork and create a pull request if you prefer

Unstable sha commit length

Sometimes when I use {commit} in format I get 8 characters length (in many cases I get 9 characters length).
I don't know why this is happening and how to predict the length of the sha.

Packaging Exception

Hi there,

Thanks for the cool project! I really appreciate it.

I have been testing on a small python project, but I am facing some issues when installing the package that uses dunamai for Version control. Is this supported or am I missing something ?

This is the setup.py:

from setuptools import find_packages, setup
from dunamai import Version, Style

setup(
    name="add_custom_dataplatform",
    version=Version.from_any_vcs().serialize(metadata=False, style=Style.SemVer),
    packages=find_packages()
)

It works great when I create the package or run the commands locally:

$ python setup.py sdist
...
Creating tar archive
removing 'add_custom_dataplatform-0.0.0.post40' (and everything under it)

But fails when I try to install it

$ pip install add_custom_dataplatform-0.0.0.post40.tar.gz
    ERROR: Command errored out with exit status 1:
     command: /Users/user/.virtualenvs/virtualenv/bin/python -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/wy/p3h2_r9d1kq_rv3wv25yh89r0000gp/T/pip-install-0pyil6o8/add-custom-dataplatform_ce9d669dee4947d58133cffb5e8fec5b/setup.py'"'"'; __file__='"'"'/private/var/folders/wy/p3h2_r9d1kq_rv3wv25yh89r0000gp/T/pip-install-0pyil6o8/add-custom-dataplatform_ce9d669dee4947d58133cffb5e8fec5b/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /private/var/folders/wy/p3h2_r9d1kq_rv3wv25yh89r0000gp/T/pip-pip-egg-info-1d0oahm_
         cwd: /private/var/folders/wy/p3h2_r9d1kq_rv3wv25yh89r0000gp/T/pip-install-0pyil6o8/add-custom-dataplatform_ce9d669dee4947d58133cffb5e8fec5b/
    Complete output (9 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/private/var/folders/wy/p3h2_r9d1kq_rv3wv25yh89r0000gp/T/pip-install-0pyil6o8/add-custom-dataplatform_ce9d669dee4947d58133cffb5e8fec5b/setup.py", line 6, in <module>
        version=Version.from_git().serialize(metadata=False, style=Style.SemVer),
      File "/Users/user/.virtualenvs/virtualenv/lib/python3.8/site-packages/dunamai/__init__.py", line 485, in from_git
        _detect_vcs(Vcs.Git)
      File "/Users/user/.virtualenvs/virtualenv/lib/python3.8/site-packages/dunamai/__init__.py", line 175, in _detect_vcs
        raise RuntimeError(
    RuntimeError: This does not appear to be a Git project

Please the installation works fine if I set a static version.

Version.serialize for SemVer fails after update to 1.6.0

Example:

from dunamai import Version
version = Version.from_git()
version_str = version.serialize(metadata=True, style=Style.SemVer)

Repository: https://github.com/splunk/addonfactory-ucc-generator

Traceback:

Traceback (most recent call last):
  File "/home/circleci/.venv/bin/ucc-gen", line 8, in <module>
    sys.exit(main())
  File "/home/circleci/.venv/lib/python3.7/site-packages/splunk_add_on_ucc_framework/__init__.py", line 873, in main
    _generate(args.source, args.config, args.ta_version)
  File "/home/circleci/.venv/lib/python3.7/site-packages/splunk_add_on_ucc_framework/__init__.py", line 691, in _generate
    version_str = version.serialize(metadata=True, style=Style.SemVer)
  File "/home/circleci/.venv/lib/python3.7/site-packages/dunamai/__init__.py", line 467, in serialize
    out = serialize_semver(base, pre=pre_parts, metadata=meta_parts)
  File "/home/circleci/.venv/lib/python3.7/site-packages/dunamai/__init__.py", line 1041, in serialize_semver
    check_version(serialized, Style.SemVer)
  File "/home/circleci/.venv/lib/python3.7/site-packages/dunamai/__init__.py", line 923, in check_version
    raise ValueError(failure_message)
ValueError: Version '0.3-beta.0.post.35+5a020de' does not conform to the Semantic Versioning style

dunamai 1.5.5 version:
Version(base='0.1.0', stage=None, revision=None, distance=224, commit='5a020de', dirty=True, tagged_metadata=None)

dunamai 1.6.0 version:
Version(base='0.3', stage='beta', revision=0, distance=35, commit='5a020de', dirty=True, tagged_metadata=None)

Declare dependency on pkg_resources

Hi

It looks like dunamai depends on pkg_resources which is provided by setuptools, so one needs it to be installed on the system so dynamic-poetry-versioning works.

Wrong version being reported

Using dunamai to obtain the last tag of project LinkML doesn't work correctly on a GitLab pipeline (locally runs as expected, even when using the same container image being used in the pipeline).

I'm letting git tag show me all the tags sorted (--sort) by all the possible keys and the result is always the same (1.5.2.xyz as of now). But when I use dunamai from git to get that version I obtain 1.5.0.xyz 😮.

I've already checked that the tags are annotated and that the initial commit is not tagged and empty.

I can reproduce it, but only in the pipeline, therefore debugging is a bit cumbersome... Any hints on how to diagnose the issue?

gitflow support

Would you be interested in gitflow branching model support?

image

With gitflow model, we're only tagging master/main branch.
We MAY want to get a version on develop branch as well, e.g. 0.1.0+3.1a2bc3
However, since dunamai is looking for the latest tag on the current branch, it can't locate the latest tag.

Something like:

latest_tag=`git describe --tags refs/remotes/origin/main`

commits_from_tag=`git rev-list --count $latest_tag..HEAD`
if [ $commits_from_tag = 0 ]
then
    version=$latest_tag
else
    last_commit=`git rev-parse --short HEAD`
    version=$latest_tag+$commits_from_tag.$last_commit
fi

echo "Detected version: $version"

export POETRY_DYNAMIC_VERSIONING_BYPASS=$version

Invalid selected tag when multiple tags are set on the same commit

Description

It seems that Dunamai selects the wrong tag when multiple tags are set on the same commit. When creating two tags on the same commit (e.g. v0.1.0-rc0 and v0.1.0-rc1), the first one is selected and used to create the full version. Isn't it supposed to be the opposite?

This behaviour may have appeared in the version 1.5.1 as version 1.5.0 selects the latest tag created by the user.

Reference

With version 1.5.1 (I have the same result with version 1.5.4):

test@test:~$ git tag v0.1.0-rc0
test@test:~$ git tag v0.1.0-rc1
test@test:~$ git tag -l
v0.1.0-rc0
v0.1.0-rc1
test@test:~$ git tag --merged HEAD --sort -creatordate
v0.1.0-rc1
v0.1.0-rc0
test@test:~$ dunamai from git --latest-tag
0.1.0rc0

But, with version 1.5.0 the output is different:

test@test:~$ git tag v0.1.0-rc0
test@test:~$ git tag v0.1.0-rc1
test@test:~$ git tag -l
v0.1.0-rc0
v0.1.0-rc1
test@test:~$ git tag --merged HEAD --sort -creatordate
v0.1.0-rc1
v0.1.0-rc0
test@test:~$ dunamai from git --latest-tag
0.1.0rc1

Bump fails for lazy clone (GitLab CI/CD) with `tag-branch = "master"`

Summary

The automatic bump fails with message fatal: malformed object name master when running in CD/CD, probably since there is no master available locally.

This is done automatically through the plugin, but it seems the issue originates from this package.

CI/CD output

Git checkout:

Getting source from Git repository 00:01
Fetching changes with git depth set to 20...
Initialized empty Git repository in /builds/<group>/<project>/.git/
Created fresh repository.
Checking out <hash> as detached HEAD (ref is master)...

The failure in when running poetry build with

$ poetry config repositories.gitlab ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi
$ poetry build
The command 'git for-each-ref "refs/tags/**" --merged master --format "%(refname)@{%(objectname)@{%(creatordate:iso-strict)@{%(*committerdate:iso-strict)@{%(taggerdate:iso-strict)"' returned code 128. Output:
fatal: malformed object name master

Environment

The pyproject.toml, relevant sections:

[tool.poetry-dynamic-versioning]
enable = true
vcs = "git"
style = "semver"
tag-branch = "master"
[tool.poetry-dynamic-versioning.substitution]
folders = [{ path = "src" }]

Installed versions:

poetry-dynamic-versioning[plugin] == 0.22.0
dunamai == 1.17.0
poetry == 1.5

Notes

  • I didn't experiment with git fetch, maybe there's a solution there.
  • Works if you remove tag-branch = "master" (not what we want) or,
  • Run:
    git for-each-ref "refs/tags/**" --merged remotes/origin/master ...
    instead of
    git for-each-ref "refs/tags/**" --merged master ...
    (manually), or
  • Use tag-branch = "remotes/origin/master" instead.

Maybe we could live with the last one if there's no better solution, assuming we stick with

Bump behavior different between `dunamai` and `poetry-dynamic-versioning`

Hi! I'm interested in integrating dunamai into the CI pipeline of some projects to do continuous deployment of prereleases and releases. Since my project adheres to semver, I want to use --bump to create prerelease versions rather than postrelease versions, which semver doesn't understand (this seems to be the reason --bump was introduced)

However, when I was playing around with --bump, I encountered something unexpected: running dunamai from git --style semver --bump on a tagged commit bumps to the next patch version rather than returning the tag version unchanged. Is this an intentional behavior?

When I went to look at poetry-dynamic-versioning, I noticed this in the documentation (emphasis mine):

bump: Boolean. Default: false. If true, then increment the last part of the version base by 1, unless the stage is set, in which case increment the revision by 1 or set it to a default of 2 if there was no revision. Does nothing when on a commit with a version tag.

Should this be the behavior of the dunamai library itself? I would prefer it, because it would allow me to put dunamai ... --bump in my CI scripts to produce both release and pre-release version strings.

1.16.0: pytest needs `setuptools`

Despite use poetry-core as pep517 backedn on use pytest in build env needs to be installed seuptools
Here is pytest output:

+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-dunamai-1.16.0-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-dunamai-1.16.0-2.fc35.x86_64/us
r/lib/python3.8/site-packages
+ /usr/bin/pytest -ra -m 'not network'
============================= test session starts ==============================
platform linux -- Python 3.8.16, pytest-7.2.2, pluggy-1.0.0
rootdir: /home/tkloczko/rpmbuild/BUILD/dunamai-1.16.0
collected 20 items / 1 error

==================================== ERRORS ====================================
_________________ ERROR collecting tests/unit/test_dunamai.py __________________
ImportError while importing test module '/home/tkloczko/rpmbuild/BUILD/dunamai-1.16.0/tests/unit/test_dunamai.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib64/python3.8/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
tests/unit/test_dunamai.py:3: in <module>
    import pkg_resources
E   ModuleNotFoundError: No module named 'pkg_resources'
=========================== short test summary info ============================
ERROR tests/unit/test_dunamai.py
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
=============================== 1 error in 0.59s ===============================

pkg_resources is part of ten setuptools.
That module alredy is marked as deprecated.
Recommendation: switch to importlib-metadata. Example how to do that: https://opendev.org/openstack/osprofiler/commit/e8dd381e

bump behavior different in command line and python API

using dunamai 1.19.2

Say I have a tag 1.3.0 in the current commit with a clean git. Running this:

from dunamai import Version, Pattern
Version.from_any_vcs(Pattern.DefaultUnprefixed).bump().serialize(format="{base}")

produces '1.3.1' (desired: '1.3.0')

command line: dunamai from any --pattern default-unprefixed --format "{base}" --bump correctly produces 1.3.0

Putting the bump inside serialize (emulating what the command line does) produces the correct 1.3.0.

Version.from_any_vcs(Pattern.DefaultUnprefixed).serialize(format="{base}", bump=True)

Pick up tags with / in name

When tags include / in git, dunamai doesn't see them.

Example:

git init
git commit --allow-empty -m 1 # Avoid #14 
git commit --allow-empty -m 2
git tag v1.0.0
git commit --allow-empty -m 3
git tag test/v1.0.0

dunamai from git --debug --pattern '^test/v(?P<base>\d+\.\d+\.\d+)$'
# Pattern '^test/v(?P<base>\d+\.\d+\.\d+)$' did not match any tags from ['v1.0.0']

This is because on init.py#501 has the following:

git for-each-ref "refs/tags/*'

Which in the above case returns:

refs/tags/v1.0.0

If you use (two asterisks):

git for-each-ref "refs/tags/**'

It works as expected

Request: add branch and timstamp of last commit information

Hi,

I came across this project while experimenting with poetry, and looking for automatic versioning plugin. dunamai looks great, it does (almost) what I want, and the poetry plugin works in the same way as I'm patching my packages at build time. Great!

But I miss information about the current branch and the timestamp of the last commit. In my projects I add this 2 to the version description (after the + character). Or I use the timestamp as a patch version (in YYYYMMDDhhmmss as UTC to get a monotonic patch version, e.g. 0.0.20211212113742+main.dirty). Looks ugly, but this helps the user to find the corresponding revision in the repo more easily, and gives a hint how old the version is.

Am I right,is this currently not available? Would it be possible to add this 2 attributes? I think it shouldn't be too complicated. Would be great!

Thanks,
Andi

Fix wrong version being found

@mtkennerly in #29 (comment):

I found an interesting side effect of this change when I ran the tests locally. I have Dunamai 1.5.5 installed globally, and the virtual environment has 1.6.0 because it's in pyproject.toml. The new get_version implementation finds 1.5.5 instead of the expected 1.6.0.

________________________ test__get_version__from_name _________________________

    def test__get_version__from_name() -> None:
>       assert get_version("dunamai") == Version(pkg_resources.get_distribution("dunamai").version)
E       AssertionError: assert Version(base='1.5.5', stage=None, revision=None, distance=0, commit=None, dirty=None, tagged_metadata=None) == Version(base='1.6.0', stage=None, revision=None, distance=0, commit=None, dirty=None, tagged_metadata=None)
E        +  where Version(base='1.5.5', stage=None, revision=None, distance=0, commit=None, dirty=None, tagged_metadata=None) = get_version('dunamai')
E        +  and   Version(base='1.6.0', stage=None, revision=None, distance=0, commit=None, dirty=None, tagged_metadata=None) = Version('1.6.0')
E        +    where '1.6.0' = dunamai 1.6.0 (d:\github\mtkennerly\dunamai\.venv\lib\site-packages).version
E        +      where dunamai 1.6.0 (d:\github\mtkennerly\dunamai\.venv\lib\site-packages) = <function get_distribution at 0x045AB780>('dunamai')
E        +        where <function get_distribution at 0x045AB780> = pkg_resources.get_distribution

tests\unit\test_dunamai.py:417: AssertionError

I'll look into this some more before making a new release.

Tags not found in monorepo setup

I have a monorepo with a few packages, and I am using a git tag naming scheme like packagename/v0.1.2.
Thus, I am setting pattern accordingly (adapted from the default, looking like ^packagename/v((?P<epoch>\\d+)!)?(?P<base>\\d+(\\.\\d+)*) in the middle part).

So far so good, but I found I am not getting all the tags offered with dunamai while e.g. git tag -l shows them all. My tags are like packagename1/v0.1.2, packagename2/v0.1.2, packagename3/v0.1.2, potentially all pointing to the same git hash.

Crash if there's a tag on the root commit

Description

Dunamai crashes if there's a tag on the root git commit

It seems there's a bug in git that prevents it from listing a tag in git log --simplify-by-decoration if that tag happens to be of the first commit, but the tag still appears in git tags --list. Consequently, commit_offset fails with a runtime error because the tag cannot be found.

I'll let you be the judge of whether you want to fix or wait for a proper upstream fix

Workaround

The workaround for me will be to delete my root tag. It wasn't 100% useful anyway, but I didn't expect I'd have to delete it.

Additional info

I spent 20 minutes failing to determine whether this was fixed in recent git version, or at least a known bug in git, let alone reporting it. This is an open source investement I'm not ready to make :D

Reference

$ poetry export --dev --without-hashes |grep dunamai
dunamai==1.5.4; python_version >= "3.5" and python_version < "4.0"

$ poetry run dunamai from git
Unable to determine commit offset for ref refs/tags/0.0.0 in data: {'refs/tags/1.0.3': 0, 'refs/tags/1.0.2': 1, 'refs/tags/1.0.1': 2, 'refs/tags/1.0.0': 3}

$ git tag -l
0.0.0
1.0.0
1.0.1
1.0.2
1.0.3

$ git log --simplify-by-decoration --topo-order --decorate=full HEAD "--format=%H%d"
7374a4b0e06f708a33690e358cd3750a0f5e3c02 (HEAD -> refs/heads/main, tag: refs/tags/1.0.3)
771eec2673f85cef430fb48eefccfc3653866f65 (refs/heads/fix-draft)
b4e39239ff5958fb1a83eacf2f39058cb83fb349 (refs/heads/github-actions)
b6fd6bafeb10e1d2a1a1a88a780f42f3dc4f6ab0 (tag: refs/tags/1.0.2)
8b7fa1df8b8c0cd7c7dc1d5652c5aa2922b4f3f1 (refs/heads/draft-releases)
07f5f7b0cb4d58b2aca7a7798853a10c0f0f6b0a (tag: refs/tags/1.0.1)
cc1930a90a7b030f5c4e8a47117b14d3384adc27 (tag: refs/tags/1.0.0)

Create pre instead of post versions

I've been using setuptools_scm for quite a while and dunamai/poetry-dynamic-versioning are exactly what I was looking for to migrate my projects to poetry. Almost actually as there is a big difference.

Let's start with a tag for version 0.1.0. In dunamai, the version computed after n commits will be something like 0.1.0-post<n>.dev0+<git-hash>. In setuptools_scm the version will be something like 0.1.1.dev<n>+g<git-hash>.

In my workflow the commits after putting a tag are considered as the beginning of a new version more than fixes to the previous one. In a perfect world the version would be 0.2.0.dev<n>+g<git-hash> but setuptools_scm is definitely closer to my workflow than dunamai.

using CalVer

What would be the best way to use dunamai for getting a calendar version with CalVer?

Upgrade dunamai to Python 3.6

Python 3.5 is end-of-life, and upgrading to 3.6 will allow dunamai to drop the dependency on setuptools.

Is there any need to keep 3.5 compatibility?

I will submit a PR for updating to 3.6 and removing setuptools.

Wrong PEP440 version being outputted

With a repo like this:

❯ git log --graph --decorate
* commit a6ff36f297c7468c6e68303ba2bf4e9832f60505 (HEAD, tag: v2.0.0.alpha1, origin/master, origin/HEAD, master)
| Author: Jairo Llopis <[email protected]>
| Date:   Sun Oct 31 07:34:03 2021 +0000
| 
|     v2a1
| 
* commit fde2a1107b5f2d6610227019d2679593d5677161 (tag: v2.0.0.dev1)
| Author: Jairo Llopis <[email protected]>
| Date:   Sun Oct 31 07:34:03 2021 +0000
| 
|     v2dev1
| 
* commit afd5acd645b4617968ea1089c4bf1100bfd3ea68 (tag: v1.0.0)
  Author: Jairo Llopis <[email protected]>
  Date:   Sun Oct 31 07:34:03 2021 +0000
  
      v1

You get a version like this:

❯ dunamai from git --style pep440
1.0.0.post2.dev0+a6ff36f

However packaging seems to parse the version just fine:

>>> from packaging.version import Version
>>> Version('v2.0.0.alpha1')
<Version('2.0.0a1')>

Because v2.0.0.alpha1 is a valid PEP440 version. See:

How to undo the version string into a VCS ref?

So I'm in a repo and I do this:

❯ dunamai from git --style pep440
3.0.0.post3.dev0+d929b5a

Cool!

However, would there be any way to obtain the VCS ref that I can checkout based on that version? Like a to command:

❯ dunamai to git --style pep440 3.0.0.post3.dev0+d929b5a .
v3.0.0-3-gd929b5a

That ref is something git understands and that I can pass to git checkout. Actually you can use git to get it:

❯ git describe --tags --always HEAD
v3.0.0-3-gd929b5a

Note: this example is obtained while using this repo and commit, in case it helps: Tecnativa/doodba-copier-template@d929b5a

`test__version__from_fossil` fails without home

The test__version__from_fossil test fails when there is no home set:

__________________________ test__version__from_fossil __________________________

tmp_path = PosixPath('/tmp/pytest-of-marcel/pytest-18/test__version__from_fossil0')

    @pytest.mark.skipif(shutil.which("fossil") is None, reason="Requires Fossil")
    def test__version__from_fossil(tmp_path) -> None:
        vcs = tmp_path / "dunamai-fossil"
        vcs.mkdir()
        run = make_run_callback(vcs)
        from_vcs = make_from_callback(Version.from_fossil)
        b = "trunk"

        with chdir(vcs):
>           run("fossil init repo")

tests/integration/test_dunamai.py:800:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/integration/test_dunamai.py:44: in inner
    _, out = _run_cmd(command, where=where, codes=[expected_code], env=env)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

command = 'fossil init repo'
where = PosixPath('/tmp/pytest-of-marcel/pytest-18/test__version__from_fossil0/dunamai-fossil')
codes = [0], shell = False, env = None

    def _run_cmd(
        command: str,
        where: Optional[Path],
        codes: Sequence[int] = (0,),
        shell: bool = False,
        env: Optional[dict] = None,
    ) -> Tuple[int, str]:
        result = subprocess.run(
            shlex.split(command),
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            cwd=str(where) if where is not None else None,
            shell=shell,
            env=env,
        )
        output = result.stdout.decode().strip()
        if codes and result.returncode not in codes:
>           raise RuntimeError(
                "The command '{}' returned code {}. Output:\n{}".format(
                    command, result.returncode, output
                )
            )
E           RuntimeError: The command 'fossil init repo' returned code 1. Output:
E           cannot locate home directory - please set one of the FOSSIL_HOME, XDG_CONFIG_HOME, or HOME environment variables

dunamai/__init__.py:207: RuntimeError

Please note that once I provide home (by setting HOME to /tmp) then test complains with this:

>           raise RuntimeError(
                "The command '{}' returned code {}. Output:\n{}".format(
                    command, result.returncode, output
                )
            )
E           RuntimeError: The command 'fossil init repo' returned code 1. Output:
E           cannot determine user
E           Cannot figure out who you are!  Consider using the --user
E           command line option, setting your USER environment variable,
E           or setting a default user with "fossil user default USER".

So user needs to be provided too. It looks like fossil is too picky and is unable to call getuid() :-). Nomen omen? :-)

Support getting versions from VCS at a specified directory

Although it's certainly not the best approach, it's not uncommon during development for packages to be made importable by simply adding their directory to the PYTHONPATH rather than installing them. Despite the advantages of modern editable installs I expect that the practice of modifying PYTHONPATH will persist. It seems that all of dunamai's logic for detecting versions (the Version.from_* methods) assumes that the current directory is the root, which is incompatible with packages added via PYTHONPATH. This could be overcome by using dunamai.get_version with a custom third_choice function that changes directories globally via os.chdir, but that's a fairly intrusive change to make in something like a package's __init__.py file where you might normally include dunamai code for version inference. Would it be possible to support a root or path kwarg for the from_* methods to indicate where to look for a package's git data and then use os.path.join internally to manage that without changing directories?

MRE:

(main) vyasr-dt% mkdir pkg
(main) vyasr-dt% cd pkg
(main) vyasr-dt% git init
Initialized empty Git repository in /home/vyasr/local/testing/dunamai_pythonpath/pkg/.git/
(main) vyasr-dt% echo "import dunamai" >> __init__.py
(main) vyasr-dt% echo "dunamai.get_version('pkg', third_choice=dunamai.Version.from_git)" >> __init__.py
(main) vyasr-dt% cd ..                          
(main) vyasr-dt% PYTHONPATH=${PWD}:${PYTHONPATH}
(main) vyasr-dt% cd /
(main) vyasr-dt% python -c "import pkg"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/vyasr/local/testing/dunamai_pythonpath/pkg/__init__.py", line 2, in <module>
    dunamai.get_version('pkg', third_choice=dunamai.Version.from_git)
  File "/home/vyasr/miniconda3/envs/main/lib/python3.8/site-packages/dunamai/__init__.py", line 2011, in get_version
    third_ver = third_choice()
  File "/home/vyasr/miniconda3/envs/main/lib/python3.8/site-packages/dunamai/__init__.py", line 1060, in from_git
    _detect_vcs(vcs)
  File "/home/vyasr/miniconda3/envs/main/lib/python3.8/site-packages/dunamai/__init__.py", line 355, in _detect_vcs
    raise RuntimeError(
RuntimeError: This does not appear to be a Git project

sdist is missing tests

The sdist package at PyPI is missing tests. Please add tests to sdist to make downstream testing easier. Thank you.

Does not find new tags (made on same day?)

Found this super useful tool via poetry-dynamic-versioning.

However, after working the first time, subsequent builds failed to add the patch version, instead adding revisions to my first patch.

git describe --tags returns 0.1.4, but running dunamai from git returns 0.1.1.post8.dev0+9838662f09. Did some digging and the command I found here returns these tags:

0.1.4
0.1.3
0.1.2
v0.1.1
0.1.1

Is that the right order? This answer seems to use the same/similar syntax, but in reverse order.

--no-show-signature breaks compatibility with git 2.7

Hi, I just encountered an issue using dunamai on centos. My understanding of the issue comes from reading about the issues others have encountered eg. conventional-changelog/conventional-changelog#734. As a result, I'm not able to use poetry-dynamic-versioning.

>$ git --version
git version 2.8.3
>$ git log --no-show-signature
fatal: unrecognized argument: --no-show-signature
>$ poetry install

The command 'git log --no-show-signature -n 1 --pretty=format:"%cI"' returned code 128. Output:
fatal: unrecognized argument: --no-show-signature

Is the fix described here appropriate for this project? Or should the git required version be updated?
https://go-review.googlesource.com/c/vgo/+/127956/3/vendor/cmd/go/internal/modfetch/codehost/git.go

Thanks for your time!

`RuntimeError` when calling `Version.from_any_vcs()` in newly-cloned repository

I called Version.from_any_vcs().serialize() in a newly cloned repository (specifically https://github.com/JaimeCalzadaNOAA/adcircpy), but get error: unknown option 'merged'

(coupledmodeldriver) Orion-login-2[64] zburnett$ python
Python 3.8.2 (default, Mar 25 2020, 17:03:02)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from dunamai import Version
>>> Version.from_any_vcs().serialize()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/zburnett/miniconda3/envs/coupledmodeldriver/lib/python3.8/site-packages/dunamai/__init__.py", line 865, in from_any_vcs
    return cls._do_vcs_callback(vcs, pattern, latest_tag, tag_dir)
  File "/home/zburnett/miniconda3/envs/coupledmodeldriver/lib/python3.8/site-packages/dunamai/__init__.py", line 906, in _do_vcs_callback
    return mapping[vcs](**kwargs)
  File "/home/zburnett/miniconda3/envs/coupledmodeldriver/lib/python3.8/site-packages/dunamai/__init__.py", line 500, in from_git
    code, msg = _run_cmd(
  File "/home/zburnett/miniconda3/envs/coupledmodeldriver/lib/python3.8/site-packages/dunamai/__init__.py", line 76, in _run_cmd
    raise RuntimeError(
RuntimeError: The command 'git for-each-ref "refs/tags/*" --merged HEAD --format "%(refname)@{%(objectname)@{%(creatordate:iso-strict)@{%(*committerdate:iso-strict)@{%(taggerdate:iso-strict)"' returned code 129. Output:
error: unknown option `merged'
usage: git for-each-ref [options] [<pattern>]

    -s, --shell           quote placeholders suitably for shells
    -p, --perl            quote placeholders suitably for perl
    --python              quote placeholders suitably for python
    --tcl                 quote placeholders suitably for tcl

    --count <n>           show only <n> matched refs
    --format <format>     format to use for the output
    --sort <key>          field name to sort on

this appears to be from the following lines:

dunamai/dunamai/__init__.py

Lines 500 to 508 in 22cdbfc

code, msg = _run_cmd(
'git for-each-ref "refs/tags/*" --merged HEAD'
' --format "%(refname)'
"@{%(objectname)"
"@{%(creatordate:iso-strict)"
"@{%(*committerdate:iso-strict)"
"@{%(taggerdate:iso-strict)"
'"'
)

dunamai.Version.from_git() fails if 'v' prefix not set

If I have a repository with a version tagged 0.1.3.post1 (exemple), doing a dunamai.Version.from_git() will fail because of the missing front 'v'.
I managed to make it work in my project by doing a preliminary step:

dunamai.VERSION_SOURCE_PATTERN = r"""
    (?x)                                                        (?# ignore whitespace)
    ^v?((?P<epoch>\d+)!)?(?P<base>\d+(\.\d+)*)                  (?# v1.2.3 or v1!2000.1.2)
    ([-._]?((?P<stage>[a-zA-Z]+)[-._]?(?P<revision>\d+)?))?     (?# b0)
    (\+(?P<tagged_metadata>.+))?$                               (?# +linux)
""".strip()

Notice the '?' after the v.

Isn't a thing it should support from scratch as PEP440 does not require it ?

Note: using version 1.15.0

dunamai 1.18.0 silently does not produce version with `--strict` in CI

I recently upgraded dunamai to 1.1.18 and it started failing in my GitLab CI.

  1. It started displaying this error: Detected Git repository, but failed because of dubious ownership, so I quickly added git config --global --add safe.directory '*' to my Dockerfile as the first stackoverflow answer suggested. Not sure if this is relevant to the issue.
  2. dunamai from git --style pep440 --strict in CI is executing with exit code 0, but doesn't produce any stdout. It runs normally locally.

I'm using Docker executor with GitLab so everything is running inside Docker.

dunamai cannot parse tagged PEP 440 post-release

For a tagged PEP 440-style post-release, dunamai chops the dot off and reports that the version does not conform to PEP 440:

$ git describe --tags
v1.31.0.post1
$ git status --porcelain
$ echo $status
0
$ dunamai from git
Version '1.31.0post1' does not conform to the PEP 440 style

Change design to "operation mode"

After seeing the way dunamai is done, and problems like #32, I think there's a conceptual problem: it tries to have an input regexp to rule them all. IMHO if I'm parsing a PEP440 project, dunamai should instead:

  1. Extract latest tags.
  2. Pass them through packaging.version.Version
  3. On failure, skip the tag.
  4. When found the one closest to current commit, continue.
  5. Append .dev{commit_number}+{commit_hash} as needed.

Which of course doesn't make any sense if I'm on a semver project.

This would make its behavior more predictable, and it would save dunamai from maintaining the correct regexp (it won't work as a drop-in for dunamai, BTW).

So, instead of an input regexp and an output format, dunamai should just have a mode of operation, which affects both input and output.

calver versioning

Any chance to get you interested in adding calver versioning?
This format is used by quite a few large projects. It allows people to see a dead project really quickly.

some reference:
https://calver.org/
https://github.com/StephaneBour/actions-calver/blob/master/entrypoint.sh

imo, DDDD.M.D-patchlevel, where patch level is the number of releases if more than one were made in the same day, first release has no patch level so (DDDD.M.D aka 2023.9.3), and the third release that day would be 2023.9.3-2.

For pre-releases, as defined by pypi/pep, 2023.9.2-SHORTHASH (git)

I dont think there is an easy way to make this project (and by extension poetry-dynaminc-versioning) create and manage versions for this format. currently I am going to get the version from calver and use it to set versions and then commit with the release message and build/push. Its a lot of moving parts that I would rather do right in poetry.

Allow easy generation of preversion

Hello,

This is linked to !2, I would like to easily generated preversion instead of postversion.

From what I understand, post version is not supported by semver 2.0.
If we are 5 commits ahead of version 1.2.3, dunamai generate:

$ dunamai from any --no-metadata --style semver
1.2.3-post.3

while Semver would require (to my understanding) a version such as 1.2.4-pre.3. This is important since some implementation might put 1.2.3-post.3 actually before 1.2.3.

Would it be possible to add an option to the command line argument to prefer .pre instead of .post.

Today I manage to have this behavior in my poetry package (V.post allowed but I prefer to stick with what PBR do, like (V+1).devX), with a jinja template:

format-jinja = """
    {%- if distance == 0 -%}
        {{ serialize_pep440(base, stage, revision) }}
    {%- elif revision is not none -%}
        {{ serialize_pep440(base, stage, revision + 1, dev=distance) }}
    {%- else -%}
        {{ serialize_pep440(bump_version(base), stage, revision, dev=distance) }}
    {%- endif -%}
"""

but this is easy to do in command line.
thanks

Documentation for output substitutions

Two thoughts around documentation...

Something I've struggled with a couple times here is knowing what options are available for substitutions in the custom output format and knowing what exactly each one mean. The list is available in the help (dunamai from any --help), but it'd be nice if it was also available here in the README, with an explanation of what each substitution means.

It's also unclear from the documentation as to whether or not substitutions are always included or if some substitutions would be omitted if the distance from a base tag is 0. (If not, that might be an interesting feature - defining an optional portion of a custom format...)

I'd be happy to make a PR to update the docs if you're interested.

unrecognized argument: --decorate-refs=refs/tags/*

We just recently started seeing this error and I have not yet concluded that it's because of the recent dunamai release, but I suspect it can be related so I am just quickly writing this ticket here:

$ poetry install -v --no-root

...

[RuntimeError]
The command 'git log --simplify-by-decoration --topo-order --decorate=full "--decorate-refs=refs/tags/*" HEAD "--format=%H%d"' returned code 128. Output:
fatal: unrecognized argument: --decorate-refs=refs/tags/*

This is with:

  • poetry==1.0.10
  • poetry-dynamic-versioning==0.9.0

Workflow question

Hey there, thanks for this project!

The past time I've been slowly trying to learn about Python packaging, continuous integration, and other various things. As part of that I'm moving some of my projects to poetry. For versioning I am using your library. I've used versioneer in the past.

My question regards to workflow, version numbers are automatically fetched from the closest parent tag in the commit graph (if I understand correctly). However this means I must first tag before using the commands to update my version in pyproject.toml and my projects _version.py.

The problem here is that the tag needs to include the changes to these files so my current flow is mostly to tag a version, then update those files, then delete/re-tag and commit/push.

Is there a more sane way of doing this? I've seen the runtime dependency which would work for at least _version.py but not for pyproject.toml.

How do you do this?

Could not properly parse with Version.parse

Looks like Version.parse could not properly parse

A minimal working example showing mentioned behaviour is:
dunamai.Version.parse(dunamai.Version.from_git().serialize())

result of the following command:

{
    "base": "0.0.0.post341.dev0+5d7b186",
    "stage": None,
    "revision": None,
    "distance": 0,
    "commit": None,
    "dirty": None,
    "tagged_metadata": None,
    "epoch": None,
    "branch": None,
    "timestamp": None,
    "_matched_tag": None,
    "_newer_unmatched_tags": None
}

From what i get, it should parse (since by default it uses Pattern.DEFAULT) to something like:

{
    "base": "0.0.0",
    "stage": None,
    "revision": None,
    "distance": 341,
    "commit": "5d7b186",
    "dirty": True,
    "tagged_metadata": None,
    "epoch": None,
    "branch": None,
    "timestamp": None,
    "_matched_tag": None,
    "_newer_unmatched_tags": None
}

Always assumes repo is tagged using SemVer

See this session:

❯ git init .

❯ touch a

❯ git add -A

❯ git commit -amwip
[master (commit-raíz) dfbff1f] wip
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a

❯ git tag v1

❯ dunamai from git --style pep440
Pattern '(?x)                                                (?# ignore whitespace)
    ^v(?P<base>\d+\.\d+\.\d+)                           (?# v1.2.3)
    (-?((?P<stage>[a-zA-Z]+)\.?(?P<revision>\d+)?))?    (?# b0)
    (\+(?P<tagged_metadata>.+))?$                       (?# +linux)' did not match any tags from ['v1']

It seems that even when I add --style pep440 to the command, dunamai only tries to find tags formatted with semver, because it's using this regexp:

_VERSION_PATTERN = r"""
(?x) (?# ignore whitespace)
^v(?P<base>\d+\.\d+\.\d+) (?# v1.2.3)
(-?((?P<stage>[a-zA-Z]+)\.?(?P<revision>\d+)?))? (?# b0)
(\+(?P<tagged_metadata>.+))?$ (?# +linux)
""".strip()

With that regexp for example, these tags would fail:

  • 1
  • v1
  • v1.0
  • 1.2.3
  • 0.1.0.1
  • 1.2.3.alpha1.post4.dev3

So I think that it should:

  1. prefix v be optional
  2. add a specific regex for each versioning system

As a workaround, there's the possibility to pass a custom pattern if running from python:

dunamai/dunamai/__init__.py

Lines 851 to 857 in 14a9891

:param pattern: Regular expression matched against the version source.
This must contain one capture group named `base` corresponding to
the release segment of the source. Optionally, it may contain another
two groups named `stage` and `revision` corresponding to a prerelease
type (such as 'alpha' or 'rc') and number (such as in 'alpha-2' or 'rc3').
It may also contain a group named `tagged_metadata` corresponding to extra
metadata after the main part of the version (typically after a plus sign).

Possibly misleading vcs check message for git

Git introduced stricter repository ownership checks. When the check fails, git status fails:

$ git status
fatal: detected dubious ownership in repository at '/path/redacted'
To add an exception for this directory, call:
	git config --global --add safe.directory /path/redacted

When using dunamai (via poetry-dynamic-versioning), this is replaced with:
This does not appear to be a Git project

Having the original error message or having this specific error mapped to a more detailed error message would make debugging this easier. Happy to add a pull merge request with preferred approach.

PS. Thank you for your packages, poetry-dynamic-versioning makes my life easier 👍

Git version detection fails if `log.excludeDecoration = refs/tags` set in git config

We have some engineers that have log.excludeDecoration = refs/tags set in their .gitconfig since we have some repos with a large number of tags.

These same engineers would attempt to install a Python package that uses poetry-dynamic-versioning and dunamai and get a failure like RuntimeError: Unable to determine commit offset for ref refs/tags/v1.0.0 in data: {}.

After some digging, we found that with tags excluded from the logs, _GitRefInfo.from_git_tag_topo_order can't find any tags, leading to the RuntimeError.

I think a fix could be to switch to use the git rev-list plumbing command instead of the git log porcelain command. Happy to take a crack at a PR if that approach makes sense.

git tag : x.y.z and pep440 not compatible ?

Hi,

We are migrating from versioneer.

We tag our repo with the number format of X.Y.Z

$ git tag
1.2.3

However, when querying with dunamai, I get a pattern error

I have tried both

dunamai from git

and

dunamai from git --style pep440

Both times, I got the following message

Pattern '(?x)                                                        (?# ignore whitespace)
    ^v((?P<epoch>\d+)!)?(?P<base>\d+(\.\d+)*)                   (?# v1.2.3 or v1!2000.1.2)
    ([-._]?((?P<stage>[a-zA-Z]+)[-._]?(?P<revision>\d+)?))?     (?# b0)
    (\+(?P<tagged_metadata>.+))?$                               (?# +linux)' did not match any tags from ['1.2.3']

In addition, I would like to retrieve the version not on the commandline but within the setup.py so I would need to make the query with the dunamai module via the API itself.

Cheers

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.