Skip to content

!import tag

Constructor

ImportConstructor dataclass

Custom PyYAML constructor for the !import tag, which loads an entire file into the current document.

As a Constructor, it can be called with a yaml.Loader and a yaml.Node to attempt to construct a given node tagged as !import into a Python object. In any valid use of the tag, this node should always be a scalar string, e.g.:

my-data: !import path/to/my/file.yml

To standardize the parsing of the tag's argument, the Constructor uses an ImportSpec dataclass to hold the path to the file to be imported, as a relative path.

Methods:

Name Description
__call__

Construct a node tagged as !import into a Python object.

load

Using a specified loader type, load the contents of the file specified in the ImportSpec dataclass.

Source code in yaml_extras/yaml_import.py
@dataclass
class ImportConstructor:
    """Custom PyYAML constructor for the `!import` tag, which loads an entire file into the current
    document.

    As a Constructor, it can be called with a `yaml.Loader` and a `yaml.Node` to attempt to
    construct a given node tagged as `!import` into a Python object. In any valid use of the tag,
    this node should always be a scalar string, e.g.:

    ```yaml
    my-data: !import path/to/my/file.yml
    ```

    To standardize the parsing of the tag's argument, the Constructor uses an
    [`ImportSpec`](./#yaml_extras.yaml_import.ImportSpec)
    dataclass to hold the path to the file to be imported, as a relative path.

    Methods:
        __call__: Construct a node tagged as `!import` into a Python object.
        load: Using a specified loader type, load the contents of the file specified in the
            `ImportSpec` dataclass.
    """

    def __call__(self, loader: yaml.Loader, node: yaml.Node) -> Any:
        """Using the specified loader, attempt to construct a node tagged as `!import` into a Python
        object.

        For any valid use of the tag, the node should always be a scalar string in the form of
        a relative file path.

        Heavily inspired by [@tanbro](https://github.com/tanbro)'s
        [pyyaml-include](https://github.com/tanbro/pyyaml-include) library.

        Args:
            loader (yaml.Loader): YAML loader
            node (yaml.Node): `!import`-tagged node

        Returns:
            Any: Result of loading the file's contents using the specified loader.
        """
        import_spec: ImportSpec
        if isinstance(node, yaml.ScalarNode):
            val = loader.construct_scalar(node)
            if isinstance(val, str):
                import_spec = ImportSpec.from_str(val)
            else:
                raise TypeError(f"!import Expected a string, got {type(val)}")
        else:
            raise TypeError(f"!import Expected a string scalar, got {type(node)}")
        return self.load(type(loader), import_spec)

    def load(self, loader_type: Type[yaml.Loader], import_spec: ImportSpec) -> Any:
        """Utility function to load the contents of the file specified in the `ImportSpec`
        dataclass.

        Args:
            loader_type (Type[yaml.Loader]): YAML loader type
            import_spec (ImportSpec): Dataclass containing the path to the file to be imported.

        Returns:
            Any: Result of loading the file's contents using the specified loader type.
        """
        # Just load the contents of the file
        return yaml.load(import_spec.path.open("r"), loader_type)

__call__(loader, node)

Using the specified loader, attempt to construct a node tagged as !import into a Python object.

For any valid use of the tag, the node should always be a scalar string in the form of a relative file path.

Heavily inspired by @tanbro's pyyaml-include library.

Parameters:

Name Type Description Default
loader Loader

YAML loader

required
node Node

!import-tagged node

required

Returns:

Name Type Description
Any Any

Result of loading the file's contents using the specified loader.

Source code in yaml_extras/yaml_import.py
def __call__(self, loader: yaml.Loader, node: yaml.Node) -> Any:
    """Using the specified loader, attempt to construct a node tagged as `!import` into a Python
    object.

    For any valid use of the tag, the node should always be a scalar string in the form of
    a relative file path.

    Heavily inspired by [@tanbro](https://github.com/tanbro)'s
    [pyyaml-include](https://github.com/tanbro/pyyaml-include) library.

    Args:
        loader (yaml.Loader): YAML loader
        node (yaml.Node): `!import`-tagged node

    Returns:
        Any: Result of loading the file's contents using the specified loader.
    """
    import_spec: ImportSpec
    if isinstance(node, yaml.ScalarNode):
        val = loader.construct_scalar(node)
        if isinstance(val, str):
            import_spec = ImportSpec.from_str(val)
        else:
            raise TypeError(f"!import Expected a string, got {type(val)}")
    else:
        raise TypeError(f"!import Expected a string scalar, got {type(node)}")
    return self.load(type(loader), import_spec)

load(loader_type, import_spec)

Utility function to load the contents of the file specified in the ImportSpec dataclass.

Parameters:

Name Type Description Default
loader_type Type[Loader]

YAML loader type

required
import_spec ImportSpec

Dataclass containing the path to the file to be imported.

required

Returns:

Name Type Description
Any Any

Result of loading the file's contents using the specified loader type.

Source code in yaml_extras/yaml_import.py
def load(self, loader_type: Type[yaml.Loader], import_spec: ImportSpec) -> Any:
    """Utility function to load the contents of the file specified in the `ImportSpec`
    dataclass.

    Args:
        loader_type (Type[yaml.Loader]): YAML loader type
        import_spec (ImportSpec): Dataclass containing the path to the file to be imported.

    Returns:
        Any: Result of loading the file's contents using the specified loader type.
    """
    # Just load the contents of the file
    return yaml.load(import_spec.path.open("r"), loader_type)

Utility dataclass

ImportSpec dataclass

Small utility dataclass for typing the parsed argument to the !import tag. E.g.,

my-data: !import path/to/file.yml

Shall be parsed as,

ImportSpec(Path("path/to/file.yml"))

Attributes:

Name Type Description
path Path

Relative path to the file to be imported

Methods:

Name Description
from_str

Parse a string into an ImportSpec dataclass.

Source code in yaml_extras/yaml_import.py
@dataclass
class ImportSpec:
    """Small utility dataclass for typing the parsed argument to the `!import` tag. E.g.,

    ```yaml
    my-data: !import path/to/file.yml
    ```

    Shall be parsed as,

    ```python
    ImportSpec(Path("path/to/file.yml"))
    ```

    Attributes:
        path (Path): Relative path to the file to be imported

    Methods:
        from_str: Parse a string into an `ImportSpec` dataclass.
    """

    path: Path

    @classmethod
    def from_str(cls, path_str: str) -> "ImportSpec":
        """Parse a string into an `ImportSpec` dataclass.

        Args:
            path_str (str): Relative path to the file to be imported

        Returns:
            ImportSpec: Dataclass containing the path to the file to be imported.
        """
        return cls(Path(get_import_relative_dir() / path_str))

from_str(path_str) classmethod

Parse a string into an ImportSpec dataclass.

Parameters:

Name Type Description Default
path_str str

Relative path to the file to be imported

required

Returns:

Name Type Description
ImportSpec ImportSpec

Dataclass containing the path to the file to be imported.

Source code in yaml_extras/yaml_import.py
@classmethod
def from_str(cls, path_str: str) -> "ImportSpec":
    """Parse a string into an `ImportSpec` dataclass.

    Args:
        path_str (str): Relative path to the file to be imported

    Returns:
        ImportSpec: Dataclass containing the path to the file to be imported.
    """
    return cls(Path(get_import_relative_dir() / path_str))