frequenz-quantities 1.0.0__py3-none-any.whl
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.
- frequenz/quantities/__init__.py +112 -0
- frequenz/quantities/_apparent_power.py +234 -0
- frequenz/quantities/_current.py +131 -0
- frequenz/quantities/_energy.py +188 -0
- frequenz/quantities/_frequency.py +115 -0
- frequenz/quantities/_percentage.py +66 -0
- frequenz/quantities/_power.py +244 -0
- frequenz/quantities/_quantity.py +541 -0
- frequenz/quantities/_reactive_power.py +235 -0
- frequenz/quantities/_temperature.py +39 -0
- frequenz/quantities/_voltage.py +148 -0
- frequenz/quantities/conftest.py +13 -0
- frequenz/quantities/experimental/__init__.py +11 -0
- frequenz/quantities/experimental/marshmallow.py +271 -0
- frequenz/quantities/py.typed +0 -0
- frequenz_quantities-1.0.0.dist-info/LICENSE +21 -0
- frequenz_quantities-1.0.0.dist-info/METADATA +103 -0
- frequenz_quantities-1.0.0.dist-info/RECORD +20 -0
- frequenz_quantities-1.0.0.dist-info/WHEEL +5 -0
- frequenz_quantities-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# License: All rights reserved
|
|
2
|
+
# Copyright © 2024 Frequenz Energy-as-a-Service GmbH
|
|
3
|
+
|
|
4
|
+
"""Custom marshmallow fields and schema.
|
|
5
|
+
|
|
6
|
+
This module provides custom marshmallow fields for quantities and
|
|
7
|
+
a [QuantitySchema][frequenz.quantities.experimental.marshmallow.QuantitySchema] class to
|
|
8
|
+
be used as base schema for dataclasses containing quantities.
|
|
9
|
+
|
|
10
|
+
Danger:
|
|
11
|
+
This module contains experimental features for which the API is not yet stable.
|
|
12
|
+
|
|
13
|
+
Any module or class in this package may be removed or changed in a future release,
|
|
14
|
+
even in minor or patch releases.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from typing import Any, Type
|
|
18
|
+
|
|
19
|
+
from marshmallow import Schema, ValidationError, fields
|
|
20
|
+
|
|
21
|
+
from .._apparent_power import ApparentPower
|
|
22
|
+
from .._current import Current
|
|
23
|
+
from .._energy import Energy
|
|
24
|
+
from .._frequency import Frequency
|
|
25
|
+
from .._percentage import Percentage
|
|
26
|
+
from .._power import Power
|
|
27
|
+
from .._quantity import Quantity
|
|
28
|
+
from .._reactive_power import ReactivePower
|
|
29
|
+
from .._temperature import Temperature
|
|
30
|
+
from .._voltage import Voltage
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class _QuantityField(fields.Field):
|
|
34
|
+
"""Custom field for Quantity objects supporting per-field serialization configuration.
|
|
35
|
+
|
|
36
|
+
This class handles serialization and deserialization of ALL Quantity
|
|
37
|
+
subclasses.
|
|
38
|
+
The specific Quantity subclass is determined by the field_type attribute.
|
|
39
|
+
|
|
40
|
+
* Deserialization auto-detects the type of deserialization (float or string)
|
|
41
|
+
based on the input type.
|
|
42
|
+
* Serialization uses either the schema's default or the per-field
|
|
43
|
+
configuration found in the metadata.
|
|
44
|
+
|
|
45
|
+
We need distinct QuantityField subclasses for each Quantity subclass, so
|
|
46
|
+
they can be used in the TYPE_MAPPING in the `QuantitySchema`.
|
|
47
|
+
Which means this class is not intended to be used directly.
|
|
48
|
+
|
|
49
|
+
Instead, we use the specific QuantityField subclasses for each Quantity.
|
|
50
|
+
Each field subclass simply sets the field_type attribute to the corresponding
|
|
51
|
+
Quantity subclass.
|
|
52
|
+
|
|
53
|
+
Those subclasses are generated and stored in the QUANTITY_FIELD_CLASSES
|
|
54
|
+
mapping and are used for the TYPE_MAPPING in the `QuantitySchema`.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
field_type: Type[Quantity] | None = None
|
|
58
|
+
"""The specific Quantity subclass."""
|
|
59
|
+
|
|
60
|
+
def _serialize(
|
|
61
|
+
self, value: Quantity, attr: str | None, obj: Any, **kwargs: Any
|
|
62
|
+
) -> Any:
|
|
63
|
+
"""Serialize the Quantity object based on per-field configuration."""
|
|
64
|
+
if self.field_type is None or not issubclass(self.field_type, Quantity):
|
|
65
|
+
raise TypeError(
|
|
66
|
+
"field_type must be set to a Quantity subclass in the subclass."
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
assert self.parent is not None
|
|
70
|
+
|
|
71
|
+
# Determine the serialization format
|
|
72
|
+
serialize_as_string = self.metadata.get(
|
|
73
|
+
"serialize_as_string",
|
|
74
|
+
self.parent.context.get("serialize_as_string_default", False),
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
if serialize_as_string:
|
|
78
|
+
# Use the Quantity's native string representation (includes unit)
|
|
79
|
+
return str(value)
|
|
80
|
+
|
|
81
|
+
# Serialize as float using the Quantity's base value
|
|
82
|
+
return value.base_value
|
|
83
|
+
|
|
84
|
+
def _deserialize(
|
|
85
|
+
self, value: Any, attr: str | None, data: Any, **kwargs: Any
|
|
86
|
+
) -> Quantity:
|
|
87
|
+
"""Deserialize the Quantity object from float or string."""
|
|
88
|
+
if self.field_type is None or not issubclass(self.field_type, Quantity):
|
|
89
|
+
raise TypeError(
|
|
90
|
+
"field_type must be set to a Quantity subclass in the subclass."
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
if isinstance(value, str):
|
|
94
|
+
# Use the Quantity's from_string method
|
|
95
|
+
try:
|
|
96
|
+
return self.field_type.from_string(value)
|
|
97
|
+
except Exception as error: # pylint: disable=broad-except
|
|
98
|
+
raise ValidationError(str(error)) from error
|
|
99
|
+
if isinstance(value, (float, int)):
|
|
100
|
+
try:
|
|
101
|
+
# Use `_new` method for creating instance from base value
|
|
102
|
+
return self.field_type._new( # pylint: disable=protected-access
|
|
103
|
+
float(value)
|
|
104
|
+
)
|
|
105
|
+
except Exception as error: # pylint: disable=broad-except
|
|
106
|
+
raise ValidationError(str(error)) from error
|
|
107
|
+
|
|
108
|
+
raise ValidationError("Invalid input type for QuantityField.")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
_QUANTITY_SUBCLASSES = [
|
|
112
|
+
ApparentPower,
|
|
113
|
+
Current,
|
|
114
|
+
Energy,
|
|
115
|
+
Frequency,
|
|
116
|
+
Percentage,
|
|
117
|
+
Power,
|
|
118
|
+
ReactivePower,
|
|
119
|
+
Temperature,
|
|
120
|
+
Voltage,
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class ApparentPowerField(_QuantityField):
|
|
125
|
+
"""Custom field for ApparentPower objects."""
|
|
126
|
+
|
|
127
|
+
field_type = ApparentPower
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class CurrentField(_QuantityField):
|
|
131
|
+
"""Custom field for Current objects."""
|
|
132
|
+
|
|
133
|
+
field_type = Current
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class EnergyField(_QuantityField):
|
|
137
|
+
"""Custom field for Energy objects."""
|
|
138
|
+
|
|
139
|
+
field_type = Energy
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class FrequencyField(_QuantityField):
|
|
143
|
+
"""Custom field for Frequency objects."""
|
|
144
|
+
|
|
145
|
+
field_type = Frequency
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class PercentageField(_QuantityField):
|
|
149
|
+
"""Custom field for Percentage objects."""
|
|
150
|
+
|
|
151
|
+
field_type = Percentage
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class PowerField(_QuantityField):
|
|
155
|
+
"""Custom field for Power objects."""
|
|
156
|
+
|
|
157
|
+
field_type = Power
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class ReactivePowerField(_QuantityField):
|
|
161
|
+
"""Custom field for ReactivePower objects."""
|
|
162
|
+
|
|
163
|
+
field_type = ReactivePower
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class TemperatureField(_QuantityField):
|
|
167
|
+
"""Custom field for Temperature objects."""
|
|
168
|
+
|
|
169
|
+
field_type = Temperature
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class VoltageField(_QuantityField):
|
|
173
|
+
"""Custom field for Voltage objects."""
|
|
174
|
+
|
|
175
|
+
field_type = Voltage
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
QUANTITY_FIELD_CLASSES: dict[type[Quantity], type[fields.Field]] = {
|
|
179
|
+
ApparentPower: ApparentPowerField,
|
|
180
|
+
Current: CurrentField,
|
|
181
|
+
Energy: EnergyField,
|
|
182
|
+
Frequency: FrequencyField,
|
|
183
|
+
Percentage: PercentageField,
|
|
184
|
+
Power: PowerField,
|
|
185
|
+
ReactivePower: ReactivePowerField,
|
|
186
|
+
Temperature: TemperatureField,
|
|
187
|
+
Voltage: VoltageField,
|
|
188
|
+
}
|
|
189
|
+
"""Mapping of Quantity subclasses to their corresponding QuantityField subclasses.
|
|
190
|
+
|
|
191
|
+
This mapping is used in the `QuantitySchema` to determine the correct field
|
|
192
|
+
class for each Quantity subclass.
|
|
193
|
+
|
|
194
|
+
The keys are Quantity subclasses (e.g., Percentage, Energy) and the values are
|
|
195
|
+
the corresponding QuantityField subclasses.
|
|
196
|
+
"""
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class QuantitySchema(Schema):
|
|
200
|
+
"""A schema for quantities.
|
|
201
|
+
|
|
202
|
+
Example usage:
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
from dataclasses import dataclass, field
|
|
206
|
+
from marshmallow_dataclass import class_schema
|
|
207
|
+
from marshmallow.validate import Range
|
|
208
|
+
from frequenz.quantities import Percentage
|
|
209
|
+
from frequenz.quantities.experimental.marshmallow import QuantitySchema
|
|
210
|
+
from typing import cast
|
|
211
|
+
|
|
212
|
+
@dataclass
|
|
213
|
+
class Config:
|
|
214
|
+
percentage_always_as_string: Percentage = field(
|
|
215
|
+
default_factory=lambda: Percentage.from_percent(25.0),
|
|
216
|
+
metadata={
|
|
217
|
+
"metadata": {
|
|
218
|
+
"description": "A percentage field",
|
|
219
|
+
},
|
|
220
|
+
"validate": Range(Percentage.zero(), Percentage.from_percent(100.0)),
|
|
221
|
+
"serialize_as_string": True,
|
|
222
|
+
},
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
percentage_always_as_float: Percentage = field(
|
|
226
|
+
default_factory=lambda: Percentage.from_percent(25.0),
|
|
227
|
+
metadata={
|
|
228
|
+
"metadata": {
|
|
229
|
+
"description": "A percentage field",
|
|
230
|
+
},
|
|
231
|
+
"validate": Range(Percentage.zero(), Percentage.from_percent(100.0)),
|
|
232
|
+
"serialize_as_string": False,
|
|
233
|
+
},
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
percentage_serialized_as_schema_default: Percentage = field(
|
|
237
|
+
default_factory=lambda: Percentage.from_percent(25.0),
|
|
238
|
+
metadata={
|
|
239
|
+
"metadata": {
|
|
240
|
+
"description": "A percentage field",
|
|
241
|
+
},
|
|
242
|
+
"validate": Range(Percentage.zero(), Percentage.from_percent(100.0)),
|
|
243
|
+
},
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
@classmethod
|
|
247
|
+
def load(cls, config: dict[str, Any]) -> "Config":
|
|
248
|
+
schema = class_schema(cls, base_schema=QuantitySchema)(
|
|
249
|
+
serialize_as_string_default=True # type: ignore[call-arg]
|
|
250
|
+
)
|
|
251
|
+
return cast(Config, schema.load(config))
|
|
252
|
+
```
|
|
253
|
+
"""
|
|
254
|
+
|
|
255
|
+
TYPE_MAPPING: dict[type[Quantity], type[fields.Field]] = QUANTITY_FIELD_CLASSES
|
|
256
|
+
|
|
257
|
+
def __init__(
|
|
258
|
+
self, *args: Any, serialize_as_string_default: bool = False, **kwargs: Any
|
|
259
|
+
) -> None:
|
|
260
|
+
"""
|
|
261
|
+
Initialize the schema with a default serialization format.
|
|
262
|
+
|
|
263
|
+
Args:
|
|
264
|
+
*args: Additional positional arguments.
|
|
265
|
+
serialize_as_string_default: Default serialization format for quantities.
|
|
266
|
+
If True, quantities are serialized as strings with units.
|
|
267
|
+
If False, quantities are serialized as floats.
|
|
268
|
+
**kwargs: Additional keyword arguments.
|
|
269
|
+
"""
|
|
270
|
+
super().__init__(*args, **kwargs)
|
|
271
|
+
self.context["serialize_as_string_default"] = serialize_as_string_default
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright © 2024 Frequenz Energy-as-a-Service GmbH
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: frequenz-quantities
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Types for holding quantities with units
|
|
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-quantities-python/
|
|
8
|
+
Project-URL: Changelog, https://github.com/frequenz-floss/frequenz-quantities-python/releases
|
|
9
|
+
Project-URL: Issues, https://github.com/frequenz-floss/frequenz-quantities-python/issues
|
|
10
|
+
Project-URL: Repository, https://github.com/frequenz-floss/frequenz-quantities-python
|
|
11
|
+
Project-URL: Support, https://github.com/frequenz-floss/frequenz-quantities-python/discussions/categories/support
|
|
12
|
+
Keywords: frequenz,python,lib,library,quantities,unit,conversion
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
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.5.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: frequenz-quantities[dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest,marshmallow]; extra == "dev"
|
|
26
|
+
Provides-Extra: dev-flake8
|
|
27
|
+
Requires-Dist: flake8==7.1.1; extra == "dev-flake8"
|
|
28
|
+
Requires-Dist: flake8-docstrings==1.7.0; extra == "dev-flake8"
|
|
29
|
+
Requires-Dist: flake8-pyproject==1.2.3; extra == "dev-flake8"
|
|
30
|
+
Requires-Dist: pydoclint==0.5.9; extra == "dev-flake8"
|
|
31
|
+
Requires-Dist: pydocstyle==6.3.0; extra == "dev-flake8"
|
|
32
|
+
Provides-Extra: dev-formatting
|
|
33
|
+
Requires-Dist: black==24.10.0; extra == "dev-formatting"
|
|
34
|
+
Requires-Dist: isort==5.13.2; extra == "dev-formatting"
|
|
35
|
+
Provides-Extra: dev-mkdocs
|
|
36
|
+
Requires-Dist: Markdown==3.7; extra == "dev-mkdocs"
|
|
37
|
+
Requires-Dist: black==24.10.0; extra == "dev-mkdocs"
|
|
38
|
+
Requires-Dist: mike==2.1.3; extra == "dev-mkdocs"
|
|
39
|
+
Requires-Dist: mkdocs-gen-files==0.5.0; extra == "dev-mkdocs"
|
|
40
|
+
Requires-Dist: mkdocs-literate-nav==0.6.1; extra == "dev-mkdocs"
|
|
41
|
+
Requires-Dist: mkdocs-macros-plugin==1.3.7; extra == "dev-mkdocs"
|
|
42
|
+
Requires-Dist: mkdocs-material==9.5.43; extra == "dev-mkdocs"
|
|
43
|
+
Requires-Dist: mkdocstrings[python]==0.26.2; extra == "dev-mkdocs"
|
|
44
|
+
Requires-Dist: mkdocstrings-python==1.12.2; extra == "dev-mkdocs"
|
|
45
|
+
Requires-Dist: frequenz-repo-config[lib]==0.10.0; extra == "dev-mkdocs"
|
|
46
|
+
Provides-Extra: dev-mypy
|
|
47
|
+
Requires-Dist: mypy==1.13.0; extra == "dev-mypy"
|
|
48
|
+
Requires-Dist: types-Markdown==3.7.0.20240822; extra == "dev-mypy"
|
|
49
|
+
Requires-Dist: frequenz-quantities[dev-mkdocs,dev-noxfile,dev-pytest,marshmallow]; extra == "dev-mypy"
|
|
50
|
+
Provides-Extra: dev-noxfile
|
|
51
|
+
Requires-Dist: nox==2024.10.9; extra == "dev-noxfile"
|
|
52
|
+
Requires-Dist: frequenz-repo-config[lib]==0.10.0; extra == "dev-noxfile"
|
|
53
|
+
Provides-Extra: dev-pylint
|
|
54
|
+
Requires-Dist: frequenz-quantities[dev-mkdocs,dev-noxfile,dev-pytest,marshmallow]; extra == "dev-pylint"
|
|
55
|
+
Provides-Extra: dev-pytest
|
|
56
|
+
Requires-Dist: pytest==8.3.3; extra == "dev-pytest"
|
|
57
|
+
Requires-Dist: pylint==3.3.1; extra == "dev-pytest"
|
|
58
|
+
Requires-Dist: frequenz-repo-config[extra-lint-examples]==0.10.0; extra == "dev-pytest"
|
|
59
|
+
Requires-Dist: pytest-mock==3.14.0; extra == "dev-pytest"
|
|
60
|
+
Requires-Dist: pytest-asyncio==0.24.0; extra == "dev-pytest"
|
|
61
|
+
Requires-Dist: async-solipsism==0.7; extra == "dev-pytest"
|
|
62
|
+
Requires-Dist: hypothesis==6.116.0; extra == "dev-pytest"
|
|
63
|
+
Requires-Dist: frequenz-quantities[marshmallow]; extra == "dev-pytest"
|
|
64
|
+
Provides-Extra: marshmallow
|
|
65
|
+
Requires-Dist: marshmallow<4,>=3.0.0; extra == "marshmallow"
|
|
66
|
+
Requires-Dist: marshmallow-dataclass<9,>=8.0.0; extra == "marshmallow"
|
|
67
|
+
|
|
68
|
+
# Frequenz Quantities Library
|
|
69
|
+
|
|
70
|
+
[](https://github.com/frequenz-floss/frequenz-quantities-python/actions/workflows/ci.yaml)
|
|
71
|
+
[](https://pypi.org/project/frequenz-quantities/)
|
|
72
|
+
[](https://frequenz-floss.github.io/frequenz-quantities-python/)
|
|
73
|
+
|
|
74
|
+
## Introduction
|
|
75
|
+
|
|
76
|
+
This library provide types for holding quantities with units. The main goal is
|
|
77
|
+
to avoid mistakes while working with different types of quantities, for example
|
|
78
|
+
avoiding adding a length to a time.
|
|
79
|
+
|
|
80
|
+
It also prevents mistakes when operating between the same quantity but in
|
|
81
|
+
different units, like adding a power in Joules to a power in Watts without
|
|
82
|
+
converting one of them.
|
|
83
|
+
|
|
84
|
+
Quantities store the value in a base unit, and then provide methods to get that
|
|
85
|
+
quantity as a particular unit.
|
|
86
|
+
|
|
87
|
+
## Documentation
|
|
88
|
+
|
|
89
|
+
For more information on how to use this library and examples, please check the
|
|
90
|
+
[Documentation website](https://frequenz-floss.github.io/frequenz-quantities-python/).
|
|
91
|
+
|
|
92
|
+
## Supported Platforms
|
|
93
|
+
|
|
94
|
+
The following platforms are officially supported (tested):
|
|
95
|
+
|
|
96
|
+
- **Python:** 3.11
|
|
97
|
+
- **Operating System:** Ubuntu Linux 20.04
|
|
98
|
+
- **Architectures:** amd64, arm64
|
|
99
|
+
|
|
100
|
+
## Contributing
|
|
101
|
+
|
|
102
|
+
If you want to know how to build this project and contribute to it, please
|
|
103
|
+
check out the [Contributing Guide](CONTRIBUTING.md).
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
frequenz/quantities/__init__.py,sha256=WCmf6AdoCd6qD25704053TCIWLVkbgT_EgAjBeOWsqY,4420
|
|
2
|
+
frequenz/quantities/_apparent_power.py,sha256=XYWhcAhYIU1a_ciLXwvUPaXTmpSSWsDP3C-W8kpQ4y0,6988
|
|
3
|
+
frequenz/quantities/_current.py,sha256=9y4v9AeZfr4cCkzFLbSzhzh7ZPXje7i5-V6nf0qdIgs,3573
|
|
4
|
+
frequenz/quantities/_energy.py,sha256=jfp2ZMb2bJV3etAZwNP7r3eWw0zcp1IQOI0hpTxVDFI,5274
|
|
5
|
+
frequenz/quantities/_frequency.py,sha256=Y_ljIdd-gBFbyBIFHhPeVeD2JQrPTwOeoHI79B7B-ys,2933
|
|
6
|
+
frequenz/quantities/_percentage.py,sha256=vdf7eBbr5EEHKj-0aPVLL6TSjE6OnFcHGN22knFTrlI,1775
|
|
7
|
+
frequenz/quantities/_power.py,sha256=KtT5hED-BzlGqFgKDZktE8UkudLV5khfBZ80zu0b2Vo,7074
|
|
8
|
+
frequenz/quantities/_quantity.py,sha256=sfYAc5hYRlkVRQ5AAgt-79x2-eZwYN1DrlxVrGxJEWw,17134
|
|
9
|
+
frequenz/quantities/_reactive_power.py,sha256=UiOKvY8oPW_7H2FFCE47FGyPIm-TcimfihK76fSUPFc,7203
|
|
10
|
+
frequenz/quantities/_temperature.py,sha256=PlQnavtvBe395ZmsgHTedh520pOAd9-jSRHkqfjv8-k,868
|
|
11
|
+
frequenz/quantities/_voltage.py,sha256=WuYLfC3FsWdWrHMfqxFYTAJmP1CdIFpPVeeGHlOV-eo,4057
|
|
12
|
+
frequenz/quantities/conftest.py,sha256=kxmvkzTdvGfh7SiDINIFX0FG9PU0EoKROl9YY75zN8w,409
|
|
13
|
+
frequenz/quantities/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
+
frequenz/quantities/experimental/__init__.py,sha256=nYOmkSXnHz9kqOf1QwawV0xFqRbBwjgKwGqbxFIVGeI,350
|
|
15
|
+
frequenz/quantities/experimental/marshmallow.py,sha256=P9P7GUVf9uE6fZZuPFxzWvsxeyh-bbPegQPG5OZMX5M,8742
|
|
16
|
+
frequenz_quantities-1.0.0.dist-info/LICENSE,sha256=zt0sW1KvE_KWE2ILOabrQYlfOoP0zUZXC3xCLrzGpIA,1089
|
|
17
|
+
frequenz_quantities-1.0.0.dist-info/METADATA,sha256=B9YoeLZd2CqsOS5L3kVt37vPA5y8MLnmhBsMPRGoTDs,5162
|
|
18
|
+
frequenz_quantities-1.0.0.dist-info/WHEEL,sha256=bFJAMchF8aTQGUgMZzHJyDDMPTO3ToJ7x23SLJa1SVo,92
|
|
19
|
+
frequenz_quantities-1.0.0.dist-info/top_level.txt,sha256=x08GRcWytsyKXa2Ayme9e5pg3L5Kcq6lw_BaQmToMO4,9
|
|
20
|
+
frequenz_quantities-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
frequenz
|