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.
Files changed (46) hide show
  1. typedunit-0.0.10/.coveragerc +22 -0
  2. {typedunit-0.0.7 → typedunit-0.0.10}/.github/dependabot.yml +1 -1
  3. {typedunit-0.0.7 → typedunit-0.0.10}/.github/workflows/deploy_anaconda.yml +4 -4
  4. typedunit-0.0.10/.gitignore +35 -0
  5. typedunit-0.0.10/.pre-commit-config.yaml +17 -0
  6. {typedunit-0.0.7 → typedunit-0.0.10}/PKG-INFO +1 -1
  7. typedunit-0.0.10/TypedUnit/__init__.py +9 -0
  8. {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit/_version.py +3 -3
  9. {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit/units.py +93 -46
  10. {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit.egg-info/PKG-INFO +1 -1
  11. {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit.egg-info/SOURCES.txt +3 -1
  12. {typedunit-0.0.7 → typedunit-0.0.10}/pyproject.toml +0 -24
  13. typedunit-0.0.10/pytest.ini +21 -0
  14. {typedunit-0.0.7 → typedunit-0.0.10}/tests/test_0.py +191 -138
  15. typedunit-0.0.7/.gitignore +0 -28
  16. typedunit-0.0.7/TypedUnit/__init__.py +0 -9
  17. typedunit-0.0.7/docs/source/gallery/index.rst +0 -71
  18. {typedunit-0.0.7 → typedunit-0.0.10}/.flake8 +0 -0
  19. {typedunit-0.0.7 → typedunit-0.0.10}/.github/workflows/deploy_PyPi.yml +0 -0
  20. {typedunit-0.0.7 → typedunit-0.0.10}/.github/workflows/deploy_coverage.yml +0 -0
  21. {typedunit-0.0.7 → typedunit-0.0.10}/.github/workflows/deploy_documentation.yml +0 -0
  22. {typedunit-0.0.7 → typedunit-0.0.10}/LICENSE +0 -0
  23. {typedunit-0.0.7 → typedunit-0.0.10}/README.rst +0 -0
  24. {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit/directories.py +0 -0
  25. {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit/helper.py +0 -0
  26. {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit/utils.py +0 -0
  27. {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit.egg-info/dependency_links.txt +0 -0
  28. {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit.egg-info/requires.txt +0 -0
  29. {typedunit-0.0.7 → typedunit-0.0.10}/TypedUnit.egg-info/top_level.txt +0 -0
  30. {typedunit-0.0.7 → typedunit-0.0.10}/docs/Makefile +0 -0
  31. {typedunit-0.0.7 → typedunit-0.0.10}/docs/examples/README.rst +0 -0
  32. {typedunit-0.0.7 → typedunit-0.0.10}/docs/examples/example_0.py +0 -0
  33. {typedunit-0.0.7 → typedunit-0.0.10}/docs/examples/example_1.py +0 -0
  34. {typedunit-0.0.7 → typedunit-0.0.10}/docs/images/logo.png +0 -0
  35. {typedunit-0.0.7 → typedunit-0.0.10}/docs/make.bat +0 -0
  36. {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/_static/default.css +0 -0
  37. {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/_static/thumbnail.png +0 -0
  38. {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/code.rst +0 -0
  39. {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/conf.py +0 -0
  40. {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/index.rst +0 -0
  41. {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/references.rst +0 -0
  42. {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/sg_execution_times.rst +0 -0
  43. {typedunit-0.0.7 → typedunit-0.0.10}/docs/source/theory.rst +0 -0
  44. {typedunit-0.0.7 → typedunit-0.0.10}/meta.yaml +0 -0
  45. {typedunit-0.0.7 → typedunit-0.0.10}/setup.cfg +0 -0
  46. {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
@@ -6,6 +6,6 @@ updates:
6
6
  directory: "/"
7
7
  target-branch: "master"
8
8
  schedule:
9
- interval: "weekly"
9
+ interval: "monthly"
10
10
  day: "sunday"
11
11
  time: "09:00"
@@ -11,11 +11,11 @@ permissions:
11
11
  contents: write
12
12
 
13
13
  jobs:
14
- ManyLinux_x86_64:
14
+ linux:
15
15
  uses: MartinPdeS/MPSActions/.github/workflows/publish_compiled_package_to_anaconda.yml@master
16
16
  with:
17
- python-versions: '["3.11", "3.12", "3.13"]'
18
- apt-package: ""
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: TypedUnit
3
- Version: 0.0.7
3
+ Version: 0.0.10
4
4
  Summary: A package wrapping pint for handling typed units in Python.
5
5
  Author-email: Martin Poinsinet de Sivry-Houle <martin.poinsinet.de.sivry@gmail.com>
6
6
  License: MIT License
@@ -0,0 +1,9 @@
1
+ try:
2
+ from ._version import version as __version__ # noqa: F401
3
+
4
+ except ImportError:
5
+ __version__ = "0.0.0"
6
+
7
+ from TypedUnit.units import *
8
+ from TypedUnit.helper import validate_units
9
+ from TypedUnit.units import ureg, Quantity
@@ -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.7'
32
- __version_tuple__ = version_tuple = (0, 0, 7)
31
+ __version__ = version = '0.0.10'
32
+ __version_tuple__ = version_tuple = (0, 0, 10)
33
33
 
34
- __commit_id__ = commit_id = 'gdd1c6b1a7'
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 = f"({getattr(cls, '_expected_dim')})*({getattr(other, '_expected_dim')})"
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(value, Quantity), f"Expected a pint Quantity instance, got {type(value)}"
65
- assert value.check(cls._expected_dim), f"Value units {value.dimensionality} do not match {cls.__name__} units"
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
- # print(test)
258
+ ureg.AU = ureg.dimensionless
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: TypedUnit
3
- Version: 0.0.7
3
+ Version: 0.0.10
4
4
  Summary: A package wrapping pint for handling typed units in Python.
5
5
  Author-email: Martin Poinsinet de Sivry-Houle <martin.poinsinet.de.sivry@gmail.com>
6
6
  License: MIT License
@@ -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, Time, Power, Voltage, Current, Resistance,
20
- Temperature, Length, Volume, FlowRate, Frequency, Mass,
21
- Angle, RefractiveIndex, Dimensionless,
22
- ureg, Quantity, validate_units
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("quantity,unit_type,expected", [
28
- # Energy tests
29
- (100 * ureg.joule, Energy, True),
30
- (1.5 * ureg.kilowatt_hour, Energy, True),
31
- (250 * ureg.calorie, Energy, True),
32
- (10 * ureg.second, Energy, False), # Time, not Energy
33
- (5 * ureg.meter, Energy, False), # Length, not Energy
34
-
35
- # Time tests
36
- (30 * ureg.second, Time, True),
37
- (5 * ureg.minute, Time, True),
38
- (2 * ureg.hour, Time, True),
39
- (500 * ureg.millisecond, Time, True),
40
- (100 * ureg.joule, Time, False), # Energy, not Time
41
-
42
- # Power tests
43
- (1500 * ureg.watt, Power, True),
44
- (2.5 * ureg.kilowatt, Power, True),
45
- (1 * ureg.horsepower, Power, True),
46
- (12 * ureg.volt, Power, False), # Voltage, not Power
47
-
48
- # Electrical units
49
- (12 * ureg.volt, Voltage, True),
50
- (2.5 * ureg.ampere, Current, True),
51
- (4.8 * ureg.ohm, Resistance, True),
52
- (12 * ureg.volt, Current, False), # Cross-check
53
- (2.5 * ureg.ampere, Resistance, False),
54
-
55
- # Mechanical units
56
- (10 * ureg.meter, Length, True),
57
- (50 * ureg.millimeter, Length, True),
58
- (2 * ureg.kilometer, Length, True),
59
- (5 * ureg.liter, Volume, True),
60
- (250 * ureg.milliliter, Volume, True),
61
- (10 * ureg.meter, Volume, False), # Length, not Volume
62
-
63
- # Temperature tests
64
- (300 * ureg.kelvin, Temperature, True),
65
- (77 * ureg.kelvin, Temperature, True),
66
- # (50 * ureg.hertz, Temperature, False),
67
-
68
- # # Frequency and angle
69
- (50 * ureg.hertz, Frequency, True),
70
- (1.57 * ureg.radian, Angle, True),
71
-
72
- # Other tests
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("non_quantity", [
83
- 42, # int
84
- 3.14, # float
85
- "10 meters", # string
86
- [1, 2, 3], # list
87
- {'value': 10}, # dict
88
- None, # None
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 = [Energy, Time, Power, Voltage, Current, Resistance,
93
- Temperature, Length, Volume, Frequency, Angle]
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("unit_type,valid_quantity,invalid_quantity", [
100
- (Energy, 100 * ureg.joule, 10 * ureg.meter),
101
- (Time, 30 * ureg.second, 100 * ureg.joule),
102
- (Power, 1500 * ureg.watt, 10 * ureg.meter),
103
- (Voltage, 12 * ureg.volt, 5 * ureg.ampere),
104
- (Current, 2.5 * ureg.ampere, 12 * ureg.volt),
105
- (Resistance, 4.8 * ureg.ohm, 100 * ureg.joule),
106
- (Length, 100 * ureg.meter, 50 * ureg.joule),
107
- (Temperature, 300 * ureg.kelvin, 2.5 * ureg.ampere),
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("invalid_input", [
120
- 42,
121
- 3.14,
122
- "not a quantity",
123
- None,
124
- [1, 2, 3],
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 instance"):
158
+ with pytest.raises(AssertionError, match="Expected a pint Quantity"):
129
159
  Energy.check(invalid_input)
130
160
 
131
161
 
132
- @pytest.mark.parametrize("energy_quantity", [
133
- 100 * ureg.joule,
134
- 1.5 * ureg.kilowatt_hour,
135
- 250 * ureg.calorie,
136
- 500 * ureg.british_thermal_unit,
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("time_quantity", [
144
- 30 * ureg.second,
145
- 5 * ureg.minute,
146
- 2 * ureg.hour,
147
- 500 * ureg.millisecond,
148
- 0.1 * ureg.microsecond,
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("power_quantity", [
156
- 1500 * ureg.watt,
157
- 2.5 * ureg.kilowatt,
158
- 1 * ureg.horsepower,
159
- 100 * ureg.milliwatt,
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("temperature_quantity", [
195
- 300 * ureg.kelvin,
196
- # 25 * ureg.celsius,
197
- # 77 * ureg.fahrenheit,
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("frequency_quantity", [
205
- 50 * ureg.hertz,
206
- 2.4 * ureg.kilohertz,
207
- 1.0 * ureg.megahertz,
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("angle_quantity", [
215
- 45 * ureg.degree,
216
- 1.57 * ureg.radian,
217
- 90 * ureg.degree,
218
- 3.14159 * ureg.radian,
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("energy_quantity", [
302
- 1000 * ureg.joule,
303
- 1.5 * ureg.kilowatt_hour,
304
- 250 * ureg.calorie,
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("invalid_input", [
356
- None,
357
- 42,
358
- "10 joules",
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(work.to(ureg.kilowatt_hour).magnitude, 0.06) # 60W * 1h = 0.06 kWh
414
-
415
-
416
- @pytest.mark.parametrize("length_quantity", [
417
- 100 * ureg.meter,
418
- 50 * ureg.millimeter,
419
- 2 * ureg.kilometer,
420
- 328 * ureg.foot, # Imperial if supported
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)
@@ -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,9 +0,0 @@
1
- try:
2
- from ._version import version as __version__ # noqa: F401
3
-
4
- except ImportError:
5
- __version__ = "0.0.0"
6
-
7
-
8
- from .units import *
9
- from .helper import validate_units
@@ -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