frequenz-core 1.1.0__tar.gz → 1.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. {frequenz_core-1.1.0/src/frequenz_core.egg-info → frequenz_core-1.2.0}/PKG-INFO +8 -8
  2. frequenz_core-1.2.0/RELEASE_NOTES.md +41 -0
  3. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/pyproject.toml +8 -8
  4. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/src/frequenz/core/enum.py +58 -0
  5. {frequenz_core-1.1.0 → frequenz_core-1.2.0/src/frequenz_core.egg-info}/PKG-INFO +8 -8
  6. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/src/frequenz_core.egg-info/requires.txt +7 -7
  7. frequenz_core-1.1.0/RELEASE_NOTES.md +0 -21
  8. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/LICENSE +0 -0
  9. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/MANIFEST.in +0 -0
  10. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/README.md +0 -0
  11. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/setup.cfg +0 -0
  12. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/src/frequenz/core/__init__.py +0 -0
  13. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/src/frequenz/core/conftest.py +0 -0
  14. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/src/frequenz/core/datetime.py +0 -0
  15. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/src/frequenz/core/id.py +0 -0
  16. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/src/frequenz/core/math.py +0 -0
  17. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/src/frequenz/core/module.py +0 -0
  18. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/src/frequenz/core/py.typed +0 -0
  19. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/src/frequenz/core/typing.py +0 -0
  20. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/src/frequenz_core.egg-info/SOURCES.txt +0 -0
  21. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/src/frequenz_core.egg-info/dependency_links.txt +0 -0
  22. {frequenz_core-1.1.0 → frequenz_core-1.2.0}/src/frequenz_core.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frequenz-core
3
- Version: 1.1.0
3
+ Version: 1.2.0
4
4
  Summary: Core utilities to complement Python's standard library
5
5
  Author-email: Frequenz Energy-as-a-Service GmbH <floss@frequenz.com>
6
6
  License: MIT
@@ -25,7 +25,7 @@ Provides-Extra: dev-flake8
25
25
  Requires-Dist: flake8==7.3.0; extra == "dev-flake8"
26
26
  Requires-Dist: flake8-docstrings==1.7.0; extra == "dev-flake8"
27
27
  Requires-Dist: flake8-pyproject==1.2.3; extra == "dev-flake8"
28
- Requires-Dist: pydoclint==0.6.6; extra == "dev-flake8"
28
+ Requires-Dist: pydoclint==0.6.11; extra == "dev-flake8"
29
29
  Requires-Dist: pydocstyle==6.3.0; extra == "dev-flake8"
30
30
  Provides-Extra: dev-formatting
31
31
  Requires-Dist: black==25.1.0; extra == "dev-formatting"
@@ -36,14 +36,14 @@ Requires-Dist: black==25.1.0; extra == "dev-mkdocs"
36
36
  Requires-Dist: mike==2.1.3; extra == "dev-mkdocs"
37
37
  Requires-Dist: mkdocs-gen-files==0.5.0; extra == "dev-mkdocs"
38
38
  Requires-Dist: mkdocs-literate-nav==0.6.2; extra == "dev-mkdocs"
39
- Requires-Dist: mkdocs-macros-plugin==1.3.7; extra == "dev-mkdocs"
40
- Requires-Dist: mkdocs-material==9.6.16; extra == "dev-mkdocs"
39
+ Requires-Dist: mkdocs-macros-plugin==1.3.9; extra == "dev-mkdocs"
40
+ Requires-Dist: mkdocs-material==9.6.18; extra == "dev-mkdocs"
41
41
  Requires-Dist: mkdocstrings[python]==0.30.0; extra == "dev-mkdocs"
42
- Requires-Dist: mkdocstrings-python==1.17.0; extra == "dev-mkdocs"
42
+ Requires-Dist: mkdocstrings-python==1.18.2; extra == "dev-mkdocs"
43
43
  Requires-Dist: frequenz-repo-config[lib]==0.13.5; extra == "dev-mkdocs"
44
44
  Provides-Extra: dev-mypy
45
45
  Requires-Dist: mypy==1.17.1; extra == "dev-mypy"
46
- Requires-Dist: types-Markdown==3.8.0.20250708; extra == "dev-mypy"
46
+ Requires-Dist: types-Markdown==3.8.0.20250809; extra == "dev-mypy"
47
47
  Requires-Dist: frequenz-core[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-mypy"
48
48
  Provides-Extra: dev-noxfile
49
49
  Requires-Dist: nox==2025.5.1; extra == "dev-noxfile"
@@ -52,12 +52,12 @@ Provides-Extra: dev-pylint
52
52
  Requires-Dist: frequenz-core[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-pylint"
53
53
  Provides-Extra: dev-pytest
54
54
  Requires-Dist: pytest==8.4.1; extra == "dev-pytest"
55
- Requires-Dist: pylint==3.3.7; extra == "dev-pytest"
55
+ Requires-Dist: pylint==3.3.8; extra == "dev-pytest"
56
56
  Requires-Dist: frequenz-repo-config[extra-lint-examples]==0.13.5; extra == "dev-pytest"
57
57
  Requires-Dist: pytest-mock==3.14.1; extra == "dev-pytest"
58
58
  Requires-Dist: pytest-asyncio==1.1.0; extra == "dev-pytest"
59
59
  Requires-Dist: async-solipsism==0.8; extra == "dev-pytest"
60
- Requires-Dist: hypothesis==6.138.2; extra == "dev-pytest"
60
+ Requires-Dist: hypothesis==6.138.11; extra == "dev-pytest"
61
61
  Provides-Extra: dev
62
62
  Requires-Dist: frequenz-core[dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]; extra == "dev"
63
63
  Dynamic: license-file
@@ -0,0 +1,41 @@
1
+ # Frequenz Core Library Release Notes
2
+
3
+ ## Summary
4
+
5
+ ## New Features
6
+
7
+ * `frequenz.core.enum` now provides a `@unique` decorator that is aware of deprecations, and will only check for uniqueness among non-deprecated enum members.
8
+
9
+ For example this works:
10
+
11
+ ```py
12
+ >>> from frequenz.core.enum import DeprecatedMember, Enum, unique
13
+ >>>
14
+ >>> @unique
15
+ ... class Status(Enum):
16
+ ... ACTIVE = 1
17
+ ... INACTIVE = 2
18
+ ... PENDING = DeprecatedMember(1, "PENDING is deprecated, use ACTIVE instead")
19
+ ...
20
+ >>>
21
+ ```
22
+
23
+ While using the standard library's `enum.unique` decorator raises a `ValueError`:
24
+
25
+ ```py
26
+ >>> from enum import unique
27
+ >>> from frequenz.core.enum import DeprecatedMember, Enum
28
+ >>>
29
+ >>> @unique
30
+ ... class Status(Enum):
31
+ ... ACTIVE = 1
32
+ ... INACTIVE = 2
33
+ ... PENDING = DeprecatedMember(1, "PENDING is deprecated, use ACTIVE instead")
34
+ ...
35
+ Traceback (most recent call last):
36
+ File "<stdin>", line 1, in <module>
37
+ File "/usr/lib/python3.12/enum.py", line 1617, in unique
38
+ raise ValueError('duplicate values found in %r: %s' %
39
+ ValueError: duplicate values found in <enum 'Status'>: PENDING -> ACTIVE
40
+ >>>
41
+ ```
@@ -4,7 +4,7 @@
4
4
  [build-system]
5
5
  requires = [
6
6
  "setuptools == 80.9.0",
7
- "setuptools_scm[toml] == 8.3.1",
7
+ "setuptools_scm[toml] == 9.2.0",
8
8
  "frequenz-repo-config[lib] == 0.13.5",
9
9
  ]
10
10
  build-backend = "setuptools.build_meta"
@@ -49,7 +49,7 @@ dev-flake8 = [
49
49
  "flake8 == 7.3.0",
50
50
  "flake8-docstrings == 1.7.0",
51
51
  "flake8-pyproject == 1.2.3", # For reading the flake8 config from pyproject.toml
52
- "pydoclint == 0.6.6",
52
+ "pydoclint == 0.6.11",
53
53
  "pydocstyle == 6.3.0",
54
54
  ]
55
55
  dev-formatting = ["black == 25.1.0", "isort == 6.0.1"]
@@ -59,15 +59,15 @@ dev-mkdocs = [
59
59
  "mike == 2.1.3",
60
60
  "mkdocs-gen-files == 0.5.0",
61
61
  "mkdocs-literate-nav == 0.6.2",
62
- "mkdocs-macros-plugin == 1.3.7",
63
- "mkdocs-material == 9.6.16",
62
+ "mkdocs-macros-plugin == 1.3.9",
63
+ "mkdocs-material == 9.6.18",
64
64
  "mkdocstrings[python] == 0.30.0",
65
- "mkdocstrings-python == 1.17.0",
65
+ "mkdocstrings-python == 1.18.2",
66
66
  "frequenz-repo-config[lib] == 0.13.5",
67
67
  ]
68
68
  dev-mypy = [
69
69
  "mypy == 1.17.1",
70
- "types-Markdown == 3.8.0.20250708",
70
+ "types-Markdown == 3.8.0.20250809",
71
71
  # For checking the noxfile, docs/ script, and tests
72
72
  "frequenz-core[dev-mkdocs,dev-noxfile,dev-pytest]",
73
73
  ]
@@ -79,12 +79,12 @@ dev-pylint = [
79
79
  ]
80
80
  dev-pytest = [
81
81
  "pytest == 8.4.1",
82
- "pylint == 3.3.7", # We need this to check for the examples
82
+ "pylint == 3.3.8", # We need this to check for the examples
83
83
  "frequenz-repo-config[extra-lint-examples] == 0.13.5",
84
84
  "pytest-mock == 3.14.1",
85
85
  "pytest-asyncio == 1.1.0",
86
86
  "async-solipsism == 0.8",
87
- "hypothesis == 6.138.2",
87
+ "hypothesis == 6.138.11",
88
88
  ]
89
89
  dev = [
90
90
  "frequenz-core[dev-mkdocs,dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]",
@@ -205,3 +205,61 @@ else:
205
205
 
206
206
  __deprecated_names__: ClassVar[Mapping[str, str]]
207
207
  __deprecated_value_map__: ClassVar[Mapping[Self, str]]
208
+
209
+
210
+ def unique(enumeration: type[EnumT]) -> type[EnumT]:
211
+ """Class decorator for enums that ensures unique non-deprecated values.
212
+
213
+ This works similarly to [`@enum.unique`][enum.unique], but it only enforces
214
+ uniqueness for members that are not deprecated. This allows deprecated members to
215
+ be aliases for non-deprecated members without causing a `ValueError`.
216
+
217
+ If you need strict uniqueness for all deprecated and non-deprecated members, use
218
+ [`@enum.unique`][enum.unique] instead.
219
+
220
+ Example:
221
+ ```python
222
+ from frequenz.core.enum import Enum, DeprecatedMember, unique
223
+
224
+ @unique
225
+ class TaskStatus(Enum):
226
+ OPEN = 1
227
+ IN_PROGRESS = 2
228
+ # This is okay, as PENDING is a deprecated alias.
229
+ PENDING = DeprecatedMember(1, "Use OPEN instead")
230
+ ```
231
+
232
+ Args:
233
+ enumeration: The enum class to decorate.
234
+
235
+ Returns:
236
+ The decorated enum class.
237
+
238
+ Raises:
239
+ ValueError: If duplicate values are found among non-deprecated members.
240
+ """
241
+ # Retrieve the map of deprecated names created by the metaclass.
242
+ deprecated_names = enumeration.__dict__.get("__deprecated_names__", {})
243
+
244
+ duplicates = []
245
+ seen_values: dict[Any, str] = {}
246
+ for member_name, member in enumeration.__members__.items():
247
+ # Ignore members that are marked as deprecated.
248
+ if member_name in deprecated_names:
249
+ continue
250
+
251
+ value = member.value
252
+ if value in seen_values:
253
+ duplicates.append((member_name, seen_values[value]))
254
+ else:
255
+ seen_values[value] = member_name
256
+
257
+ if duplicates:
258
+ alias_details = ", ".join(
259
+ f"{name!r} -> {alias!r}" for name, alias in duplicates
260
+ )
261
+ raise ValueError(
262
+ f"duplicate values found in {enumeration.__name__}: {alias_details}"
263
+ )
264
+
265
+ return enumeration
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frequenz-core
3
- Version: 1.1.0
3
+ Version: 1.2.0
4
4
  Summary: Core utilities to complement Python's standard library
5
5
  Author-email: Frequenz Energy-as-a-Service GmbH <floss@frequenz.com>
6
6
  License: MIT
@@ -25,7 +25,7 @@ Provides-Extra: dev-flake8
25
25
  Requires-Dist: flake8==7.3.0; extra == "dev-flake8"
26
26
  Requires-Dist: flake8-docstrings==1.7.0; extra == "dev-flake8"
27
27
  Requires-Dist: flake8-pyproject==1.2.3; extra == "dev-flake8"
28
- Requires-Dist: pydoclint==0.6.6; extra == "dev-flake8"
28
+ Requires-Dist: pydoclint==0.6.11; extra == "dev-flake8"
29
29
  Requires-Dist: pydocstyle==6.3.0; extra == "dev-flake8"
30
30
  Provides-Extra: dev-formatting
31
31
  Requires-Dist: black==25.1.0; extra == "dev-formatting"
@@ -36,14 +36,14 @@ Requires-Dist: black==25.1.0; extra == "dev-mkdocs"
36
36
  Requires-Dist: mike==2.1.3; extra == "dev-mkdocs"
37
37
  Requires-Dist: mkdocs-gen-files==0.5.0; extra == "dev-mkdocs"
38
38
  Requires-Dist: mkdocs-literate-nav==0.6.2; extra == "dev-mkdocs"
39
- Requires-Dist: mkdocs-macros-plugin==1.3.7; extra == "dev-mkdocs"
40
- Requires-Dist: mkdocs-material==9.6.16; extra == "dev-mkdocs"
39
+ Requires-Dist: mkdocs-macros-plugin==1.3.9; extra == "dev-mkdocs"
40
+ Requires-Dist: mkdocs-material==9.6.18; extra == "dev-mkdocs"
41
41
  Requires-Dist: mkdocstrings[python]==0.30.0; extra == "dev-mkdocs"
42
- Requires-Dist: mkdocstrings-python==1.17.0; extra == "dev-mkdocs"
42
+ Requires-Dist: mkdocstrings-python==1.18.2; extra == "dev-mkdocs"
43
43
  Requires-Dist: frequenz-repo-config[lib]==0.13.5; extra == "dev-mkdocs"
44
44
  Provides-Extra: dev-mypy
45
45
  Requires-Dist: mypy==1.17.1; extra == "dev-mypy"
46
- Requires-Dist: types-Markdown==3.8.0.20250708; extra == "dev-mypy"
46
+ Requires-Dist: types-Markdown==3.8.0.20250809; extra == "dev-mypy"
47
47
  Requires-Dist: frequenz-core[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-mypy"
48
48
  Provides-Extra: dev-noxfile
49
49
  Requires-Dist: nox==2025.5.1; extra == "dev-noxfile"
@@ -52,12 +52,12 @@ Provides-Extra: dev-pylint
52
52
  Requires-Dist: frequenz-core[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-pylint"
53
53
  Provides-Extra: dev-pytest
54
54
  Requires-Dist: pytest==8.4.1; extra == "dev-pytest"
55
- Requires-Dist: pylint==3.3.7; extra == "dev-pytest"
55
+ Requires-Dist: pylint==3.3.8; extra == "dev-pytest"
56
56
  Requires-Dist: frequenz-repo-config[extra-lint-examples]==0.13.5; extra == "dev-pytest"
57
57
  Requires-Dist: pytest-mock==3.14.1; extra == "dev-pytest"
58
58
  Requires-Dist: pytest-asyncio==1.1.0; extra == "dev-pytest"
59
59
  Requires-Dist: async-solipsism==0.8; extra == "dev-pytest"
60
- Requires-Dist: hypothesis==6.138.2; extra == "dev-pytest"
60
+ Requires-Dist: hypothesis==6.138.11; extra == "dev-pytest"
61
61
  Provides-Extra: dev
62
62
  Requires-Dist: frequenz-core[dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]; extra == "dev"
63
63
  Dynamic: license-file
@@ -7,7 +7,7 @@ frequenz-core[dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pyli
7
7
  flake8==7.3.0
8
8
  flake8-docstrings==1.7.0
9
9
  flake8-pyproject==1.2.3
10
- pydoclint==0.6.6
10
+ pydoclint==0.6.11
11
11
  pydocstyle==6.3.0
12
12
 
13
13
  [dev-formatting]
@@ -20,15 +20,15 @@ black==25.1.0
20
20
  mike==2.1.3
21
21
  mkdocs-gen-files==0.5.0
22
22
  mkdocs-literate-nav==0.6.2
23
- mkdocs-macros-plugin==1.3.7
24
- mkdocs-material==9.6.16
23
+ mkdocs-macros-plugin==1.3.9
24
+ mkdocs-material==9.6.18
25
25
  mkdocstrings[python]==0.30.0
26
- mkdocstrings-python==1.17.0
26
+ mkdocstrings-python==1.18.2
27
27
  frequenz-repo-config[lib]==0.13.5
28
28
 
29
29
  [dev-mypy]
30
30
  mypy==1.17.1
31
- types-Markdown==3.8.0.20250708
31
+ types-Markdown==3.8.0.20250809
32
32
  frequenz-core[dev-mkdocs,dev-noxfile,dev-pytest]
33
33
 
34
34
  [dev-noxfile]
@@ -40,9 +40,9 @@ frequenz-core[dev-mkdocs,dev-noxfile,dev-pytest]
40
40
 
41
41
  [dev-pytest]
42
42
  pytest==8.4.1
43
- pylint==3.3.7
43
+ pylint==3.3.8
44
44
  frequenz-repo-config[extra-lint-examples]==0.13.5
45
45
  pytest-mock==3.14.1
46
46
  pytest-asyncio==1.1.0
47
47
  async-solipsism==0.8
48
- hypothesis==6.138.2
48
+ hypothesis==6.138.11
@@ -1,21 +0,0 @@
1
- # Frequenz Core Library Release Notes
2
-
3
- ## New Features
4
-
5
- - A new `frequenz.core.enum` module was added, providing a drop-in replacement `Enum` that supports deprecating members.
6
-
7
- Example:
8
-
9
- ```python
10
- from frequenz.core.enum import Enum, DeprecatedMember
11
-
12
- class TaskStatus(Enum):
13
- OPEN = 1
14
- IN_PROGRESS = 2
15
- PENDING = DeprecatedMember(1, "PENDING is deprecated, use OPEN instead")
16
- DONE = DeprecatedMember(3, "DONE is deprecated, use FINISHED instead")
17
- FINISHED = 4
18
-
19
- status1 = TaskStatus.PENDING # Warns: "PENDING is deprecated, use OPEN instead"
20
- assert status1 is TaskStatus.OPEN
21
- ```
File without changes
File without changes
File without changes
File without changes