Files
rougail/src/rougail/path.py

219 lines
8.9 KiB
Python
Raw Normal View History

2021-01-17 18:39:15 +01:00
"""Manage path to find objects
2021-01-30 08:15:26 +01:00
Created by:
EOLE (http://eole.orion.education.fr)
Copyright (C) 2005-2018
Forked by:
Cadoles (http://www.cadoles.com)
Copyright (C) 2019-2021
distribued with GPL-2 or later license
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2021-01-17 18:39:15 +01:00
"""
from typing import List
2020-07-06 19:47:45 +02:00
from .i18n import _
2021-01-12 13:36:27 +01:00
from .error import DictConsistencyError
2021-01-17 17:15:58 +01:00
from .utils import normalize_family
2020-07-06 19:47:45 +02:00
class Path:
2021-02-22 19:28:51 +01:00
"""Helper class to handle the `path` attribute.
2020-07-06 19:47:45 +02:00
sample: path="creole.general.condition"
"""
2021-02-16 12:08:45 +01:00
def __init__(self,
rougailconfig: 'RougailConfig',
) -> None:
2020-07-06 19:47:45 +02:00
self.variables = {}
self.families = {}
2020-11-11 16:59:44 +01:00
self.full_paths_families = {}
self.full_paths_variables = {}
2021-02-16 12:08:45 +01:00
self.variable_namespace = rougailconfig['variable_namespace']
2020-07-06 19:47:45 +02:00
# Family
def add_family(self,
namespace: str,
name: str,
2020-07-06 20:58:11 +02:00
variableobj: str,
2021-02-14 10:10:48 +01:00
subpath: str,
2020-07-06 19:47:45 +02:00
) -> str: # pylint: disable=C0111
2021-01-17 18:39:15 +01:00
"""Add a new family
"""
2021-02-16 12:08:45 +01:00
if namespace == self.variable_namespace:
2021-02-14 10:10:48 +01:00
full_name = '.'.join([subpath, name])
2021-02-16 12:08:45 +01:00
if name in self.full_paths_families:
2021-02-18 17:00:12 +01:00
msg = _(f'Duplicate family name "{name}"')
raise DictConsistencyError(msg, 55, variableobj.xmlfiles)
2020-11-11 16:59:44 +01:00
self.full_paths_families[name] = full_name
2020-07-24 14:59:09 +02:00
else:
2021-01-17 18:39:15 +01:00
if '.' not in name: # pragma: no cover
msg = _(f'Variable "{name}" in namespace "{namespace}" must have dot')
raise DictConsistencyError(msg, 39, variableobj.xmlfiles)
2020-07-24 14:59:09 +02:00
full_name = name
2021-01-11 22:34:16 +01:00
if full_name in self.families and \
self.families[full_name]['variableobj'] != variableobj: # pragma: no cover
2021-02-18 17:00:12 +01:00
msg = _(f'Duplicate family name "{name}"')
raise DictConsistencyError(msg, 37, variableobj.xmlfiles)
if full_name in self.variables:
msg = _(f'A variable and a family has the same path "{full_name}"')
raise DictConsistencyError(msg, 56, variableobj.xmlfiles)
2020-07-24 14:59:09 +02:00
self.families[full_name] = dict(name=name,
namespace=namespace,
variableobj=variableobj,
)
2021-01-11 22:34:16 +01:00
variableobj.path = full_name
def get_family(self,
name: str,
2021-01-17 17:15:58 +01:00
current_namespace: str,
2021-01-11 22:34:16 +01:00
) -> 'Family': # pylint: disable=C0111
2021-01-17 18:39:15 +01:00
"""Get a family
"""
2021-01-17 17:15:58 +01:00
name = '.'.join([normalize_family(subname) for subname in name.split('.')])
if name not in self.families and name in self.full_paths_families:
name = self.full_paths_families[name]
if name not in self.families:
raise DictConsistencyError(_(f'unknown option {name}'), 42, [])
2021-01-17 17:15:58 +01:00
dico = self.families[name]
2021-02-16 12:08:45 +01:00
if current_namespace not in [self.variable_namespace, 'services'] and \
2021-01-17 18:39:15 +01:00
current_namespace != dico['namespace']:
msg = _(f'A family located in the "{dico["namespace"]}" namespace '
f'shall not be used in the "{current_namespace}" namespace')
raise DictConsistencyError(msg, 38, [])
2021-01-17 17:15:58 +01:00
return dico['variableobj']
2021-01-16 08:50:11 +01:00
def is_leader(self, path): # pylint: disable=C0111
2021-01-17 18:39:15 +01:00
"""Is the variable is a leader
"""
2021-01-16 08:50:11 +01:00
variable = self._get_variable(path)
if not variable['leader']:
return False
leadership = self.get_family(variable['leader'], variable['variableobj'].namespace)
return next(iter(leadership.variable.values())).path == path
2020-07-06 19:47:45 +02:00
2021-02-17 22:32:28 +01:00
def is_follower(self, path):
"""Is the variable is a follower
"""
variable = self._get_variable(path)
if not variable['leader']:
return False
leadership = self.get_family(variable['leader'], variable['variableobj'].namespace)
return next(iter(leadership.variable.values())).path != path
2021-02-17 22:32:28 +01:00
2020-07-06 19:47:45 +02:00
# Variable
2021-01-19 19:28:29 +01:00
def add_variable(self, # pylint: disable=R0913
2020-07-06 19:47:45 +02:00
namespace: str,
name: str,
family: str,
is_dynamic: bool,
2020-07-06 20:58:11 +02:00
variableobj,
leader: 'self.objectspace.family'=None,
2020-07-06 19:47:45 +02:00
) -> str: # pylint: disable=C0111
2021-01-17 18:39:15 +01:00
"""Add a new variable (with path)
"""
2020-07-24 14:59:09 +02:00
if '.' not in name:
2021-01-16 08:50:11 +01:00
full_path = '.'.join([family, name])
2021-02-16 12:08:45 +01:00
if namespace == self.variable_namespace:
2021-01-10 09:07:22 +01:00
self.full_paths_variables[name] = full_path
2020-07-06 19:47:45 +02:00
else:
2021-01-10 09:07:22 +01:00
full_path = name
variableobj.path = full_path
if full_path in self.families:
msg = _(f'A family and a variable has the same path "{full_path}"')
raise DictConsistencyError(msg, 57, variableobj.xmlfiles)
2021-01-10 09:07:22 +01:00
self.variables[full_path] = dict(name=name,
2020-07-24 14:59:09 +02:00
family=family,
leader=leader,
2020-07-24 14:59:09 +02:00
is_dynamic=is_dynamic,
2020-12-26 15:15:51 +01:00
variableobj=variableobj,
)
2020-07-06 19:47:45 +02:00
2021-01-17 18:04:49 +01:00
def get_variable(self,
name: str,
xmlfiles: List[str]=[],
2021-01-17 18:04:49 +01:00
) -> 'Variable': # pylint: disable=C0111
2021-01-17 18:39:15 +01:00
"""Get variable object from a path
"""
variable, suffix = self._get_variable(name, with_suffix=True, xmlfiles=xmlfiles)
2021-01-12 13:36:27 +01:00
if suffix:
raise DictConsistencyError(_(f"{name} is a dynamic variable"), 36, [])
2021-01-12 13:36:27 +01:00
return variable['variableobj']
2020-07-06 19:47:45 +02:00
2021-01-16 08:50:11 +01:00
def get_variable_family_path(self,
2020-07-06 19:47:45 +02:00
name: str,
xmlfiles: List[str]=False,
2020-07-06 19:47:45 +02:00
) -> str: # pylint: disable=C0111
2021-01-17 18:39:15 +01:00
"""Get the full path of a family
"""
return self._get_variable(name, xmlfiles=xmlfiles)['family']
2020-07-06 19:47:45 +02:00
def get_variable_path(self,
name: str,
current_namespace: str,
xmlfiles: List[str]=[],
2020-07-06 19:47:45 +02:00
) -> str: # pylint: disable=C0111
2021-01-17 18:39:15 +01:00
"""get full path of a variable
"""
2021-01-12 13:36:27 +01:00
dico, suffix = self._get_variable(name,
with_suffix=True,
xmlfiles=xmlfiles,
2021-01-12 13:36:27 +01:00
)
namespace = dico['variableobj'].namespace
2021-02-16 12:08:45 +01:00
if namespace not in [self.variable_namespace, 'services'] and \
2021-01-17 18:39:15 +01:00
current_namespace != namespace:
msg = _(f'A variable located in the "{namespace}" namespace shall not be used '
f'in the "{current_namespace}" namespace')
raise DictConsistencyError(msg, 41, xmlfiles)
2021-01-12 13:36:27 +01:00
return dico['variableobj'].path, suffix
2020-07-06 19:47:45 +02:00
def path_is_defined(self,
2021-01-17 18:39:15 +01:00
path: str,
2020-07-06 19:47:45 +02:00
) -> str: # pylint: disable=C0111
2021-01-17 18:39:15 +01:00
"""The path is a valid path
"""
if '.' not in path and path not in self.variables and path in self.full_paths_variables:
2020-07-24 14:59:09 +02:00
return True
2021-01-17 18:39:15 +01:00
return path in self.variables
2020-07-06 19:47:45 +02:00
2020-12-24 18:26:15 +01:00
def variable_is_dynamic(self,
name: str,
) -> bool:
2021-01-17 18:39:15 +01:00
"""This variable is in dynamic family
"""
2020-12-24 18:26:15 +01:00
return self._get_variable(name)['is_dynamic']
2020-07-06 19:47:45 +02:00
def _get_variable(self,
name: str,
with_suffix: bool=False,
xmlfiles: List[str]=[],
2020-07-06 19:47:45 +02:00
) -> str:
2021-01-17 17:15:58 +01:00
name = '.'.join([normalize_family(subname) for subname in name.split('.')])
2020-07-06 19:47:45 +02:00
if name not in self.variables:
2020-12-26 15:15:51 +01:00
if '.' not in name and name in self.full_paths_variables:
name = self.full_paths_variables[name]
elif with_suffix:
for var_name, full_path in self.full_paths_variables.items():
if name.startswith(var_name):
variable = self._get_variable(full_path)
if variable['is_dynamic']:
return variable, name[len(var_name):]
if name not in self.variables:
raise DictConsistencyError(_(f'unknown option "{name}"'), 42, xmlfiles)
2020-07-06 19:47:45 +02:00
if with_suffix:
return self.variables[name], None
return self.variables[name]