Return correct uri for TypeMergeError exceptions with dictionaries
diff --git a/reclass/datatypes/parameters.py b/reclass/datatypes/parameters.py
index f40b259..e40ded1 100644
--- a/reclass/datatypes/parameters.py
+++ b/reclass/datatypes/parameters.py
@@ -25,37 +25,12 @@
from collections import namedtuple
from reclass.utils.dictpath import DictPath
+from reclass.utils.parameterdict import ParameterDict
+from reclass.utils.parameterlist import ParameterList
from reclass.values.value import Value
from reclass.values.valuelist import ValueList
from reclass.errors import InfiniteRecursionError, ResolveError, ResolveErrorList, InterpolationError, BadReferencesError
-class ParameterDict(dict):
- def __init__(self, *args, **kwargs):
- self._uri = kwargs.pop('uri', None)
- dict.__init__(self, *args, **kwargs)
-
- @property
- def uri(self):
- return self._uri
-
- @uri.setter
- def uri(self, uri):
- self._uri = uri
-
-
-class ParameterList(list):
- def __init__(self, *args, **kwargs):
- self._uri = kwargs.pop('uri', None)
- list.__init__(self, *args, **kwargs)
-
- @property
- def uri(self):
- return self._uri
-
- @uri.setter
- def uri(self, uri):
- self._uri = uri
-
class Parameters(object):
'''
@@ -83,8 +58,8 @@
def __init__(self, mapping, settings, uri, parse_strings=True):
self._settings = settings
- self._base = {}
self._uri = uri
+ self._base = ParameterDict(uri=self._uri)
self._unrendered = None
self._escapes_handled = {}
self._inv_queries = []
@@ -215,6 +190,7 @@
else:
value = self._merge_recurse(cur.get(key), value)
cur[key] = value
+ cur.uri = new.uri
return cur
def _merge_recurse(self, cur, new):
diff --git a/reclass/datatypes/tests/test_parameters.py b/reclass/datatypes/tests/test_parameters.py
index 2fcc899..013bd88 100644
--- a/reclass/datatypes/tests/test_parameters.py
+++ b/reclass/datatypes/tests/test_parameters.py
@@ -17,6 +17,7 @@
from reclass.settings import Settings
from reclass.datatypes import Parameters
+from reclass.utils.parameterdict import ParameterDict
from reclass.values.value import Value
from reclass.values.scaitem import ScaItem
from reclass.errors import ChangedFixedError, InfiniteRecursionError, InterpolationError, ResolveError, ResolveErrorList, TypeMergeError
@@ -46,7 +47,7 @@
def _construct_mocked_params(self, iterable=None, settings=SETTINGS):
p = Parameters(iterable, settings, '')
self._base = base = p._base
- p._base = mock.MagicMock(spec_set=dict, wraps=base)
+ p._base = mock.MagicMock(spec_set=ParameterDict, wraps=base)
p._base.__repr__ = mock.MagicMock(autospec=dict.__repr__,
return_value=repr(base))
p._base.__getitem__.side_effect = base.__getitem__
@@ -291,6 +292,16 @@
p1.interpolate()
self.assertEqual(p1.as_dict()['key'], None)
+ def test_merge_list_over_dict(self):
+ p1 = Parameters({}, SETTINGS, '')
+ p2 = Parameters({'one': { 'a': { 'b': 'c' } } }, SETTINGS, 'second')
+ p3 = Parameters({'one': { 'a': [ 'b' ] } }, SETTINGS, 'third')
+ with self.assertRaises(TypeMergeError) as e:
+ p1.merge(p2)
+ p1.merge(p3)
+ p1.interpolate()
+ self.assertEqual(e.exception.message, "-> \n Canot merge list over dictionary, at one:a, in second; third")
+
# def test_merge_bare_dict_over_dict(self):
# settings = Settings({'allow_bare_override': True})
# p1 = Parameters(dict(key=SIMPLE), settings, '')
diff --git a/reclass/utils/parameterdict.py b/reclass/utils/parameterdict.py
new file mode 100644
index 0000000..6319a0b
--- /dev/null
+++ b/reclass/utils/parameterdict.py
@@ -0,0 +1,12 @@
+class ParameterDict(dict):
+ def __init__(self, *args, **kwargs):
+ self._uri = kwargs.pop('uri', None)
+ dict.__init__(self, *args, **kwargs)
+
+ @property
+ def uri(self):
+ return self._uri
+
+ @uri.setter
+ def uri(self, uri):
+ self._uri = uri
diff --git a/reclass/utils/parameterlist.py b/reclass/utils/parameterlist.py
new file mode 100644
index 0000000..f2473df
--- /dev/null
+++ b/reclass/utils/parameterlist.py
@@ -0,0 +1,12 @@
+class ParameterList(list):
+ def __init__(self, *args, **kwargs):
+ self._uri = kwargs.pop('uri', None)
+ list.__init__(self, *args, **kwargs)
+
+ @property
+ def uri(self):
+ return self._uri
+
+ @uri.setter
+ def uri(self, uri):
+ self._uri = uri