diff --git a/src/techui_builder/builder.py b/src/techui_builder/builder.py index fd3d6ea..8d7b0c7 100644 --- a/src/techui_builder/builder.py +++ b/src/techui_builder/builder.py @@ -1,5 +1,7 @@ +import fnmatch import json import logging +import re from collections import defaultdict from dataclasses import _MISSING_TYPE, dataclass, field from pathlib import Path @@ -114,27 +116,42 @@ def generate_screens(self): # any extras defined for component_name, component in self.conf.components.items(): screen_entities: list[Entity] = [] - # ONLY IF there is a matching component and entity, generate a screen - if component.prefix in self.entities.keys(): + # If the string set as the prefix contains a wildcard, + # do some wildcard matching + if bool(re.search(r"[\*\?\[\]]", component.prefix)): + filtered_prefixes = fnmatch.filter( + self.entities.keys(), component.prefix + ) + for prefix in filtered_prefixes: + screen_entities.extend(self.entities[prefix]) + # If the component prefix is in entities.keys, add to screen entities + elif component.prefix in self.entities.keys(): screen_entities.extend(self.entities[component.prefix]) - if component.extras is not None: - # If component has any extras, add them to the entries to generate - for extra_p in component.extras: - if extra_p not in self.entities.keys(): - LOGGER.error( - f"Extra prefix {extra_p} for {component_name} does not \ -exist." - ) - continue - screen_entities.extend(self.entities[extra_p]) - - self._generate_screen(component_name, screen_entities) else: LOGGER.warning( - f"{self.techui.name}: The prefix [bold]{component.prefix}[/bold]\ - set in the component [bold]{component_name}[/bold] does not match any P field in the\ - ioc.yaml files in services" + f"{self.techui.name}: [bold]{component.prefix}[/bold] set in \ +[bold]{component_name}[/bold] does not match any P field in the ioc.yaml \ +files in services" ) + # If component extras is non empty, for each extra, + # Check if there are any wild card expressions that cause matches and extend + # the screen_entities list if there are any matches + if component.extras is not None: + # If component has any extras, add them to the entries to generate + for extra_p in component.extras: + if bool(re.search(r"[\*\?\[\]]", extra_p)): + filtered_extra = fnmatch.filter(self.entities.keys(), extra_p) + for filtered in filtered_extra: + screen_entities.extend(self.entities[filtered]) + elif extra_p not in self.entities.keys(): + LOGGER.error( + f"Extra prefix {extra_p} for {component_name} does not \ +exist." + ) + continue + screen_entities.extend(self.entities[extra_p]) + + self._generate_screen(component_name, screen_entities) def _generate_json_map( self, screen_path: Path, dest_path: Path, visited: set[Path] | None = None diff --git a/src/techui_builder/models.py b/src/techui_builder/models.py index 87cb239..26ba2a9 100644 --- a/src/techui_builder/models.py +++ b/src/techui_builder/models.py @@ -24,25 +24,25 @@ r""" ^ # start of string (?= # lookahead to ensure the following pattern matches - [A-Za-z0-9-]{13,16} # match 13 to 16 alphanumeric characters or hyphens - [:A-Za-z0-9]* # match zero or more colons or alphanumeric characters - [.A-Za-z0-9] # match a dot or alphanumeric character + [A-Za-z0-9*?\[\]-]{2,16} # match 2-16 alphanumeric chars,-/wildcards + [:A-Za-z0-9*?[\]]* # match >=0 colons or alphanumeric chars/wildcards + [.A-Za-z0-9*?[\]] # match a dot or alphanumeric chars or wildcards ) (?!.*--) # negative lookahead to ensure no double hyphens (?!.*:\..) # negative lookahead to ensure no colon followed by a dot ( # start of capture group 1 - (?:[A-Za-z0-9]{2,5}-){3} # match 2 to 5 alphanumeric characters followed + (?:[A-Za-z0-9*?,\[\]-])* # match >1 alphanumeric characters followed # by a hyphen, repeated 3 times - [\d]* # match zero or more digits + [\d*] # match zero or more digits [^:]? # match zero or one non-colon character ) - (?::([a-zA-Z0-9:]*))? # match zero or one colon followed by zero or more + (?::([a-zA-Z0-9*:]*))? # match zero or one colon followed by zero or more # alphanumeric characters or colons (capture group 2) - (?:\.([a-zA-Z0-9]+))? # match zero or one dot followed by one or more + (?:\.([a-zA-Z0-9*]+))? # match zero or one dot followed by one or more # alphanumeric characters (capture group 3) $ # end of string """, - re.VERBOSE, + re.VERBOSE | re.UNICODE, ) _LONG_DOM_RE = re.compile(r"^[a-zA-Z]{2}\d{2}[a-zA-Z]$") _SHORT_DOM_RE = re.compile(r"^[a-zA-Z]{1}\d{2}(-[0-9]{1})?$")