frequenz-core 1.0.2__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 (25) hide show
  1. frequenz_core-1.2.0/PKG-INFO +236 -0
  2. frequenz_core-1.2.0/README.md +172 -0
  3. frequenz_core-1.2.0/RELEASE_NOTES.md +41 -0
  4. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/pyproject.toml +19 -19
  5. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/src/frequenz/core/datetime.py +1 -1
  6. frequenz_core-1.2.0/src/frequenz/core/enum.py +265 -0
  7. frequenz_core-1.2.0/src/frequenz_core.egg-info/PKG-INFO +236 -0
  8. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/src/frequenz_core.egg-info/SOURCES.txt +1 -0
  9. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/src/frequenz_core.egg-info/requires.txt +17 -17
  10. frequenz_core-1.0.2/PKG-INFO +0 -91
  11. frequenz_core-1.0.2/README.md +0 -27
  12. frequenz_core-1.0.2/RELEASE_NOTES.md +0 -17
  13. frequenz_core-1.0.2/src/frequenz_core.egg-info/PKG-INFO +0 -91
  14. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/LICENSE +0 -0
  15. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/MANIFEST.in +0 -0
  16. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/setup.cfg +0 -0
  17. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/src/frequenz/core/__init__.py +0 -0
  18. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/src/frequenz/core/conftest.py +0 -0
  19. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/src/frequenz/core/id.py +0 -0
  20. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/src/frequenz/core/math.py +0 -0
  21. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/src/frequenz/core/module.py +0 -0
  22. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/src/frequenz/core/py.typed +0 -0
  23. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/src/frequenz/core/typing.py +0 -0
  24. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/src/frequenz_core.egg-info/dependency_links.txt +0 -0
  25. {frequenz_core-1.0.2 → frequenz_core-1.2.0}/src/frequenz_core.egg-info/top_level.txt +0 -0
@@ -0,0 +1,236 @@
1
+ Metadata-Version: 2.4
2
+ Name: frequenz-core
3
+ Version: 1.2.0
4
+ Summary: Core utilities to complement Python's standard library
5
+ Author-email: Frequenz Energy-as-a-Service GmbH <floss@frequenz.com>
6
+ License: MIT
7
+ Project-URL: Documentation, https://frequenz-floss.github.io/frequenz-core-python/
8
+ Project-URL: Changelog, https://github.com/frequenz-floss/frequenz-core-python/releases
9
+ Project-URL: Issues, https://github.com/frequenz-floss/frequenz-core-python/issues
10
+ Project-URL: Repository, https://github.com/frequenz-floss/frequenz-core-python
11
+ Project-URL: Support, https://github.com/frequenz-floss/frequenz-core-python/discussions/categories/support
12
+ Keywords: asyncio,collections,core,datetime,frequenz,lib,library,math,python,stdlib,typing
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Topic :: Software Development :: Libraries
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: <4,>=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: typing-extensions<5,>=4.13.0
24
+ Provides-Extra: dev-flake8
25
+ Requires-Dist: flake8==7.3.0; extra == "dev-flake8"
26
+ Requires-Dist: flake8-docstrings==1.7.0; extra == "dev-flake8"
27
+ Requires-Dist: flake8-pyproject==1.2.3; extra == "dev-flake8"
28
+ Requires-Dist: pydoclint==0.6.11; extra == "dev-flake8"
29
+ Requires-Dist: pydocstyle==6.3.0; extra == "dev-flake8"
30
+ Provides-Extra: dev-formatting
31
+ Requires-Dist: black==25.1.0; extra == "dev-formatting"
32
+ Requires-Dist: isort==6.0.1; extra == "dev-formatting"
33
+ Provides-Extra: dev-mkdocs
34
+ Requires-Dist: Markdown==3.8.2; extra == "dev-mkdocs"
35
+ Requires-Dist: black==25.1.0; extra == "dev-mkdocs"
36
+ Requires-Dist: mike==2.1.3; extra == "dev-mkdocs"
37
+ Requires-Dist: mkdocs-gen-files==0.5.0; extra == "dev-mkdocs"
38
+ Requires-Dist: mkdocs-literate-nav==0.6.2; 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
+ Requires-Dist: mkdocstrings[python]==0.30.0; extra == "dev-mkdocs"
42
+ Requires-Dist: mkdocstrings-python==1.18.2; extra == "dev-mkdocs"
43
+ Requires-Dist: frequenz-repo-config[lib]==0.13.5; extra == "dev-mkdocs"
44
+ Provides-Extra: dev-mypy
45
+ Requires-Dist: mypy==1.17.1; extra == "dev-mypy"
46
+ Requires-Dist: types-Markdown==3.8.0.20250809; extra == "dev-mypy"
47
+ Requires-Dist: frequenz-core[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-mypy"
48
+ Provides-Extra: dev-noxfile
49
+ Requires-Dist: nox==2025.5.1; extra == "dev-noxfile"
50
+ Requires-Dist: frequenz-repo-config[lib]==0.13.5; extra == "dev-noxfile"
51
+ Provides-Extra: dev-pylint
52
+ Requires-Dist: frequenz-core[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-pylint"
53
+ Provides-Extra: dev-pytest
54
+ Requires-Dist: pytest==8.4.1; extra == "dev-pytest"
55
+ Requires-Dist: pylint==3.3.8; extra == "dev-pytest"
56
+ Requires-Dist: frequenz-repo-config[extra-lint-examples]==0.13.5; extra == "dev-pytest"
57
+ Requires-Dist: pytest-mock==3.14.1; extra == "dev-pytest"
58
+ Requires-Dist: pytest-asyncio==1.1.0; extra == "dev-pytest"
59
+ Requires-Dist: async-solipsism==0.8; extra == "dev-pytest"
60
+ Requires-Dist: hypothesis==6.138.11; extra == "dev-pytest"
61
+ Provides-Extra: dev
62
+ Requires-Dist: frequenz-core[dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]; extra == "dev"
63
+ Dynamic: license-file
64
+
65
+ # Frequenz Core Library
66
+
67
+ [![Build Status](https://github.com/frequenz-floss/frequenz-core-python/actions/workflows/ci.yaml/badge.svg)](https://github.com/frequenz-floss/frequenz-core-python/actions/workflows/ci.yaml)
68
+ [![PyPI Package](https://img.shields.io/pypi/v/frequenz-core)](https://pypi.org/project/frequenz-core/)
69
+ [![Docs](https://img.shields.io/badge/docs-latest-informational)](https://frequenz-floss.github.io/frequenz-core-python/)
70
+
71
+ ## Introduction
72
+
73
+ Core utilities to complement Python's standard library. This library provides
74
+ essential building blocks for Python applications, including mathematical
75
+ utilities, datetime constants, typing helpers, strongly-typed identifiers, and
76
+ module introspection tools.
77
+
78
+ The `frequenz-core` library is designed to be lightweight, type-safe, and
79
+ follow modern Python best practices. It fills common gaps in the standard
80
+ library with utilities that are frequently needed across different projects.
81
+
82
+ ## Supported Platforms
83
+
84
+ The following platforms are officially supported (tested):
85
+
86
+ - **Python:** 3.11
87
+ - **Operating System:** Ubuntu Linux 20.04
88
+ - **Architectures:** amd64, arm64
89
+
90
+ ## Installation
91
+
92
+ You can install the library from PyPI using pip:
93
+
94
+ ```bash
95
+ python -m pip install frequenz-core
96
+ ```
97
+
98
+ Or add it to your project's dependencies in `pyproject.toml`:
99
+
100
+ ```toml
101
+ [project]
102
+ dependencies = [
103
+ "frequenz-core >= 1.0.2, < 2",
104
+ ]
105
+ ```
106
+
107
+ > [!NOTE]
108
+ > We recommend pinning the dependency to the latest version for programs,
109
+ > like `"frequenz-core == 1.0.2"`, and specifying a version range spanning
110
+ > one major version for libraries, like `"frequenz-core >= 1.0.2, < 2"`.
111
+ > We follow [semver](https://semver.org/).
112
+
113
+ ## Quick Start
114
+
115
+ Here's a quick overview of the main functionality:
116
+
117
+ ```python
118
+ from frequenz.core.math import is_close_to_zero, Interval
119
+ from frequenz.core.datetime import UNIX_EPOCH
120
+ from frequenz.core.module import get_public_module_name
121
+
122
+ # Math utilities
123
+ print(is_close_to_zero(1e-10)) # True - check if float is close to zero
124
+ interval = Interval(1, 10)
125
+ print(5 in interval) # True - check if value is in range
126
+
127
+ # Datetime utilities
128
+ print(UNIX_EPOCH) # 1970-01-01 00:00:00+00:00
129
+
130
+ # Module utilities
131
+ public_name = get_public_module_name("my.package._private.module")
132
+ print(public_name) # "my.package"
133
+ ```
134
+
135
+ ## Code Examples
136
+
137
+ ### Math Utilities
138
+
139
+ The math module provides utilities for floating-point comparisons and interval
140
+ checking:
141
+
142
+ ```python
143
+ from frequenz.core.math import is_close_to_zero, Interval
144
+
145
+ # Robust floating-point zero comparison
146
+ assert is_close_to_zero(1e-10) # True
147
+ assert not is_close_to_zero(0.1) # False
148
+
149
+ # Interval checking with inclusive bounds
150
+ numbers = Interval(0, 100)
151
+ assert 50 in numbers # True
152
+ assert not (150 in numbers) # False - 150 is outside the interval
153
+
154
+ # Unbounded intervals
155
+ positive = Interval(0, None) # [0, ∞]
156
+ assert 1000 in positive # True
157
+ ```
158
+
159
+ ### `Enum` with deprecated members
160
+
161
+ Define enums with deprecated members that raise deprecation warnings when
162
+ accessed:
163
+
164
+ ```python
165
+ from frequenz.core.enum import Enum, DeprecatedMember
166
+
167
+ class TaskStatus(Enum):
168
+ OPEN = 1
169
+ IN_PROGRESS = 2
170
+ PENDING = DeprecatedMember(1, "PENDING is deprecated, use OPEN instead")
171
+ DONE = DeprecatedMember(3, "DONE is deprecated, use FINISHED instead")
172
+ FINISHED = 4
173
+
174
+ status1 = TaskStatus.PENDING # Warns: "PENDING is deprecated, use OPEN instead"
175
+ assert status1 is TaskStatus.OPEN
176
+ ```
177
+
178
+ ### Typing Utilities
179
+
180
+ Disable class constructors to enforce factory pattern usage:
181
+
182
+ ```python
183
+ from frequenz.core.typing import disable_init
184
+
185
+ @disable_init
186
+ class ApiClient:
187
+ @classmethod
188
+ def create(cls, api_key: str) -> "ApiClient":
189
+ # Factory method with validation
190
+ instance = cls.__new__(cls)
191
+ # Custom initialization logic here
192
+ return instance
193
+
194
+ # This will raise TypeError:
195
+ # client = ApiClient() # ❌ TypeError
196
+
197
+ # Use factory method instead:
198
+ client = ApiClient.create("my-api-key") # ✅ Works
199
+ ```
200
+
201
+ ### Strongly-Typed IDs
202
+
203
+ Create type-safe identifiers for different entities:
204
+
205
+ ```python
206
+ from frequenz.core.id import BaseId
207
+
208
+ class UserId(BaseId, str_prefix="USR"):
209
+ pass
210
+
211
+ class OrderId(BaseId, str_prefix="ORD"):
212
+ pass
213
+
214
+ user_id = UserId(123)
215
+ order_id = OrderId(456)
216
+
217
+ print(f"User: {user_id}") # User: USR123
218
+ print(f"Order: {order_id}") # Order: ORD456
219
+
220
+ # Type safety prevents mixing different ID types
221
+ def process_user(user_id: UserId) -> None:
222
+ print(f"Processing user: {user_id}")
223
+
224
+ process_user(user_id) # ✅ Works
225
+ # process_user(order_id) # ❌ Type error
226
+ ```
227
+
228
+ ## Documentation
229
+
230
+ For information on how to use this library, please refer to the
231
+ [documentation](https://frequenz-floss.github.io/frequenz-core-python/).
232
+
233
+ ## Contributing
234
+
235
+ If you want to know how to build this project and contribute to it, please
236
+ check out the [Contributing Guide](CONTRIBUTING.md).
@@ -0,0 +1,172 @@
1
+ # Frequenz Core Library
2
+
3
+ [![Build Status](https://github.com/frequenz-floss/frequenz-core-python/actions/workflows/ci.yaml/badge.svg)](https://github.com/frequenz-floss/frequenz-core-python/actions/workflows/ci.yaml)
4
+ [![PyPI Package](https://img.shields.io/pypi/v/frequenz-core)](https://pypi.org/project/frequenz-core/)
5
+ [![Docs](https://img.shields.io/badge/docs-latest-informational)](https://frequenz-floss.github.io/frequenz-core-python/)
6
+
7
+ ## Introduction
8
+
9
+ Core utilities to complement Python's standard library. This library provides
10
+ essential building blocks for Python applications, including mathematical
11
+ utilities, datetime constants, typing helpers, strongly-typed identifiers, and
12
+ module introspection tools.
13
+
14
+ The `frequenz-core` library is designed to be lightweight, type-safe, and
15
+ follow modern Python best practices. It fills common gaps in the standard
16
+ library with utilities that are frequently needed across different projects.
17
+
18
+ ## Supported Platforms
19
+
20
+ The following platforms are officially supported (tested):
21
+
22
+ - **Python:** 3.11
23
+ - **Operating System:** Ubuntu Linux 20.04
24
+ - **Architectures:** amd64, arm64
25
+
26
+ ## Installation
27
+
28
+ You can install the library from PyPI using pip:
29
+
30
+ ```bash
31
+ python -m pip install frequenz-core
32
+ ```
33
+
34
+ Or add it to your project's dependencies in `pyproject.toml`:
35
+
36
+ ```toml
37
+ [project]
38
+ dependencies = [
39
+ "frequenz-core >= 1.0.2, < 2",
40
+ ]
41
+ ```
42
+
43
+ > [!NOTE]
44
+ > We recommend pinning the dependency to the latest version for programs,
45
+ > like `"frequenz-core == 1.0.2"`, and specifying a version range spanning
46
+ > one major version for libraries, like `"frequenz-core >= 1.0.2, < 2"`.
47
+ > We follow [semver](https://semver.org/).
48
+
49
+ ## Quick Start
50
+
51
+ Here's a quick overview of the main functionality:
52
+
53
+ ```python
54
+ from frequenz.core.math import is_close_to_zero, Interval
55
+ from frequenz.core.datetime import UNIX_EPOCH
56
+ from frequenz.core.module import get_public_module_name
57
+
58
+ # Math utilities
59
+ print(is_close_to_zero(1e-10)) # True - check if float is close to zero
60
+ interval = Interval(1, 10)
61
+ print(5 in interval) # True - check if value is in range
62
+
63
+ # Datetime utilities
64
+ print(UNIX_EPOCH) # 1970-01-01 00:00:00+00:00
65
+
66
+ # Module utilities
67
+ public_name = get_public_module_name("my.package._private.module")
68
+ print(public_name) # "my.package"
69
+ ```
70
+
71
+ ## Code Examples
72
+
73
+ ### Math Utilities
74
+
75
+ The math module provides utilities for floating-point comparisons and interval
76
+ checking:
77
+
78
+ ```python
79
+ from frequenz.core.math import is_close_to_zero, Interval
80
+
81
+ # Robust floating-point zero comparison
82
+ assert is_close_to_zero(1e-10) # True
83
+ assert not is_close_to_zero(0.1) # False
84
+
85
+ # Interval checking with inclusive bounds
86
+ numbers = Interval(0, 100)
87
+ assert 50 in numbers # True
88
+ assert not (150 in numbers) # False - 150 is outside the interval
89
+
90
+ # Unbounded intervals
91
+ positive = Interval(0, None) # [0, ∞]
92
+ assert 1000 in positive # True
93
+ ```
94
+
95
+ ### `Enum` with deprecated members
96
+
97
+ Define enums with deprecated members that raise deprecation warnings when
98
+ accessed:
99
+
100
+ ```python
101
+ from frequenz.core.enum import Enum, DeprecatedMember
102
+
103
+ class TaskStatus(Enum):
104
+ OPEN = 1
105
+ IN_PROGRESS = 2
106
+ PENDING = DeprecatedMember(1, "PENDING is deprecated, use OPEN instead")
107
+ DONE = DeprecatedMember(3, "DONE is deprecated, use FINISHED instead")
108
+ FINISHED = 4
109
+
110
+ status1 = TaskStatus.PENDING # Warns: "PENDING is deprecated, use OPEN instead"
111
+ assert status1 is TaskStatus.OPEN
112
+ ```
113
+
114
+ ### Typing Utilities
115
+
116
+ Disable class constructors to enforce factory pattern usage:
117
+
118
+ ```python
119
+ from frequenz.core.typing import disable_init
120
+
121
+ @disable_init
122
+ class ApiClient:
123
+ @classmethod
124
+ def create(cls, api_key: str) -> "ApiClient":
125
+ # Factory method with validation
126
+ instance = cls.__new__(cls)
127
+ # Custom initialization logic here
128
+ return instance
129
+
130
+ # This will raise TypeError:
131
+ # client = ApiClient() # ❌ TypeError
132
+
133
+ # Use factory method instead:
134
+ client = ApiClient.create("my-api-key") # ✅ Works
135
+ ```
136
+
137
+ ### Strongly-Typed IDs
138
+
139
+ Create type-safe identifiers for different entities:
140
+
141
+ ```python
142
+ from frequenz.core.id import BaseId
143
+
144
+ class UserId(BaseId, str_prefix="USR"):
145
+ pass
146
+
147
+ class OrderId(BaseId, str_prefix="ORD"):
148
+ pass
149
+
150
+ user_id = UserId(123)
151
+ order_id = OrderId(456)
152
+
153
+ print(f"User: {user_id}") # User: USR123
154
+ print(f"Order: {order_id}") # Order: ORD456
155
+
156
+ # Type safety prevents mixing different ID types
157
+ def process_user(user_id: UserId) -> None:
158
+ print(f"Processing user: {user_id}")
159
+
160
+ process_user(user_id) # ✅ Works
161
+ # process_user(order_id) # ❌ Type error
162
+ ```
163
+
164
+ ## Documentation
165
+
166
+ For information on how to use this library, please refer to the
167
+ [documentation](https://frequenz-floss.github.io/frequenz-core-python/).
168
+
169
+ ## Contributing
170
+
171
+ If you want to know how to build this project and contribute to it, please
172
+ check out the [Contributing Guide](CONTRIBUTING.md).
@@ -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,8 +4,8 @@
4
4
  [build-system]
5
5
  requires = [
6
6
  "setuptools == 80.9.0",
7
- "setuptools_scm[toml] == 8.3.1",
8
- "frequenz-repo-config[lib] == 0.13.4",
7
+ "setuptools_scm[toml] == 9.2.0",
8
+ "frequenz-repo-config[lib] == 0.13.5",
9
9
  ]
10
10
  build-backend = "setuptools.build_meta"
11
11
 
@@ -46,45 +46,45 @@ email = "floss@frequenz.com"
46
46
 
47
47
  [project.optional-dependencies]
48
48
  dev-flake8 = [
49
- "flake8 == 7.2.0",
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"]
56
56
  dev-mkdocs = [
57
- "Markdown == 3.8",
57
+ "Markdown == 3.8.2",
58
58
  "black == 25.1.0",
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.14",
64
- "mkdocstrings[python] == 0.29.1",
65
- "mkdocstrings-python == 1.16.11",
66
- "frequenz-repo-config[lib] == 0.13.4",
62
+ "mkdocs-macros-plugin == 1.3.9",
63
+ "mkdocs-material == 9.6.18",
64
+ "mkdocstrings[python] == 0.30.0",
65
+ "mkdocstrings-python == 1.18.2",
66
+ "frequenz-repo-config[lib] == 0.13.5",
67
67
  ]
68
68
  dev-mypy = [
69
- "mypy == 1.16.0",
70
- "types-Markdown == 3.8.0.20250415",
69
+ "mypy == 1.17.1",
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
  ]
74
- dev-noxfile = ["nox == 2025.5.1", "frequenz-repo-config[lib] == 0.13.4"]
74
+ dev-noxfile = ["nox == 2025.5.1", "frequenz-repo-config[lib] == 0.13.5"]
75
75
  dev-pylint = [
76
76
  # dev-pytest already defines a dependency to pylint because of the examples
77
77
  # For checking the noxfile, docs/ script, and tests
78
78
  "frequenz-core[dev-mkdocs,dev-noxfile,dev-pytest]",
79
79
  ]
80
80
  dev-pytest = [
81
- "pytest == 8.3.5",
82
- "pylint == 3.3.7", # We need this to check for the examples
83
- "frequenz-repo-config[extra-lint-examples] == 0.13.4",
81
+ "pytest == 8.4.1",
82
+ "pylint == 3.3.8", # We need this to check for the examples
83
+ "frequenz-repo-config[extra-lint-examples] == 0.13.5",
84
84
  "pytest-mock == 3.14.1",
85
- "pytest-asyncio == 0.26.0",
86
- "async-solipsism == 0.7",
87
- "hypothesis == 6.132.0",
85
+ "pytest-asyncio == 1.1.0",
86
+ "async-solipsism == 0.8",
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]",
@@ -1,7 +1,7 @@
1
1
  # License: MIT
2
2
  # Copyright © 2024 Frequenz Energy-as-a-Service GmbH
3
3
 
4
- """Timeseries basic types."""
4
+ """Date and time utilities."""
5
5
 
6
6
  from datetime import datetime, timezone
7
7
  from typing import Final