diff --git a/pysercomb/parsers/units.py b/pysercomb/parsers/units.py index b9d19d8..20efdaf 100644 --- a/pysercomb/parsers/units.py +++ b/pysercomb/parsers/units.py @@ -77,6 +77,7 @@ def inner(subtree): # can't index because we are at the bottom # FIXME this has ambiguous semantics continue + return subtree[0] lisped = inner(return_value) if lisped != return_value: @@ -319,12 +320,12 @@ def parse_for_tests(parameter_expression=None): return tests, prefix_expr_tests, weirds, should_fail, param_test_strings, _all, parsed + def main(): import pprint from time import time from pathlib import Path from desc.prof import profile_me - from IPython import embed from pysercomb.pyr.units import SExpr from protcur.config import __units_folder__ as units_path @@ -369,7 +370,9 @@ def timeit(): for t in tests + weirds), key=lambda v: v[25:])) print(test_expression2) test_fails = [parameter_expression(t) for t in tests] - embed() + if __name__ == '__main__': + from IPython import embed + embed() if __name__ == '__main__': diff --git a/pysercomb/pyr/units.py b/pysercomb/pyr/units.py index 2e4dd9f..4fd3525 100644 --- a/pysercomb/pyr/units.py +++ b/pysercomb/pyr/units.py @@ -4,6 +4,7 @@ from enum import Enum from pathlib import Path from pysercomb import exceptions as exc +from pysercomb.utils import log, logd from pysercomb.parsers.units import get_unit_dicts, _plus_or_minus, make_unit_parser from protcur.config import __script_folder__ as pasf @@ -479,20 +480,17 @@ def bindPython(cls, *classes): return type('ParamParser', (cls,), class_dict) def parse_failure(self, *args): - error = exc.ParseFailure('no context to know what the expr was') + e = exc.ParseFailure('no context to know what the expr was') if self._config.parser_failure_mode == mode.FAIL: - raise error + raise e - return error + logd.error(str(e)) + return e def expr(self, sexp): return sexp def unit_expr(self, expression): # TODO probably a macro - #if ' * ' in expression: - # FIXME ... would prefer to detect ahead of time - #expression = expression.replace(' * ', '*') - return expression @macro # oops, sometime unit expressions are hidden in units :x @@ -566,11 +564,13 @@ def approximately(self, expression): def plus_or_minus(self, base, error=None): if error is None: - e = exc.BadNotationError(f'error is a required argument for plus_or_minus ' - 'someone is misusing the notation!') + msg = (f'error is a required argument for plus_or_minus ' + 'someone is misusing the notation!') + e = exc.BadNotationError(msg) if self._config.data_failure_mode == mode.FAIL: raise e + logd.error(str(e)) return e return PlusOrMinus(base, error) diff --git a/pysercomb/utils.py b/pysercomb/utils.py index ddad3d5..3f35e37 100644 --- a/pysercomb/utils.py +++ b/pysercomb/utils.py @@ -1,3 +1,23 @@ +import logging + + +def makeSimpleLogger(name, level=logging.INFO): + # TODO use extra ... + logger = logging.getLogger(name) + logger.setLevel(level) + ch = logging.StreamHandler() # FileHander goes to disk + fmt = ('[%(asctime)s] - %(levelname)8s - ' + '%(name)14s - ' + '%(filename)16s:%(lineno)-4d - ' + '%(message)s') + formatter = logging.Formatter(fmt) + ch.setFormatter(formatter) + logger.addHandler(ch) + return logger + + +log = makeSimpleLogger('pysercomb') +logd = makeSimpleLogger('pysercomb-data') def coln(n, iterable): diff --git a/test/test_units.py b/test/test_units.py index 36fab96..53f00b5 100644 --- a/test/test_units.py +++ b/test/test_units.py @@ -1,36 +1,55 @@ import unittest from .common import * +from pysercomb.parsers import units class TestForms(unittest.TestCase): - def test_time_vs_dilution(self): - assert parameter_expression('1:1000') == (True, ('param:dilution', 1, 1000), ''), 'dilution failed' - assert (parameter_expression('00:00:01') - == (True, ('param:quantity', 1, ('param:unit', "'seconds")), '')), 'duration failed' - assert (parameter_expression('00:01:01') - == (True, ('param:quantity', 61, ('param:unit', "'seconds")), '')), 'duration failed' - assert (parameter_expression('01:01:01') - == (True, ('param:quantity', 3661, ('param:unit', "'seconds")), '')), 'duration failed' - assert (parameter_expression('1:99:01') - == (True, ('param:quantity', 9541, ('param:unit', "'seconds")), '')), 'duration failed' + def test_dilution(self): + assert parameter_expression('1:1000')[1] == ('param:dilution', 1, 1000), 'dilution failed' + + def test_time_seconds(self): + assert (parameter_expression('00:00:01')[1] + == ('param:quantity', 1, ('param:unit', "'seconds"))), 'duration failed' + + def test_time_minutes(self): + assert (parameter_expression('00:01:01')[1] + == ('param:quantity', 61, ('param:unit', "'seconds"))), 'duration failed' + + def test_time_hours(self): + assert (parameter_expression('01:01:01')[1] + == ('param:quantity', 3661, ('param:unit', "'seconds"))), 'duration failed' + + def test_time_weird(self): + assert (parameter_expression('1:99:01')[1] + == ('param:quantity', 9541, ('param:unit', "'seconds"))), 'duration failed' class TestUnit(unittest.TestCase): - def test_no_imperial_prefix(self): + def test_minutes(self): """ make sure we don't parse min -> milli inches """ assert unit('min') == (True, ('param:unit', "'minutes"), ''), 'min did not parse to minutes' + + def test_inches(self): assert unit('in') == (True, ('param:unit', "'inches"), ''), 'in did not parse to inches' - def test_rcf_ohms(self): + def test_ohms(self): assert unit('R') == (True, ('param:unit', "'ohms"), ''), 'R did not parse to ohms' + + def test_rcf(self): assert unit('RCF') == (True, ('param:unit', "'relative-centrifugal-force"), ''), 'RCF did not parse to relative-centrifugal-force' - def test_numerical_aperture(self): + def test_newtons(self): assert unit('N') == (True, ('param:unit', "'newtons"), ''), 'N did not parse to newtons' + + def test_numerical_aperture(self): msg = 'NA did not parse to numerical-aperture' assert unit('NA') == (True, ('param:unit', "'numerical-aperture"), ''), msg - def test_dimension_not_fold(self): + def test_fold(self): + msg = 'Ax failed to parse as fold!' + assert parameter_expression('40x')[1] == ('param:quantity', 40, ('param:unit', "'fold")), msg + + def test_dimension(self): msg = 'A x B failed to parse as dimensions!' assert parameter_expression('50 x 50 um')[1] == ('param:dimensions', ('param:quantity', 50, ()), @@ -114,3 +133,9 @@ def test_infix_expr_noncommutative(self): ('param:quantity', 2, ())),), '') assert out == test + + +class TestMain(unittest.TestCase): + def test_main(self): + """ catch any changes here as well, eventually we should remove main for this ... """ + units.main()