Skip to content

Commit cb2ab98

Browse files
author
Dylan
committed
adding tests
1 parent 0f856e7 commit cb2ab98

28 files changed

Lines changed: 1110 additions & 124 deletions

README.md

Lines changed: 100 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ print(result) # [[<Quantity(1.23, 'gram / centimeter ** 3')>, <Quantity(25, 'deg
6868

6969
### Merging Quantities
7070

71-
Some times when you are doing parsing, you get multiple values from the parser. So it would be nice to reduce it
71+
Sometimes when you are doing parsing, you get multiple values from the parser. So it would be nice to reduce it
7272
down just to one value/value+condition/series+condition. `reduce_quantities` does exactly that!
7373

7474
It will group approximate equivalent quantities and throw out bad units (units that are not like the most common).
@@ -77,14 +77,14 @@ You can select your preference for return priority with the `order` parameter.
7777
```python
7878
from unit_parse import Quantity, reduce_quantities
7979

80-
quantities = [Quantity("68 degree_Fahrenheit"), Quantity("68.0 degree_Fahrenheit"), Quantity("20.0 degree_Celsius"),
80+
quantities = [Quantity("68 degF"), Quantity("68.0 degF"), Quantity("20.0 degC"),
8181
Quantity("293.15 kelvin * speed_of_light ** 2")]
8282

8383
result = reduce_quantities(quantities)
84-
print(result) # Quantity("68 degF")],
84+
print(result) # Quantity("68 degF")
8585
```
8686

87-
87+
---
8888
---
8989
## Logging
9090

@@ -164,16 +164,104 @@ Output:
164164
Yep, there's alot of them!
165165

166166
```python
167-
# Simple conversions
168-
5 -> 5 dimensionless
169-
5 g -> 5 gram
170-
5 g/ml -> 5.0 gram / milliliter
171-
1 K -> 1 kelvin
172-
173-
# stuff
167+
# Simple conversions
168+
5 --> 5
169+
5 g --> 5 g
170+
5 g/ml --> 5.0 g / ml
171+
1 K --> 1 K
172+
40 °F --> 40 °F
173+
-40 °F --> -40 °F
174+
170°C --> 170 °C
175+
40°F --> 40 °F
176+
20.80 mmHg --> 20.8 mmHg
177+
20.80 mm Hg --> 20.8 mmHg
178+
# scientific notation
179+
15*10**2 s --> 1500 s
180+
15*10^2 s --> 1500 s
181+
15 10**2 s --> 1500 s
182+
8.20x10**+1 ppm --> 82.0 ppm
183+
8.20x10+1 ppm --> 82.0 ppm
184+
5e1 g/mol --> 50.0 g / mol
185+
5E1 g/mol --> 50.0 g / mol
186+
5 e1 g/mol --> 50.0 g / mol
187+
5 E1 g/mol --> 50.0 g / mol
188+
5e+1 g/mol --> 50.0 g / mol
189+
5E-1 g/mol --> 0.5 g / mol
190+
66.11·10-62 ml/mol --> -6.611e-61 ml / mol
191+
66.11·10+62 ml/mol --> -6.611e+63 ml / mol
192+
66.11·1062 ml/mol --> -6.611e+63 ml / mol
193+
# messed up units/ units with powers
194+
2.3 gcm --> 2.3 cm * g
195+
5e5 gmol/s --> 500000.0 g * mol / s
196+
2.3 gcm**3 --> 2.3 cm ** 3 * g
197+
2.3 gcm**3 --> 2.3 cm ** 3 * g
198+
2.3 g --> 2.3 g
199+
1.10*10**-05 atm-m**3/mole --> 1.1000000000000001e-05 atm * m ** 3 / mol
200+
-54.6e-5 atm-m**3/mole --> -0.000546 atm * m ** 3 / mol
201+
2.3 mlgcm --> 2.3 cm * g * ml
202+
42.3 gcm-3 --> 42.3 g / cm ** 3
203+
42.3 g cm-3 --> 42.3 g / cm ** 3
204+
66.11·10-62 cm3/mol --> -6.611e-61 cm ** 3 / mol
205+
66.11·10+62 cm3/mol --> -6.611000000000001e+63 cm ** 3 / mol
206+
66.11·1062 cm3/mol --> -6.611000000000001e+63 cm ** 3 / mol
207+
345.234 KCAL/MOLE --> 345.234 kcal / mol
208+
# parenthesis (brackets turn into parenthesis)
209+
(4.0 °C) --> 4.0 °C
210+
[4.0 °C] --> 4.0 °C
211+
4.0 (°C) --> 4.0 °C
212+
4.0 (°C)) --> 4.0 °C
213+
)4.0 (°C) --> 4.0 °C
214+
(4.0 (°C) --> 4.0 °C
215+
()4.0 (°C) --> 4.0 °C
216+
4.0 °C [39.2 g/[mol * s]] --> [[<Quantity(4.0, 'degree_Celsius')>, <Quantity(39.2, 'gram / mole / second')>]]
217+
1.0722 at 68 °F (EPA, 1998) --> [[1.0722, <Quantity(68, 'degree_Fahrenheit')>]]
218+
# conditions
219+
37.34 kJ/mole (at 25 °C) --> [[<Quantity(37.34, 'kilojoule / mole')>, <Quantity(25, 'degree_Celsius')>]]
220+
20.8 mm Hg @ 25 °C --> [[<Quantity(20.8, 'millimeter_Hg')>, <Quantity(25, 'degree_Celsius')>]]
221+
20.8 mm Hg (25 °C) --> [[<Quantity(20.8, 'millimeter_Hg')>, <Quantity(25, 'degree_Celsius')>]]
222+
20.8 mm Hg at 25 °C --> [[<Quantity(20.8, 'millimeter_Hg')>, <Quantity(25, 'degree_Celsius')>]]
223+
-4,395.63 kJ/mol at 25 °C --> [[<Quantity(-4395.63, 'kilojoule / mole')>, <Quantity(25, 'degree_Celsius')>]]
224+
# list of quantities
225+
18 mm Hg; 20 mm Hg --> [<Quantity(18, 'millimeter_Hg')>, <Quantity(20, 'millimeter_Hg')>]
226+
18 mm Hg; 20 mm Hg --> [<Quantity(18, 'millimeter_Hg')>, <Quantity(20, 'millimeter_Hg')>]
227+
18 mm Hg @ 68 °F; 20 mm Hg @ 77° F --> [[<Quantity(18, 'millimeter_Hg')>, <Quantity(68, 'degree_Fahrenheit')>], [<Quantity(20, 'millimeter_Hg')>, <Quantity(77, 'degree_Fahrenheit')>]]
228+
18 mm Hg @ 68 °F ; 20 mm Hg @ 77° F (NTP, 1992) --> [[<Quantity(18, 'millimeter_Hg')>, <Quantity(68, 'degree_Fahrenheit')>], [<Quantity(20, 'millimeter_Hg')>, <Quantity(77, 'degree_Fahrenheit')>]]
229+
18 mm Hg at 68 °F ; 20 mm Hg at 77 °F --> [[<Quantity(18, 'millimeter_Hg')>, <Quantity(68, 'degree_Fahrenheit')>], [<Quantity(20, 'millimeter_Hg')>, <Quantity(77, 'degree_Fahrenheit')>]]
230+
Low threshold= 13.1150 mg/cu m; High threshold= 26840 mg/cu m; Irritating concn= 22875 mg/cu m. --> 22875.0 mg / m ** 3
231+
# ranges
232+
115.2-115.3 °C --> 115.2 °C
233+
115.2 - 115.3 °C --> 115.2 °C
234+
# words
235+
8.20x10+1 ppm; pure --> 82.0 ppm
236+
40 °F (NTP, 1992) --> 40 °F
237+
4.0 °C (39.2 °F) - closed cup --> 4.0 °C
238+
4.0 °C [39.2 g/[mol * s]] - closed cup --> [[<Quantity(4.0, 'degree_Celsius')>, <Quantity(39.2, 'gram / mole / second')>]]
239+
4.0 °C [39.2 g/[mol * s] approx.] - closed cup --> [[<Quantity(4.0, 'degree_Celsius')>, <Quantity(39.2, 'gram / mole / second')>]]
240+
4.0 °C [39.2g/[mol*s] approx.] - closed cup --> [[<Quantity(4.0, 'degree_Celsius')>, <Quantity(39.2, 'gram / mole / second')>]]
241+
4.0 °C [39.2g/[mol*s]approx.] - closed cup --> [[<Quantity(4.0, 'degree_Celsius')>, <Quantity(39.2, 'gram / mole / second')>]]
242+
Detection in water: 0.73 ppm; Chemically pure --> 0.73 ppm
243+
Odor Threshold Range: 0.15 to 25 ppm --> 0.15 ppm
244+
0.05 ppm purity specified --> 0.05 ppm
245+
Odor detection in air, 0.05 ppm (purity not specified) --> 0.05 ppm
246+
Relative density (water = 1): 1.04-1.13 --> 1.04
247+
Density approximately 6.5 lb / gal. --> 6.5 lb / gal
248+
# duplicates of same quantity different units
249+
4.0 °C (39.2 °F) --> 4.0 °C
250+
-7991 cal/g = -334.6X10+5 J/KG --> -33460000.000000004 J / kg
251+
# complex
252+
18 mm Hg at 68 °F ; 20 mm Hg at 77° F (NTP, 1992) --> [[<Quantity(18, 'millimeter_Hg')>, <Quantity(68, 'degree_Fahrenheit')>], [<Quantity(20, 'millimeter_Hg')>, <Quantity(77, 'degree_Fahrenheit')>]]
253+
Sound travels at 0.34 km/s --> 0.34 km / s
254+
Pass me a 300 ml beer. --> 300 ml
174255
```
175256

176257

258+
Stuff it gets wrong. No one is perfect!
259+
```python
260+
Index of refraction: 1.50920 @ 20 °C/D --> [[1.5092, <Quantity(293.15, 'kelvin / debye')>]]
261+
Vapor pressure, kPa at 20 °C: 2.0 --> 2.0
262+
```
263+
264+
---
177265
---
178266
## Configuration
179267

@@ -272,7 +360,7 @@ result = unit_parse.parser("100 MOL") # pint is case-sensitive, so this will re
272360
print(result) # Quantity("100 mole")
273361
```
274362

275-
363+
---
276364
---
277365
## Notes
278366

dev_files/main.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
['−66.11·1062 cm3/mol', Quantity('-66.11*10**62 cm**3/mol')],
5353
["345.234 KCAL/MOLE", Quantity("345.234 kcal/mole")],
5454

55-
# parenthesis (brackets turned to parenthesis)
55+
# parenthesis (brackets turn into parenthesis)
5656
["(4.0 °C)", Quantity("4 degC")],
5757
["[4.0 °C]", Quantity("4 degC")],
5858
["4.0 (°C)", Quantity("4 degC")],
@@ -99,6 +99,7 @@
9999
["0.05 ppm purity specified", Quantity("0.05 part_per_million")],
100100
["Odor detection in air, 0.05 ppm (purity not specified)", Quantity("0.05 part_per_million")],
101101
["Relative density (water = 1): 1.04-1.13", Quantity("1.04")],
102+
["Density approximately 6.5 lb / gal.", Quantity("6.5 lb/ gal")],
102103

103104
# duplicates of same quantity different units
104105
["4.0 °C (39.2 °F)", Quantity("4 degC")],
@@ -118,7 +119,6 @@
118119
]
119120

120121

121-
122122
def pre_process_values():
123123
for example in examples:
124124
result = parser(example[0])
@@ -130,4 +130,4 @@ def main():
130130

131131

132132
if __name__ == '__main__':
133-
main()
133+
pre_process_values()

dev_files/reduce_quantity_list.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from unit_parse import logger, Q, U, reduce_quantities
55

66
test_logger.setLevel(logging.DEBUG)
7-
logger.setLevel(logging.WARNING)
7+
logger.setLevel(logging.INFO)
88

99
examples = [ # [Input, Output]
1010
# positive control (works, does changes)
@@ -49,19 +49,44 @@
4949
[[Q("18 mmHg"), Q("68 degF")], [Q("20 mmHg"), Q("77.0 degF")]], [Q("20.8 mmHg"), Q("25 degC")]],
5050
[[Q("18 mmHg"), Q("68 degF")], [Q("20 mmHg"), Q("77.0 degF")]]],
5151

52+
[[[[Q("68 degF"), Q("760.0 mmHg")]], Q("68.0 degF"), Q("20.0 degC"), Q("293.15 kelvin * speed_of_light ** 2"),
53+
Q("68 degF"), Q("68 degF")],
54+
[[Q("68 degF"), Q("760.0 mmHg")]]],
55+
5256
[[[Q("68 degF"), Q("760.0 mmHg")], Q("68.0 degF"), Q("20.0 degC"), Q("293.15 kelvin * speed_of_light ** 2"),
5357
Q("68 degF"), Q("68 degF")],
54-
[Q("68 degF"), Q("760.0 mmHg")]],
58+
Q("68 degF")],
5559

5660
[[0.65, Q('0.66'), Q('0.65'), Q('0.65')], Q('0.65')],
5761

58-
[[[0.65, Q('25 degC')], Q('0.65'), Q('0.65')], [0.65, Q('25 degC')]],
62+
[[[0.65, Q('25 degC')], Q('0.65'), Q('0.65')], Q('0.65')],
63+
64+
[[[Q('50 kg'), Q('25 kg')], Q('0.65 dimensionless'), Q('0.65 dimensionless')],
65+
[Q('50 kg'), Q('25 kg')]],
66+
67+
[[6, 5, 5, 3, 4, 5], 5],
68+
[[6, 5, 3, 4, 7], 5],
69+
[[[6, 5, 5, 3, 4, 5], 5, 6], [6, 5, 5, 3, 4, 5]],
70+
[[Q("1 g"), Q("2 g"), Q("3 g"), Q("4 g"), Q("5 g")], Q("3 g")],
71+
[[[Q("6 g"), Q("6 g"), Q("5 g"), Q("5.5 g"), Q("6.2 g")], Q("6")],
72+
[Q("6 g"), Q("6 g"), Q("5 g"), Q("5.5 g"), Q("6.2 g")]],
73+
74+
[[[[Q("-15 degC"), Q("1 mmHg")]], Q("-41.6 degC"), Q("-42 degC"), Q("-40 degC"), Q("-40 degC")],
75+
[[Q("-15 degC"), Q("1 mmHg")]]],
76+
77+
[[[[Q("-1500 degC"), Q("1 mmHg")]], Q("-41.6 degC"), Q("-42 degC"), Q("-40 degC"), Q("-40 degC")],
78+
Q("-40 degC")],
5979

60-
[[[Q('50 kg'), Q('25 degC')], Q('0.65 dimensionless'), Q('0.65 dimensionless')],
61-
[Q('50 kg'), Q('25 degC')]]
6280

6381
# negative control (fails/ does no changes)
82+
[Q('25 degC'), Q('25 degC')],
83+
[[Q('25 degC')], Q('25 degC')]
6484

6585
]
6686

6787
testing_func(reduce_quantities, examples)
88+
89+
90+
# input_ = [[[Q("2 ppm"), Q("5 mol/ml"), Q("10 mol/cm**3")], Q("2 ppm"), {"order": (1, 2, 3, 0)}]]
91+
#
92+
# testing_func(reduce_quantities, input_)

dev_files/single.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
# ]
2424
# testing_func(remove_words, test_remove_words, {"words": config.english_dict})
2525

26-
result = parser("1.0722 at 68 °F (EPA, 1998)")
26+
result = parser("Density approximately 6.5 lb / gal.")
2727

2828
print(result)
2929

pyproject.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ exclude_lines = [
2020
"if __name__ == .__main__.:"
2121
]
2222

23+
[tool.coverage.run]
24+
omit = [
25+
"src/unit_parse/logger.py",
26+
"src/unit_parse/config.py",
27+
"src/unit_parse/support_files/*"
28+
]
29+
2330
[tool.mypy]
2431
mypy_path = "src"
2532
check_untyped_defs = true

setup.cfg

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = unit_parse
3-
version = 0.0.9
3+
version = 0.1.0
44
description = Parse units from strings. From mess to order!
55
long_description = file: README.md
66
long_description_content_type = text/markdown
@@ -34,4 +34,5 @@ testing =
3434
flake8>=3.9
3535

3636
[flake8]
37-
max-line-length = 160
37+
max-line-length = 160
38+
exclude = /unit_parse/support_files

src/__init__.py

Whitespace-only changes.

src/unit_parse/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
from unit_parse.reduce_quantities import reduce_quantities
55

66
__all__ = [
7-
"Unit", "U", "Q", "Quantity", "parser", "logger", "reduce_quantities"
7+
"Unit", "U", "Q", "Quantity", "parser", "logger", "reduce_quantities", "config"
88
]

src/unit_parse/config.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
11
import os
22
import sys
3+
import inspect
34

45
from unit_parse.logger import logger
56

67

7-
def _get_from_stack(obj):
8+
def get_unit_registry():
89
"""
910
Gets object from Python stack/globals
1011
Stops at first object it finds
1112
1213
"""
13-
for i in range(100): # 100 is to limit the depth it looks
14-
frames = sys._getframe(i)
15-
globals_ = frames.f_globals
16-
found_obj = [globals_[k] for k, v in globals_.items() if isinstance(v, obj) and k[0] != "_"]
17-
if found_obj:
18-
found_obj = found_obj[0]
19-
break
14+
stack = inspect.stack()
15+
for frame in stack:
16+
attrs: dict = frame.frame.f_locals
17+
for attr in attrs.values():
18+
if hasattr(attr, "_REGISTRY"):
19+
return attr._REGISTRY
2020
else:
21-
mes = f"{obj} not found in globals."
21+
mes = "Pint UnitRegistry not found."
2222
raise Exception(mes)
2323

24-
return found_obj
25-
2624

2725
def check_for_pint():
2826
""" Check for Pint
@@ -41,18 +39,20 @@ def check_for_pint():
4139
logger.warning("'Pint' module found in stack. (you have 'import pint' somewhere in your code).")
4240
# get unit registry
4341
try:
44-
u = _get_from_stack(modules["pint.registry"].UnitRegistry)
42+
u_ = get_unit_registry()
4543
logger.warning("\033[32m Unit registry found. :) \033[0m")
46-
return u
44+
return u_
4745
except Exception:
4846
logger.warning("Pint unit registry not found in stack. Loading 'unit_parser' registry. (Note: "
4947
"Pint unit registries are not interoperable. ")
5048

5149
# if no pint found, load local
5250
import pint
5351
current_path = os.path.dirname(os.path.realpath(__file__))
54-
return pint.UnitRegistry(autoconvert_offset_to_baseunit=True,
52+
u_ = pint.UnitRegistry(autoconvert_offset_to_baseunit=True,
5553
filename=os.path.join(current_path, "support_files\\default_en.txt"))
54+
u_.default_format = "~"
55+
return u_
5656

5757

5858
# set pint units
@@ -99,8 +99,8 @@ def __init__(self):
9999
["°C", "degC"], # eliminates issue with capitalization step
100100
["(?<=[0-9]{1})[ ]{0,1}X[ ]{0,1}(?=[0-9]{1})", "*"], # unify multiplication symbols
101101
["(?<=[0-9]{1})[ ]{0,1}x[ ]{0,1}(?=[0-9]{1})", "*"], # unify multiplication symbols
102-
["\[", "("], # make all brackets parenthesis
103-
["\]", ")"], # make all brackets parenthesis
102+
["\[", "("], # noqa: W605 # make all brackets parenthesis
103+
["\]", ")"], # noqa: W605 # make all brackets parenthesis
104104
["^.*={1}", ""], # delete everything in front of equal
105105
["^.*:{1}", ""], # delete everything in front of collen
106106
["( to )", "-"], # unify how range are represented

src/unit_parse/core.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
from typing import List, Union
99
import re
1010

11-
from .config import Unit, Quantity, config
12-
from .pre_processing_substitution import sub_general
13-
from .utils import flatten_list, contains_number, sig_figs, remove_empty_str, split_list
14-
from .logger import log_debug, log_info, logger
11+
from unit_parse.config import Unit, Quantity, config
12+
from unit_parse.pre_processing_substitution import sub_general
13+
from unit_parse.utils import flatten_list, contains_number, sig_figs, remove_empty_str, split_list
14+
from unit_parse.logger import log_debug, log_info, logger
1515

1616

1717
@log_info
@@ -341,7 +341,7 @@ def split_on_multiplication_symbol(text_in: Union[str, list[str], list[Union[str
341341
except Exception:
342342
pass
343343
if bool(re.match("([^*]+)[ ]?[*][ ]?([^*-0-9].*)", split)):
344-
new_splits[ii] = split_on_multiplication_symbol(split) # recursive
344+
new_splits[ii] = split_on_multiplication_symbol(split) # pragma: no cover recursive
345345

346346
text_in[i] = new_splits
347347
continue

0 commit comments

Comments
 (0)