TypedUnit 0.0.8__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.8 → typedunit-0.0.10}/.github/workflows/deploy_anaconda.yml +4 -4
- {typedunit-0.0.8 → typedunit-0.0.10}/.gitignore +2 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/PKG-INFO +1 -1
- typedunit-0.0.10/TypedUnit/__init__.py +9 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/TypedUnit/_version.py +3 -3
- {typedunit-0.0.8 → typedunit-0.0.10}/TypedUnit/units.py +4 -2
- {typedunit-0.0.8 → typedunit-0.0.10}/TypedUnit.egg-info/PKG-INFO +1 -1
- {typedunit-0.0.8 → typedunit-0.0.10}/TypedUnit.egg-info/SOURCES.txt +2 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/pyproject.toml +0 -24
- typedunit-0.0.10/pytest.ini +21 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/tests/test_0.py +191 -138
- typedunit-0.0.8/TypedUnit/__init__.py +0 -10
- {typedunit-0.0.8 → typedunit-0.0.10}/.flake8 +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/.github/dependabot.yml +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/.github/workflows/deploy_PyPi.yml +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/.github/workflows/deploy_coverage.yml +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/.github/workflows/deploy_documentation.yml +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/.pre-commit-config.yaml +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/LICENSE +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/README.rst +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/TypedUnit/directories.py +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/TypedUnit/helper.py +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/TypedUnit/utils.py +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/TypedUnit.egg-info/dependency_links.txt +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/TypedUnit.egg-info/requires.txt +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/TypedUnit.egg-info/top_level.txt +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/docs/Makefile +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/docs/examples/README.rst +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/docs/examples/example_0.py +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/docs/examples/example_1.py +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/docs/images/logo.png +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/docs/make.bat +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/docs/source/_static/default.css +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/docs/source/_static/thumbnail.png +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/docs/source/code.rst +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/docs/source/conf.py +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/docs/source/index.rst +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/docs/source/references.rst +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/docs/source/sg_execution_times.rst +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/docs/source/theory.rst +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/meta.yaml +0 -0
- {typedunit-0.0.8 → typedunit-0.0.10}/setup.cfg +0 -0
- {typedunit-0.0.8 → 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
|
-
|
|
@@ -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,6 +12,8 @@ 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
|
+
|
|
15
17
|
|
|
16
18
|
__all__ = [
|
|
17
19
|
"Energy",
|
|
@@ -96,7 +98,7 @@ class BaseUnit(metaclass=UnitMeta):
|
|
|
96
98
|
return value
|
|
97
99
|
assert isinstance(
|
|
98
100
|
value, Quantity
|
|
99
|
-
), f"Expected a pint Quantity instance, got {type(value)}"
|
|
101
|
+
), f"Expected a pint Quantity [{cls._expected_dim}] instance, got {type(value)}"
|
|
100
102
|
assert value.check(
|
|
101
103
|
cls._expected_dim
|
|
102
104
|
), f"Value units {value.dimensionality} do not match {cls.__name__} units"
|
|
@@ -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)
|
|
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
|
|
File without changes
|
|
File without changes
|