Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ jobs:
exit 1
fi

- name: Write release date into package
if: github.event_name == 'push'
run: |
RELEASE_DATE=$(git log -1 --format=%cs)
printf '"""Generated by the release workflow. Do not edit."""\n\nRELEASE_DATE = "%s"\n' "$RELEASE_DATE" > solarfarmer/_release_info.py
cat solarfarmer/_release_info.py

- name: Build package
run: uv build --sdist --wheel --out-dir dist/

Expand All @@ -54,7 +61,7 @@ jobs:

- name: Verify package imports and list installed sizes
run: |
PYTHONPATH=./tmp_install uv run python -c "import solarfarmer; print(solarfarmer.__version__)"
PYTHONPATH=./tmp_install uv run python -c "import solarfarmer; from solarfarmer.__version__ import __released__; print(solarfarmer.__version__, __released__)"
du -h solarfarmer
working-directory: ./tmp_install

Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ venv/
build/
dist/
*.egg-info/
# Generated by the release workflow at build time
solarfarmer/_release_info.py
*.egg
.eggs/

Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
"Narrow your search" message (e.g. `eff=9860.0%` is now `eff=98.6%`).
- `PVSystem.payload_to_file()` now writes indented JSON instead of a single compact line, and keeps
non-ASCII characters (e.g. in module or inverter file names) instead of escaping them as `\uXXXX`.
- `solarfarmer.__version__` no longer returns `"unknown"` for pip-installed packages; it now reads the
metadata of the `dnv-solarfarmer` distribution.
- `__released__` now reports the release date of installed wheels instead of `"unreleased"` or the tag
date of whichever git repository the user's working directory belonged to.

## [0.7.0] - 2026-10-07

Expand Down
50 changes: 37 additions & 13 deletions solarfarmer/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

This module provides version information with the following fallback chain:
- __version__: Package metadata → pyproject.toml → "unknown"
- __released__: Most recent git tag date → "unreleased" (development)
- __released__: Build-time ``_release_info.py`` → SDK repo's latest git tag date → "unreleased"
"""

__all__ = ["__version__", "__released__"]

# Distribution name on PyPI (differs from the import package name "solarfarmer")
_DISTRIBUTION_NAME = "dnv-solarfarmer"


def _get_version():
"""Get version from package metadata, fallback to pyproject.toml for development.
Expand All @@ -18,7 +21,7 @@ def _get_version():
try:
from importlib.metadata import version

return version("solarfarmer")
return version(_DISTRIBUTION_NAME)
except Exception:
pass

Expand Down Expand Up @@ -51,33 +54,54 @@ def _get_version():


def _get_release_date():
"""Get release date from most recent git tag.
"""Get the release date of the installed SDK.

Released wheels ship a ``_release_info.py`` module generated by the release
workflow. For source checkouts, the date of the latest tag in the SDK's own
git repository is used instead.

Returns:
str: ISO date string (YYYY-MM-DD) of last tagged release,
or "unreleased" if no tags exist (development mode).
str: ISO date string (YYYY-MM-DD) of the release,
or "unreleased" if it cannot be determined (development mode).
"""
try:
from ._release_info import RELEASE_DATE

return RELEASE_DATE
except ImportError:
pass

import subprocess
from pathlib import Path

repo_root = Path(__file__).resolve().parents[1]
try:
# Get the date of the most recent tag
result = subprocess.run(
["git", "log", "-1", "--format=%ci", "--tags", "--no-walk"],
# Only trust git if the package lives in its own checkout; otherwise an
# install inside an unrelated repo would report that repo's tag dates.
toplevel = subprocess.run(
["git", "rev-parse", "--show-toplevel"],
capture_output=True,
text=True,
check=False,
timeout=2,
cwd=None, # Use current directory
cwd=repo_root,
)
if toplevel.returncode != 0 or Path(toplevel.stdout.strip()).resolve() != repo_root:
return "unreleased"

result = subprocess.run(
["git", "log", "-1", "--format=%cs", "--tags", "--no-walk"],
capture_output=True,
text=True,
check=False,
timeout=2,
cwd=repo_root,
)
if result.returncode == 0 and result.stdout.strip():
# Parse git date format: "2026-02-23 10:30:45 +0100"
date_str = result.stdout.strip().split()[0]
return date_str
return result.stdout.strip()
except Exception:
pass

# If no tags exist, this is unreleased development version
return "unreleased"


Expand Down
Loading