diff options
author | Hernan Grecco <hernan.grecco@gmail.com> | 2013-11-07 00:19:31 -0300 |
---|---|---|
committer | Hernan Grecco <hernan.grecco@gmail.com> | 2013-11-07 00:19:31 -0300 |
commit | f7434e72185e35c6f09b13e2eedd419c4a6d4a99 (patch) | |
tree | 7f5fea935ba1609a804ba629aa5f5d939e14cdc5 | |
parent | c71f104b95de9d56f29ec18026e86e269a5dadf3 (diff) | |
download | pint-f7434e72185e35c6f09b13e2eedd419c4a6d4a99.tar.gz |
ParseHelper can now parse units named like python keywords
ParseHelper gains a new class method to perform the common operation of
creating an object with a single unit and exponent 1.
Still to do:
- Do something similar for UnitRegistry.parse_expression
- Unify the __getitem__ and __getattr__ behaviour in UnitRegistry
- Parse unicode identifier
fix #69
-rw-r--r-- | pint/testsuite/test_issues.py | 6 | ||||
-rw-r--r-- | pint/util.py | 53 |
2 files changed, 40 insertions, 19 deletions
diff --git a/pint/testsuite/test_issues.py b/pint/testsuite/test_issues.py index 5cd7bba..cbaa60b 100644 --- a/pint/testsuite/test_issues.py +++ b/pint/testsuite/test_issues.py @@ -93,6 +93,12 @@ class TestIssues(unittest.TestCase): self.assertEqual(ureg.get_base_units(ureg.degC.units), (1., UnitsContainer({'degC': 1}))) + def test_issue69(self): + ureg = UnitRegistry() + q = ureg['m'].to(ureg['in']) + self.assertEqual(q, ureg['m'].to('in')) + + @unittest.skipUnless(HAS_NUMPY, 'Numpy not present') class TestIssuesNP(TestCase): diff --git a/pint/util.py b/pint/util.py index 51e4ba7..5634212 100644 --- a/pint/util.py +++ b/pint/util.py @@ -19,7 +19,7 @@ from numbers import Number from fractions import Fraction import logging -from token import STRING, NAME, OP, NUMBER +from token import STRING, NAME, OP from tokenize import untokenize logger = logging.getLogger(__name__) @@ -285,6 +285,17 @@ class ParserHelper(dict): dict.__init__(self, *args, **kwargs) @classmethod + def from_word(cls, input_word): + """Creates a ParserHelper object with a single variable with exponent one. + + Equivalent to: ParserHelper({'word': 1}) + + """ + ret = cls() + ret.add(input_word, 1) + return ret + + @classmethod def from_string(cls, input_string): """Parse linear expression mathematical units and return a quantity object. """ @@ -296,20 +307,20 @@ class ParserHelper(dict): if '[' in input_string: input_string = input_string.replace('[', '__obra__').replace(']', '__cbra__') - brackets = True + reps = True else: - brackets = False + reps = False gen = ptok(input_string) result = [] for toknum, tokval, _, _, _ in gen: - if toknum in (STRING, NAME): + if toknum == NAME: if not tokval: continue result.extend([ (NAME, 'L_'), (OP, '('), - (STRING, tokval), (OP, '='), (NUMBER, '1'), + (STRING, '"' + tokval + '"'), (OP, ')') ]) else: @@ -317,12 +328,11 @@ class ParserHelper(dict): ret = eval(untokenize(result), {'__builtins__': None}, - {'L_': cls}) - + {'L_': cls.from_word}) if isinstance(ret, Number): return ParserHelper(ret) - if not brackets: + if not reps: return ret return ParserHelper(ret.scale, @@ -399,22 +409,27 @@ class ParserHelper(dict): return self +#: List of regex substitution pairs. +_subs_re = [(r"({0}) squared", r"\1**2"), # Handle square and cube + (r"({0}) cubed", r"\1**3"), + (r"cubic ({0})", r"\1**3"), + (r"square ({0})", r"\1**2"), + (r"sq ({0})", r"\1**2"), + (r"(\w)\s+(?=\w)", r"\1*"), # Handle space for multiplication + (r"([0-9])(?={0})(?!(?:[e|E][-+]?[0-9]+))", r"\1*") + ] + +#: Compiles the regex and replace {0} by a regex that matches an identifier. +_subs_re = [(re.compile(a.format(r"[_a-zA-Z][_a-zA-Z0-9]*")), b) for a, b in _subs_re] + + def string_preprocessor(input_string): input_string = input_string.replace(",", "") input_string = input_string.replace(" per ", "/") - # Handle square and cube - input_string = re.sub(r"([_a-zA-Z]+) squared", r"\1**2", input_string) - input_string = re.sub(r"([_a-zA-Z]+) cubed", r"\1**3", input_string) - input_string = re.sub(r"cubic ([_a-zA-Z]+)", r"\1**3", input_string) - input_string = re.sub(r"square ([_a-zA-Z]+)", r"\1**2", input_string) - input_string = re.sub(r"sq ([_a-zA-Z]+)", r"\1**2", input_string) - - # Handle space for multiplication - input_string = re.sub(r"([_a-zA-Z0-9])\s+(?=[_a-zA-Z0-9])", r"\1*", input_string) - - input_string = re.sub(r"([0-9])(?=[_a-zA-Z][_a-zA-Z0-9]*)(?!(?:[e|E][-+]?[0-9]+))", r"\1*", input_string) + for a, b in _subs_re: + input_string = a.sub(b, input_string) # Handle caret exponentiation input_string = input_string.replace("^", "**") |