Skip to content

Commit

Permalink
Add new dynamic_version option
Browse files Browse the repository at this point in the history
  • Loading branch information
amyreese committed Oct 26, 2024
1 parent 7ee1f03 commit 083520c
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 2 deletions.
25 changes: 25 additions & 0 deletions attribution/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,28 @@
"""

__version__ = "1.8.0"

try:
import re
import subprocess
from pathlib import Path

version_suffix = "+dev"
path = Path(__file__).resolve().parent
while path != path.parent:
if (path / ".git").is_dir():
proc = subprocess.run(
("git", "describe"), text=True, capture_output=True, check=True
)
if match := re.search(r"-(\d+)-(g[a-f0-9]+)$", proc.stdout):
count, ref = match.groups()
version_suffix = f"+dev{count}-{ref}"
break

path = path.parent

except Exception as e:
print(f"version suffix failed: {e}")

finally:
__version__ += version_suffix
39 changes: 39 additions & 0 deletions attribution/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,45 @@ class VersionFile(GeneratedFile):
'''


class DynamicVersionFile(GeneratedFile):
FILENAME = "{project.package}/__version__.py"
TEMPLATE = '''\
"""
This file is automatically generated by attribution.
Do not edit manually. Get more info at https://attribution.omnilib.dev
"""
__version__ = "{{ project.latest.version }}"
try:
import re
import subprocess
from pathlib import Path
version_suffix = "+dev"
path = Path(__file__).resolve().parent
while path != path.parent:
if (path / ".git").is_dir():
proc = subprocess.run(
("git", "describe"), text=True, capture_output=True, check=True
)
if match := re.search(r"-(\\d+)-(g[a-f0-9]+)$", proc.stdout):
count, ref = match.groups()
version_suffix = f"+dev{count}-{ref}"
break
path = path.parent
except Exception as e:
print(f"version suffix failed: {e}")
finally:
__version__ += version_suffix
'''


class CargoFile(GeneratedFile):
EXPECTS = ("package_name", "package_dir")
FILENAME = "{package_dir}/Cargo.toml"
Expand Down
19 changes: 17 additions & 2 deletions attribution/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import tomlkit

from attribution import __version__
from .generate import CargoFile, Changelog, NpmFile, VersionFile
from .generate import CargoFile, Changelog, DynamicVersionFile, NpmFile, VersionFile
from .helpers import sh
from .project import Project
from .tag import Tag
Expand All @@ -37,6 +37,12 @@ def init() -> None:
version_file = click.confirm(
"Use __version__.py file", default=project.config["version_file"]
)
dynamic_version = False
if version_file:
dynamic_version = click.confirm(
"Use dynamic version suffix (eg. '1.0+git4-gabc123')",
default=project.config["dynamic_version"],
)
signed_tags = click.confirm(
"Use GPG signed tags", default=project.config["signed_tags"]
)
Expand Down Expand Up @@ -66,13 +72,17 @@ def init() -> None:
table["package"] = package
table["signed_tags"] = signed_tags
table["version_file"] = version_file
table["dynamic_version"] = dynamic_version

project.pyproject_path().write_text(tomlkit.dumps(pyproject))

# pick up any changes
project = Project.load()
if version_file:
VersionFile(project).write()
if dynamic_version:
DynamicVersionFile(project).write()
else:
VersionFile(project).write()


@main.command("debug")
Expand Down Expand Up @@ -186,6 +196,11 @@ def tag_release(version: Version, message: Optional[str]) -> None:
sh("git commit --amend --no-edit")
tag.update(message=message, signed=project.config["signed_tags"])

if project.config.get("dynamic_version"):
path = DynamicVersionFile(project).write()
sh(f"git add {path}")
sh("git commit -m 'Dynamic version file'")

except Exception:
mfile = Path(f".attribution-{version}.txt").resolve()
mfile.write_text(message)
Expand Down
1 change: 1 addition & 0 deletions attribution/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ def load(cls, path: Optional[Path] = None) -> "Project":
"ignored_authors": [],
"version_file": True,
"signed_tags": True,
"dynamic_version": False,
}

if cls.pyproject_path(path).is_file():
Expand Down
6 changes: 6 additions & 0 deletions attribution/tests/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ def test_load(self, cwd_mock):
"cargo_packages": [],
"ignored_authors": [],
"version_file": True,
"dynamic_version": False,
"signed_tags": True,
},
)
Expand All @@ -181,6 +182,7 @@ def test_load(self, cwd_mock):
"cargo_packages": [],
"ignored_authors": [],
"version_file": True,
"dynamic_version": False,
"signed_tags": True,
},
)
Expand All @@ -197,6 +199,7 @@ def test_load(self, cwd_mock):
"cargo_packages": [],
"ignored_authors": [],
"version_file": True,
"dynamic_version": False,
"signed_tags": True,
},
)
Expand All @@ -213,6 +216,7 @@ def test_load(self, cwd_mock):
"cargo_packages": [],
"ignored_authors": [],
"version_file": False,
"dynamic_version": False,
"signed_tags": True,
},
)
Expand All @@ -228,6 +232,7 @@ def test_load(self, cwd_mock):
"cargo_packages": [],
"ignored_authors": [],
"version_file": True,
"dynamic_version": False,
"signed_tags": True,
},
)
Expand All @@ -243,6 +248,7 @@ def test_load(self, cwd_mock):
"cargo_packages": [],
"ignored_authors": [],
"version_file": True,
"dynamic_version": False,
"signed_tags": True,
},
)
16 changes: 16 additions & 0 deletions docs/guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,22 @@ Options available are described as follows:
to not have a managed ``__version__.py`` file, this value should be set to
``false``.

.. attribute:: dynamic_version
:type: bool
:value: False

Enables generating a dynamic ``__version__.py`` that generates version
suffixes based on the local repository's revision relative to the last
release. When a release is tagged, a static version file is committed,
without the dynamic suffix logic, before tagging the version bump, and
then the dynamic version file is reinstated after the release is tagged.

If the project's git revision can be queried, then the dynamic version
string will look like ``1.8.0+dev6-g3c61fc2``. Otherwise, the version
string will fall back to the generic form ``1.8.0+dev``.

Requires enabling :attr:`version_file`.


Alternative Packaging
^^^^^^^^^^^^^^^^^^^^^
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ ignored_authors = ["dependabot[bot]", "pyup.io bot"]
version_file = true
signed_tags = true
cargo_packages = ["fake_crate"]
dynamic_version = true

[tool.coverage.run]
branch = true
Expand Down

0 comments on commit 083520c

Please sign in to comment.