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
6 changes: 4 additions & 2 deletions docs/RELEASE_CHECKLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ Update version numbers in the following files:
| File | Location | Example |
|------|----------|---------|
| `pyproject.toml` | Line ~35 | `version = "X.Y.Z"` |
| `src/birdnetpi/config/manager.py` | Line ~19 | `CURRENT_VERSION = "X.Y.Z"` |
| `src/birdnetpi/config/versions/vX_Y_Z.py` | Line ~22 | `version = "X.Y.Z"` |
| `src/birdnetpi/cli/manage_translations.py` | Line ~74 | `--version=X.Y.Z` |

> **Note:** The config version is defined in version handler files (e.g., `v2_0_0.py`). When creating a new schema version, create a new version handler file.

## Translations

Run the translation workflow to ensure all strings are extracted and compiled:
Expand Down Expand Up @@ -78,7 +80,7 @@ docker compose down
### Commit Changes
```bash
# Stage all release-related changes
git add pyproject.toml src/birdnetpi/config/manager.py src/birdnetpi/cli/manage_translations.py
git add pyproject.toml src/birdnetpi/config/versions/ src/birdnetpi/cli/manage_translations.py
git add locales/

# Create release commit
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ profiling = [

[project]
name = "birdnet-pi"
version = "2.0.0a"
version = "2.0.0a0"
description = "The next generation of real-time, acoustic bird classification."
authors = [
{name = "Matthew de Verteuil", email = "mverteuil@users.noreply.github.com"},
Expand Down
5 changes: 5 additions & 0 deletions src/birdnetpi/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""BirdNET-Pi - Bird sound recognition system."""

from importlib.metadata import version

__version__ = version("birdnet-pi")
3 changes: 2 additions & 1 deletion src/birdnetpi/cli/manage_translations.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import click

import birdnetpi
from birdnetpi.system.path_resolver import PathResolver


Expand Down Expand Up @@ -71,7 +72,7 @@ def extract(obj: dict[str, Any]) -> None:
"-k",
"_",
"--project=BirdNET-Pi",
"--version=2.0.0",
f"--version={birdnetpi.__version__}",
"--msgid-bugs-address=https://github.com/mverteuil/BirdNET-Pi/issues",
"--copyright-holder=BirdNET-Pi Contributors",
"-o",
Expand Down
23 changes: 16 additions & 7 deletions src/birdnetpi/config/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
class ConfigManager:
"""Manages configuration loading, saving, and migration."""

CURRENT_VERSION = "2.0.0"

@staticmethod
def _is_profiling_enabled() -> bool:
"""Check if profiling is enabled via environment variable.
Expand Down Expand Up @@ -66,6 +64,17 @@ def __init__(self, path_resolver: PathResolver | None = None):
self.config_path = self.path_resolver.get_birdnetpi_config_path()
self.template_path = self.path_resolver.get_config_template_path()

@property
def current_version(self) -> str:
"""Get the current configuration version from the registry.

The version handler files are the single source of truth for schema versions.

Returns:
str: Current configuration version string (e.g., "2.0.0")
"""
return self.registry.get_current_version().version

def load(self) -> BirdNETConfig:
"""Load configuration with migration and validation.

Expand All @@ -86,11 +95,11 @@ def load(self) -> BirdNETConfig:
raw_config = version_handler.apply_defaults(raw_config)

# Migrate to current version if needed
if config_version != self.CURRENT_VERSION:
if config_version != self.current_version:
raw_config = self._migrate_to_current(raw_config, config_version)

# Validate final config
current_handler = self.registry.get_version(self.CURRENT_VERSION)
current_handler = self.registry.get_version(self.current_version)
errors = current_handler.validate(raw_config)
if errors:
raise ValueError(f"Configuration validation failed: {', '.join(errors)}")
Expand Down Expand Up @@ -140,9 +149,9 @@ def _ensure_config_exists(self) -> None:
self.config_path.parent.mkdir(parents=True, exist_ok=True)

# Create config from current version defaults
current_handler = self.registry.get_version(self.CURRENT_VERSION)
current_handler = self.registry.get_version(self.current_version)
config_with_defaults = current_handler.apply_defaults(
{"config_version": self.CURRENT_VERSION}
{"config_version": self.current_version}
)

# Save the config with defaults
Expand All @@ -168,7 +177,7 @@ def _migrate_to_current(self, raw_config: dict[str, Any], from_version: str) ->
Returns:
dict: Migrated configuration
"""
upgrade_path = self.registry.get_upgrade_path(from_version, self.CURRENT_VERSION)
upgrade_path = self.registry.get_upgrade_path(from_version, self.current_version)

for version_handler in upgrade_path:
raw_config = version_handler.upgrade_from_previous(raw_config)
Expand Down
Loading