Skip to content

API Reference

dirconf.config

DirConfig dataclass

DirConfig()

A base dataclass representing a collection of configuration files.

This either be subclassed explicitly, i.e. via class MyConfig(DirConfig): ..., or through the make_dirconfig function. All fields are expected to be instances of Node.

nodes

nodes(recurse: bool = False) -> Iterator[Node]

An iterator over all nodes (fields) in the configuration.

Parameters:

  • recurse (bool, default: False ) –

    In cases where one or more of the nodes of the DirConfig is a directory whose Handler is itself instance of DirConfig, passing recurse=True will also yield the nodes from these children.

Yields:

  • nodes ( Node ) –

    Instances of Node corresponding to the files and directories in the configuration.

read

read(path: str | PathLike) -> dict[str, Any]

Read a configuration from a given path and return its contents as a dict.

Parameters:

  • path (str | PathLike) –

    A path to a directory containing the configuration files.

Returns:

  • config ( dict[str, Any] ) –

    The read configuration as a Python dict. The keys of the dictionary will be the field names of the DirConfig subclass.

tree

tree(max_depth: int | None = None, details: bool = True) -> str

Returns a tree-like representation of the configuration.

Parameters:

  • max_depth (int | None, default: None ) –

    Optionally truncate the tree at a certain depth.

  • details (bool, default: True ) –

    If set to False, details about the path and handler are suppressed.

Returns:

  • tree_repr ( str ) –

    A printable tree-like representation of the configuration.

write

write(
    path: str | PathLike, data: dict[str, Any], *, overwrite_ok: bool = False
) -> None

Write a configuration to a given path.

Parameters:

  • path (str | PathLike) –

    A path to a directory where the configuration will be written. The directory need not yet exist.

  • data (dict[str, Any]) –

    A dict whose keys match the field names for this DirConfig, and whose values contain the data to be written.

  • overwrite_ok (bool, default: False ) –

    A flag indicating whether overwriting existing files is acceptable. Nothing is done with this argument other than to pass it to the write method for all of the handlers.

make_dirconfig

make_dirconfig(
    cls_name: str, spec: dict | str | PathLike, **kwargs: Any
) -> type[DirConfig]

A function that generates subclasses of DirConfig.

This is a wrapper around dataclasses.make_dataclass that sets the base class to dirconf.config.DirConfig and constructs fields using the provided spec.

Parameters:

  • cls_name (str) –

    A name for the class being created.

  • spec (dict | str | PathLike) –

    A dict specifying the node (field) names, paths and handlers.

  • kwargs (Any, default: {} ) –

    Additional arguments to pass to make_dataclass.

Returns:

  • DirConfigSubclass ( type[DirConfig] ) –

    The resulting subclass of DirConfig.


dirconf.filter

MISSING module-attribute

MISSING = _Missing()

A sentinel value that may be used in place of missing data.

MissingWarning

Bases: Warning

A warning indicating that a filter test has failed, perhaps unexpectedly.

filter

filter(
    read: Callable[[Path], bool] | None = None,
    write: Callable[..., bool] | None = None,
    label: str | None = None,
    warn: bool = False,
) -> Callable[[Any], Any]

A decorator for classes satisfying the Handler protocol.

This provides an alternative to decorating both the read method with filter_read and the write method with filter_write.

Parameters:

  • read (Callable[[Path], bool] | None, default: None ) –

    A test to run when the read method is called.

  • write (Callable[..., bool] | None, default: None ) –

    A test to run when the write method is called.

  • warn (bool, default: False ) –

    If True, emit a warning when a test fails.

See Also

filter_missing

filter_missing(warn: bool = False) -> Callable[[Any], Any]

Filter out non-existent paths from read and MISSING data from `write.

This is implemented purely for convenience, since it simply calls filter with two specific test functions.

return filter(
    read=lambda path: path.exists(),
    write=lambda path, data, **_: data is not MISSING,
    warn=warn,
)

filter_read

filter_read(
    test: Callable[[Path], bool], label: str | None = None, warn: bool = False
) -> Callable[[ReadMethod], ReadMethod]

A decorator for read methods that allows for filtering.

The path-like argument to read is first cast to a pathlib.Path before being passed into test. If the output of test(path) is True, the wrapped read method is called and nothing else is done. If the output is False, then the read is not attempted and instead a special value, MISSING, is returned. In the latter case, a MissingWarning is also emitted if warn=True.

Parameters:

  • test (Callable[[Path], bool]) –

    A function which causes the read to be skipped if False is returned.

  • label (str | None, default: None ) –

    An optional label for this filter. If blank or None one will be generated automatically.

  • warn (bool, default: False ) –

    If True, test failure causes a warning is emitted.

filter_write

filter_write(
    test: Callable[..., bool], label: str | None = None, warn: bool = False
) -> Callable[[WriteMethod], WriteMethod]

A decorator for write methods that allows for filtering.

The path-like argument to write is first cast to a pathlib.Path before being passed into test along with data and the remaining argument(s). If the output of test(path, data, **kwargs) is True, the wrapped write method is called and nothing else is done. If the output is False, then the write is not attempted and the function simply returns. In the latter case, a MissingWarning is also emitted if warn=True.

Parameters:

  • test (Callable[..., bool]) –

    A function which causes the write to be skipped if False is returned.

  • label (str | None, default: None ) –

    An optional label for this filter. If blank or None one will be generated automatically.

  • warn (bool, default: False ) –

    If True, test failure causes a warning is emitted.


dirconf.handler

HandlerFactory

HandlerFactory = Callable[[], Handler]

Type alias for a zero-argument callable that returns a Handler.

ReadMethod

ReadMethod = Callable[..., Any]

Type alias for the read method of a handler.

Expected signature: (self, path: str | PathLike) -> Any

WriteMethod

WriteMethod = Callable[..., None]

Type alias for the write method of a handler.

Expected signature

(self, path: str | PathLike, data: Any, *, overwrite_ok: bool) -> None

Note: Callable cannot express keyword-only parameters or self binding. The overwrite_ok parameter must be passed as a keyword argument at runtime.

Handler

Bases: Protocol

A Protocol for all valid handlers.

As with any Protocol, it is not necessary to subclass Handler. However, any valid handler must implement the read and write methods with signatures matching the abstract methods given here.

read abstractmethod

read(path: str | PathLike) -> Any

Abstract method for reading data from a file or directory.

write abstractmethod

write(path: str | PathLike, data: Any, *, overwrite_ok: bool) -> None

Abstract method for writing data to a file or directory.

infer_handler_from_path

infer_handler_from_path(path: str | PathLike) -> HandlerFactory

Infers the desired HandlerFactory based on the file extension.

parse_handler

parse_handler(input: str | HandlerFactory) -> HandlerFactory

Returns a HandlerFactory given any valid input.

register_handler

register_handler(
    name: str, handler: HandlerFactory, extensions: list[str] | None = None
) -> None

Add a handler factory to the registry.


dirconf.node

Node dataclass

Node(path: str | PathLike, handler: HandlerFactory)

A dataclass representing a file or directory.

handler instance-attribute

handler: HandlerFactory

A HandlerFactory that produces valid handlers with read and write methods for the file or directory.

path instance-attribute

path: str | PathLike

A path corresponding to a file or directory.

dict_to_node

dict_to_node(path_and_handler: dict) -> Node

Converts a valid dict to a Node.

path_to_node

path_to_node(
    handler: HandlerFactory | None = None,
) -> Callable[[str | PathLike | dict[str, str | PathLike]], Node]

Returns a transform that attempts to construct a Node from a path only.

to_node

to_node(input: Node | dict | str | PathLike) -> Node

A catch-all transform that produces a Node.


dirconf.utils

switch_dir

switch_dir(path: str | PathLike)

Context manager for changing to existing directory.

dict_to_namespace

dict_to_namespace(dict_: dict) -> SimpleNamespace

Converts a dict into a SimpleNamespace supporting 'dot' access.

namespace_to_dict

namespace_to_dict(namespace: SimpleNamespace) -> dict

Converts a SimpleNamespace back to a dict.

tree

tree(path: str | PathLike) -> str

Constructs a tree-like representation of a directory.

This is primarily for sanity-checking by comparing the output of DirConfig.tree with an actual directory.

Note

This is inspired by GNU tree and is an adaptation of this stackoverflow answer by Aaron Hall.