Skip to content

Pattern resolver

pattern_resolver #

MissingPlaceholderValueError #

MissingPlaceholderValueError(
    missing_keys: set[str], class_name: str, key: str
)

Bases: imgtools.pattern_parser.pattern_resolver.PatternResolverError

Raised when a required placeholder value is missing in the context.

Source code in src/imgtools/pattern_parser/pattern_resolver.py
def __init__(
    self, missing_keys: set[str], class_name: str, key: str
) -> None:
    self.missing_keys = missing_keys
    self.class_name = class_name
    self.key = key
    super().__init__(self._build_message())

PatternResolver dataclass #

PatternResolver(filename_format: str)

Handles parsing and validating filename patterns.

By default, this class uses the following pattern parser:

DEFAULT_PATTERN: re.Pattern = re.compile( ... r"%(\w+)|{(\w+)}" ... )

This will match placeholders of the form {key} or %(key)s.

Example

Given a filename format like "{subject_id}_{date}/{disease}.txt", the pattern parser will extract the following keys:

pattern_resolver.keys

And the following formatted pattern:

pattern_resolver.formatted_pattern %(subject_id)s_%(date)s/%(disease)s.txt

So you could resolve the pattern like this:

data_dict = { ... "subject_id": "JohnDoe", ... "date": "January-01-2025", ... "disease": "cancer", ... }

pattern_resolver.formatted_pattern % data_dict 'JohnDoe_01-01-2025/cancer.txt'

A more convenient way to resolve the pattern is to use the resolve method:

pattern_resolver.resolve(data_dict)) 'JohnDoe_01-01-2025/cancer.txt'

Methods:

Name Description
parse

Parse and validate the pattern.

resolve

Resolve the pattern using the provided context dictionary.

Source code in src/imgtools/pattern_parser/pattern_resolver.py
def __init__(self, filename_format: str) -> None:
    self.filename_format = filename_format

    try:
        self.pattern_parser = PatternParser(
            self.filename_format, pattern_matcher=self.DEFAULT_PATTERN
        )
        self.formatted_pattern, self.keys = (
            self.parse()
        )  # Validate the pattern by parsing it
    except InvalidPatternError as e:
        msg = f"Invalid filename format: {e}"
        raise PatternResolverError(msg) from e
    else:
        logger.debug(
            "Pattern validation successful.",
            keys=self.keys,
            formatted_pattern=self.formatted_pattern,
        )

parse #

parse() -> typing.Tuple[str, list[str]]

Parse and validate the pattern.

Returns:

Type Description
typing.Tuple[str, List[str]]

The formatted pattern string and a list of extracted keys.

Source code in src/imgtools/pattern_parser/pattern_resolver.py
def parse(self) -> Tuple[str, list[str]]:
    """
    Parse and validate the pattern.

    Returns
    -------
    Tuple[str, List[str]]
        The formatted pattern string and a list of extracted keys.

    Raises
    ------
    InvalidPatternError
        If the pattern contains no valid placeholders or is invalid.
    """
    if hasattr(self, "formatted_pattern") and hasattr(self, "keys"):
        return self.formatted_pattern, self.keys

    self.formatted_pattern, self.keys = self.pattern_parser.parse()
    return self.formatted_pattern, self.keys

resolve #

resolve(context: typing.Dict[str, typing.Any]) -> str

Resolve the pattern using the provided context dictionary.

Parameters:

Name Type Description Default
context #
typing.Dict[str, typing.Any]

Dictionary containing key-value pairs to substitute in the pattern.

required

Returns:

Type Description
str

The resolved pattern string with placeholders replaced by values.

Source code in src/imgtools/pattern_parser/pattern_resolver.py
def resolve(self, context: Dict[str, Any]) -> str:
    """Resolve the pattern using the provided context dictionary.

    Parameters
    ----------
    context : Dict[str, Any]
        Dictionary containing key-value pairs to substitute in the pattern.

    Returns
    -------
    str
        The resolved pattern string with placeholders replaced by values.

    Raises
    ------
    PatternResolverError
        If a required key is missing from the context dictionary.
    """

    # simultaneously check for None values and validate the pattern
    if len(none_keys := [k for k, v in context.items() if v is None]) > 0:
        msg = "None is not a valid value for a placeholder in the pattern."
        msg += f" None keys: {none_keys}"
        raise PatternResolverError(msg)

    try:
        return self.formatted_pattern % context
    except KeyError as e:
        # Determine the missing key and construct the error dynamically
        missing_keys = set(self.keys) - set(context.keys())
        raise MissingPlaceholderValueError(
            missing_keys=missing_keys,
            class_name=self.__class__.__name__,
            key=e.args[0],
        ) from e

PatternResolverError #

Bases: Exception

Base exception for errors in pattern resolution.