summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHernan Grecco <hernan.grecco@gmail.com>2014-03-24 18:46:45 -0300
committerHernan Grecco <hernan.grecco@gmail.com>2014-03-24 18:54:45 -0300
commit17fc8731abe2d01c8b5cb03cd1b83c12b6bd029e (patch)
tree78de85c895e49b6d7230854d4b21cdc6df9d9eb9
parentcaaf23e2af78c7aca99f74541e2bd7f79df3246c (diff)
downloadpint-17fc8731abe2d01c8b5cb03cd1b83c12b6bd029e.tar.gz
Raise exception or warn upon redefinition of units.
In the DEFAULT_REGISTRY, an exception (ValueError) is raised. In any other registry, issue a warning The behaviour can be chaged using the `on_redefinition` argument in the constructor. Close #108
-rw-r--r--pint/testsuite/test_unit.py26
-rw-r--r--pint/unit.py39
2 files changed, 58 insertions, 7 deletions
diff --git a/pint/testsuite/test_unit.py b/pint/testsuite/test_unit.py
index 192af78..64de85c 100644
--- a/pint/testsuite/test_unit.py
+++ b/pint/testsuite/test_unit.py
@@ -4,6 +4,7 @@ from __future__ import division, unicode_literals, print_function, absolute_impo
import math
import copy
+import warnings
import operator as op
from pint.unit import (ScaleConverter, OffsetConverter, UnitsContainer,
@@ -495,6 +496,20 @@ class TestEquivalents(TestCase):
self.assertEqual(ureg.parse_units(''), UnitsContainer())
self.assertRaises(ValueError, ureg.parse_units, '2 * meter')
+ def test_redefinition(self):
+ d = UnitRegistry().define
+
+ with warnings.catch_warnings(record=True) as w:
+ d('meter = [time]')
+ d('kilo- = 1000')
+ d('[speed] = [length]')
+
+ # aliases
+ d('bla = 3.2 meter = inch')
+ d('myk- = 1000 = kilo-')
+
+ self.assertEqual(len(w), 5)
+
class TestRegistryWithDefaultRegistry(TestRegistry):
@@ -512,6 +527,17 @@ class TestRegistryWithDefaultRegistry(TestRegistry):
q = y['meter']
self.assertIsInstance(y, UnitRegistry)
+ def test_redefinition(self):
+ d = self.ureg.define
+ self.assertRaises(ValueError, d, 'meter = [time]')
+ self.assertRaises(ValueError, d, 'kilo- = 1000')
+ self.assertRaises(ValueError, d, '[speed] = [length]')
+
+ # aliases
+ self.assertIn('inch', self.ureg._units)
+ self.assertRaises(ValueError, d, 'bla = 3.2 meter = inch')
+ self.assertRaises(ValueError, d, 'myk- = 1000 = kilo-')
+
class TestErrors(unittest.TestCase):
diff --git a/pint/unit.py b/pint/unit.py
index 4122b69..31046b6 100644
--- a/pint/unit.py
+++ b/pint/unit.py
@@ -173,6 +173,10 @@ class Definition(object):
return self._symbol or self._name
@property
+ def has_symbol(self):
+ return bool(self._symbol)
+
+ @property
def aliases(self):
return self._aliases
@@ -388,12 +392,16 @@ class UnitRegistry(object):
:param force_ndarray: convert any input, scalar or not to a numpy.ndarray.
:param default_to_delta: In the context of a multiplication of units, interpret
non-multiplicative units as their *delta* counterparts.
+ :param on_redefinition: action to take in case a unit is redefined.
+ 'warn', 'raise', 'ignore'
+ :type on_redefintion: str
"""
- def __init__(self, filename='', force_ndarray=False, default_to_delta=True):
+ def __init__(self, filename='', force_ndarray=False, default_to_delta=True, on_redefinition='warn'):
self.Quantity = build_quantity_class(self, force_ndarray)
self.Measurement = build_measurement_class(self, force_ndarray)
+ self._on_redefinition = on_redefinition
#: Map dimension name (string) to its definition (DimensionDefinition).
self._dimensions = {}
@@ -592,8 +600,11 @@ class UnitRegistry(object):
d = self._units
if definition.is_base:
for dimension in definition.reference.keys():
- if dimension != '[]' and dimension in self._dimensions:
- raise ValueError('Only one unit per dimension can be a base unit.')
+ if dimension in self._dimensions:
+ if dimension != '[]':
+ raise ValueError('Only one unit per dimension can be a base unit.')
+ continue
+
self.define(DimensionDefinition(dimension, '', (), None, is_base=True))
elif isinstance(definition, PrefixDefinition):
@@ -601,15 +612,26 @@ class UnitRegistry(object):
else:
raise TypeError('{0} is not a valid definition.'.format(definition))
- d[definition.name] = definition
+ def _adder(key, value, action=self._on_redefinition, selected_dict=d):
+ if key in selected_dict:
+ if action == 'raise':
+ raise ValueError("Cannot redefine '%s' (%s) in the default registry"
+ % (key, type(value)))
+ elif action == 'warn':
+ logger.warning("Redefining '%s' (%s)", key, type(value))
- if definition.symbol:
- d[definition.symbol] = definition
+ selected_dict[key] = value
+
+ _adder(definition.name, definition)
+
+ if definition.has_symbol:
+ _adder(definition.symbol, definition)
for alias in definition.aliases:
if ' ' in alias:
logger.warn('Alias cannot contain a space: ' + alias)
- d[alias] = definition
+
+ _adder(alias, definition)
if isinstance(definition.converter, OffsetConverter):
d_name = 'delta_' + definition.name
@@ -1180,10 +1202,13 @@ class LazyRegistry(object):
def __init(self):
args, kwargs = self.__dict__['params']
+ kwargs['on_redefinition'] = 'raise'
self.__class__ = UnitRegistry
self.__init__(*args, **kwargs)
def __getattr__(self, item):
+ if item == '_on_redefinition':
+ return 'raise'
self.__init()
return getattr(self, item)