Tables, hash and dynamic subscriptions is fully tested.

packages
Иванов Денис 4 years ago
parent 91d3f4f3cb
commit 224b646793

@ -310,6 +310,8 @@ class VariableWrapper:
value = self._variable.get_value()
if isinstance(value, Hash):
value = value.get_hash()
elif isinstance(value, Table):
value = value.get_table()
return value
@property
@ -492,6 +494,11 @@ class VariableNode:
self.value = self.variable_type.process_value(value, self)
def set(self, value):
self._invalidate()
self.set_by_user = True
self.value = self.variable_type.process_value(value, self)
@property
def source(self):
return self._source
@ -501,7 +508,11 @@ class VariableNode:
if self._readonly:
raise VariableError("can not change the variable '{}': read only")
if self._source != source:
# Если источники не совпадают или текущее значение переменной было
# установлено пользователем, то инвалидируем переменную и меняем
# источник.
if self._source != source or self.set_by_user:
self.set_by_user = False
self._invalidate()
self._source = source
@ -521,7 +532,7 @@ class VariableNode:
'''Метод для инвалидации данной переменной и всех зависящих от нее
переменных.'''
print('{} is invalidated'.format(self.fullname))
if self.value is not None:
if self.value is not None and not self.set_by_user:
self.value = None
for subscriber in self.subscribers:
subscriber._invalidate()
@ -538,7 +549,7 @@ class VariableNode:
def get_value(self) -> Any:
'''Метод для получения значения переменной.'''
if self.value is None:
if self.value is None and not self.set_by_user:
self.update_value()
return self.value

@ -54,27 +54,6 @@ class TestNamespace:
assert namespace_1['var_1'].fullname == 'namespace_1.var_1'
assert namespace_1['var_2'].fullname == 'namespace_1.var_2'
def test_find_vars(self):
Namespace.reset()
datavars = Namespace.datavars
with Namespace('namespace_1'):
Variable('var_1', source='val_1')
Variable('var_2', source=2, type=IntegerType)
Variable('var_3', source=4, type=IntegerType)
with Namespace('namespace_1_1'):
Variable('var_1', source='val_1')
assert Dependence._find_variable('.var_1') ==\
datavars.namespace_1.namespace_1_1['var_1']
assert Dependence._find_variable('..var_3') ==\
datavars.namespace_1['var_3']
with Namespace('namespace_2'):
assert Dependence._find_variable('namespace_1.var_2') ==\
datavars.namespace_1['var_2']
def test_compare_two_dependencies_equal(self):
namespace_1 = NamespaceNode('namespace_1')
variable_1 = VariableNode('var_1', namespace_1, source=2,
@ -145,7 +124,7 @@ class TestNamespace:
dependence_2 = Dependence(variable_1, variable_2, depend=comparator)
assert dependence_1 != dependence_2
def test_if_a_variable_subscribed_to_two_other_variables_using_set_function__the_(self):
def test_if_a_variable_subscribed_to_two_other_variables_using_set_function__the_variable_updates_using_the_variables_and_the_set_function_to_calculate_its_value(self):
namespace_1 = NamespaceNode('namespace_1')
variable_1 = VariableNode('var_1', namespace_1, source=2,
variable_type=IntegerType)
@ -164,33 +143,151 @@ class TestNamespace:
assert namespace_2.var_1 == 'greater'
# Теперь тестируем интерфейс создания переменных.
def test_api(self):
def test_if_variables_creation_api_is_used_for_creating_of_a_number_of_variables_without_any_dependencies_in_their_sources__the_api_fabrics_creates_the_variables(self):
Namespace.reset()
datavars = Namespace.datavars
with Namespace('namespace_1'):
Variable('var_1', source='val_1')
var_2 = Variable('var_2', source=2, type=IntegerType)
Variable('var_2', source=2, type=IntegerType)
Variable('var_3', source=4, type=IntegerType)
with Namespace('namespace_2'):
Variable('var_1', source=Dependence(
var_2, '..namespace_1.var_3', depend=lambda arg_1, arg_2:
'greater' if arg_1.value > arg_2.value else 'less'))
with Namespace('namespace_2_1'):
with Namespace('namespace_1_1'):
Variable('var_1', source='val_1')
datavars = Namespace.datavars
assert datavars.namespace_1.var_1 == 'val_1'
assert datavars.namespace_1.var_2 == 2
assert datavars.namespace_1.var_3 == 4
assert datavars.namespace_1.namespace_1_1.var_1 == 'val_1'
def test_if_dependence_interface_object_is_used_for_finding_an_existing_variable_from_an_other_namespace_using_absolute_variable_name__the_find_variable_method_returns_the_desired_variable(self):
Namespace.reset()
datavars = Namespace.datavars
with Namespace('namespace_1'):
Variable('var_1', source='val_1', type=StringType)
with Namespace('namespace_2'):
assert Dependence._find_variable('namespace_1.var_1') ==\
datavars.namespace_1['var_1']
def test_if_dependence_interface_object_is_used_for_finding_an_unexisting_variable_from_an_other_namespace_using_absolute_variable_name__the_find_variable_method_raises_the_VariableError_exception(self):
Namespace.reset()
with Namespace('namespace_1'):
Variable('var_1', source='val_1', type=StringType)
with Namespace('namespace_2'):
with pytest.raises(VariableError):
Dependence._find_variable('namespace_1.var_2')
def test_if_dependence_interface_object_is_used_for_finding_an_existing_variable_from_a_same_namespace_using_relative_variable_name__the_find_variable_method_returns_the_desired_variable(self):
Namespace.reset()
datavars = Namespace.datavars
with Namespace('namespace_1'):
Variable('var_1', source='val_1', type=StringType)
Variable('var_2', source=2, type=IntegerType)
Variable('var_3', source=4, type=IntegerType)
with Namespace('namespace_1_1'):
Variable('var_1', source='val_1', type=StringType)
assert Dependence._find_variable('.var_1') ==\
datavars.namespace_1.namespace_1_1['var_1']
assert Dependence._find_variable('..var_3') ==\
datavars.namespace_1['var_3']
def test_if_dependence_interface_object_is_used_for_finding_an_unexisting_variable_from_a_same_namespace_using_relative_variable_name__the_find_variable_method_raises_the_VariableError_exception(self):
Namespace.reset()
with Namespace('namespace_1'):
Variable('var_1', source='val_1', type=StringType)
Variable('var_2', source=2, type=IntegerType)
with Namespace('namespace_1_1'):
with pytest.raises(VariableError):
Dependence._find_variable('..var_3')
def test_if_variable_is_created_with_dependence_in_its_source_and_the_dependence_has_only_set_function_without_any_arguments__the_variable_updates_its_value_using_only_set_function(self):
Namespace.reset()
datavars = Namespace.datavars
with Namespace('namespace_1'):
def source_function():
return 'value_from_function'
Variable('var', source=Dependence(depend=source_function),
type=VariableType)
assert datavars.namespace_1.var == 'value_from_function'
def test_if_a_variable_is_created_using_dependence_with_three_variables_and_a_set_function_but_during_the_calculation_only_two_variables_was_used__the_unused_variable_is_not_in_variable_subscriptions_and_is_invalidated_before_first_usage(self):
Namespace.reset()
datavars = Namespace.datavars
with Namespace('namespace_1'):
Variable('var_1', source=5, type=IntegerType)
Variable('var_2', source='less')
Variable('var_3', source='greater')
def solver(arg_1, arg_2, arg_3):
if arg_1.value < 6:
return arg_2.value
else:
return arg_3.value
Variable('var_4', type=StringType,
source=Dependence('.var_1', '.var_2', '.var_3',
depend=solver))
assert datavars.namespace_1.var_4 == datavars.namespace_1.var_2
assert datavars.namespace_1['var_1'] in\
datavars.namespace_1['var_4']._subscriptions
assert datavars.namespace_1['var_2'] in\
datavars.namespace_1['var_4']._subscriptions
assert datavars.namespace_1['var_3'] not in\
datavars.namespace_1['var_4']._subscriptions
assert datavars.namespace_1['var_3'].value is None
def test_if_variables_creation_api_is_used_for_creating_of_a_number_of_variables_with_existing_variables_dependencies_in_their_sources__the_api_fabrics_creates_the_variables(self):
Namespace.reset()
datavars = Namespace.datavars
with Namespace('namespace_1'):
var_1 = Variable('var_1', source=2, type=IntegerType)
Variable('var_2', source=4, type=IntegerType)
with Namespace('namespace_2'):
Variable('var_1', source=Dependence(
var_1, '..namespace_1.var_2', depend=lambda arg_1, arg_2:
'greater' if arg_1.value > arg_2.value else 'less'))
assert datavars.namespace_1.var_1 == 2
assert datavars.namespace_1.var_2 == 4
assert datavars.namespace_2.var_1 == 'less'
assert datavars.namespace_2.namespace_2_1.var_1 == 'val_1'
datavars.namespace_1['var_2'].source = 5
def test_if_variable_has_variable_dependence_in_its_source_and_the_subscription_variable_source_is_changed__the_subscriber_is_invalidated_and_then_updates_its_value(self):
Namespace.reset()
datavars = Namespace.datavars
with Namespace('namespace_1'):
var_1 = Variable('var_1', source=2, type=IntegerType)
Variable('var_2', source=4, type=IntegerType)
with Namespace('namespace_2'):
Variable('var_1', source=Dependence(
var_1, '..namespace_1.var_2', depend=lambda arg_1, arg_2:
'greater' if arg_1.value > arg_2.value else 'less'))
datavars = Namespace.datavars
assert datavars.namespace_2.var_1 == 'less'
datavars.namespace_1['var_1'].source = 5
assert datavars.namespace_2['var_1'].value is None
assert datavars.namespace_2.var_1 == 'greater'
def test_rewriting_if_source_changed_to_a_value(self):
def test_if_variable_was_created_using_variables_api_and_then_was_created_again_with_simple_source_value__the_variable_just_changes_its_source(self):
Namespace.reset()
datavars = Namespace.datavars
@ -208,7 +305,7 @@ class TestNamespace:
assert datavars.namespace_1.var_1 == 'value_2'
assert datavars.namespace_1.var_2 == 'from var_1: value_2'
def test_rewriting_if_source_changed_to_a_dependence(self):
def test_if_variable_was_created_using_variables_api_and_then_was_created_again_with_a_new_dependency_as_its_source__the_variable_just_changes_its_source_to_the_new_dependency(self):
Namespace.reset()
datavars = Namespace.datavars
@ -229,7 +326,7 @@ class TestNamespace:
assert datavars.namespace_1.var_2 == 'from var_3: value_3'
def test_cyclic_dependence(self):
def test_if_some_variables_created_with_dependencies_in_its_sources_and_subscribed_to_each_other__variables_raise_the_CyclicVariableError_exception_while_its_calculating(self):
Namespace.reset()
datavars = Namespace.datavars
@ -249,7 +346,35 @@ class TestNamespace:
with pytest.raises(CyclicVariableError):
datavars.namespace_1.var_3
def test_hash(self):
def test_if_a_variable_is_created_as_readonly_variable_and_there_is_a_try_to_change_its_source__the_variable_raises_the_VariableError_exception(self):
Namespace.reset()
with Namespace('namespace_1'):
Variable('var_1', source='value_1', type=StringType, readonly=True)
with Namespace('namespace_1'):
with pytest.raises(VariableError):
Variable('var_1', source='value_2', type=StringType)
def test_if_hash_variable_is_created_with_Hash_type_and_with_a_dictionary_in_its_source__the_variable_is_created_with_Hash_value_in_it(self):
Namespace.reset()
datavars = Namespace.datavars
with Namespace('namespace_1'):
Variable('var_1', type=HashType, source={'key_1': 'value_1',
'key_2': 'value_2'})
assert datavars.namespace_1.var_1.key_1 == 'value_1'
assert datavars.namespace_1.var_1.key_2 == 'value_2'
with Namespace('namespace_1'):
Variable('var_1', source={'key_1': 'another_value',
'key_2': 'other_value'})
assert datavars.namespace_1.var_1.key_1 == 'another_value'
assert datavars.namespace_1.var_1.key_2 == 'other_value'
def test_if_hash_variable_is_created_with_Hash_type_and_with_a_dependence_in_its_source__the_variable_is_created_with_Hash_value_in_it_using_dictionary_returned_by_depend_function(self):
Namespace.reset()
datavars = Namespace.datavars
@ -267,7 +392,6 @@ class TestNamespace:
source=Dependence('.var_1', '.var_2.key_1',
depend=depend_hash))
assert datavars.namespace_1.var_2.key_1 == 'value_1'
assert datavars.namespace_1.var_4.key_1 == 'value'
assert datavars.namespace_1.var_4.key_2 == 'value_1'
assert datavars.namespace_1.var_4.key_3 == 'value_1'
@ -276,11 +400,12 @@ class TestNamespace:
Variable('var_1', source='other_value', type=StringType)
Variable('var_2', source={'key_1': 'another_value',
'key_2': 'value_2'})
assert datavars.namespace_1.var_2.key_1 == 'another_value'
assert datavars.namespace_1.var_4.key_2 == 'other_value'
assert datavars.namespace_1.var_4.key_3 == 'another_value'
def test_getting_all_hash_to_depend_function(self):
def test_if_variable_is_created_with_dependence_and_one_of_arguments_of_a_depend_function_is_whole_hash__the_variable_will_set_this_argument_as_dictionary_of_the_whole_hash_in_a_depend_function(self):
Namespace.reset()
datavars = Namespace.datavars
@ -297,75 +422,52 @@ class TestNamespace:
assert datavars.namespace_1.var_4 == 'value_1'
def test_readonly(self):
def test_if_a_variable_has_TableType_and_created_using_list_of_dicts_in_its_source_and_other_variable_created_using_depend_function_with_the_first_variable_in_its_arg__the_fitst_variable_is_created_with_Table_value_and_depend_function_of_the_second_variable_can_use_whole_table_for_the_calculating_of_the_variable_s_value(self):
Namespace.reset()
datavars = Namespace.datavars
with Namespace('namespace_1'):
Variable('var_1', source='value_1', type=StringType, readonly=True)
with Namespace('namespace_1'):
print('namespace_1:')
for name, namespace in datavars.namespaces.items():
print(namespace.fullname)
for name, variable in datavars.variables.items():
print(variable.fullname)
with pytest.raises(VariableError):
Variable('var_1', source='value_2', type=StringType)
def test_source_function_without_vars(self):
Namespace.reset()
datavars = Namespace.datavars
with Namespace('namespace_1'):
def source_function():
return 'value_from_function'
Variable('var', source=Dependence(depend=source_function),
type=VariableType)
assert datavars.namespace_1.var == 'value_from_function'
Variable('var_1', type=TableType, source=[{'name': 'name_1',
'value': 'value_1'},
{'name': 'name_2',
'value': 'value_2'},
{'name': 'name_3',
'value': 'value_3'}])
def test_source_function_with_dynamic_subscription(self):
def depend_function(table):
for row in table.value:
if row['name'] == 'name_2':
return row['value']
Variable('var_2', type=StringType,
source=Dependence('os.var_1',
depend=depend_function))
assert datavars.namespace_1.var_2 == 'value_2'
def test_if_variable_of_TableType_is_created_using_dependence_that_creates_table__the_created_variable_has_generated_table_as_its_value(self):
from portage.package.ebuild.config import config
value = [{'name': name, 'path': path}
for path, name in
config().repositories.location_map.items()]
Namespace.reset()
datavars = Namespace.datavars
with Namespace('namespace_1'):
Variable('var_1', source=5, type=IntegerType)
Variable('var_2', source='less')
Variable('var_3', source='greater')
def solver(arg_1, arg_2, arg_3):
if arg_1.value < 6:
return arg_2.value
else:
return arg_3.value
Variable('var_4', type=StringType,
source=Dependence('.var_1', '.var_2', '.var_3',
depend=solver))
assert datavars.namespace_1['var_4'].value is None
def test_tables(self):
Namespace.reset()
# datavars = Namespace.datavars
with Namespace('main'):
Variable('chroot', source='/', type=StringType, readonly=True)
with Namespace('os'):
def source_function(chroot_path):
from portage.package.ebuild.config import config
if chroot_path == '/':
with stderr_devnull():
return config()
if chroot_path.value == '/':
return config()
Variable('config', source=Dependence('main.chroot',
depend=source_function),
type=VariableType)
Variable('var_1', source='value_1', type=StringType)
Variable('var_2', type=TableType, source=[{'name': 'name_1',
'value': 'value_1'},
{'name': 'name_2',
'value': 'value_2'},
{'name': 'name_3',
'value': 'value_3'}])
def config_source(config):
return [{'name': name, 'path': path}
for path, name in
config.value.repositories.location_map.items()]
Variable('repositories', type=TableType,
source=Dependence('.config', depend=config_source))
assert datavars.os.repositories.get_table() == value

Loading…
Cancel
Save