Skip to content

configclass

configclass(cls=None, recursive=False)

Construct a Config in dataclass style.

This decorator creates a Config instance with the provided class attributes.

See Also

dataclass

Parameters:

Name Type Description Default
cls Type[Any]

The class to be enhanced, provided directly if no parentheses are used.

None
recursive bool

If True, recursively copy class attributes. Only applicable if used with parentheses.

False

Returns:

Type Description

A modified class with Config functionalities or a decorator with bound parameters.

Examples:

Python Console Session
>>> @configclass
... class DataloaderConfig:
...     batch_size: int = 64
...     num_workers: int = 4
...     pin_memory: bool = True
>>> config = DataloaderConfig()
>>> print(config)
DataloaderConfig(<class 'chanfig.config.Config'>,
  ('batch_size'): 64
  ('num_workers'): 4
  ('pin_memory'): True
)
Source code in chanfig/configclasses.py
Python
def configclass(cls=None, recursive: bool = False):
    """
    Construct a Config in [`dataclass`][dataclasses.dataclass] style.

    This decorator creates a Config instance with the provided class attributes.

    See Also:
        [`dataclass`][dataclasses.dataclass]

    Args:
        cls (Type[Any]): The class to be enhanced, provided directly if no parentheses are used.
        recursive (bool): If True, recursively copy class attributes. Only applicable if used with parentheses.

    Returns:
        A modified class with Config functionalities or a decorator with bound parameters.

    Examples:
        >>> @configclass
        ... class DataloaderConfig:
        ...     batch_size: int = 64
        ...     num_workers: int = 4
        ...     pin_memory: bool = True
        >>> config = DataloaderConfig()
        >>> print(config)
        DataloaderConfig(<class 'chanfig.config.Config'>,
          ('batch_size'): 64
          ('num_workers'): 4
          ('pin_memory'): True
        )
    """

    def decorator(cls: Type[Any]):
        if not issubclass(cls, Config):
            config_cls = type(cls.__name__, (Config, cls), dict(cls.__dict__))
            cls = config_cls

        cls_init = cls.__init__

        @wraps(cls_init)
        def init(self, *args, **kwargs):
            cls_init(self)
            self.copy_class_attributes(recursive=recursive)
            self.merge(*args, **kwargs)

        setattr(cls, "__init__", init)  # noqa: B010

        return cls

    if cls is None:
        return decorator
    else:
        return decorator(cls)