ucon 0.5.2__py3-none-any.whl → 0.6.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.
@@ -1,443 +0,0 @@
1
- # © 2026 The Radiativity Company
2
- # Licensed under the Apache License, Version 2.0
3
- # See the LICENSE file for details.
4
-
5
- """
6
- Tests for the default ConversionGraph with temperature, pressure, and base SI conversions.
7
-
8
- These tests verify that Number.to() works correctly with the default graph for:
9
- - Temperature conversions (Celsius, Kelvin, Fahrenheit) using AffineMap
10
- - Pressure conversions (Pascal, Bar, PSI, Atmosphere)
11
- - Base SI conversions (length, mass, time, volume, energy, power, information)
12
- """
13
-
14
- import unittest
15
-
16
- from ucon import units
17
- from ucon.graph import get_default_graph, reset_default_graph
18
-
19
-
20
- class TestTemperatureConversions(unittest.TestCase):
21
- """Tests for temperature conversions using AffineMap in the default graph."""
22
-
23
- def setUp(self):
24
- reset_default_graph()
25
-
26
- def test_celsius_to_kelvin_freezing(self):
27
- """0°C = 273.15 K"""
28
- result = units.celsius(0).to(units.kelvin)
29
- self.assertAlmostEqual(result.quantity, 273.15, places=2)
30
-
31
- def test_celsius_to_kelvin_boiling(self):
32
- """100°C = 373.15 K"""
33
- result = units.celsius(100).to(units.kelvin)
34
- self.assertAlmostEqual(result.quantity, 373.15, places=2)
35
-
36
- def test_kelvin_to_celsius_absolute_zero(self):
37
- """0 K = -273.15°C"""
38
- result = units.kelvin(0).to(units.celsius)
39
- self.assertAlmostEqual(result.quantity, -273.15, places=2)
40
-
41
- def test_kelvin_to_celsius_room_temp(self):
42
- """293.15 K = 20°C"""
43
- result = units.kelvin(293.15).to(units.celsius)
44
- self.assertAlmostEqual(result.quantity, 20, places=1)
45
-
46
- def test_fahrenheit_to_celsius_freezing(self):
47
- """32°F = 0°C"""
48
- result = units.fahrenheit(32).to(units.celsius)
49
- self.assertAlmostEqual(result.quantity, 0, places=1)
50
-
51
- def test_fahrenheit_to_celsius_boiling(self):
52
- """212°F = 100°C"""
53
- result = units.fahrenheit(212).to(units.celsius)
54
- self.assertAlmostEqual(result.quantity, 100, places=1)
55
-
56
- def test_celsius_to_fahrenheit_freezing(self):
57
- """0°C = 32°F"""
58
- result = units.celsius(0).to(units.fahrenheit)
59
- self.assertAlmostEqual(result.quantity, 32, places=1)
60
-
61
- def test_celsius_to_fahrenheit_boiling(self):
62
- """100°C = 212°F"""
63
- result = units.celsius(100).to(units.fahrenheit)
64
- self.assertAlmostEqual(result.quantity, 212, places=1)
65
-
66
- def test_fahrenheit_to_kelvin_absolute_zero(self):
67
- """-459.67°F = 0 K (approximately)"""
68
- result = units.fahrenheit(-459.67).to(units.kelvin)
69
- self.assertAlmostEqual(result.quantity, 0, places=0)
70
-
71
- def test_kelvin_to_fahrenheit_boiling(self):
72
- """373.15 K = 212°F"""
73
- result = units.kelvin(373.15).to(units.fahrenheit)
74
- self.assertAlmostEqual(result.quantity, 212, places=0)
75
-
76
- def test_temperature_round_trip_celsius(self):
77
- """Round-trip: C → K → C"""
78
- original = 25.0
79
- via_kelvin = units.celsius(original).to(units.kelvin)
80
- back = via_kelvin.to(units.celsius)
81
- self.assertAlmostEqual(back.quantity, original, places=10)
82
-
83
- def test_temperature_round_trip_fahrenheit(self):
84
- """Round-trip: F → C → F"""
85
- original = 98.6 # body temperature
86
- via_celsius = units.fahrenheit(original).to(units.celsius)
87
- back = via_celsius.to(units.fahrenheit)
88
- self.assertAlmostEqual(back.quantity, original, places=10)
89
-
90
-
91
- class TestPressureConversions(unittest.TestCase):
92
- """Tests for pressure conversions in the default graph."""
93
-
94
- def setUp(self):
95
- reset_default_graph()
96
-
97
- def test_pascal_to_bar(self):
98
- """100000 Pa = 1 bar"""
99
- result = units.pascal(100000).to(units.bar)
100
- self.assertAlmostEqual(result.quantity, 1.0, places=5)
101
-
102
- def test_bar_to_pascal(self):
103
- """1 bar = 100000 Pa"""
104
- result = units.bar(1).to(units.pascal)
105
- self.assertAlmostEqual(result.quantity, 100000, places=0)
106
-
107
- def test_pascal_to_psi(self):
108
- """6894.76 Pa ≈ 1 psi"""
109
- result = units.pascal(6894.76).to(units.psi)
110
- self.assertAlmostEqual(result.quantity, 1.0, places=2)
111
-
112
- def test_psi_to_pascal(self):
113
- """1 psi ≈ 6894.76 Pa"""
114
- result = units.psi(1).to(units.pascal)
115
- self.assertAlmostEqual(result.quantity, 6894.76, places=0)
116
-
117
- def test_atmosphere_to_pascal(self):
118
- """1 atm = 101325 Pa"""
119
- result = units.atmosphere(1).to(units.pascal)
120
- self.assertAlmostEqual(result.quantity, 101325, places=0)
121
-
122
- def test_pascal_to_atmosphere(self):
123
- """101325 Pa = 1 atm"""
124
- result = units.pascal(101325).to(units.atmosphere)
125
- self.assertAlmostEqual(result.quantity, 1.0, places=5)
126
-
127
- def test_atmosphere_to_bar(self):
128
- """1 atm ≈ 1.01325 bar"""
129
- result = units.atmosphere(1).to(units.bar)
130
- self.assertAlmostEqual(result.quantity, 1.01325, places=4)
131
-
132
- def test_bar_to_atmosphere(self):
133
- """1 bar ≈ 0.986923 atm"""
134
- result = units.bar(1).to(units.atmosphere)
135
- self.assertAlmostEqual(result.quantity, 0.986923, places=4)
136
-
137
- def test_atmosphere_to_psi(self):
138
- """1 atm ≈ 14.696 psi"""
139
- result = units.atmosphere(1).to(units.psi)
140
- self.assertAlmostEqual(result.quantity, 14.696, places=2)
141
-
142
- def test_psi_to_atmosphere(self):
143
- """14.696 psi ≈ 1 atm"""
144
- result = units.psi(14.696).to(units.atmosphere)
145
- self.assertAlmostEqual(result.quantity, 1.0, places=2)
146
-
147
- def test_pressure_round_trip(self):
148
- """Round-trip: Pa → bar → Pa"""
149
- original = 250000
150
- via_bar = units.pascal(original).to(units.bar)
151
- back = via_bar.to(units.pascal)
152
- self.assertAlmostEqual(back.quantity, original, places=5)
153
-
154
-
155
- class TestBaseSILengthConversions(unittest.TestCase):
156
- """Tests for length conversions in the default graph."""
157
-
158
- def setUp(self):
159
- reset_default_graph()
160
-
161
- def test_meter_to_foot(self):
162
- """1 m ≈ 3.28084 ft"""
163
- result = units.meter(1).to(units.foot)
164
- self.assertAlmostEqual(result.quantity, 3.28084, places=4)
165
-
166
- def test_foot_to_meter(self):
167
- """1 ft ≈ 0.3048 m"""
168
- result = units.foot(1).to(units.meter)
169
- self.assertAlmostEqual(result.quantity, 0.3048, places=4)
170
-
171
- def test_foot_to_inch(self):
172
- """1 ft = 12 in"""
173
- result = units.foot(1).to(units.inch)
174
- self.assertAlmostEqual(result.quantity, 12, places=10)
175
-
176
- def test_inch_to_foot(self):
177
- """12 in = 1 ft"""
178
- result = units.inch(12).to(units.foot)
179
- self.assertAlmostEqual(result.quantity, 1.0, places=10)
180
-
181
- def test_meter_to_inch(self):
182
- """1 m ≈ 39.37 in (via foot)"""
183
- result = units.meter(1).to(units.inch)
184
- self.assertAlmostEqual(result.quantity, 39.37, places=1)
185
-
186
- def test_foot_to_yard(self):
187
- """3 ft = 1 yd"""
188
- result = units.foot(3).to(units.yard)
189
- self.assertAlmostEqual(result.quantity, 1.0, places=10)
190
-
191
- def test_yard_to_foot(self):
192
- """1 yd = 3 ft"""
193
- result = units.yard(1).to(units.foot)
194
- self.assertAlmostEqual(result.quantity, 3.0, places=10)
195
-
196
- def test_mile_to_foot(self):
197
- """1 mi = 5280 ft"""
198
- result = units.mile(1).to(units.foot)
199
- self.assertAlmostEqual(result.quantity, 5280, places=0)
200
-
201
- def test_foot_to_mile(self):
202
- """5280 ft = 1 mi"""
203
- result = units.foot(5280).to(units.mile)
204
- self.assertAlmostEqual(result.quantity, 1.0, places=10)
205
-
206
- def test_meter_to_mile(self):
207
- """1609.34 m ≈ 1 mi (multi-hop: m → ft → mi)"""
208
- result = units.meter(1609.34).to(units.mile)
209
- self.assertAlmostEqual(result.quantity, 1.0, places=2)
210
-
211
- def test_meter_to_yard(self):
212
- """1 m ≈ 1.094 yd (multi-hop: m → ft → yd)"""
213
- result = units.meter(1).to(units.yard)
214
- self.assertAlmostEqual(result.quantity, 1.094, places=2)
215
-
216
-
217
- class TestBaseSIMassConversions(unittest.TestCase):
218
- """Tests for mass conversions in the default graph."""
219
-
220
- def setUp(self):
221
- reset_default_graph()
222
-
223
- def test_kilogram_to_gram(self):
224
- """1 kg = 1000 g"""
225
- result = units.kilogram(1).to(units.gram)
226
- self.assertAlmostEqual(result.quantity, 1000, places=10)
227
-
228
- def test_gram_to_kilogram(self):
229
- """1000 g = 1 kg"""
230
- result = units.gram(1000).to(units.kilogram)
231
- self.assertAlmostEqual(result.quantity, 1.0, places=10)
232
-
233
- def test_kilogram_to_pound(self):
234
- """1 kg ≈ 2.20462 lb"""
235
- result = units.kilogram(1).to(units.pound)
236
- self.assertAlmostEqual(result.quantity, 2.20462, places=4)
237
-
238
- def test_pound_to_kilogram(self):
239
- """1 lb ≈ 0.453592 kg"""
240
- result = units.pound(1).to(units.kilogram)
241
- self.assertAlmostEqual(result.quantity, 0.453592, places=4)
242
-
243
- def test_pound_to_ounce(self):
244
- """1 lb = 16 oz"""
245
- result = units.pound(1).to(units.ounce)
246
- self.assertAlmostEqual(result.quantity, 16, places=10)
247
-
248
- def test_ounce_to_pound(self):
249
- """16 oz = 1 lb"""
250
- result = units.ounce(16).to(units.pound)
251
- self.assertAlmostEqual(result.quantity, 1.0, places=10)
252
-
253
- def test_gram_to_pound(self):
254
- """453.592 g ≈ 1 lb (via kg)"""
255
- result = units.gram(453.592).to(units.pound)
256
- self.assertAlmostEqual(result.quantity, 1.0, places=2)
257
-
258
- def test_kilogram_to_ounce(self):
259
- """1 kg ≈ 35.274 oz (multi-hop: kg → lb → oz)"""
260
- result = units.kilogram(1).to(units.ounce)
261
- self.assertAlmostEqual(result.quantity, 35.274, places=1)
262
-
263
-
264
- class TestBaseSITimeConversions(unittest.TestCase):
265
- """Tests for time conversions in the default graph."""
266
-
267
- def setUp(self):
268
- reset_default_graph()
269
-
270
- def test_second_to_minute(self):
271
- """60 s = 1 min"""
272
- result = units.second(60).to(units.minute)
273
- self.assertAlmostEqual(result.quantity, 1.0, places=10)
274
-
275
- def test_minute_to_second(self):
276
- """1 min = 60 s"""
277
- result = units.minute(1).to(units.second)
278
- self.assertAlmostEqual(result.quantity, 60, places=10)
279
-
280
- def test_minute_to_hour(self):
281
- """60 min = 1 hr"""
282
- result = units.minute(60).to(units.hour)
283
- self.assertAlmostEqual(result.quantity, 1.0, places=10)
284
-
285
- def test_hour_to_minute(self):
286
- """1 hr = 60 min"""
287
- result = units.hour(1).to(units.minute)
288
- self.assertAlmostEqual(result.quantity, 60, places=10)
289
-
290
- def test_hour_to_day(self):
291
- """24 hr = 1 day"""
292
- result = units.hour(24).to(units.day)
293
- self.assertAlmostEqual(result.quantity, 1.0, places=10)
294
-
295
- def test_day_to_hour(self):
296
- """1 day = 24 hr"""
297
- result = units.day(1).to(units.hour)
298
- self.assertAlmostEqual(result.quantity, 24, places=10)
299
-
300
- def test_second_to_hour(self):
301
- """3600 s = 1 hr (multi-hop: s → min → hr)"""
302
- result = units.second(3600).to(units.hour)
303
- self.assertAlmostEqual(result.quantity, 1.0, places=10)
304
-
305
- def test_second_to_day(self):
306
- """86400 s = 1 day (multi-hop: s → min → hr → day)"""
307
- result = units.second(86400).to(units.day)
308
- self.assertAlmostEqual(result.quantity, 1.0, places=10)
309
-
310
- def test_day_to_second(self):
311
- """1 day = 86400 s"""
312
- result = units.day(1).to(units.second)
313
- self.assertAlmostEqual(result.quantity, 86400, places=0)
314
-
315
-
316
- class TestBaseSIVolumeConversions(unittest.TestCase):
317
- """Tests for volume conversions in the default graph."""
318
-
319
- def setUp(self):
320
- reset_default_graph()
321
-
322
- def test_liter_to_gallon(self):
323
- """1 L ≈ 0.264172 gal"""
324
- result = units.liter(1).to(units.gallon)
325
- self.assertAlmostEqual(result.quantity, 0.264172, places=5)
326
-
327
- def test_gallon_to_liter(self):
328
- """1 gal ≈ 3.78541 L"""
329
- result = units.gallon(1).to(units.liter)
330
- self.assertAlmostEqual(result.quantity, 3.78541, places=3)
331
-
332
-
333
- class TestBaseSIEnergyConversions(unittest.TestCase):
334
- """Tests for energy conversions in the default graph."""
335
-
336
- def setUp(self):
337
- reset_default_graph()
338
-
339
- def test_joule_to_calorie(self):
340
- """4.184 J = 1 cal"""
341
- result = units.joule(4.184).to(units.calorie)
342
- self.assertAlmostEqual(result.quantity, 1.0, places=3)
343
-
344
- def test_calorie_to_joule(self):
345
- """1 cal = 4.184 J"""
346
- result = units.calorie(1).to(units.joule)
347
- self.assertAlmostEqual(result.quantity, 4.184, places=3)
348
-
349
- def test_joule_to_btu(self):
350
- """1055.06 J ≈ 1 BTU"""
351
- result = units.joule(1055.06).to(units.btu)
352
- self.assertAlmostEqual(result.quantity, 1.0, places=2)
353
-
354
- def test_btu_to_joule(self):
355
- """1 BTU ≈ 1055.06 J"""
356
- result = units.btu(1).to(units.joule)
357
- self.assertAlmostEqual(result.quantity, 1055.06, places=0)
358
-
359
- def test_calorie_to_btu(self):
360
- """252 cal ≈ 1 BTU (multi-hop via joule)"""
361
- result = units.calorie(252).to(units.btu)
362
- self.assertAlmostEqual(result.quantity, 1.0, places=1)
363
-
364
-
365
- class TestBaseSIPowerConversions(unittest.TestCase):
366
- """Tests for power conversions in the default graph."""
367
-
368
- def setUp(self):
369
- reset_default_graph()
370
-
371
- def test_watt_to_horsepower(self):
372
- """745.7 W ≈ 1 hp"""
373
- result = units.watt(745.7).to(units.horsepower)
374
- self.assertAlmostEqual(result.quantity, 1.0, places=2)
375
-
376
- def test_horsepower_to_watt(self):
377
- """1 hp ≈ 745.7 W"""
378
- result = units.horsepower(1).to(units.watt)
379
- self.assertAlmostEqual(result.quantity, 745.7, places=0)
380
-
381
-
382
- class TestInformationConversions(unittest.TestCase):
383
- """Tests for information unit conversions in the default graph."""
384
-
385
- def setUp(self):
386
- reset_default_graph()
387
-
388
- def test_byte_to_bit(self):
389
- """1 B = 8 b"""
390
- result = units.byte(1).to(units.bit)
391
- self.assertAlmostEqual(result.quantity, 8, places=10)
392
-
393
- def test_bit_to_byte(self):
394
- """8 b = 1 B"""
395
- result = units.bit(8).to(units.byte)
396
- self.assertAlmostEqual(result.quantity, 1.0, places=10)
397
-
398
- def test_kilobyte_to_bit(self):
399
- """1 KB = 8000 b (using Scale.kilo)"""
400
- from ucon.core import Scale
401
- kilobyte = Scale.kilo * units.byte
402
- result = kilobyte(1).to(units.bit)
403
- self.assertAlmostEqual(result.quantity, 8000, places=0)
404
-
405
-
406
- class TestConversionRoundTrips(unittest.TestCase):
407
- """Tests verifying round-trip conversion accuracy."""
408
-
409
- def setUp(self):
410
- reset_default_graph()
411
-
412
- def test_length_round_trip(self):
413
- """meter → foot → meter"""
414
- original = 42.5
415
- via_foot = units.meter(original).to(units.foot)
416
- back = via_foot.to(units.meter)
417
- self.assertAlmostEqual(back.quantity, original, places=8)
418
-
419
- def test_mass_round_trip(self):
420
- """kilogram → pound → kilogram"""
421
- original = 75.0
422
- via_pound = units.kilogram(original).to(units.pound)
423
- back = via_pound.to(units.kilogram)
424
- self.assertAlmostEqual(back.quantity, original, places=8)
425
-
426
- def test_time_round_trip(self):
427
- """second → day → second"""
428
- original = 172800 # 2 days
429
- via_day = units.second(original).to(units.day)
430
- back = via_day.to(units.second)
431
- self.assertAlmostEqual(back.quantity, original, places=5)
432
-
433
- def test_pressure_multi_hop_round_trip(self):
434
- """pascal → atmosphere → bar → pascal"""
435
- original = 500000
436
- via_atm = units.pascal(original).to(units.atmosphere)
437
- via_bar = via_atm.to(units.bar)
438
- back = via_bar.to(units.pascal)
439
- self.assertAlmostEqual(back.quantity, original, places=2)
440
-
441
-
442
- if __name__ == '__main__':
443
- unittest.main()
@@ -1,248 +0,0 @@
1
- # © 2026 The Radiativity Company
2
- # Licensed under the Apache License, Version 2.0
3
- # See the LICENSE file for details.
4
-
5
- """
6
- Tests for v0.5.0 dimensionless units (pseudo-dimensions).
7
-
8
- Tests pseudo-dimension isolation, angle/solid-angle/ratio unit conversions,
9
- and cross-pseudo-dimension conversion failure.
10
- """
11
-
12
- import math
13
- import unittest
14
-
15
- from ucon import units
16
- from ucon.core import Dimension, Vector
17
- from ucon.graph import ConversionNotFound
18
-
19
-
20
- class TestPseudoDimensionIsolation(unittest.TestCase):
21
- """Test that pseudo-dimensions are semantically isolated."""
22
-
23
- def test_angle_not_equal_to_none(self):
24
- self.assertNotEqual(Dimension.angle, Dimension.none)
25
-
26
- def test_solid_angle_not_equal_to_none(self):
27
- self.assertNotEqual(Dimension.solid_angle, Dimension.none)
28
-
29
- def test_ratio_not_equal_to_none(self):
30
- self.assertNotEqual(Dimension.ratio, Dimension.none)
31
-
32
- def test_angle_not_equal_to_solid_angle(self):
33
- self.assertNotEqual(Dimension.angle, Dimension.solid_angle)
34
-
35
- def test_angle_not_equal_to_ratio(self):
36
- self.assertNotEqual(Dimension.angle, Dimension.ratio)
37
-
38
- def test_solid_angle_not_equal_to_ratio(self):
39
- self.assertNotEqual(Dimension.solid_angle, Dimension.ratio)
40
-
41
- def test_angle_equal_to_itself(self):
42
- self.assertEqual(Dimension.angle, Dimension.angle)
43
-
44
- def test_none_equal_to_itself(self):
45
- self.assertEqual(Dimension.none, Dimension.none)
46
-
47
- def test_all_pseudo_dimensions_have_zero_vector(self):
48
- zero = Vector()
49
- self.assertEqual(Dimension.none.vector, zero)
50
- self.assertEqual(Dimension.angle.vector, zero)
51
- self.assertEqual(Dimension.solid_angle.vector, zero)
52
- self.assertEqual(Dimension.ratio.vector, zero)
53
-
54
-
55
- class TestPseudoDimensionHashing(unittest.TestCase):
56
- """Test that pseudo-dimensions can coexist in sets and dicts."""
57
-
58
- def test_all_pseudo_dimensions_in_set(self):
59
- dims = {Dimension.none, Dimension.angle, Dimension.solid_angle, Dimension.ratio}
60
- self.assertEqual(len(dims), 4)
61
-
62
- def test_all_pseudo_dimensions_as_dict_keys(self):
63
- d = {
64
- Dimension.none: "none",
65
- Dimension.angle: "angle",
66
- Dimension.solid_angle: "solid_angle",
67
- Dimension.ratio: "ratio",
68
- }
69
- self.assertEqual(len(d), 4)
70
- self.assertEqual(d[Dimension.angle], "angle")
71
- self.assertEqual(d[Dimension.ratio], "ratio")
72
-
73
- def test_distinct_hashes(self):
74
- hashes = {
75
- hash(Dimension.none),
76
- hash(Dimension.angle),
77
- hash(Dimension.solid_angle),
78
- hash(Dimension.ratio),
79
- }
80
- self.assertEqual(len(hashes), 4)
81
-
82
-
83
- class TestAlgebraicResolution(unittest.TestCase):
84
- """Test that algebraic operations resolve to none, not pseudo-dimensions."""
85
-
86
- def test_length_divided_by_length_is_none(self):
87
- result = Dimension.length / Dimension.length
88
- self.assertEqual(result, Dimension.none)
89
- self.assertIs(result, Dimension.none)
90
-
91
- def test_energy_divided_by_energy_is_none(self):
92
- result = Dimension.energy / Dimension.energy
93
- self.assertEqual(result, Dimension.none)
94
- self.assertIs(result, Dimension.none)
95
-
96
- def test_angle_times_length_is_length(self):
97
- # Since angle has zero vector, angle * length = length
98
- result = Dimension.angle * Dimension.length
99
- self.assertEqual(result, Dimension.length)
100
-
101
-
102
- class TestUnitDimensions(unittest.TestCase):
103
- """Test that units have correct dimensions."""
104
-
105
- def test_radian_is_angle(self):
106
- self.assertEqual(units.radian.dimension, Dimension.angle)
107
-
108
- def test_degree_is_angle(self):
109
- self.assertEqual(units.degree.dimension, Dimension.angle)
110
-
111
- def test_steradian_is_solid_angle(self):
112
- self.assertEqual(units.steradian.dimension, Dimension.solid_angle)
113
-
114
- def test_square_degree_is_solid_angle(self):
115
- self.assertEqual(units.square_degree.dimension, Dimension.solid_angle)
116
-
117
- def test_percent_is_ratio(self):
118
- self.assertEqual(units.percent.dimension, Dimension.ratio)
119
-
120
- def test_ppm_is_ratio(self):
121
- self.assertEqual(units.ppm.dimension, Dimension.ratio)
122
-
123
-
124
- class TestAngleConversions(unittest.TestCase):
125
- """Test angle unit conversions."""
126
-
127
- def test_radian_to_degree(self):
128
- angle = units.radian(math.pi)
129
- result = angle.to(units.degree)
130
- self.assertAlmostEqual(result.value, 180, places=9)
131
-
132
- def test_degree_to_radian(self):
133
- angle = units.degree(90)
134
- result = angle.to(units.radian)
135
- self.assertAlmostEqual(result.value, math.pi / 2, places=9)
136
-
137
- def test_turn_to_degree(self):
138
- angle = units.turn(1)
139
- result = angle.to(units.degree)
140
- self.assertAlmostEqual(result.value, 360, places=9)
141
-
142
- def test_turn_to_radian(self):
143
- angle = units.turn(1)
144
- result = angle.to(units.radian)
145
- self.assertAlmostEqual(result.value, 2 * math.pi, places=9)
146
-
147
- def test_turn_to_gradian(self):
148
- angle = units.turn(1)
149
- result = angle.to(units.gradian)
150
- self.assertAlmostEqual(result.value, 400, places=9)
151
-
152
- def test_degree_to_arcminute(self):
153
- angle = units.degree(1)
154
- result = angle.to(units.arcminute)
155
- self.assertAlmostEqual(result.value, 60, places=9)
156
-
157
- def test_arcminute_to_arcsecond(self):
158
- angle = units.arcminute(1)
159
- result = angle.to(units.arcsecond)
160
- self.assertAlmostEqual(result.value, 60, places=9)
161
-
162
- def test_degree_to_arcsecond_composed(self):
163
- angle = units.degree(1)
164
- result = angle.to(units.arcsecond)
165
- self.assertAlmostEqual(result.value, 3600, places=9)
166
-
167
-
168
- class TestSolidAngleConversions(unittest.TestCase):
169
- """Test solid angle unit conversions."""
170
-
171
- def test_steradian_to_square_degree(self):
172
- solid = units.steradian(1)
173
- result = solid.to(units.square_degree)
174
- expected = (180 / math.pi) ** 2
175
- self.assertAlmostEqual(result.value, expected, places=1)
176
-
177
- def test_square_degree_to_steradian(self):
178
- solid = units.square_degree(1)
179
- result = solid.to(units.steradian)
180
- expected = (math.pi / 180) ** 2
181
- self.assertAlmostEqual(result.value, expected, places=9)
182
-
183
-
184
- class TestRatioConversions(unittest.TestCase):
185
- """Test ratio unit conversions."""
186
-
187
- def test_one_to_percent(self):
188
- r = units.ratio_one(0.5)
189
- result = r.to(units.percent)
190
- self.assertAlmostEqual(result.value, 50, places=9)
191
-
192
- def test_percent_to_one(self):
193
- r = units.percent(25)
194
- result = r.to(units.ratio_one)
195
- self.assertAlmostEqual(result.value, 0.25, places=9)
196
-
197
- def test_one_to_ppm(self):
198
- r = units.ratio_one(0.001)
199
- result = r.to(units.ppm)
200
- self.assertAlmostEqual(result.value, 1000, places=9)
201
-
202
- def test_ppm_to_ppb(self):
203
- r = units.ppm(1)
204
- result = r.to(units.ppb)
205
- self.assertAlmostEqual(result.value, 1000, places=9)
206
-
207
- def test_one_to_permille(self):
208
- r = units.ratio_one(0.005)
209
- result = r.to(units.permille)
210
- self.assertAlmostEqual(result.value, 5, places=9)
211
-
212
- def test_basis_point_to_percent(self):
213
- r = units.basis_point(100)
214
- result = r.to(units.percent)
215
- self.assertAlmostEqual(result.value, 1, places=9)
216
-
217
- def test_percent_to_basis_point(self):
218
- r = units.percent(0.25)
219
- result = r.to(units.basis_point)
220
- self.assertAlmostEqual(result.value, 25, places=9)
221
-
222
-
223
- class TestCrossPseudoDimensionFails(unittest.TestCase):
224
- """Test that cross-pseudo-dimension conversions fail."""
225
-
226
- def test_radian_to_percent_fails(self):
227
- with self.assertRaises(ConversionNotFound):
228
- units.radian(1).to(units.percent)
229
-
230
- def test_percent_to_degree_fails(self):
231
- with self.assertRaises(ConversionNotFound):
232
- units.percent(50).to(units.degree)
233
-
234
- def test_radian_to_steradian_fails(self):
235
- with self.assertRaises(ConversionNotFound):
236
- units.radian(1).to(units.steradian)
237
-
238
- def test_steradian_to_percent_fails(self):
239
- with self.assertRaises(ConversionNotFound):
240
- units.steradian(1).to(units.percent)
241
-
242
- def test_ppm_to_arcminute_fails(self):
243
- with self.assertRaises(ConversionNotFound):
244
- units.ppm(1000).to(units.arcminute)
245
-
246
-
247
- if __name__ == "__main__":
248
- unittest.main()