Compare commits
No commits in common. "7d830d5e40e3607fe025750310d2ad7a01815019" and "7a5a1b42e80cfe0b63f2d107e727ce420fcecff9" have entirely different histories.
7d830d5e40
...
7a5a1b42e8
3 changed files with 1 additions and 247 deletions
|
|
@ -1,9 +1,3 @@
|
||||||
## 1.2.0a6 (2025-01-02)
|
|
||||||
|
|
||||||
### Fix
|
|
||||||
|
|
||||||
- add path.py
|
|
||||||
|
|
||||||
## 1.2.0a5 (2025-01-02)
|
## 1.2.0a5 (2025-01-02)
|
||||||
|
|
||||||
### Feat
|
### Feat
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ requires = ["flit_core >=3.8.0,<4"]
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "rougail"
|
name = "rougail"
|
||||||
version = "1.2.0a6"
|
version = "1.2.0a5"
|
||||||
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
|
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
description = "A consistency handling system that was initially designed in the configuration management"
|
description = "A consistency handling system that was initially designed in the configuration management"
|
||||||
|
|
|
||||||
|
|
@ -1,240 +0,0 @@
|
||||||
"""
|
|
||||||
Copyright (C) 2024
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU Lesser General Public License as published by the
|
|
||||||
Free Software Foundation, either version 3 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 Lesser General Public License for more
|
|
||||||
details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import (
|
|
||||||
Any,
|
|
||||||
Dict,
|
|
||||||
List,
|
|
||||||
Union,
|
|
||||||
)
|
|
||||||
import logging
|
|
||||||
from re import compile, findall
|
|
||||||
|
|
||||||
from .i18n import _
|
|
||||||
from .object_model import Family, Variable
|
|
||||||
from .utils import normalize_family
|
|
||||||
|
|
||||||
|
|
||||||
class Paths:
|
|
||||||
regexp_relative = compile(r"^_*\.(.*)$")
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
default_namespace: str,
|
|
||||||
) -> None:
|
|
||||||
self._data: Dict[str, Union[Variable, Family]] = {}
|
|
||||||
self._dynamics: Dict[str:str] = {}
|
|
||||||
if default_namespace is not None:
|
|
||||||
default_namespace = normalize_family(default_namespace)
|
|
||||||
self.default_namespace = default_namespace
|
|
||||||
|
|
||||||
def has_value(self) -> bool:
|
|
||||||
return self._data != {}
|
|
||||||
|
|
||||||
def add(
|
|
||||||
self,
|
|
||||||
path: str,
|
|
||||||
data: Any,
|
|
||||||
is_dynamic: bool,
|
|
||||||
dynamic: str,
|
|
||||||
*,
|
|
||||||
force: bool = False,
|
|
||||||
) -> None:
|
|
||||||
self._data[path] = data
|
|
||||||
if not force and is_dynamic:
|
|
||||||
self._dynamics[path] = dynamic
|
|
||||||
|
|
||||||
def get_full_path(
|
|
||||||
self,
|
|
||||||
path: str,
|
|
||||||
current_path: str,
|
|
||||||
):
|
|
||||||
relative, subpath = path.split(".", 1)
|
|
||||||
relative_len = len(relative)
|
|
||||||
path_len = current_path.count(".")
|
|
||||||
if path_len + 1 == relative_len:
|
|
||||||
return subpath
|
|
||||||
parent_path = current_path.rsplit(".", relative_len)[0]
|
|
||||||
return parent_path + "." + subpath
|
|
||||||
|
|
||||||
def get_with_dynamic(
|
|
||||||
self,
|
|
||||||
path: str,
|
|
||||||
# identifier_path: str,
|
|
||||||
current_path: str,
|
|
||||||
version: str,
|
|
||||||
namespace: str,
|
|
||||||
xmlfiles: List[str],
|
|
||||||
) -> Any:
|
|
||||||
identifier = None
|
|
||||||
if version != "1.0" and self.regexp_relative.search(path):
|
|
||||||
path = self.get_full_path(
|
|
||||||
path,
|
|
||||||
current_path,
|
|
||||||
)
|
|
||||||
# elif identifier_path:
|
|
||||||
# path = f"{identifier_path}.{path}"
|
|
||||||
dynamic = None
|
|
||||||
# version 1.0
|
|
||||||
if version == "1.0":
|
|
||||||
if not path in self._data and "{{ suffix }}" not in path:
|
|
||||||
new_path = None
|
|
||||||
current_path = None
|
|
||||||
identifiers = []
|
|
||||||
for name in path.split("."):
|
|
||||||
parent_path = current_path
|
|
||||||
if current_path:
|
|
||||||
current_path += "." + name
|
|
||||||
else:
|
|
||||||
current_path = name
|
|
||||||
if current_path in self._data:
|
|
||||||
if new_path:
|
|
||||||
new_path += "." + name
|
|
||||||
else:
|
|
||||||
new_path = name
|
|
||||||
continue
|
|
||||||
for dynamic_path in self._dynamics:
|
|
||||||
if "." in dynamic_path:
|
|
||||||
parent_dynamic, name_dynamic = dynamic_path.rsplit(".", 1)
|
|
||||||
else:
|
|
||||||
parent_dynamic = None
|
|
||||||
name_dynamic = dynamic_path
|
|
||||||
if (
|
|
||||||
parent_dynamic == parent_path
|
|
||||||
and name_dynamic.endswith("{{ identifier }}")
|
|
||||||
and name == name_dynamic.replace("{{ identifier }}", "")
|
|
||||||
):
|
|
||||||
new_path += "." + name_dynamic
|
|
||||||
break
|
|
||||||
regexp = "^" + name_dynamic.replace("{{ identifier }}", "(.*)")
|
|
||||||
finded = findall(regexp, name)
|
|
||||||
if len(finded) != 1 or not finded[0]:
|
|
||||||
continue
|
|
||||||
if finded[0] == "{{ identifier }}":
|
|
||||||
identifiers.append(None)
|
|
||||||
else:
|
|
||||||
identifiers.append(finded[0])
|
|
||||||
if new_path is None:
|
|
||||||
new_path = name_dynamic
|
|
||||||
else:
|
|
||||||
new_path += "." + name_dynamic
|
|
||||||
parent_path = dynamic_path
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
if new_path:
|
|
||||||
new_path += "." + name
|
|
||||||
else:
|
|
||||||
new_path = name
|
|
||||||
path = new_path
|
|
||||||
else:
|
|
||||||
identifiers = None
|
|
||||||
if "{{ suffix }}" in path:
|
|
||||||
path = path.replace("{{ suffix }}", "{{ identifier }}")
|
|
||||||
elif not path in self._data:
|
|
||||||
current_path = None
|
|
||||||
parent_path = None
|
|
||||||
new_path = current_path
|
|
||||||
identifiers = []
|
|
||||||
for name in path.split("."):
|
|
||||||
if current_path:
|
|
||||||
current_path += "." + name
|
|
||||||
else:
|
|
||||||
current_path = name
|
|
||||||
# parent_path, name_path = path.rsplit('.', 1)
|
|
||||||
if current_path in self._data:
|
|
||||||
if new_path:
|
|
||||||
new_path += "." + name
|
|
||||||
else:
|
|
||||||
new_path = name
|
|
||||||
parent_path = current_path
|
|
||||||
continue
|
|
||||||
for dynamic_path in self._dynamics:
|
|
||||||
if "." in dynamic_path:
|
|
||||||
parent_dynamic, name_dynamic = dynamic_path.rsplit(".", 1)
|
|
||||||
else:
|
|
||||||
parent_dynamic = None
|
|
||||||
name_dynamic = dynamic_path
|
|
||||||
if (
|
|
||||||
"{{ identifier }}" not in name_dynamic
|
|
||||||
or parent_path != parent_dynamic
|
|
||||||
):
|
|
||||||
continue
|
|
||||||
regexp = "^" + name_dynamic.replace("{{ identifier }}", "(.*)")
|
|
||||||
finded = findall(regexp, name)
|
|
||||||
if len(finded) != 1 or not finded[0]:
|
|
||||||
continue
|
|
||||||
if finded[0] == "{{ identifier }}":
|
|
||||||
identifiers.append(None)
|
|
||||||
else:
|
|
||||||
identifiers.append(finded[0])
|
|
||||||
if new_path is None:
|
|
||||||
new_path = name_dynamic
|
|
||||||
else:
|
|
||||||
new_path += "." + name_dynamic
|
|
||||||
parent_path = dynamic_path
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
if new_path:
|
|
||||||
new_path += "." + name
|
|
||||||
else:
|
|
||||||
new_path = name
|
|
||||||
if "{{ identifier }}" in name:
|
|
||||||
identifiers.append(None)
|
|
||||||
parent_path = current_path
|
|
||||||
path = new_path
|
|
||||||
else:
|
|
||||||
identifiers = None
|
|
||||||
if path not in self._data:
|
|
||||||
return None, None
|
|
||||||
option = self._data[path]
|
|
||||||
option_namespace = option.namespace
|
|
||||||
if (
|
|
||||||
self.default_namespace not in [namespace, option_namespace]
|
|
||||||
and namespace != option_namespace
|
|
||||||
):
|
|
||||||
msg = _(
|
|
||||||
'A variable or a family located in the "{0}" namespace shall not be used in the "{1}" namespace'
|
|
||||||
).format(option_namespace, namespace)
|
|
||||||
raise DictConsistencyError(msg, 38, xmlfiles)
|
|
||||||
return option, identifiers
|
|
||||||
|
|
||||||
def __getitem__(
|
|
||||||
self,
|
|
||||||
path: str,
|
|
||||||
) -> Union[Family, Variable]:
|
|
||||||
if not path in self._data:
|
|
||||||
raise AttributeError(f"cannot find variable or family {path}")
|
|
||||||
return self._data[path]
|
|
||||||
|
|
||||||
def __contains__(
|
|
||||||
self,
|
|
||||||
path: str,
|
|
||||||
) -> bool:
|
|
||||||
return path in self._data
|
|
||||||
|
|
||||||
def __delitem__(
|
|
||||||
self,
|
|
||||||
path: str,
|
|
||||||
) -> None:
|
|
||||||
logging.info("remove empty family %s", path)
|
|
||||||
del self._data[path]
|
|
||||||
|
|
||||||
def is_dynamic(self, path: str) -> bool:
|
|
||||||
return path in self._dynamics
|
|
||||||
|
|
||||||
def get(self):
|
|
||||||
return self._data.values()
|
|
||||||
Loading…
Reference in a new issue