Skip to content

feat(version): append +dev suffix for non-release builds#99

Merged
igoropaniuk merged 1 commit into
mainfrom
feat/version_dev_suffix
May 24, 2026
Merged

feat(version): append +dev suffix for non-release builds#99
igoropaniuk merged 1 commit into
mainfrom
feat/version_dev_suffix

Conversation

@igoropaniuk

Copy link
Copy Markdown
Owner

A wheel install from PyPI ships only the static version recorded in pyproject.toml, so stonks --version from a release looks like 0.6.3. Source checkouts (pip install -e . against a git working tree, or uv sync in a clone) have no such cue, and users running an in-progress build look identical to release users when filing bug reports.

Detect source checkouts by looking for a .git directory next to the src/ tree and, when present, append a PEP 440 local-version suffix derived from git describe --tags --always --dirty=.dirty:

  • exact tag, clean tree -> 0.6.3
  • exact tag, dirty tree -> 0.6.3+dirty
  • past tag, clean tree -> 0.6.3+dev.<N>.g<sha>
  • past tag, dirty tree -> 0.6.3+dev.<N>.g<sha>.dirty
  • no reachable tag -> 0.6.3+dev.<sha>[.dirty]

Failures (missing git, timeout, repo not present) silently drop back to the bare version so PyPI / wheel installs never pay for the probe and never carry the suffix.

doctor._version_tuple is updated to strip the local-version segment before parsing so a dev build of 0.6.3 still compares equal to PyPI's 0.6.3, instead of collapsing to (0, 6) and triggering a spurious "out of date" warning.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces dynamic versioning for source checkouts by appending PEP 440 local-version suffixes derived from git metadata. It also modifies the version parsing logic in the doctor module to correctly handle these suffixes during version comparisons and adds a comprehensive test suite. Feedback suggests enhancing the tag detection logic to support both 'v'-prefixed and non-prefixed git tags.

Comment on lines +58 to +71
tag_prefix = f"v{base}"
# Exactly on the release tag with a clean tree -- no suffix needed.
if desc == tag_prefix:
return ""
# On the release tag with uncommitted changes.
if desc == f"{tag_prefix}.dirty":
return "+dirty"
# Past the release tag: "v0.6.3-2-gabc1234[.dirty]" -> "+dev.2.gabc1234[.dirty]"
if desc.startswith(f"{tag_prefix}-"):
rest = desc[len(tag_prefix) + 1 :]
return f"+dev.{rest.replace('-', '.')}"
# No reachable matching tag (shallow clone, different tag, etc.) --
# fall back to whatever git describe returned, normalized for PEP 440.
return f"+dev.{desc.replace('-', '.')}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation assumes that git tags always have a v prefix (e.g., v0.6.3). While common, some repositories use tags without the prefix (e.g., 0.6.3). Making this check more robust by supporting both formats ensures the version string remains clean even if the tagging convention changes or differs from the assumption.

Suggested change
tag_prefix = f"v{base}"
# Exactly on the release tag with a clean tree -- no suffix needed.
if desc == tag_prefix:
return ""
# On the release tag with uncommitted changes.
if desc == f"{tag_prefix}.dirty":
return "+dirty"
# Past the release tag: "v0.6.3-2-gabc1234[.dirty]" -> "+dev.2.gabc1234[.dirty]"
if desc.startswith(f"{tag_prefix}-"):
rest = desc[len(tag_prefix) + 1 :]
return f"+dev.{rest.replace('-', '.')}"
# No reachable matching tag (shallow clone, different tag, etc.) --
# fall back to whatever git describe returned, normalized for PEP 440.
return f"+dev.{desc.replace('-', '.')}"
# Handle both 'v1.2.3' and '1.2.3' tag formats
for prefix in (f"v{base}", base):
if desc == prefix:
return ""
if desc == f"{prefix}.dirty":
return "+dirty"
if desc.startswith(f"{prefix}-"):
rest = desc[len(prefix) + 1 :]
return f"+dev.{rest.replace('-', '.')}"
# No reachable matching tag (shallow clone, different tag, etc.) --
# fall back to whatever git describe returned, normalized for PEP 440.
return f"+dev.{desc.replace('-', '.')}"

A wheel install from PyPI ships only the static version recorded in
pyproject.toml, so ``stonks --version`` from a release looks like
``0.6.3``.  Source checkouts (``pip install -e .`` against a git
working tree, or ``uv sync`` in a clone) have no such cue, and users
running an in-progress build look identical to release users when
filing bug reports.

Detect source checkouts by looking for a ``.git`` directory next to the
``src/`` tree and, when present, append a PEP 440 local-version suffix
derived from ``git describe --tags --always --dirty=.dirty``:

* exact tag, clean tree            -> ``0.6.3``
* exact tag, dirty tree            -> ``0.6.3+dirty``
* past tag, clean tree             -> ``0.6.3+dev.<N>.g<sha>``
* past tag, dirty tree             -> ``0.6.3+dev.<N>.g<sha>.dirty``
* no reachable tag                 -> ``0.6.3+dev.<sha>[.dirty]``

Failures (missing git, timeout, repo not present) silently drop back
to the bare version so PyPI / wheel installs never pay for the probe
and never carry the suffix.

``doctor._version_tuple`` is updated to strip the local-version
segment before parsing so a dev build of 0.6.3 still compares equal
to PyPI's 0.6.3, instead of collapsing to ``(0, 6)`` and triggering a
spurious "out of date" warning.

Signed-off-by: Igor Opaniuk <igor.opaniuk@gmail.com>
@igoropaniuk igoropaniuk force-pushed the feat/version_dev_suffix branch from a215a52 to d3b642c Compare May 24, 2026 10:32
@codecov

codecov Bot commented May 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.93939% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/stonks_cli/__init__.py 93.54% 1 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@igoropaniuk igoropaniuk merged commit badc325 into main May 24, 2026
10 checks passed
@igoropaniuk igoropaniuk deleted the feat/version_dev_suffix branch May 24, 2026 11:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant