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
17 changes: 10 additions & 7 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

## Summary

This is the initial release of the Frequenz Core Library, which provides a set of fundamental tools and utilities for Python.
<!-- Here goes a general summary of what this release is about -->

The library currently includes:
## Upgrading

- `datetime`: For utilities related to dates and times.
* `id`: For creating unique system-wide ID types.
* `math`: For utilities related to math.
* `typing`: For type annotations and type-checking utilities.
<!-- Here goes notes on how to upgrade from previous versions, including deprecations and what they should be replaced with -->

But more tools will be added in the future.
## New Features

<!-- Here goes the main new features and examples or instructions on how to use them -->

## Bug Fixes

* `BaseId` will now warn instead of raising an exception when a duplicate prefix is detected. This is to fix [a problem with code examples](https://github.com/frequenz-floss/frequenz-repo-config-python/issues/421) being tested using sybil and the class being imported multiple times, which caused the exception to be raised.
10 changes: 6 additions & 4 deletions src/frequenz/core/id.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class CustomNameForId(BaseId, str_prefix="CST", allow_custom_name=True):


from typing import Any, ClassVar, Self, cast
from warnings import warn


class BaseId:
Expand Down Expand Up @@ -105,17 +106,18 @@ def __init_subclass__(
**kwargs: Forwarded to the parent's __init_subclass__.

Raises:
ValueError: If the `str_prefix` is already registered by another
ID type.
TypeError: If `allow_custom_name` is False and the class name
does not end with "Id".
"""
super().__init_subclass__(**kwargs)

if str_prefix in BaseId._registered_prefixes:
raise ValueError(
# We want to raise an exception here, but currently can't due to
# https://github.com/frequenz-floss/frequenz-repo-config-python/issues/421
warn(
f"Prefix '{str_prefix}' is already registered. "
"ID prefixes must be unique."
"ID prefixes must be unique.",
Copy link

Copilot AI Jun 18, 2025

Choose a reason for hiding this comment

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

It is recommended to explicitly specify the warning category (e.g., UserWarning) in the warn() call for clarity and consistency, even though the default is UserWarning.

Suggested change
"ID prefixes must be unique.",
"ID prefixes must be unique.",
category=UserWarning,

Copilot uses AI. Check for mistakes.
stacklevel=2,
)
BaseId._registered_prefixes.add(str_prefix)

Expand Down
18 changes: 18 additions & 0 deletions tests/test_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,24 @@ def test_valid() -> None:
assert int(id_obj) == 42


def test_use_a_subclass() -> None:
"""Test that BaseId cannot be instantiated directly."""
with pytest.raises(
TypeError, match="BaseId cannot be instantiated directly. Use a subclass."
):
BaseId(42)


def test_warn_non_unique_prefix() -> None:
"""Test that using a non-unique prefix raises a warning."""
with pytest.warns(UserWarning, match="Prefix 'TEST_ID' is already registered"):

class _TestDuplicateId(BaseId, str_prefix="TEST_ID"):
"""A duplicate test ID class with the same prefix as _TestId."""

_TestDuplicateId(1)


def test_negative_raises() -> None:
"""Test that creating a negative ID raises ValueError."""
with pytest.raises(ValueError, match="_TestId can't be negative"):
Expand Down
Loading