Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def test_get_top():
stack = Metastack()
stack._set_layer(0, 'base', {'something': 123})
assert stack.get('something') == 123
def test_requesting_empty_path():
stack = Metastack()
stack._set_layer(0, 'base', {'foo': {'bar': 'baz'}})
assert stack.get('', 'default') == 'default'
def test_merge_sets_multi_layers():
stack = Metastack()
stack._set_layer(0, 'base', {'something': {'a_set': {1, 2}, 'a_value': 5}})
stack._set_layer(0, 'overlay', {'something': {'a_set': {3}}})
stack._set_layer(0, 'unrelated', {'something': {'another_value': 10}})
assert stack.get('something/a_set', None) == {1, 2, 3}
def test_deepcopy():
stack = Metastack()
stack._set_layer(0, 'base', {'foo': {'bar': {1, 2, 3}}})
foo = stack.get('foo', None)
foo['bar'].add(4)
assert stack.get('foo/bar') == {1, 2, 3}
del foo['bar']
assert stack.get('foo/bar')
def test_merge_lists_with_multiple_used_layers():
stack = Metastack()
stack._set_layer(0, 'base', {'something': {'a_list': [1, 2], 'a_value': 5}})
stack._set_layer(0, 'overlay1', {'something': {'a_list': [3]}})
stack._set_layer(0, 'overlay2', {'something': {'a_list': [4]}})
stack._set_layer(0, 'overlay3', {'something': {'a_list': [6, 5]}})
assert sorted(stack.get('something/a_list', None)) == sorted([1, 2, 3, 4, 5, 6])
def test_overlay_value():
stack = Metastack()
stack._set_layer(0, 'base', {'something': {'a_list': [1, 2], 'a_value': 5}})
stack._set_layer(0, 'overlay', {'something': {'a_value': 10}})
assert stack.get('something/a_value', None) == 10
def test_merge_lists_multi_layers():
stack = Metastack()
stack._set_layer(0, 'base', {'something': {'a_list': [1, 2], 'a_value': 5}})
stack._set_layer(0, 'overlay', {'something': {'a_list': [3]}})
stack._set_layer(0, 'unrelated', {'something': {'another_value': 10}})
# Objects in Metastacks are frozen. This converts lists to tuples.
# Unlike set and frozenset, list and tuple doesn't naturally support
# "is equal".
#
# This is acceptable, because in metaprocs people are expected to
# maybe check if something is in a list and maybe access some item
# of a list. All that works. Operations like .append() do not work
# and they are not supposed to.
assert len(stack.get('something/a_list', None)) == 3
assert stack.get('something/a_list', None)[0] == 1
assert stack.get('something/a_list', None)[1] == 2
assert stack.get('something/a_list', None)[2] == 3
def test_as_blame():
stack = Metastack()
stack._set_layer(0, 'base', {'something': {'a_list': [1, 2], 'a_value': 5}})
stack._set_layer(0, 'overlay', {'something': {'a_list': [3]}})
stack._set_layer(0, 'unrelated', {'something': {'another_value': 10}})
assert stack._as_blame() == {
('something',): ['base', 'overlay', 'unrelated'],
('something', 'a_list'): ['base', 'overlay'],
('something', 'a_value'): ['base'],
('something', 'another_value'): ['unrelated'],
}
Returns full or partial metadata for this node. This is the
primary entrypoint accessed from node.metadata.
Partial metadata may only be requested from inside a metadata
reactor.
If necessary, this method will build complete metadata for this
node and all related nodes. Related meaning nodes that this node
depends on in one of its metadata reactors.
"""
if self.__in_a_reactor:
if node_name in self._node_metadata_complete:
# We already completed metadata for this node, but partial must
# return a Metastack, so we build a single-layered one just for
# the interface.
metastack = Metastack()
metastack._set_layer(
0,
"flattened",
self._node_metadata_complete[node_name],
)
return metastack
else:
self.__partial_metadata_accessed_for.add(node_name)
return self.__metastacks.setdefault(node_name, Metastack())
if blame or stack:
# cannot return cached result here, force rebuild
try:
del self._node_metadata_complete[node_name]
except KeyError:
pass
def __initial_run_for_node(self, node_name):
io.debug(f"initial metadata run for {node_name}")
node = self.get_node(node_name)
self.__metastacks[node_name] = Metastack()
# randomize order to increase chance of exposing clashing defaults
for defaults_name, defaults in randomize_order(node.metadata_defaults):
self.__metastacks[node_name]._set_layer(
2,
defaults_name,
defaults,
)
self.__metastacks[node_name]._cache_partition(2)
group_order = _flatten_group_hierarchy(node.groups)
for group_name in group_order:
self.__metastacks[node_name]._set_layer(
0,
"group:{}".format(group_name),
self.get_group(group_name)._attributes.get('metadata', {}),