summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHernan Grecco <hernan.grecco@gmail.com>2013-11-07 00:19:31 -0300
committerHernan Grecco <hernan.grecco@gmail.com>2013-11-07 00:19:31 -0300
commitf7434e72185e35c6f09b13e2eedd419c4a6d4a99 (patch)
tree7f5fea935ba1609a804ba629aa5f5d939e14cdc5
parentc71f104b95de9d56f29ec18026e86e269a5dadf3 (diff)
downloadpint-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.py6
-rw-r--r--pint/util.py53
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("^", "**")