TypedUnit 0.0.7__tar.gz → 0.0.10__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.
- typedunit-0.0.10/.coveragerc +22 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/.github/dependabot.yml +1 -1
- {typedunit-0.0.7 → typedunit-0.0.10}/.github/workflows/deploy_anaconda.yml +4 -4
- typedunit-0.0.10/.gitignore +35 -0
- typedunit-0.0.10/.pre-commit-config.yaml +17 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/PKG-INFO +1 -1
- typedunit-0.0.10/TypedUnit/__init__.py +9 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit/_version.py +3 -3
- {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit/units.py +93 -46
- {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit.egg-info/PKG-INFO +1 -1
- {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit.egg-info/SOURCES.txt +3 -1
- {typedunit-0.0.7 → typedunit-0.0.10}/pyproject.toml +0 -24
- typedunit-0.0.10/pytest.ini +21 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/tests/test_0.py +191 -138
- typedunit-0.0.7/.gitignore +0 -28
- typedunit-0.0.7/TypedUnit/__init__.py +0 -9
- typedunit-0.0.7/docs/source/gallery/index.rst +0 -71
- {typedunit-0.0.7 → typedunit-0.0.10}/.flake8 +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/.github/workflows/deploy_PyPi.yml +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/.github/workflows/deploy_coverage.yml +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/.github/workflows/deploy_documentation.yml +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/LICENSE +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/README.rst +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit/directories.py +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit/helper.py +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit/utils.py +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit.egg-info/dependency_links.txt +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit.egg-info/requires.txt +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit.egg-info/top_level.txt +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/docs/Makefile +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/docs/examples/README.rst +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/docs/examples/example_0.py +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/docs/examples/example_1.py +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/docs/images/logo.png +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/docs/make.bat +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/_static/default.css +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/_static/thumbnail.png +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/code.rst +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/conf.py +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/index.rst +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/references.rst +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/sg_execution_times.rst +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/theory.rst +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/meta.yaml +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/setup.cfg +0 -0
- {typedunit-0.0.7 → typedunit-0.0.10}/tests/__init__.py +0 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# .coveragerc
|
|
2
|
+
[run]
|
|
3
|
+
source = TypedUnit
|
|
4
|
+
branch = True
|
|
5
|
+
relative_files = True
|
|
6
|
+
parallel = True
|
|
7
|
+
omit =
|
|
8
|
+
**/__init__.py
|
|
9
|
+
TypedUnit/_version.py
|
|
10
|
+
TypedUnit/directories.py
|
|
11
|
+
TypedUnit/**/__main__.py
|
|
12
|
+
|
|
13
|
+
[report]
|
|
14
|
+
skip_covered = True
|
|
15
|
+
show_missing = True
|
|
16
|
+
precision = 2
|
|
17
|
+
|
|
18
|
+
[html]
|
|
19
|
+
directory = htmlcov
|
|
20
|
+
|
|
21
|
+
[xml]
|
|
22
|
+
output = coverage.xml
|
|
@@ -11,11 +11,11 @@ permissions:
|
|
|
11
11
|
contents: write
|
|
12
12
|
|
|
13
13
|
jobs:
|
|
14
|
-
|
|
14
|
+
linux:
|
|
15
15
|
uses: MartinPdeS/MPSActions/.github/workflows/publish_compiled_package_to_anaconda.yml@master
|
|
16
16
|
with:
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
python_versions: '["3.11", "3.12", "3.13"]'
|
|
18
|
+
apt_package: ""
|
|
19
|
+
os_list: '["ubuntu-latest", "macos-latest", "windows-latest"]'
|
|
19
20
|
secrets:
|
|
20
21
|
ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_API_TOKEN }}
|
|
21
|
-
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
# Ignore all
|
|
3
|
+
/*
|
|
4
|
+
|
|
5
|
+
# Except ...
|
|
6
|
+
!.github
|
|
7
|
+
!.gitmodules
|
|
8
|
+
!extern
|
|
9
|
+
!TypedUnit
|
|
10
|
+
!development
|
|
11
|
+
!docs
|
|
12
|
+
!tests
|
|
13
|
+
!.flake8
|
|
14
|
+
!.gitignore
|
|
15
|
+
!.pre-commit-config.yaml
|
|
16
|
+
!LICENSE
|
|
17
|
+
!meta.yaml
|
|
18
|
+
!pyproject.toml
|
|
19
|
+
!README.rst
|
|
20
|
+
!notebook.ipynb
|
|
21
|
+
!CMakeLists.txt
|
|
22
|
+
!pytest.ini
|
|
23
|
+
!.coveragerc
|
|
24
|
+
|
|
25
|
+
# But ignore docs/build inside docs and code
|
|
26
|
+
docs/build/
|
|
27
|
+
docs/source/gallery/
|
|
28
|
+
|
|
29
|
+
# Compiled files in the project
|
|
30
|
+
*__pycache__*
|
|
31
|
+
*.DS_Store*
|
|
32
|
+
*.so*
|
|
33
|
+
*.a*
|
|
34
|
+
|
|
35
|
+
# Package specifics
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v4.6.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: check-merge-conflict
|
|
6
|
+
- id: end-of-file-fixer
|
|
7
|
+
- id: mixed-line-ending
|
|
8
|
+
- id: check-yaml
|
|
9
|
+
- id: check-toml
|
|
10
|
+
- id: detect-private-key
|
|
11
|
+
- id: check-json
|
|
12
|
+
- id: check-case-conflict
|
|
13
|
+
|
|
14
|
+
- repo: https://github.com/psf/black
|
|
15
|
+
rev: 24.4.2
|
|
16
|
+
hooks:
|
|
17
|
+
- id: black
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.0.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 0,
|
|
31
|
+
__version__ = version = '0.0.10'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 0, 10)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g159a86b15'
|
|
@@ -3,7 +3,7 @@ import pint as _pint
|
|
|
3
3
|
from pint import Quantity, UnitRegistry
|
|
4
4
|
import pint_pandas as pint
|
|
5
5
|
|
|
6
|
-
ureg = UnitRegistry()
|
|
6
|
+
ureg = UnitRegistry(autoconvert_offset_to_baseunit=True)
|
|
7
7
|
ureg.setup_matplotlib()
|
|
8
8
|
|
|
9
9
|
_pint.set_application_registry(ureg)
|
|
@@ -12,12 +12,44 @@ ureg.define("photoelectron = [Float64]") # Define a custom unit 'photoelectron'
|
|
|
12
12
|
ureg.define("event = [Int64]") # Define a custom unit 'events'
|
|
13
13
|
ureg.define("sqrt_hertz = Hz**0.5")
|
|
14
14
|
ureg.define("bit_bins = ![Int64]")
|
|
15
|
+
ureg.define("dB_per_Hz = dB / hertz")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"Energy",
|
|
20
|
+
"Time",
|
|
21
|
+
"Power",
|
|
22
|
+
"Voltage",
|
|
23
|
+
"Current",
|
|
24
|
+
"Resistance",
|
|
25
|
+
"Temperature",
|
|
26
|
+
"Length",
|
|
27
|
+
"Volume",
|
|
28
|
+
"FlowRate",
|
|
29
|
+
"Frequency",
|
|
30
|
+
"Angle",
|
|
31
|
+
"Mass",
|
|
32
|
+
"RefractiveIndex",
|
|
33
|
+
"Dimensionless",
|
|
34
|
+
"Responsitivity",
|
|
35
|
+
"Viscosity",
|
|
36
|
+
"Area",
|
|
37
|
+
"ElectricField",
|
|
38
|
+
"Velocity",
|
|
39
|
+
"Ohm",
|
|
40
|
+
"Concentration",
|
|
41
|
+
"Particle",
|
|
42
|
+
"ParticleFlux",
|
|
43
|
+
"AnyUnit",
|
|
44
|
+
]
|
|
45
|
+
|
|
15
46
|
|
|
16
47
|
class UnitMeta(type):
|
|
17
48
|
"""
|
|
18
49
|
Metaclass that makes isinstance(x, SomeUnit) return True
|
|
19
50
|
when x is a pint.Quantity with the right dimensionality.
|
|
20
51
|
"""
|
|
52
|
+
|
|
21
53
|
def __instancecheck__(cls, obj):
|
|
22
54
|
if not isinstance(obj, Quantity):
|
|
23
55
|
return False
|
|
@@ -44,7 +76,9 @@ class UnitMeta(type):
|
|
|
44
76
|
a = cls.__name__
|
|
45
77
|
b = other.__name__
|
|
46
78
|
name = f"{a}Times{b}"
|
|
47
|
-
expected =
|
|
79
|
+
expected = (
|
|
80
|
+
f"({getattr(cls, '_expected_dim')})*({getattr(other, '_expected_dim')})"
|
|
81
|
+
)
|
|
48
82
|
return UnitMeta(name, (BaseUnit,), {"_expected_dim": expected})
|
|
49
83
|
|
|
50
84
|
def __pow__(cls, power):
|
|
@@ -54,6 +88,7 @@ class UnitMeta(type):
|
|
|
54
88
|
expected = f"({getattr(cls, '_expected_dim')})**{power}"
|
|
55
89
|
return UnitMeta(name, (BaseUnit,), {"_expected_dim": expected})
|
|
56
90
|
|
|
91
|
+
|
|
57
92
|
class BaseUnit(metaclass=UnitMeta):
|
|
58
93
|
_expected_dim: str | None = None
|
|
59
94
|
|
|
@@ -61,151 +96,163 @@ class BaseUnit(metaclass=UnitMeta):
|
|
|
61
96
|
def check(cls, value):
|
|
62
97
|
if cls._expected_dim is None:
|
|
63
98
|
return value
|
|
64
|
-
assert isinstance(
|
|
65
|
-
|
|
99
|
+
assert isinstance(
|
|
100
|
+
value, Quantity
|
|
101
|
+
), f"Expected a pint Quantity [{cls._expected_dim}] instance, got {type(value)}"
|
|
102
|
+
assert value.check(
|
|
103
|
+
cls._expected_dim
|
|
104
|
+
), f"Value units {value.dimensionality} do not match {cls.__name__} units"
|
|
66
105
|
return value
|
|
67
106
|
|
|
107
|
+
|
|
68
108
|
class Energy(BaseUnit):
|
|
69
109
|
"""Quantity specifically for energy units."""
|
|
110
|
+
|
|
70
111
|
_expected_dim = "joule"
|
|
71
112
|
|
|
113
|
+
|
|
72
114
|
class Time(BaseUnit):
|
|
73
115
|
"""Quantity specifically for time units."""
|
|
116
|
+
|
|
74
117
|
_expected_dim = "second"
|
|
75
118
|
|
|
119
|
+
|
|
76
120
|
class Power(BaseUnit):
|
|
77
121
|
"""Quantity specifically for power units."""
|
|
122
|
+
|
|
78
123
|
_expected_dim = "watt"
|
|
79
124
|
|
|
125
|
+
|
|
80
126
|
class Voltage(BaseUnit):
|
|
81
127
|
"""Quantity specifically for voltage units."""
|
|
128
|
+
|
|
82
129
|
_expected_dim = "volt"
|
|
83
130
|
|
|
131
|
+
|
|
84
132
|
class Current(BaseUnit):
|
|
85
133
|
"""Quantity specifically for current units."""
|
|
134
|
+
|
|
86
135
|
_expected_dim = "ampere"
|
|
87
136
|
|
|
137
|
+
|
|
88
138
|
class Resistance(BaseUnit):
|
|
89
139
|
"""Quantity specifically for resistance units."""
|
|
140
|
+
|
|
90
141
|
_expected_dim = "ohm"
|
|
91
142
|
|
|
143
|
+
|
|
92
144
|
class Temperature(BaseUnit):
|
|
93
145
|
"""Quantity specifically for temperature units."""
|
|
146
|
+
|
|
94
147
|
_expected_dim = "kelvin"
|
|
95
148
|
|
|
149
|
+
|
|
96
150
|
class Length(BaseUnit):
|
|
97
151
|
"""Quantity specifically for length units."""
|
|
152
|
+
|
|
98
153
|
_expected_dim = "meter"
|
|
99
154
|
|
|
155
|
+
|
|
100
156
|
class Volume(BaseUnit):
|
|
101
157
|
"""Quantity specifically for volume units."""
|
|
158
|
+
|
|
102
159
|
_expected_dim = "liter"
|
|
103
160
|
|
|
161
|
+
|
|
104
162
|
class FlowRate(BaseUnit):
|
|
105
163
|
"""Quantity specifically for flow rate units."""
|
|
164
|
+
|
|
106
165
|
_expected_dim = "liter / second"
|
|
107
166
|
|
|
167
|
+
|
|
108
168
|
class Frequency(BaseUnit):
|
|
109
169
|
"""Quantity specifically for frequency units."""
|
|
170
|
+
|
|
110
171
|
_expected_dim = "hertz"
|
|
111
172
|
|
|
173
|
+
|
|
112
174
|
class Angle(BaseUnit):
|
|
113
175
|
"""Quantity specifically for angle units."""
|
|
176
|
+
|
|
114
177
|
_expected_dim = "degree"
|
|
115
178
|
|
|
179
|
+
|
|
116
180
|
class Mass(BaseUnit):
|
|
117
181
|
"""Quantity specifically for mass units."""
|
|
182
|
+
|
|
118
183
|
_expected_dim = "kilogram"
|
|
119
184
|
|
|
185
|
+
|
|
120
186
|
class RefractiveIndex(BaseUnit):
|
|
121
187
|
"""Quantity specifically for refractive index units."""
|
|
188
|
+
|
|
122
189
|
_expected_dim = "refractive_index_units"
|
|
123
190
|
|
|
191
|
+
|
|
124
192
|
class Dimensionless(BaseUnit):
|
|
125
193
|
"""Quantity specifically for dimensionless units."""
|
|
194
|
+
|
|
126
195
|
_expected_dim = ""
|
|
127
196
|
|
|
197
|
+
|
|
128
198
|
class Responsitivity(BaseUnit):
|
|
129
199
|
"""Quantity specifically for responsitivity units."""
|
|
200
|
+
|
|
130
201
|
_expected_dim = "ampere / watt"
|
|
131
202
|
|
|
203
|
+
|
|
132
204
|
class Viscosity(BaseUnit):
|
|
133
205
|
"""Quantity specifically for viscosity units."""
|
|
206
|
+
|
|
134
207
|
_expected_dim = "pascal * second"
|
|
135
208
|
|
|
209
|
+
|
|
136
210
|
class Area(BaseUnit):
|
|
137
211
|
"""Quantity specifically for viscosity units."""
|
|
212
|
+
|
|
138
213
|
_expected_dim = "meter * meter"
|
|
139
214
|
|
|
215
|
+
|
|
140
216
|
class ElectricField(BaseUnit):
|
|
141
217
|
"""Quantity specifically for electric field units."""
|
|
218
|
+
|
|
142
219
|
_expected_dim = "volt / meter"
|
|
143
220
|
|
|
221
|
+
|
|
144
222
|
class Velocity(BaseUnit):
|
|
145
223
|
"""Quantity specifically for velocity units."""
|
|
224
|
+
|
|
146
225
|
_expected_dim = "meter / second"
|
|
147
226
|
|
|
227
|
+
|
|
148
228
|
class Ohm(BaseUnit):
|
|
149
229
|
"""Quantity specifically for resistance units."""
|
|
230
|
+
|
|
150
231
|
_expected_dim = "ohm"
|
|
151
232
|
|
|
233
|
+
|
|
152
234
|
class Concentration(BaseUnit):
|
|
153
235
|
"""Quantity specifically for concentration units."""
|
|
236
|
+
|
|
154
237
|
_expected_dim = "particle / liter"
|
|
155
238
|
|
|
239
|
+
|
|
156
240
|
class Particle(BaseUnit):
|
|
157
241
|
"""Quantity specifically for particle units."""
|
|
242
|
+
|
|
158
243
|
_expected_dim = "particle"
|
|
159
244
|
|
|
245
|
+
|
|
160
246
|
class ParticleFlux(BaseUnit):
|
|
161
247
|
"""Quantity specifically for particle flux units."""
|
|
248
|
+
|
|
162
249
|
_expected_dim = "particle / second"
|
|
163
250
|
|
|
164
|
-
class Any(BaseUnit):
|
|
165
|
-
"""Quantity that can have any unit."""
|
|
166
|
-
_expected_dim = None # Accept any dimensionality
|
|
167
251
|
|
|
168
252
|
class AnyUnit(BaseUnit):
|
|
169
253
|
"""Quantity that can have any unit."""
|
|
170
|
-
_expected_dim = None # Accept any dimensionality
|
|
171
|
-
|
|
172
|
-
ureg.AU = ureg.dimensionless
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
# from pydantic.dataclasses import dataclass
|
|
185
|
-
|
|
186
|
-
# config_dict = dict(
|
|
187
|
-
# arbitrary_types_allowed=True,
|
|
188
|
-
# kw_only=True,
|
|
189
|
-
# slots=True,
|
|
190
|
-
# extra='forbid'
|
|
191
|
-
# )
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
# @dataclass(config=config_dict)
|
|
197
|
-
# class Sphere():
|
|
198
|
-
# name: str
|
|
199
|
-
# refractive_index: RefractiveIndex
|
|
200
|
-
# diameter: Length
|
|
201
|
-
# particle_count: Particle
|
|
202
254
|
|
|
255
|
+
_expected_dim = None # Accept any dimensionality
|
|
203
256
|
|
|
204
|
-
# test = Sphere(
|
|
205
|
-
# name="Test Sphere",
|
|
206
|
-
# refractive_index=1 * ureg.refractive_index_units,
|
|
207
|
-
# diameter=1 * ureg.meter,
|
|
208
|
-
# particle_count=1 * 5e9 * ureg.particle / ureg.milliliter
|
|
209
|
-
# )
|
|
210
257
|
|
|
211
|
-
|
|
258
|
+
ureg.AU = ureg.dimensionless
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
.coveragerc
|
|
1
2
|
.flake8
|
|
2
3
|
.gitignore
|
|
4
|
+
.pre-commit-config.yaml
|
|
3
5
|
LICENSE
|
|
4
6
|
README.rst
|
|
5
7
|
meta.yaml
|
|
6
8
|
pyproject.toml
|
|
9
|
+
pytest.ini
|
|
7
10
|
.github/dependabot.yml
|
|
8
11
|
.github/workflows/deploy_PyPi.yml
|
|
9
12
|
.github/workflows/deploy_anaconda.yml
|
|
@@ -34,6 +37,5 @@ docs/source/sg_execution_times.rst
|
|
|
34
37
|
docs/source/theory.rst
|
|
35
38
|
docs/source/_static/default.css
|
|
36
39
|
docs/source/_static/thumbnail.png
|
|
37
|
-
docs/source/gallery/index.rst
|
|
38
40
|
tests/__init__.py
|
|
39
41
|
tests/test_0.py
|
|
@@ -61,27 +61,3 @@ documentation = [
|
|
|
61
61
|
"sphinx-rtd-theme >=2,<4",
|
|
62
62
|
"pydata-sphinx-theme ~=0.15"
|
|
63
63
|
]
|
|
64
|
-
|
|
65
|
-
[tool.pytest.ini_options]
|
|
66
|
-
minversion = "6.0"
|
|
67
|
-
xfail_strict = true
|
|
68
|
-
log_cli_level = "INFO"
|
|
69
|
-
testpaths = ["tests"]
|
|
70
|
-
addopts = [
|
|
71
|
-
'-v',
|
|
72
|
-
'-rA',
|
|
73
|
-
'-rw',
|
|
74
|
-
'--cov=TypedUnit',
|
|
75
|
-
'--cov-report=html',
|
|
76
|
-
"--cov-report=term"
|
|
77
|
-
]
|
|
78
|
-
|
|
79
|
-
[tool.coverage.run]
|
|
80
|
-
source = ['TypedUnit']
|
|
81
|
-
omit = [
|
|
82
|
-
'*\__init__.py',
|
|
83
|
-
'*/_version.py',
|
|
84
|
-
'*/directories.py',
|
|
85
|
-
]
|
|
86
|
-
branch = true
|
|
87
|
-
relative_files = true
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# pytest.ini
|
|
2
|
+
[pytest]
|
|
3
|
+
minversion = 6.0
|
|
4
|
+
xfail_strict = true
|
|
5
|
+
log_cli_level = INFO
|
|
6
|
+
|
|
7
|
+
addopts =
|
|
8
|
+
-vv
|
|
9
|
+
-rA
|
|
10
|
+
-rw
|
|
11
|
+
--cov
|
|
12
|
+
--cov-report=html
|
|
13
|
+
--cov-report=term
|
|
14
|
+
--cov-config=.coveragerc
|
|
15
|
+
--capture=tee-sys
|
|
16
|
+
|
|
17
|
+
testpaths = tests
|
|
18
|
+
|
|
19
|
+
python_files = *.py
|
|
20
|
+
python_classes = Test_*
|
|
21
|
+
python_functions = test_*
|
|
@@ -16,96 +16,123 @@ import numpy
|
|
|
16
16
|
|
|
17
17
|
# Import the TypedUnits components
|
|
18
18
|
from TypedUnit import (
|
|
19
|
-
Energy,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
Energy,
|
|
20
|
+
Time,
|
|
21
|
+
Power,
|
|
22
|
+
Voltage,
|
|
23
|
+
Current,
|
|
24
|
+
Resistance,
|
|
25
|
+
Temperature,
|
|
26
|
+
Length,
|
|
27
|
+
Volume,
|
|
28
|
+
FlowRate,
|
|
29
|
+
Frequency,
|
|
30
|
+
Mass,
|
|
31
|
+
Angle,
|
|
32
|
+
RefractiveIndex,
|
|
33
|
+
Dimensionless,
|
|
34
|
+
ureg,
|
|
35
|
+
Quantity,
|
|
36
|
+
validate_units,
|
|
23
37
|
)
|
|
24
38
|
|
|
25
39
|
|
|
26
40
|
# Test data for parametrized tests
|
|
27
|
-
@pytest.mark.parametrize(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
(1 * ureg.RIU, RefractiveIndex, True),
|
|
74
|
-
(1 * ureg.dimensionless, Dimensionless, True),
|
|
75
|
-
(1 * ureg.gram, Mass, True)
|
|
76
|
-
])
|
|
41
|
+
@pytest.mark.parametrize(
|
|
42
|
+
"quantity,unit_type,expected",
|
|
43
|
+
[
|
|
44
|
+
# Energy tests
|
|
45
|
+
(100 * ureg.joule, Energy, True),
|
|
46
|
+
(1.5 * ureg.kilowatt_hour, Energy, True),
|
|
47
|
+
(250 * ureg.calorie, Energy, True),
|
|
48
|
+
(10 * ureg.second, Energy, False), # Time, not Energy
|
|
49
|
+
(5 * ureg.meter, Energy, False), # Length, not Energy
|
|
50
|
+
# Time tests
|
|
51
|
+
(30 * ureg.second, Time, True),
|
|
52
|
+
(5 * ureg.minute, Time, True),
|
|
53
|
+
(2 * ureg.hour, Time, True),
|
|
54
|
+
(500 * ureg.millisecond, Time, True),
|
|
55
|
+
(100 * ureg.joule, Time, False), # Energy, not Time
|
|
56
|
+
# Power tests
|
|
57
|
+
(1500 * ureg.watt, Power, True),
|
|
58
|
+
(2.5 * ureg.kilowatt, Power, True),
|
|
59
|
+
(1 * ureg.horsepower, Power, True),
|
|
60
|
+
(12 * ureg.volt, Power, False), # Voltage, not Power
|
|
61
|
+
# Electrical units
|
|
62
|
+
(12 * ureg.volt, Voltage, True),
|
|
63
|
+
(2.5 * ureg.ampere, Current, True),
|
|
64
|
+
(4.8 * ureg.ohm, Resistance, True),
|
|
65
|
+
(12 * ureg.volt, Current, False), # Cross-check
|
|
66
|
+
(2.5 * ureg.ampere, Resistance, False),
|
|
67
|
+
# Mechanical units
|
|
68
|
+
(10 * ureg.meter, Length, True),
|
|
69
|
+
(50 * ureg.millimeter, Length, True),
|
|
70
|
+
(2 * ureg.kilometer, Length, True),
|
|
71
|
+
(5 * ureg.liter, Volume, True),
|
|
72
|
+
(250 * ureg.milliliter, Volume, True),
|
|
73
|
+
(10 * ureg.meter, Volume, False), # Length, not Volume
|
|
74
|
+
# Temperature tests
|
|
75
|
+
(300 * ureg.kelvin, Temperature, True),
|
|
76
|
+
(77 * ureg.kelvin, Temperature, True),
|
|
77
|
+
# (50 * ureg.hertz, Temperature, False),
|
|
78
|
+
# # Frequency and angle
|
|
79
|
+
(50 * ureg.hertz, Frequency, True),
|
|
80
|
+
(1.57 * ureg.radian, Angle, True),
|
|
81
|
+
# Other tests
|
|
82
|
+
(1 * ureg.RIU, RefractiveIndex, True),
|
|
83
|
+
(1 * ureg.dimensionless, Dimensionless, True),
|
|
84
|
+
(1 * ureg.gram, Mass, True),
|
|
85
|
+
],
|
|
86
|
+
)
|
|
77
87
|
def test_unit_type_checking(quantity, unit_type, expected):
|
|
78
88
|
"""Test isinstance() functionality for all unit types."""
|
|
79
89
|
assert isinstance(quantity, unit_type) == expected
|
|
80
90
|
|
|
81
91
|
|
|
82
|
-
@pytest.mark.parametrize(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
@pytest.mark.parametrize(
|
|
93
|
+
"non_quantity",
|
|
94
|
+
[
|
|
95
|
+
42, # int
|
|
96
|
+
3.14, # float
|
|
97
|
+
"10 meters", # string
|
|
98
|
+
[1, 2, 3], # list
|
|
99
|
+
{"value": 10}, # dict
|
|
100
|
+
None, # None
|
|
101
|
+
],
|
|
102
|
+
)
|
|
90
103
|
def test_non_quantity_objects_rejected(non_quantity):
|
|
91
104
|
"""Test that non-Quantity objects are properly rejected by all unit types."""
|
|
92
|
-
unit_types = [
|
|
93
|
-
|
|
105
|
+
unit_types = [
|
|
106
|
+
Energy,
|
|
107
|
+
Time,
|
|
108
|
+
Power,
|
|
109
|
+
Voltage,
|
|
110
|
+
Current,
|
|
111
|
+
Resistance,
|
|
112
|
+
Temperature,
|
|
113
|
+
Length,
|
|
114
|
+
Volume,
|
|
115
|
+
Frequency,
|
|
116
|
+
Angle,
|
|
117
|
+
]
|
|
94
118
|
|
|
95
119
|
for unit_type in unit_types:
|
|
96
120
|
assert not isinstance(non_quantity, unit_type)
|
|
97
121
|
|
|
98
122
|
|
|
99
|
-
@pytest.mark.parametrize(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
123
|
+
@pytest.mark.parametrize(
|
|
124
|
+
"unit_type,valid_quantity,invalid_quantity",
|
|
125
|
+
[
|
|
126
|
+
(Energy, 100 * ureg.joule, 10 * ureg.meter),
|
|
127
|
+
(Time, 30 * ureg.second, 100 * ureg.joule),
|
|
128
|
+
(Power, 1500 * ureg.watt, 10 * ureg.meter),
|
|
129
|
+
(Voltage, 12 * ureg.volt, 5 * ureg.ampere),
|
|
130
|
+
(Current, 2.5 * ureg.ampere, 12 * ureg.volt),
|
|
131
|
+
(Resistance, 4.8 * ureg.ohm, 100 * ureg.joule),
|
|
132
|
+
(Length, 100 * ureg.meter, 50 * ureg.joule),
|
|
133
|
+
(Temperature, 300 * ureg.kelvin, 2.5 * ureg.ampere),
|
|
134
|
+
],
|
|
135
|
+
)
|
|
109
136
|
def test_unit_check_methods(unit_type, valid_quantity, invalid_quantity):
|
|
110
137
|
"""Test the check() methods for various unit types."""
|
|
111
138
|
# Valid quantity should pass
|
|
@@ -116,48 +143,60 @@ def test_unit_check_methods(unit_type, valid_quantity, invalid_quantity):
|
|
|
116
143
|
unit_type.check(invalid_quantity)
|
|
117
144
|
|
|
118
145
|
|
|
119
|
-
@pytest.mark.parametrize(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
146
|
+
@pytest.mark.parametrize(
|
|
147
|
+
"invalid_input",
|
|
148
|
+
[
|
|
149
|
+
42,
|
|
150
|
+
3.14,
|
|
151
|
+
"not a quantity",
|
|
152
|
+
None,
|
|
153
|
+
[1, 2, 3],
|
|
154
|
+
],
|
|
155
|
+
)
|
|
126
156
|
def test_check_method_rejects_non_quantities(invalid_input):
|
|
127
157
|
"""Test that check() methods reject non-Quantity objects."""
|
|
128
|
-
with pytest.raises(AssertionError, match="Expected a pint Quantity
|
|
158
|
+
with pytest.raises(AssertionError, match="Expected a pint Quantity"):
|
|
129
159
|
Energy.check(invalid_input)
|
|
130
160
|
|
|
131
161
|
|
|
132
|
-
@pytest.mark.parametrize(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
162
|
+
@pytest.mark.parametrize(
|
|
163
|
+
"energy_quantity",
|
|
164
|
+
[
|
|
165
|
+
100 * ureg.joule,
|
|
166
|
+
1.5 * ureg.kilowatt_hour,
|
|
167
|
+
250 * ureg.calorie,
|
|
168
|
+
500 * ureg.british_thermal_unit,
|
|
169
|
+
],
|
|
170
|
+
)
|
|
138
171
|
def test_energy_type_checking_various_units(energy_quantity):
|
|
139
172
|
"""Test Energy type checking with various energy units."""
|
|
140
173
|
assert isinstance(energy_quantity, Energy)
|
|
141
174
|
|
|
142
175
|
|
|
143
|
-
@pytest.mark.parametrize(
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
176
|
+
@pytest.mark.parametrize(
|
|
177
|
+
"time_quantity",
|
|
178
|
+
[
|
|
179
|
+
30 * ureg.second,
|
|
180
|
+
5 * ureg.minute,
|
|
181
|
+
2 * ureg.hour,
|
|
182
|
+
500 * ureg.millisecond,
|
|
183
|
+
0.1 * ureg.microsecond,
|
|
184
|
+
],
|
|
185
|
+
)
|
|
150
186
|
def test_time_type_checking_various_units(time_quantity):
|
|
151
187
|
"""Test Time type checking with various time units."""
|
|
152
188
|
assert isinstance(time_quantity, Time)
|
|
153
189
|
|
|
154
190
|
|
|
155
|
-
@pytest.mark.parametrize(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
191
|
+
@pytest.mark.parametrize(
|
|
192
|
+
"power_quantity",
|
|
193
|
+
[
|
|
194
|
+
1500 * ureg.watt,
|
|
195
|
+
2.5 * ureg.kilowatt,
|
|
196
|
+
1 * ureg.horsepower,
|
|
197
|
+
100 * ureg.milliwatt,
|
|
198
|
+
],
|
|
199
|
+
)
|
|
161
200
|
def test_power_type_checking_various_units(power_quantity):
|
|
162
201
|
"""Test Power type checking with various power units."""
|
|
163
202
|
assert isinstance(power_quantity, Power)
|
|
@@ -191,32 +230,41 @@ def test_mechanical_units_cross_checking():
|
|
|
191
230
|
assert not isinstance(volume, Length)
|
|
192
231
|
|
|
193
232
|
|
|
194
|
-
@pytest.mark.parametrize(
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
233
|
+
@pytest.mark.parametrize(
|
|
234
|
+
"temperature_quantity",
|
|
235
|
+
[
|
|
236
|
+
300 * ureg.kelvin,
|
|
237
|
+
# 25 * ureg.celsius,
|
|
238
|
+
# 77 * ureg.fahrenheit,
|
|
239
|
+
],
|
|
240
|
+
)
|
|
199
241
|
def test_temperature_type_checking_various_units(temperature_quantity):
|
|
200
242
|
"""Test temperature type checking with various units."""
|
|
201
243
|
assert isinstance(temperature_quantity, Temperature)
|
|
202
244
|
|
|
203
245
|
|
|
204
|
-
@pytest.mark.parametrize(
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
246
|
+
@pytest.mark.parametrize(
|
|
247
|
+
"frequency_quantity",
|
|
248
|
+
[
|
|
249
|
+
50 * ureg.hertz,
|
|
250
|
+
2.4 * ureg.kilohertz,
|
|
251
|
+
1.0 * ureg.megahertz,
|
|
252
|
+
],
|
|
253
|
+
)
|
|
209
254
|
def test_frequency_type_checking_various_units(frequency_quantity):
|
|
210
255
|
"""Test frequency type checking with various units."""
|
|
211
256
|
assert isinstance(frequency_quantity, Frequency)
|
|
212
257
|
|
|
213
258
|
|
|
214
|
-
@pytest.mark.parametrize(
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
259
|
+
@pytest.mark.parametrize(
|
|
260
|
+
"angle_quantity",
|
|
261
|
+
[
|
|
262
|
+
45 * ureg.degree,
|
|
263
|
+
1.57 * ureg.radian,
|
|
264
|
+
90 * ureg.degree,
|
|
265
|
+
3.14159 * ureg.radian,
|
|
266
|
+
],
|
|
267
|
+
)
|
|
220
268
|
def test_angle_type_checking_various_units(angle_quantity):
|
|
221
269
|
"""Test angle type checking with various units."""
|
|
222
270
|
assert isinstance(angle_quantity, Angle)
|
|
@@ -298,11 +346,14 @@ def test_no_annotation_parameters_validation():
|
|
|
298
346
|
assert isinstance(result, Quantity)
|
|
299
347
|
|
|
300
348
|
|
|
301
|
-
@pytest.mark.parametrize(
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
349
|
+
@pytest.mark.parametrize(
|
|
350
|
+
"energy_quantity",
|
|
351
|
+
[
|
|
352
|
+
1000 * ureg.joule,
|
|
353
|
+
1.5 * ureg.kilowatt_hour,
|
|
354
|
+
250 * ureg.calorie,
|
|
355
|
+
],
|
|
356
|
+
)
|
|
306
357
|
def test_energy_conversions(energy_quantity):
|
|
307
358
|
"""Test energy unit conversions preserve type checking."""
|
|
308
359
|
# Convert to different energy units
|
|
@@ -352,13 +403,10 @@ def test_unit_arithmetic_cross_types():
|
|
|
352
403
|
assert isinstance(energy, Energy)
|
|
353
404
|
|
|
354
405
|
|
|
355
|
-
@pytest.mark.parametrize(
|
|
356
|
-
|
|
357
|
-
42,
|
|
358
|
-
|
|
359
|
-
[100, ureg.joule],
|
|
360
|
-
{'value': 100, 'unit': 'joule'}
|
|
361
|
-
])
|
|
406
|
+
@pytest.mark.parametrize(
|
|
407
|
+
"invalid_input",
|
|
408
|
+
[None, 42, "10 joules", [100, ureg.joule], {"value": 100, "unit": "joule"}],
|
|
409
|
+
)
|
|
362
410
|
def test_invalid_quantity_detection(invalid_input):
|
|
363
411
|
"""Test detection of invalid quantities."""
|
|
364
412
|
assert not isinstance(invalid_input, Energy)
|
|
@@ -410,15 +458,20 @@ def test_physics_calculations_integration():
|
|
|
410
458
|
|
|
411
459
|
# Verify the calculation
|
|
412
460
|
assert power.magnitude == 60 # 12V * 5A = 60W
|
|
413
|
-
assert numpy.isclose(
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
461
|
+
assert numpy.isclose(
|
|
462
|
+
work.to(ureg.kilowatt_hour).magnitude, 0.06
|
|
463
|
+
) # 60W * 1h = 0.06 kWh
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
@pytest.mark.parametrize(
|
|
467
|
+
"length_quantity",
|
|
468
|
+
[
|
|
469
|
+
100 * ureg.meter,
|
|
470
|
+
50 * ureg.millimeter,
|
|
471
|
+
2 * ureg.kilometer,
|
|
472
|
+
328 * ureg.foot, # Imperial if supported
|
|
473
|
+
],
|
|
474
|
+
)
|
|
422
475
|
def test_multiple_unit_systems(length_quantity):
|
|
423
476
|
"""Test working with multiple unit systems."""
|
|
424
477
|
assert isinstance(length_quantity, Length)
|
typedunit-0.0.7/.gitignore
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# General patterns
|
|
2
|
-
*.DS_store
|
|
3
|
-
*.ipynb_checkpoints*
|
|
4
|
-
*__pycache__*
|
|
5
|
-
*.so
|
|
6
|
-
*.a
|
|
7
|
-
.coverage*
|
|
8
|
-
*.pytest_cache
|
|
9
|
-
htmlcov
|
|
10
|
-
dist
|
|
11
|
-
build
|
|
12
|
-
*.egg*
|
|
13
|
-
*.whl
|
|
14
|
-
CMakeCache.txt
|
|
15
|
-
CMakeFiles
|
|
16
|
-
install_manifest.txt
|
|
17
|
-
cmake_install.cmake
|
|
18
|
-
wheelhouse
|
|
19
|
-
|
|
20
|
-
# Docs-specific patterns
|
|
21
|
-
docs/source/gallery/*
|
|
22
|
-
!docs/source/gallery/index.rst
|
|
23
|
-
PyOptik/data/**/test*
|
|
24
|
-
PyOptik/data/**/example*
|
|
25
|
-
|
|
26
|
-
# Override for documentation_build
|
|
27
|
-
!documentation_build
|
|
28
|
-
!documentation_build/**
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
:orphan:
|
|
2
|
-
|
|
3
|
-
.. _examples_gallery:
|
|
4
|
-
|
|
5
|
-
Coding examples
|
|
6
|
-
===============
|
|
7
|
-
|
|
8
|
-
Explore our gallery of examples demonstrating the usage of TypedUnits.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
.. raw:: html
|
|
13
|
-
|
|
14
|
-
<div class="sphx-glr-thumbnails">
|
|
15
|
-
|
|
16
|
-
.. thumbnail-parent-div-open
|
|
17
|
-
|
|
18
|
-
.. raw:: html
|
|
19
|
-
|
|
20
|
-
<div class="sphx-glr-thumbcontainer" tooltip="Workflow - 0">
|
|
21
|
-
|
|
22
|
-
.. only:: html
|
|
23
|
-
|
|
24
|
-
.. image:: /gallery/images/thumb/sphx_glr_example_0_thumb.png
|
|
25
|
-
:alt:
|
|
26
|
-
|
|
27
|
-
:ref:`sphx_glr_gallery_example_0.py`
|
|
28
|
-
|
|
29
|
-
.. raw:: html
|
|
30
|
-
|
|
31
|
-
<div class="sphx-glr-thumbnail-title">Workflow - 0</div>
|
|
32
|
-
</div>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
.. raw:: html
|
|
36
|
-
|
|
37
|
-
<div class="sphx-glr-thumbcontainer" tooltip="Workflow - 1">
|
|
38
|
-
|
|
39
|
-
.. only:: html
|
|
40
|
-
|
|
41
|
-
.. image:: /gallery/images/thumb/sphx_glr_example_1_thumb.png
|
|
42
|
-
:alt:
|
|
43
|
-
|
|
44
|
-
:ref:`sphx_glr_gallery_example_1.py`
|
|
45
|
-
|
|
46
|
-
.. raw:: html
|
|
47
|
-
|
|
48
|
-
<div class="sphx-glr-thumbnail-title">Workflow - 1</div>
|
|
49
|
-
</div>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
.. thumbnail-parent-div-close
|
|
53
|
-
|
|
54
|
-
.. raw:: html
|
|
55
|
-
|
|
56
|
-
</div>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
.. toctree::
|
|
60
|
-
:hidden:
|
|
61
|
-
|
|
62
|
-
/gallery/example_0
|
|
63
|
-
/gallery/example_1
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
.. only:: html
|
|
68
|
-
|
|
69
|
-
.. rst-class:: sphx-glr-signature
|
|
70
|
-
|
|
71
|
-
`Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|