Repository: kedro-org/kedro
File: kedro/io/catalog_config_resolver.py (Python)

Code before:
    """Resolves dataset configurations based on patterns and credentials."""

    def __init__(
        self,
        config: dict[str, dict[str, Any]] | None = None,
        credentials: dict[str, dict[str, Any]] | None = None,
        runtime_patterns: Patterns | None = None,
    ):
        if runtime_patterns is None:
            self._logger.warning(
                f"Since runtime patterns are not provided, setting"
                f"the runtime pattern to default value: {DEFAULT_RUNTIME_PATTERN}"
            )
        self._runtime_patterns = runtime_patterns or DEFAULT_RUNTIME_PATTERN
        self._dataset_patterns, self._default_pattern = self._extract_patterns(
            config, credentials
        )
        self._resolved_configs = self.resolve_credentials(config, credentials)

    @property
    def config(self) -> dict[str, dict[str, Any]]:
        return self._resolved_configs

    @property
    def _logger(self) -> logging.Logger:
        return logging.getLogger(__name__)

    @staticmethod
    def is_pattern(pattern: str) -> bool:
        """Check if a given string is a pattern. Assume that any name with '{' is a pattern."""
        return "{" in pattern

    @staticmethod
    def _pattern_specificity(pattern: str) -> int:
        """Calculate the specificity of a pattern based on characters outside curly brackets."""
        # Remove all the placeholders from the pattern and count the number of remaining chars
        result = re.sub(r"\{.*?\}", "", pattern)
        return len(result)

    @classmethod
    def _sort_patterns(cls, dataset_patterns: Patterns) -> Patterns:
        """Sort a dictionary of dataset patterns according to parsing rules.

        In order:
        1. Decreasing specificity (number of characters outside the curly brackets)
        2. Decreasing number of placeholders (number of curly bracket pairs)
        3. Alphabetically
        """
        sorted_keys = sorted(
            dataset_patterns,
            key=lambda pattern: (

Review comment (security):
[Nit] we have `_resolve_credentials` within the class as well. Should we call this `_resolve_credentials_helper` or with some other name to avoid confusion ?

Code after:
    """Fetch the specified credentials from the provided credentials dictionary.

    Args:
        credentials_name: Credentials name.
        credentials: A dictionary with all credentials.

    Returns:
        The set of requested credentials.

    Raises:
        KeyError: When a dataset with the given name has not yet been
            registered.

    """
    try:
        return credentials[credentials_name]
    except KeyError as exc:
        raise KeyError(
            f"Unable to find credentials '{credentials_name}': check your data "
            "catalog and credentials configuration. See "
            "https://docs.kedro.org/en/stable/data/index.html#kedrodatacatalog "
            "for an example."
        ) from exc


def _resolve_credentials(
    config: dict[str, Any], credentials: dict[str, Any]
) -> dict[str, Any]:
    """Return the dataset configuration where credentials are resolved using
    credentials dictionary provided.

    Args:
        config: Original dataset config, which may contain unresolved credentials.
        credentials: A dictionary with all credentials.

    Returns:
        The dataset config, where all the credentials are successfully resolved.
    """
    config = copy.deepcopy(config)

    def _resolve_value(key: str, value: Any) -> Any:
        if key == CREDENTIALS_KEY and isinstance(value, str):
            return _fetch_credentials(value, credentials)
        if isinstance(value, dict):
            return {k: _resolve_value(k, v) for k, v in value.items()}
        return value

    return {k: _resolve_value(k, v) for k, v in config.items()}


class CatalogConfigResolver: