simplify objectspace
This commit is contained in:
parent
6c6746c58f
commit
ccc6924866
16 changed files with 207 additions and 325 deletions
|
@ -1059,7 +1059,7 @@ class ConstraintAnnotator:
|
||||||
for idx in indexes:
|
for idx in indexes:
|
||||||
fill = fills[idx]
|
fill = fills[idx]
|
||||||
# test if it's redefined calculation
|
# test if it's redefined calculation
|
||||||
if fill.target in targets and not fill.redefine:
|
if fill.target in targets:
|
||||||
xmlfiles = self.objectspace.display_xmlfiles(fill.xmlfiles)
|
xmlfiles = self.objectspace.display_xmlfiles(fill.xmlfiles)
|
||||||
raise DictConsistencyError(_(f'A fill already exists for the target of "{fill.target}" created in {xmlfiles}'))
|
raise DictConsistencyError(_(f'A fill already exists for the target of "{fill.target}" created in {xmlfiles}'))
|
||||||
targets.append(fill.target)
|
targets.append(fill.target)
|
||||||
|
|
|
@ -50,21 +50,21 @@
|
||||||
<!ATTLIST service manage (True|False) "True">
|
<!ATTLIST service manage (True|False) "True">
|
||||||
|
|
||||||
<!ELEMENT port (#PCDATA)>
|
<!ELEMENT port (#PCDATA)>
|
||||||
<!ATTLIST port port_type (PortOption|SymLinkOption|variable) "PortOption">
|
<!ATTLIST port port_type (PortOption|variable) "PortOption">
|
||||||
<!ATTLIST port portlist CDATA #IMPLIED >
|
<!ATTLIST port portlist CDATA #IMPLIED >
|
||||||
<!ATTLIST port protocol (tcp|udp) "tcp">
|
<!ATTLIST port protocol (tcp|udp) "tcp">
|
||||||
|
|
||||||
<!ELEMENT ip (#PCDATA)>
|
<!ELEMENT ip (#PCDATA)>
|
||||||
<!ATTLIST ip iplist CDATA #IMPLIED >
|
<!ATTLIST ip iplist CDATA #IMPLIED >
|
||||||
<!ATTLIST ip ip_type (NetworkOption|SymLinkOption|variable) "NetworkOption">
|
<!ATTLIST ip ip_type (NetworkOption|variable) "NetworkOption">
|
||||||
<!ATTLIST ip interface_type (UnicodeOption|SymLinkOption|variable) "UnicodeOption">
|
<!ATTLIST ip interface_type (UnicodeOption|variable) "UnicodeOption">
|
||||||
<!ATTLIST ip interface CDATA #REQUIRED>
|
<!ATTLIST ip interface CDATA #REQUIRED>
|
||||||
<!ATTLIST ip netmask_type (NetmaskOption|SymLinkOption|variable) "NetmaskOption">
|
<!ATTLIST ip netmask_type (NetmaskOption|variable) "NetmaskOption">
|
||||||
<!ATTLIST ip netmask CDATA "255.255.255.255">
|
<!ATTLIST ip netmask CDATA "255.255.255.255">
|
||||||
|
|
||||||
<!ELEMENT file EMPTY>
|
<!ELEMENT file EMPTY>
|
||||||
<!ATTLIST file name CDATA #REQUIRED >
|
<!ATTLIST file name CDATA #REQUIRED >
|
||||||
<!ATTLIST file file_type (UnicodeOption|SymLinkOption|variable) "UnicodeOption">
|
<!ATTLIST file file_type (UnicodeOption|variable) "UnicodeOption">
|
||||||
<!ATTLIST file variable CDATA #IMPLIED>
|
<!ATTLIST file variable CDATA #IMPLIED>
|
||||||
<!ATTLIST file variable_type (variable) "variable">
|
<!ATTLIST file variable_type (variable) "variable">
|
||||||
<!ATTLIST file source CDATA #IMPLIED>
|
<!ATTLIST file source CDATA #IMPLIED>
|
||||||
|
|
|
@ -1,20 +1,25 @@
|
||||||
"""
|
"""
|
||||||
Creole flattener. Takes a bunch of Creole XML dispatched in differents folders
|
Takes a bunch of Creole XML dispatched in differents folders
|
||||||
as an input and outputs a human readable flatened XML
|
as an input and outputs a Tiramisu's file
|
||||||
|
|
||||||
Sample usage::
|
Sample usage::
|
||||||
|
|
||||||
|
eolobj.space_visitor(func)
|
||||||
|
xml = eolobj.save()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
>>> from rougail.objspace import CreoleObjSpace
|
>>> from rougail.objspace import CreoleObjSpace
|
||||||
>>> eolobj = CreoleObjSpace('/usr/share/rougail/rougail.dtd')
|
>>> eolobj = CreoleObjSpace('/usr/share/rougail/rougail.dtd')
|
||||||
>>> eolobj.create_or_populate_from_xml('rougail', ['/usr/share/eole/rougail/dicos'])
|
>>> eolobj.create_or_populate_from_xml('rougail', ['/usr/share/rougail/dicos'])
|
||||||
>>> eolobj.space_visitor()
|
>>> eolobj.space_visitor('/usr/share/rougail/funcs.py')
|
||||||
>>> eolobj.save('/tmp/rougail_flatened_output.xml')
|
>>> tiramisu = eolobj.save()
|
||||||
|
|
||||||
The CreoleObjSpace
|
The CreoleObjSpace
|
||||||
|
|
||||||
- loads the XML into an internal CreoleObjSpace representation
|
- loads the XML into an internal CreoleObjSpace representation
|
||||||
- visits/annotates the objects
|
- visits/annotates the objects
|
||||||
- dumps the object space as XML output into a single XML target
|
- dumps the object space as Tiramisu string
|
||||||
|
|
||||||
The visit/annotation stage is a complex step that corresponds to the Creole
|
The visit/annotation stage is a complex step that corresponds to the Creole
|
||||||
procedures.
|
procedures.
|
||||||
|
@ -23,11 +28,9 @@ For example: a variable is redefined and shall be moved to another family
|
||||||
means that a variable1 = Variable() object in the object space who lives in the family1 parent
|
means that a variable1 = Variable() object in the object space who lives in the family1 parent
|
||||||
has to be moved in family2. The visit procedure changes the varable1's object space's parent.
|
has to be moved in family2. The visit procedure changes the varable1's object space's parent.
|
||||||
"""
|
"""
|
||||||
from lxml.etree import Element, SubElement # pylint: disable=E0611
|
|
||||||
|
|
||||||
from .i18n import _
|
from .i18n import _
|
||||||
from .xmlreflector import XMLReflector
|
from .xmlreflector import XMLReflector
|
||||||
from .annotator import ERASED_ATTRIBUTES, SpaceAnnotator
|
from .annotator import SpaceAnnotator
|
||||||
from .tiramisureflector import TiramisuReflector
|
from .tiramisureflector import TiramisuReflector
|
||||||
from .utils import normalize_family
|
from .utils import normalize_family
|
||||||
from .error import OperationError, SpaceObjShallNotBeUpdated, DictConsistencyError
|
from .error import OperationError, SpaceObjShallNotBeUpdated, DictConsistencyError
|
||||||
|
@ -41,20 +44,8 @@ FORCE_UNREDEFINABLES = ('value',)
|
||||||
# CreoleObjSpace's elements that shall be set to the UnRedefinable type
|
# CreoleObjSpace's elements that shall be set to the UnRedefinable type
|
||||||
UNREDEFINABLE = ('multi', 'type')
|
UNREDEFINABLE = ('multi', 'type')
|
||||||
|
|
||||||
CONVERT_PROPERTIES = {'auto_save': ['force_store_value'], 'auto_freeze': ['force_store_value', 'auto_freeze']}
|
|
||||||
|
|
||||||
RENAME_ATTIBUTES = {'description': 'doc'}
|
|
||||||
|
|
||||||
FORCED_TEXT_ELTS_AS_NAME = ('choice', 'property', 'value', 'target')
|
FORCED_TEXT_ELTS_AS_NAME = ('choice', 'property', 'value', 'target')
|
||||||
|
|
||||||
CONVERT_EXPORT = {'Leadership': 'leader',
|
|
||||||
'Variable': 'variable',
|
|
||||||
'Value': 'value',
|
|
||||||
'Property': 'property',
|
|
||||||
'Choice': 'choice',
|
|
||||||
'Param': 'param',
|
|
||||||
'Check': 'check',
|
|
||||||
}
|
|
||||||
|
|
||||||
# _____________________________________________________________________________
|
# _____________________________________________________________________________
|
||||||
# special types definitions for the Object Space's internal representation
|
# special types definitions for the Object Space's internal representation
|
||||||
|
@ -65,6 +56,18 @@ class RootCreoleObject:
|
||||||
self.xmlfiles = xmlfiles
|
self.xmlfiles = xmlfiles
|
||||||
|
|
||||||
|
|
||||||
|
class Atom(RootCreoleObject):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Redefinable(RootCreoleObject):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class UnRedefinable(RootCreoleObject):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class CreoleObjSpace:
|
class CreoleObjSpace:
|
||||||
"""DOM XML reflexion free internal representation of a Creole Dictionary
|
"""DOM XML reflexion free internal representation of a Creole Dictionary
|
||||||
"""
|
"""
|
||||||
|
@ -77,11 +80,6 @@ class CreoleObjSpace:
|
||||||
an Object Space's atom object is present only once in the
|
an Object Space's atom object is present only once in the
|
||||||
object space's tree
|
object space's tree
|
||||||
"""
|
"""
|
||||||
Atom = type('Atom', (RootCreoleObject,), dict())
|
|
||||||
"A variable that can't be redefined"
|
|
||||||
Redefinable = type('Redefinable', (RootCreoleObject,), dict())
|
|
||||||
"A variable can be redefined"
|
|
||||||
UnRedefinable = type('UnRedefinable', (RootCreoleObject,), dict())
|
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, dtdfilename): # pylint: disable=R0912
|
def __init__(self, dtdfilename): # pylint: disable=R0912
|
||||||
|
@ -95,7 +93,6 @@ class CreoleObjSpace:
|
||||||
self.xmlreflector = XMLReflector()
|
self.xmlreflector = XMLReflector()
|
||||||
self.xmlreflector.parse_dtd(dtdfilename)
|
self.xmlreflector.parse_dtd(dtdfilename)
|
||||||
self.redefine_variables = None
|
self.redefine_variables = None
|
||||||
self.fill_removed = None
|
|
||||||
self.check_removed = None
|
self.check_removed = None
|
||||||
self.condition_removed = None
|
self.condition_removed = None
|
||||||
|
|
||||||
|
@ -116,25 +113,25 @@ class CreoleObjSpace:
|
||||||
for dtd_elt in self.xmlreflector.dtd.iterelements():
|
for dtd_elt in self.xmlreflector.dtd.iterelements():
|
||||||
attrs = {}
|
attrs = {}
|
||||||
if dtd_elt.name in FORCE_REDEFINABLES:
|
if dtd_elt.name in FORCE_REDEFINABLES:
|
||||||
clstype = self.Redefinable
|
clstype = Redefinable
|
||||||
|
elif not dtd_elt.attributes() and dtd_elt.name not in FORCE_UNREDEFINABLES:
|
||||||
|
clstype = Atom
|
||||||
else:
|
else:
|
||||||
clstype = self.UnRedefinable
|
clstype = UnRedefinable
|
||||||
atomic = dtd_elt.name not in FORCE_UNREDEFINABLES and dtd_elt.name not in FORCE_REDEFINABLES
|
|
||||||
forced_text_elt = dtd_elt.type == 'mixed'
|
forced_text_elt = dtd_elt.type == 'mixed'
|
||||||
for dtd_attr in dtd_elt.iterattributes():
|
for dtd_attr in dtd_elt.iterattributes():
|
||||||
atomic = False
|
if set(dtd_attr.itervalues()) == {'True', 'False'}:
|
||||||
if set(dtd_attr.itervalues()) == set(['True', 'False']):
|
|
||||||
# it's a boolean
|
# it's a boolean
|
||||||
self.booleans_attributs.append(dtd_attr.name)
|
self.booleans_attributs.append(dtd_attr.name)
|
||||||
if dtd_attr.default_value:
|
if dtd_attr.default_value:
|
||||||
# set default value for this attribute
|
# set default value for this attribute
|
||||||
default_value = dtd_attr.default_value
|
default_value = dtd_attr.default_value
|
||||||
if dtd_attr.name in self.booleans_attributs:
|
if dtd_attr.name in self.booleans_attributs:
|
||||||
default_value = self.convert_boolean(dtd_attr.default_value)
|
default_value = self.convert_boolean(default_value)
|
||||||
attrs[dtd_attr.name] = default_value
|
attrs[dtd_attr.name] = default_value
|
||||||
if dtd_attr.name == 'redefine':
|
if dtd_attr.name == 'redefine':
|
||||||
# has a redefine attribute, so it's a Redefinable object
|
# has a redefine attribute, so it's a Redefinable object
|
||||||
clstype = self.Redefinable
|
clstype = Redefinable
|
||||||
if dtd_attr.name == 'name' and forced_text_elt:
|
if dtd_attr.name == 'name' and forced_text_elt:
|
||||||
# child.text should be transform has a "name" attribute
|
# child.text should be transform has a "name" attribute
|
||||||
self.forced_text_elts.add(dtd_elt.name)
|
self.forced_text_elts.add(dtd_elt.name)
|
||||||
|
@ -142,22 +139,19 @@ class CreoleObjSpace:
|
||||||
|
|
||||||
if forced_text_elt is True:
|
if forced_text_elt is True:
|
||||||
self.forced_text_elts_as_name.add(dtd_elt.name)
|
self.forced_text_elts_as_name.add(dtd_elt.name)
|
||||||
if atomic:
|
|
||||||
# has any attribute so it's an Atomic object
|
|
||||||
clstype = self.Atom
|
|
||||||
|
|
||||||
# create ObjectSpace object
|
# create ObjectSpace object
|
||||||
setattr(self, dtd_elt.name, type(dtd_elt.name.capitalize(), (clstype,), attrs))
|
setattr(self, dtd_elt.name, type(dtd_elt.name.capitalize(), (clstype,), attrs))
|
||||||
|
|
||||||
def create_or_populate_from_xml(self,
|
def create_or_populate_from_xml(self,
|
||||||
namespace,
|
namespace,
|
||||||
xmlfolders):
|
xmlfolders,
|
||||||
|
):
|
||||||
"""Parses a bunch of XML files
|
"""Parses a bunch of XML files
|
||||||
populates the CreoleObjSpace
|
populates the CreoleObjSpace
|
||||||
"""
|
"""
|
||||||
for xmlfile, document in self.xmlreflector.load_xml_from_folders(xmlfolders):
|
for xmlfile, document in self.xmlreflector.load_xml_from_folders(xmlfolders):
|
||||||
self.redefine_variables = []
|
self.redefine_variables = []
|
||||||
self.fill_removed = []
|
|
||||||
self.check_removed = []
|
self.check_removed = []
|
||||||
self.condition_removed = []
|
self.condition_removed = []
|
||||||
self.xml_parse_document(xmlfile,
|
self.xml_parse_document(xmlfile,
|
||||||
|
@ -175,43 +169,43 @@ class CreoleObjSpace:
|
||||||
"""Parses a Creole XML file
|
"""Parses a Creole XML file
|
||||||
populates the CreoleObjSpace
|
populates the CreoleObjSpace
|
||||||
"""
|
"""
|
||||||
|
# var to check unique family name in a XML file
|
||||||
family_names = []
|
family_names = []
|
||||||
for child in document:
|
for child in document:
|
||||||
# this index enables us to reorder objects
|
# this index enables us to reorder objects
|
||||||
self.index += 1
|
|
||||||
# doesn't proceed the XML commentaries
|
|
||||||
if not isinstance(child.tag, str):
|
if not isinstance(child.tag, str):
|
||||||
|
# doesn't proceed the XML commentaries
|
||||||
continue
|
continue
|
||||||
if child.tag == 'family':
|
if child.tag == 'family':
|
||||||
if child.attrib['name'] in family_names:
|
if child.attrib['name'] in family_names:
|
||||||
raise DictConsistencyError(_(f'Family "{child.attrib["name"]}" is set several times in "{xmlfile}"'))
|
raise DictConsistencyError(_(f'Family "{child.attrib["name"]}" is set several times in "{xmlfile}"'))
|
||||||
family_names.append(child.attrib['name'])
|
family_names.append(child.attrib['name'])
|
||||||
if child.tag == 'variables':
|
if child.tag == 'variables':
|
||||||
|
# variables has no name, so force namespace name
|
||||||
child.attrib['name'] = namespace
|
child.attrib['name'] = namespace
|
||||||
if child.tag == 'value' and child.text == None:
|
if child.tag == 'value' and child.text is None:
|
||||||
# FIXME should not be here
|
|
||||||
continue
|
continue
|
||||||
# variable objects creation
|
# variable objects creation
|
||||||
try:
|
try:
|
||||||
variableobj = self.generate_variableobj(xmlfile,
|
variableobj = self.get_variableobj(xmlfile,
|
||||||
child,
|
child,
|
||||||
space,
|
space,
|
||||||
namespace,
|
namespace,
|
||||||
)
|
)
|
||||||
except SpaceObjShallNotBeUpdated:
|
except SpaceObjShallNotBeUpdated:
|
||||||
continue
|
continue
|
||||||
self.set_text_to_obj(child,
|
self.index += 1
|
||||||
|
self.set_text(child,
|
||||||
variableobj,
|
variableobj,
|
||||||
)
|
)
|
||||||
self.set_xml_attributes_to_obj(xmlfile,
|
self.set_attributes(xmlfile,
|
||||||
child,
|
child,
|
||||||
variableobj,
|
variableobj,
|
||||||
)
|
)
|
||||||
self.variableobj_tree_visitor(child,
|
self.remove(child,
|
||||||
variableobj,
|
variableobj,
|
||||||
namespace,
|
|
||||||
)
|
)
|
||||||
self.fill_variableobj_path_attribute(space,
|
self.set_path(space,
|
||||||
child,
|
child,
|
||||||
namespace,
|
namespace,
|
||||||
document,
|
document,
|
||||||
|
@ -220,6 +214,7 @@ class CreoleObjSpace:
|
||||||
self.add_to_tree_structure(variableobj,
|
self.add_to_tree_structure(variableobj,
|
||||||
space,
|
space,
|
||||||
child,
|
child,
|
||||||
|
namespace,
|
||||||
)
|
)
|
||||||
if list(child) != []:
|
if list(child) != []:
|
||||||
self.xml_parse_document(xmlfile,
|
self.xml_parse_document(xmlfile,
|
||||||
|
@ -228,34 +223,32 @@ class CreoleObjSpace:
|
||||||
namespace,
|
namespace,
|
||||||
)
|
)
|
||||||
|
|
||||||
def generate_variableobj(self,
|
def get_variableobj(self,
|
||||||
xmlfile,
|
xmlfile: str,
|
||||||
child,
|
child: list,
|
||||||
space,
|
space,
|
||||||
namespace,
|
namespace,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
instanciates or creates Creole Object Subspace objects
|
instanciates or creates Creole Object Subspace objects
|
||||||
"""
|
"""
|
||||||
variableobj = getattr(self, child.tag)(xmlfile)
|
obj = getattr(self, child.tag)
|
||||||
if isinstance(variableobj, self.Redefinable):
|
if Redefinable in obj.__mro__:
|
||||||
variableobj = self.create_or_update_redefinable_object(xmlfile,
|
return self.create_or_update_redefinable_object(xmlfile,
|
||||||
child.attrib,
|
child.attrib,
|
||||||
space,
|
space,
|
||||||
child,
|
child,
|
||||||
namespace,
|
namespace,
|
||||||
)
|
)
|
||||||
elif isinstance(variableobj, self.Atom) and child.tag in vars(space):
|
elif Atom in obj.__mro__:
|
||||||
# instanciates an object from the CreoleObjSpace's builtins types
|
if child.tag in vars(space):
|
||||||
# example : child.tag = constraints -> a self.Constraints() object is created
|
# Atom instance has to be a singleton here
|
||||||
# this Atom instance has to be a singleton here
|
|
||||||
# we do not re-create it, we reuse it
|
# we do not re-create it, we reuse it
|
||||||
variableobj = getattr(space, child.tag)
|
return getattr(space, child.tag)
|
||||||
self.create_tree_structure(space,
|
return obj(xmlfile)
|
||||||
child,
|
if child.tag not in vars(space):
|
||||||
variableobj,
|
setattr(space, child.tag, [])
|
||||||
)
|
return obj(xmlfile)
|
||||||
return variableobj
|
|
||||||
|
|
||||||
def create_or_update_redefinable_object(self,
|
def create_or_update_redefinable_object(self,
|
||||||
xmlfile,
|
xmlfile,
|
||||||
|
@ -264,59 +257,38 @@ class CreoleObjSpace:
|
||||||
child,
|
child,
|
||||||
namespace,
|
namespace,
|
||||||
):
|
):
|
||||||
"""Creates or retrieves the space object that corresponds
|
|
||||||
to the `child` XML object
|
|
||||||
|
|
||||||
Two attributes of the `child` XML object are important:
|
|
||||||
|
|
||||||
- with the `redefine` boolean flag attribute we know whether
|
|
||||||
the corresponding space object shall be created or updated
|
|
||||||
|
|
||||||
- `True` means that the corresponding space object shall be updated
|
|
||||||
- `False` means that the corresponding space object shall be created
|
|
||||||
|
|
||||||
- with the `exists` boolean flag attribute we know whether
|
|
||||||
the corresponding space object shall be created
|
|
||||||
(or nothing -- that is the space object isn't modified)
|
|
||||||
|
|
||||||
- `True` means that the corresponding space object shall be created
|
|
||||||
- `False` means that the corresponding space object is not updated
|
|
||||||
|
|
||||||
In the special case `redefine` is True and `exists` is False,
|
|
||||||
we create the corresponding space object if it doesn't exist
|
|
||||||
and we update it if it exists.
|
|
||||||
|
|
||||||
:return: the corresponding space object of the `child` XML object
|
|
||||||
"""
|
|
||||||
if child.tag in self.forced_text_elts_as_name:
|
if child.tag in self.forced_text_elts_as_name:
|
||||||
name = child.text
|
name = child.text
|
||||||
else:
|
else:
|
||||||
name = subspace['name']
|
name = subspace['name']
|
||||||
if child.tag == 'family':
|
if child.tag == 'family':
|
||||||
name = normalize_family(name)
|
name = normalize_family(name)
|
||||||
existed_var = self.is_already_exists(name,
|
existed_var = self.get_existed_obj(name,
|
||||||
space,
|
space,
|
||||||
child,
|
child,
|
||||||
namespace,
|
namespace,
|
||||||
)
|
)
|
||||||
if existed_var:
|
if existed_var:
|
||||||
|
# if redefine is set to object, default value is False
|
||||||
|
# otherwise it's always a redefinable object
|
||||||
default_redefine = child.tag in FORCE_REDEFINABLES
|
default_redefine = child.tag in FORCE_REDEFINABLES
|
||||||
redefine = self.convert_boolean(subspace.get('redefine', default_redefine))
|
redefine = self.convert_boolean(subspace.get('redefine', default_redefine))
|
||||||
exists = self.convert_boolean(subspace.get('exists', True))
|
|
||||||
if redefine is True:
|
if redefine is True:
|
||||||
existed_var.xmlfiles.append(xmlfile)
|
existed_var.xmlfiles.append(xmlfile)
|
||||||
return self.translate_in_space(name,
|
return existed_var
|
||||||
space,
|
exists = self.convert_boolean(subspace.get('exists', True))
|
||||||
child,
|
if exists is False:
|
||||||
namespace,
|
|
||||||
)
|
|
||||||
elif exists is False:
|
|
||||||
raise SpaceObjShallNotBeUpdated()
|
raise SpaceObjShallNotBeUpdated()
|
||||||
xmlfiles = self.display_xmlfiles(existed_var.xmlfiles)
|
xmlfiles = self.display_xmlfiles(existed_var.xmlfiles)
|
||||||
raise DictConsistencyError(_(f'"{child.tag}" named "{name}" cannot be re-created in "{xmlfile}", already defined in {xmlfiles}'))
|
raise DictConsistencyError(_(f'"{child.tag}" named "{name}" cannot be re-created in "{xmlfile}", already defined in {xmlfiles}'))
|
||||||
redefine = self.convert_boolean(subspace.get('redefine', False))
|
# if this object must only be modified if object already exists
|
||||||
exists = self.convert_boolean(subspace.get('exists', False))
|
exists = self.convert_boolean(subspace.get('exists', False))
|
||||||
if redefine is False or exists is True:
|
if exists is True:
|
||||||
|
raise SpaceObjShallNotBeUpdated()
|
||||||
|
redefine = self.convert_boolean(subspace.get('redefine', False))
|
||||||
|
if redefine is False:
|
||||||
|
if child.tag not in vars(space):
|
||||||
|
setattr(space, child.tag, {})
|
||||||
return getattr(self, child.tag)(xmlfile)
|
return getattr(self, child.tag)(xmlfile)
|
||||||
raise DictConsistencyError(_(f'Redefined object in "{xmlfile}": "{name}" does not exist yet'))
|
raise DictConsistencyError(_(f'Redefined object in "{xmlfile}": "{name}" does not exist yet'))
|
||||||
|
|
||||||
|
@ -327,32 +299,7 @@ class CreoleObjSpace:
|
||||||
return '"' + xmlfiles[0] + '"'
|
return '"' + xmlfiles[0] + '"'
|
||||||
return '"' + '", "'.join(xmlfiles[:-1]) + '"' + ' and ' + '"' + xmlfiles[-1] + '"'
|
return '"' + '", "'.join(xmlfiles[:-1]) + '"' + ' and ' + '"' + xmlfiles[-1] + '"'
|
||||||
|
|
||||||
def create_tree_structure(self,
|
def get_existed_obj(self,
|
||||||
space,
|
|
||||||
child,
|
|
||||||
variableobj,
|
|
||||||
): # pylint: disable=R0201
|
|
||||||
"""
|
|
||||||
Builds the tree structure of the object space here
|
|
||||||
we set services attributes in order to be populated later on
|
|
||||||
for example::
|
|
||||||
|
|
||||||
space = Family()
|
|
||||||
space.variable = dict()
|
|
||||||
another example:
|
|
||||||
space = Variable()
|
|
||||||
space.value = list()
|
|
||||||
"""
|
|
||||||
if child.tag not in vars(space):
|
|
||||||
if isinstance(variableobj, self.Redefinable):
|
|
||||||
setattr(space, child.tag, dict())
|
|
||||||
elif isinstance(variableobj, self.UnRedefinable):
|
|
||||||
setattr(space, child.tag, [])
|
|
||||||
elif not isinstance(variableobj, self.Atom): # pragma: no cover
|
|
||||||
raise OperationError(_("Creole object {} "
|
|
||||||
"has a wrong type").format(type(variableobj)))
|
|
||||||
|
|
||||||
def is_already_exists(self,
|
|
||||||
name: str,
|
name: str,
|
||||||
space: str,
|
space: str,
|
||||||
child,
|
child,
|
||||||
|
@ -362,6 +309,12 @@ class CreoleObjSpace:
|
||||||
if namespace != Config['variable_namespace']:
|
if namespace != Config['variable_namespace']:
|
||||||
name = space.path + '.' + name
|
name = space.path + '.' + name
|
||||||
if self.paths.path_is_defined(name):
|
if self.paths.path_is_defined(name):
|
||||||
|
old_family_name = self.paths.get_variable_family_name(name)
|
||||||
|
if namespace != Config['variable_namespace']:
|
||||||
|
old_family_name = namespace + '.' + old_family_name
|
||||||
|
if space.path != old_family_name:
|
||||||
|
xmlfiles = self.display_xmlfiles(space.xmlfiles)
|
||||||
|
raise DictConsistencyError(_(f'Variable was previously create in family "{old_family_name}", now it is in "{space.path}" in {xmlfiles}'))
|
||||||
return self.paths.get_variable_obj(name)
|
return self.paths.get_variable_obj(name)
|
||||||
return
|
return
|
||||||
children = getattr(space, child.tag, {})
|
children = getattr(space, child.tag, {})
|
||||||
|
@ -377,49 +330,59 @@ class CreoleObjSpace:
|
||||||
return True
|
return True
|
||||||
elif value == 'False':
|
elif value == 'False':
|
||||||
return False
|
return False
|
||||||
else:
|
|
||||||
raise TypeError(_('{} is not True or False').format(value)) # pragma: no cover
|
raise TypeError(_('{} is not True or False').format(value)) # pragma: no cover
|
||||||
|
|
||||||
def translate_in_space(self,
|
def set_text(self,
|
||||||
name,
|
child,
|
||||||
family,
|
variableobj,
|
||||||
variable,
|
|
||||||
namespace,
|
|
||||||
):
|
):
|
||||||
if not isinstance(family, self.family): # pylint: disable=E1101
|
if child.text is None:
|
||||||
return getattr(family, variable.tag)[name]
|
return
|
||||||
if namespace == Config['variable_namespace']:
|
text = child.text.strip()
|
||||||
path = name
|
if not text:
|
||||||
|
return
|
||||||
|
if child.tag in self.forced_text_elts_as_name:
|
||||||
|
variableobj.name = text
|
||||||
else:
|
else:
|
||||||
path = family.path + '.' + name
|
variableobj.text = text
|
||||||
old_family_name = self.paths.get_variable_family_name(path)
|
|
||||||
if family.path == old_family_name:
|
|
||||||
return getattr(family, variable.tag)[name]
|
|
||||||
old_family = self.space.variables[namespace].family[old_family_name] # pylint: disable=E1101
|
|
||||||
variable_obj = old_family.variable[name]
|
|
||||||
del old_family.variable[name]
|
|
||||||
if 'variable' not in vars(family):
|
|
||||||
family.variable = dict()
|
|
||||||
family.variable[name] = variable_obj
|
|
||||||
self.paths.add_variable(namespace,
|
|
||||||
name,
|
|
||||||
family.name,
|
|
||||||
False,
|
|
||||||
variable_obj,
|
|
||||||
)
|
|
||||||
return variable_obj
|
|
||||||
|
|
||||||
def remove_fill(self, name): # pylint: disable=C0111
|
def set_attributes(self,
|
||||||
if hasattr(self.space, 'constraints') and hasattr(self.space.constraints, 'fill'):
|
xmlfile,
|
||||||
remove_fills= []
|
child,
|
||||||
for idx, fill in enumerate(self.space.constraints.fill): # pylint: disable=E1101
|
variableobj,
|
||||||
if hasattr(fill, 'target') and fill.target == name:
|
):
|
||||||
remove_fills.append(idx)
|
redefine = self.convert_boolean(child.attrib.get('redefine', False))
|
||||||
|
if redefine and child.tag == 'variable':
|
||||||
|
# delete old values
|
||||||
|
has_value = hasattr(variableobj, 'value')
|
||||||
|
if has_value and len(child) != 0:
|
||||||
|
del variableobj.value
|
||||||
|
for attr, val in child.attrib.items():
|
||||||
|
if redefine and attr in UNREDEFINABLE:
|
||||||
|
xmlfiles = self.display_xmlfiles(variableobj.xmlfiles[:-1])
|
||||||
|
raise DictConsistencyError(_(f'cannot redefine attribute "{attr}" for variable "{child.attrib["name"]}" in "{xmlfile}", already defined in {xmlfiles}'))
|
||||||
|
if attr in self.booleans_attributs:
|
||||||
|
val = self.convert_boolean(val)
|
||||||
|
if attr == 'name' and getattr(variableobj, 'name', None):
|
||||||
|
# do not redefine name
|
||||||
|
continue
|
||||||
|
setattr(variableobj, attr, val)
|
||||||
|
|
||||||
remove_fills = list(set(remove_fills))
|
def remove(self,
|
||||||
remove_fills.sort(reverse=True)
|
child,
|
||||||
for idx in remove_fills:
|
variableobj,
|
||||||
self.space.constraints.fill.pop(idx) # pylint: disable=E1101
|
):
|
||||||
|
"""Creole object tree manipulations
|
||||||
|
"""
|
||||||
|
if child.tag == 'variable':
|
||||||
|
if child.attrib.get('remove_check', False):
|
||||||
|
self.remove_check(variableobj.name)
|
||||||
|
if child.attrib.get('remove_condition', False):
|
||||||
|
self.remove_condition(variableobj.name)
|
||||||
|
if child.attrib.get('remove_fill', False):
|
||||||
|
self.remove_fill(variableobj.name)
|
||||||
|
if child.tag == 'fill' and child.attrib['target'] in self.redefine_variables:
|
||||||
|
self.remove_fill(child.attrib['target'])
|
||||||
|
|
||||||
def remove_check(self, name): # pylint: disable=C0111
|
def remove_check(self, name): # pylint: disable=C0111
|
||||||
if hasattr(self.space, 'constraints') and hasattr(self.space.constraints, 'check'):
|
if hasattr(self.space, 'constraints') and hasattr(self.space.constraints, 'check'):
|
||||||
|
@ -441,83 +404,19 @@ class CreoleObjSpace:
|
||||||
for idx in remove_conditions:
|
for idx in remove_conditions:
|
||||||
del self.space.constraints.condition[idx]
|
del self.space.constraints.condition[idx]
|
||||||
|
|
||||||
def add_to_tree_structure(self,
|
def remove_fill(self, name): # pylint: disable=C0111
|
||||||
variableobj,
|
if hasattr(self.space, 'constraints') and hasattr(self.space.constraints, 'fill'):
|
||||||
space,
|
remove_fills= []
|
||||||
child,
|
for idx, fill in enumerate(self.space.constraints.fill): # pylint: disable=E1101
|
||||||
): # pylint: disable=R0201
|
if hasattr(fill, 'target') and fill.target == name:
|
||||||
if isinstance(variableobj, self.Redefinable):
|
remove_fills.append(idx)
|
||||||
name = variableobj.name
|
|
||||||
if child.tag == 'family':
|
|
||||||
name = normalize_family(name)
|
|
||||||
getattr(space, child.tag)[name] = variableobj
|
|
||||||
elif isinstance(variableobj, self.UnRedefinable):
|
|
||||||
getattr(space, child.tag).append(variableobj)
|
|
||||||
else:
|
|
||||||
setattr(space, child.tag, variableobj)
|
|
||||||
|
|
||||||
def set_text_to_obj(self,
|
remove_fills = list(set(remove_fills))
|
||||||
child,
|
remove_fills.sort(reverse=True)
|
||||||
variableobj,
|
for idx in remove_fills:
|
||||||
):
|
self.space.constraints.fill.pop(idx) # pylint: disable=E1101
|
||||||
if child.text is None:
|
|
||||||
text = None
|
|
||||||
else:
|
|
||||||
text = child.text.strip()
|
|
||||||
if text:
|
|
||||||
if child.tag in self.forced_text_elts_as_name:
|
|
||||||
variableobj.name = text
|
|
||||||
else:
|
|
||||||
variableobj.text = text
|
|
||||||
|
|
||||||
def set_xml_attributes_to_obj(self,
|
def set_path(self,
|
||||||
xmlfile,
|
|
||||||
child,
|
|
||||||
variableobj,
|
|
||||||
):
|
|
||||||
redefine = self.convert_boolean(child.attrib.get('redefine', False))
|
|
||||||
has_value = hasattr(variableobj, 'value')
|
|
||||||
if redefine is True and child.tag == 'variable' and has_value and len(child) != 0:
|
|
||||||
del variableobj.value
|
|
||||||
for attr, val in child.attrib.items():
|
|
||||||
if redefine and attr in UNREDEFINABLE:
|
|
||||||
# UNREDEFINABLE concerns only 'variable' node so we can fix name
|
|
||||||
# to child.attrib['name']
|
|
||||||
name = child.attrib['name']
|
|
||||||
xmlfiles = self.display_xmlfiles(variableobj.xmlfiles[:-1])
|
|
||||||
raise DictConsistencyError(_(f'cannot redefine attribute "{attr}" for variable "{name}" in "{xmlfile}", already defined in {xmlfiles}'))
|
|
||||||
if attr in self.booleans_attributs:
|
|
||||||
val = self.convert_boolean(val)
|
|
||||||
if not (attr == 'name' and getattr(variableobj, 'name', None) != None):
|
|
||||||
setattr(variableobj, attr, val)
|
|
||||||
keys = list(vars(variableobj).keys())
|
|
||||||
|
|
||||||
def variableobj_tree_visitor(self,
|
|
||||||
child,
|
|
||||||
variableobj,
|
|
||||||
namespace,
|
|
||||||
):
|
|
||||||
"""Creole object tree manipulations
|
|
||||||
"""
|
|
||||||
if child.tag == 'variable':
|
|
||||||
if child.attrib.get('remove_check', False):
|
|
||||||
self.remove_check(variableobj.name)
|
|
||||||
if child.attrib.get('remove_condition', False):
|
|
||||||
self.remove_condition(variableobj.name)
|
|
||||||
if child.attrib.get('remove_fill', False):
|
|
||||||
self.remove_fill(variableobj.name)
|
|
||||||
if child.tag == 'fill':
|
|
||||||
# if variable is a redefine in current dictionary
|
|
||||||
# XXX not working with variable not in variable and in leader/followers
|
|
||||||
variableobj.redefine = child.attrib['target'] in self.redefine_variables
|
|
||||||
if child.attrib['target'] in self.redefine_variables and child.attrib['target'] not in self.fill_removed:
|
|
||||||
self.remove_fill(child.attrib['target'])
|
|
||||||
self.fill_removed.append(child.attrib['target'])
|
|
||||||
if not hasattr(variableobj, 'index'):
|
|
||||||
variableobj.index = self.index
|
|
||||||
variableobj.namespace = namespace
|
|
||||||
|
|
||||||
def fill_variableobj_path_attribute(self,
|
|
||||||
space,
|
space,
|
||||||
child,
|
child,
|
||||||
namespace,
|
namespace,
|
||||||
|
@ -526,8 +425,6 @@ class CreoleObjSpace:
|
||||||
): # pylint: disable=R0913
|
): # pylint: disable=R0913
|
||||||
"""Fill self.paths attributes
|
"""Fill self.paths attributes
|
||||||
"""
|
"""
|
||||||
if isinstance(space, self.help): # pylint: disable=E1101
|
|
||||||
return
|
|
||||||
if child.tag == 'variable':
|
if child.tag == 'variable':
|
||||||
family_name = document.attrib['name']
|
family_name = document.attrib['name']
|
||||||
family_name = normalize_family(family_name)
|
family_name = normalize_family(family_name)
|
||||||
|
@ -554,6 +451,25 @@ class CreoleObjSpace:
|
||||||
)
|
)
|
||||||
variableobj.path = self.paths.get_family_path(family_name, namespace)
|
variableobj.path = self.paths.get_family_path(family_name, namespace)
|
||||||
|
|
||||||
|
def add_to_tree_structure(self,
|
||||||
|
variableobj,
|
||||||
|
space,
|
||||||
|
child,
|
||||||
|
namespace,
|
||||||
|
): # pylint: disable=R0201
|
||||||
|
if not hasattr(variableobj, 'index'):
|
||||||
|
variableobj.index = self.index
|
||||||
|
variableobj.namespace = namespace
|
||||||
|
if isinstance(variableobj, Redefinable):
|
||||||
|
name = variableobj.name
|
||||||
|
if child.tag == 'family':
|
||||||
|
name = normalize_family(name)
|
||||||
|
getattr(space, child.tag)[name] = variableobj
|
||||||
|
elif isinstance(variableobj, UnRedefinable):
|
||||||
|
getattr(space, child.tag).append(variableobj)
|
||||||
|
else:
|
||||||
|
setattr(space, child.tag, variableobj)
|
||||||
|
|
||||||
def space_visitor(self, eosfunc_file): # pylint: disable=C0111
|
def space_visitor(self, eosfunc_file): # pylint: disable=C0111
|
||||||
self.funcs_path = eosfunc_file
|
self.funcs_path = eosfunc_file
|
||||||
SpaceAnnotator(self, eosfunc_file)
|
SpaceAnnotator(self, eosfunc_file)
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
{"rougail.general.mode_conteneur_actif": "non", "rougail.other.mode_conteneur_actif1": "non"}
|
|
|
@ -1,16 +0,0 @@
|
||||||
from importlib.machinery import SourceFileLoader
|
|
||||||
func = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py').load_module()
|
|
||||||
for key, value in dict(locals()).items():
|
|
||||||
if key != ['SourceFileLoader', 'func']:
|
|
||||||
setattr(func, key, value)
|
|
||||||
try:
|
|
||||||
from tiramisu3 import *
|
|
||||||
except:
|
|
||||||
from tiramisu import *
|
|
||||||
from rougail.tiramisu import ConvertDynOptionDescription
|
|
||||||
option_3 = ChoiceOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='mode_conteneur_actif', doc='No change', multi=False, default='non', values=('oui', 'non'))
|
|
||||||
option_2 = OptionDescription(name='general', doc='general', properties=frozenset({'normal'}), children=[option_3])
|
|
||||||
option_5 = ChoiceOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='mode_conteneur_actif1', doc='No change', multi=False, default='non', values=('oui', 'non'))
|
|
||||||
option_4 = OptionDescription(name='other', doc='other', properties=frozenset({'normal'}), children=[option_5])
|
|
||||||
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4])
|
|
||||||
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1])
|
|
|
@ -1 +0,0 @@
|
||||||
{"rougail.general.mode_conteneur_actif": "non", "rougail.otherwithe.mode_conteneur_actif1": "non"}
|
|
|
@ -1,16 +0,0 @@
|
||||||
from importlib.machinery import SourceFileLoader
|
|
||||||
func = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py').load_module()
|
|
||||||
for key, value in dict(locals()).items():
|
|
||||||
if key != ['SourceFileLoader', 'func']:
|
|
||||||
setattr(func, key, value)
|
|
||||||
try:
|
|
||||||
from tiramisu3 import *
|
|
||||||
except:
|
|
||||||
from tiramisu import *
|
|
||||||
from rougail.tiramisu import ConvertDynOptionDescription
|
|
||||||
option_3 = ChoiceOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='mode_conteneur_actif', doc='No change', multi=False, default='non', values=('oui', 'non'))
|
|
||||||
option_2 = OptionDescription(name='general', doc='Général', properties=frozenset({'normal'}), children=[option_3])
|
|
||||||
option_5 = ChoiceOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='mode_conteneur_actif1', doc='No change', multi=False, default='non', values=('oui', 'non'))
|
|
||||||
option_4 = OptionDescription(name='otherwithe', doc='Otherwithé', properties=frozenset({'normal'}), children=[option_5])
|
|
||||||
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2, option_4])
|
|
||||||
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1])
|
|
|
@ -12,9 +12,9 @@ option_3 = ChoiceOption(properties=frozenset({'force_default_on_freeze', 'frozen
|
||||||
option_4 = ChoiceOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='activer_ejabberd', doc='No change', multi=False, default='non', values=('oui', 'non'))
|
option_4 = ChoiceOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='activer_ejabberd', doc='No change', multi=False, default='non', values=('oui', 'non'))
|
||||||
option_2 = OptionDescription(name='general', doc='général', properties=frozenset({'normal'}), children=[option_3, option_4])
|
option_2 = OptionDescription(name='general', doc='général', properties=frozenset({'normal'}), children=[option_3, option_4])
|
||||||
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2])
|
option_1 = OptionDescription(name='rougail', doc='rougail', children=[option_2])
|
||||||
option_7 = ChoiceOption(properties=frozenset({'mandatory', 'normal'}), name='day', doc='day', multi=False, default=Calculation(func.calc_multi_condition, Params((ParamValue("non")), kwargs={'condition_1': ParamOption(option_4, notraisepropertyerror=True, todict=False), 'match': ParamValue("none"), 'mismatch': ParamValue("daily")})), values=('none', 'daily', 'weekly', 'monthly'))
|
option_7 = StrOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='description', doc='description', multi=False, default='Exportation de la base de ejabberd')
|
||||||
option_8 = ChoiceOption(properties=frozenset({'mandatory', 'normal'}), name='mode', doc='mode', multi=False, default='pre', values=('pre', 'post'))
|
option_8 = ChoiceOption(properties=frozenset({'mandatory', 'normal'}), name='day', doc='day', multi=False, default=Calculation(func.calc_multi_condition, Params((ParamValue("non")), kwargs={'condition_1': ParamOption(option_4, notraisepropertyerror=True, todict=False), 'match': ParamValue("none"), 'mismatch': ParamValue("daily")})), values=('none', 'daily', 'weekly', 'monthly'))
|
||||||
option_9 = StrOption(properties=frozenset({'force_default_on_freeze', 'frozen', 'hidden', 'mandatory', 'normal'}), name='description', doc='description', multi=False, default='Exportation de la base de ejabberd')
|
option_9 = ChoiceOption(properties=frozenset({'mandatory', 'normal'}), name='mode', doc='mode', multi=False, default='pre', values=('pre', 'post'))
|
||||||
option_6 = OptionDescription(name='ejabberd', doc='ejabberd', properties=frozenset({'normal'}), children=[option_7, option_8, option_9])
|
option_6 = OptionDescription(name='ejabberd', doc='ejabberd', properties=frozenset({'normal'}), children=[option_7, option_8, option_9])
|
||||||
option_5 = OptionDescription(name='extra', doc='extra', children=[option_6])
|
option_5 = OptionDescription(name='extra', doc='extra', children=[option_6])
|
||||||
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1, option_5])
|
option_0 = OptionDescription(name='baseoption', doc='baseoption', children=[option_1, option_5])
|
||||||
|
|
Loading…
Reference in a new issue