The new version of the datavars module is partly implemented.

packages
Иванов Денис 4 years ago
parent 6fdcf0744b
commit df9e70a0d8

@ -3,8 +3,17 @@ import re
class VariableType:
'''Базовый класс для типов.'''
@classmethod
def check(self, value: str) -> bool:
pass
return True
class VariableError(Exception):
pass
class VariableTypeError(Exception):
pass
class StringType(VariableType):
@ -14,14 +23,16 @@ class StringType(VariableType):
class IntegerType(VariableType):
integer_pattern = re.compile(r"^-?\d+$")
def check(self, value) -> bool:
@classmethod
def check(self, value: str) -> bool:
return self.integer_pattern.match(value)
class FloatType(VariableType):
float_pattern = re.compile(r"^-?\d+(\.\d+)?$")
def check(self, value) -> bool:
@classmethod
def check(self, value: str) -> bool:
return self.integer_pattern.match(value)
@ -37,12 +48,94 @@ class ReadonlyType(VariableType):
pass
class Variable:
def __init__(self, variable_type: VariableType):
self.var_type = variable_type
class Namespace:
def __init__(self, name=''):
self._name = name
class VariableNode:
def __init__(self, name, namespace, variable_type=StringType):
self.name = name
if issubclass(variable_type, VariableType):
self.variable_type = variable_type
else:
raise VariableTypeError('variable_type must be VariableType'
', but not {}'.format(type(variable_type)))
self.namespace = namespace
self.set_function = None
self.value = None
self.subscribers = set()
self.subscriptions = tuple()
def update_value(self, value=None):
if self.set_function is not None:
if self.subscriptions:
self.value = self.set_function(*(subscription.value for
subscription in
self.subscriptions))
elif value is not None:
self.value = self.set_function(value)
else:
# Пока что полагаем ее обнуленной в этой ситуации.
# TODO Обдумать поведение.
self.value = None
elif self.subscriptions:
# Пока что будем полагать, что в такой ситуации берем значение из
# последней подписки.
self.value = self.subscriptions[-1]
else:
self.value = value
@property
def fullname(self) -> str:
if self.namespace:
return "{}.{}".format(self.namespace.fullname, self.name)
else:
return self.name
def __repr__(self):
return '<Variable: {} with value: {}>'.format(self.fullname,
self.value or
'INVALIDATED')
class NamespaceNode:
def __init__(self, name='', parent=None):
self.name = name
self.variables = dict()
self.namespaces = dict()
self.parent = parent
def add_variable(self, variable: VariableNode):
self.variables.update({variable.name: variable})
variable.namespace = self
def add_namespace(self, namespace):
self.namespaces.update({namespace.name: namespace})
namespace.parent = self
@property
def fullname(self) -> str:
if self.parent is not None:
return '{}.{}'.format(self.parent.fullname, self.name)
else:
return self.name
def get_variable_node(self, name):
if name in self.variables:
return self.variables[name]
else:
raise VariableError("Variable '{variable_name}' is not found in"
" the namespace '{namespace_name}'".format(
variable_name=name,
namespace_name=self.name))
def __getattr__(self, name: str):
if name in self.namespaces:
return self.namespaces[name]
elif name in self.variables:
return self.variables[name].value
else:
raise VariableError("'{variable_name}' is not found in the"
" namespace '{namespace_name}'".format(
variable_name=name,
namespace_name=self.name))
def __repr__(self):
return '<Namespace: {}>'.format(self.fullname)

@ -25,6 +25,7 @@ markers =
package_utils: marker for running tests for calculate.utils.contents module.
vars: marker for running tests for datavars
alt_vars: marker for testing alternative version of the datavars module.
gentoo: marker for running tests for utils.gentoo
calculateini: marker for running tests for utils.calculateini
template_engine: marker for running tests for TemplateEngine.

@ -1,6 +1,53 @@
import pytest
from calculate.vars.alt_datavars import NamespaceNode, VariableNode
@pytest.mark.alt_vars
class TestNamespace:
pass
# Сначала тестируем классы и методы необходимые для построения дерева
# переменных и пространств имен.
def test_if_NamespaceNode_just_initialized_with_its_name__the_NamespaceNode_object_contains_empty_namespaces_and_variables_dictionaries_and_fullname_method_returns_only_the_namespace_s_name(self):
namespace_1 = NamespaceNode('namespace_1')
assert namespace_1.namespaces == dict()
assert namespace_1.variables == dict()
assert namespace_1.fullname == 'namespace_1'
def test_if_namespace_node_added_in_an_other_namespace_node__a_parent_namespace_node_contains_child_namespace_in_its_namespaces_dictionary_and_child_namespace_object_has_parent_namespace_in_its_parent_attribute_and_its_fullname_method_returns_names_of_both_namespaces(self):
namespace_1 = NamespaceNode('namespace_1')
namespace_2 = NamespaceNode('namespace_2')
namespace_1.add_namespace(namespace_2)
assert namespace_1.namespaces == {'namespace_2': namespace_2}
assert namespace_1.variables == dict()
assert namespace_1.fullname == 'namespace_1'
assert namespace_2.namespaces == dict()
assert namespace_2.variables == dict()
assert namespace_2.parent == namespace_1
assert namespace_2.fullname == 'namespace_1.namespace_2'
def test_if_two_VariableNode_objects_are_initialized_and_added_to_a_namespace__the_NamespaceNode_object_contains_this_variables_and_can_be_used_to_get_variables_values_and_variables_have_namespace_name_in_their_fullnames(self):
namespace_1 = NamespaceNode('namespace_1')
variable_1 = VariableNode('var_1', namespace_1)
variable_1.update_value(value='value_1')
variable_2 = VariableNode('var_2', namespace_1)
variable_2.update_value(value='value_2')
namespace_1.add_variable(variable_1)
namespace_1.add_variable(variable_2)
assert namespace_1.namespaces == dict()
assert namespace_1.variables == {'var_1': variable_1,
'var_2': variable_2}
assert namespace_1.fullname == 'namespace_1'
assert namespace_1.var_1 == 'value_1'
assert namespace_1.var_2 == 'value_2'
assert namespace_1.get_variable_node('var_1').fullname ==\
'namespace_1.var_1'
assert namespace_1.get_variable_node('var_2').fullname ==\
'namespace_1.var_2'
def test_updating_variable_using_set_function(self):
pass

Loading…
Cancel
Save