Skip to content
Snippets Groups Projects
Commit 641ca8c2 authored by Henrik tom Wörden's avatar Henrik tom Wörden
Browse files

ENH: add a decorator that adds a path variable

file system related structure elements can use it to have a variable
that can be accessed in the cfood that contains the file system path of
the structure element

Also, did some refactoring of the related StructureElements
parent f326deec
No related branches found
No related tags found
2 merge requests!105REL: v0.4.0,!100ENH: add a decorator that adds a path variable
Pipeline #33674 failed
......@@ -110,6 +110,19 @@ class ConverterValidationError(Exception):
self.message = msg
def create_path_value(func):
"""decorator for create_values functions that adds a value containing the path
should be used for StructureElement that are associated with file system objects that have a
path, like File or Directory.
"""
def inner(self, values: GeneralStore, element: StructureElement):
func(self, values=values, element=element)
values.update({self.name + "_path": element.path})
return inner
def replace_variables(propvalue, values: GeneralStore):
"""
This function replaces variables in property values (and possibly other locations,
......@@ -478,6 +491,10 @@ class DirectoryConverter(Converter):
return children
@create_path_value
def create_values(self, values: GeneralStore, element: StructureElement):
super().create_values(values=values, element=element)
def typecheck(self, element: StructureElement):
return isinstance(element, Directory)
......@@ -525,6 +542,10 @@ class SimpleFileConverter(Converter):
def create_children(self, generalStore: GeneralStore, element: StructureElement):
return list()
@create_path_value
def create_values(self, values: GeneralStore, element: StructureElement):
super().create_values(values=values, element=element)
@Converter.debug_matching("name")
def match(self, element: StructureElement):
# TODO: See comment on types and inheritance
......@@ -543,7 +564,7 @@ class FileConverter(SimpleFileConverter):
super().__init__(*args, **kwargs)
class MarkdownFileConverter(Converter):
class MarkdownFileConverter(SimpleFileConverter):
"""
reads the yaml header of markdown files (if a such a header exists).
"""
......@@ -553,8 +574,15 @@ class MarkdownFileConverter(Converter):
if not isinstance(element, File):
raise RuntimeError("A markdown file is needed to create children.")
header = yaml_header_tools.get_header_from_file(
element.path, clean=False)
try:
header = yaml_header_tools.get_header_from_file(
element.path, clean=False)
except yaml_header_tools.NoValidHeader:
path = generalStore[self.name]
raise ConverterValidationError(
"Error during the validation (yaml header cannot be read) of the markdown file "
"located at the following node in the data structure:\n"
f"{path}\n" + err.message)
children: List[StructureElement] = []
for name, entry in header.items():
......@@ -567,25 +595,6 @@ class MarkdownFileConverter(Converter):
"Header entry {} has incompatible type.".format(name))
return children
def typecheck(self, element: StructureElement):
return isinstance(element, File)
@Converter.debug_matching("name")
def match(self, element: StructureElement):
# TODO: See comment on types and inheritance
if not isinstance(element, File):
raise RuntimeError("Element must be a file.")
m = re.match(self.definition["match"], element.name)
if m is None:
return None
try:
yaml_header_tools.get_header_from_file(element.path)
except yaml_header_tools.NoValidHeader:
# TODO(salexan): Raise a validation error instead of just not
# matching silently.
return None
return m.groupdict()
def convert_basic_element(element: Union[list, dict, bool, int, float, str, None], name=None,
msg_prefix=""):
......@@ -692,20 +701,7 @@ class DictDictElementConverter(DictElementConverter):
super().__init__(*args, **kwargs)
class JSONFileConverter(Converter):
def typecheck(self, element: StructureElement):
return isinstance(element, File)
@Converter.debug_matching("name")
def match(self, element: StructureElement):
# TODO: See comment on types and inheritance
if not self.typecheck(element):
raise RuntimeError("Element must be a file")
m = re.match(self.definition["match"], element.name)
if m is None:
return None
return m.groupdict()
class JSONFileConverter(SimpleFileConverter):
def create_children(self, generalStore: GeneralStore, element: StructureElement):
# TODO: See comment on types and inheritance
if not isinstance(element, File):
......@@ -727,20 +723,7 @@ class JSONFileConverter(Converter):
return [structure_element]
class YAMLFileConverter(Converter):
def typecheck(self, element: StructureElement):
return isinstance(element, File)
@Converter.debug_matching("name")
def match(self, element: StructureElement):
# TODO: See comment on types and inheritance
if not self.typecheck(element):
raise RuntimeError("Element must be a file")
m = re.match(self.definition["match"], element.name)
if m is None:
return None
return m.groupdict()
class YAMLFileConverter(SimpleFileConverter):
def create_children(self, generalStore: GeneralStore, element: StructureElement):
# TODO: See comment on types and inheritance
if not isinstance(element, File):
......
......@@ -610,3 +610,17 @@ def test_load_converters():
assert "SimpleFile" in converter_registry
assert "Directory" in converter_registry
assert "ListElement" in converter_registry
def test_create_path_value(converter_registry):
""" test using the "test_directories" folder"""
dc = Converter.converter_factory(
definition={
"type": "Directory",
"match": ".*"
},
name="Test", converter_registry=converter_registry)
values = GeneralStore()
dc.create_values(values, Directory("a", "/a"))
assert "Test_path" in values
assert values["Test_path"] == "/a"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment