scriptconfig.dataconfig module

The new way to declare configurations.

Similar to the old-style Config objects, you simply declare a class that inherits from scriptconfig.DataConfig (or is wrapped by scriptconfig.datconf()) and declare the class variables as the config attributes much like you would write a dataclass.

Creating an instance of a DataConfig class works just like a regular dataclass, and nothing special happens. You can create the argument parser by using the :func:DataConfig.cli classmethod, which works similarly to the old-style scriptconfig.Config constructor.

The following is the same top-level example as in scriptconfig.config, but using DataConfig instead. It works as a drop-in replacement.

Example

>>> import scriptconfig as scfg
>>> # In its simplest incarnation, the config class specifies default values.
>>> # For each configuration parameter.
>>> class ExampleConfig(scfg.DataConfig):
>>>      num = 1
>>>      mode = 'bar'
>>>      ignore = ['baz', 'biz']
>>> # Creating an instance, starts using the defaults
>>> config = ExampleConfig()
>>> # Typically you will want to update default from a dict or file.  By
>>> # specifying cmdline=True you denote that it is ok for the contents of
>>> # `sys.argv` to override config values. Here we pass a dict to `load`.
>>> kwargs = {'num': 2}
>>> config.load(kwargs, cmdline=False)
>>> assert config['num'] == 2
>>> # The `load` method can also be passed a json/yaml file/path.
>>> import tempfile
>>> config_fpath = tempfile.mktemp()
>>> open(config_fpath, 'w').write('{"num": 3}')
>>> config.load(config_fpath, cmdline=False)
>>> assert config['num'] == 3
>>> # It is possbile to load only from CLI by setting cmdline=True
>>> # or by setting it to a custom sys.argv
>>> config.load(cmdline=['--num=4', '--mode' ,'fiz'])
>>> assert config['num'] == 4
>>> assert config['mode'] == 'fiz'
>>> # You can also just use the command line string itself
>>> config.load(cmdline='--num=4 --mode fiz')
>>> assert config['num'] == 4
>>> assert config['mode'] == 'fiz'
>>> # Note that using `config.load(cmdline=True)` will just use the
>>> # contents of sys.argv

Notes

https://docs.python.org/3/library/dataclasses.html

scriptconfig.dataconfig.dataconf(cls)[source]

Aims to be similar to the dataclass decorator

Note

It is currently recommended to extend from the DataConfig object instead of decorating with @dataconf. These have slightly different behaviors and the former is more well-tested.

Example

>>> from scriptconfig.dataconfig import *  # NOQA
>>> import scriptconfig as scfg
>>> @dataconf
>>> class ExampleDataConfig2:
>>>     chip_dims = scfg.Value((256, 256), help='chip size')
>>>     time_dim = scfg.Value(3, help='number of time steps')
>>>     channels = scfg.Value('*:(red|green|blue)', help='sensor / channel code')
>>>     time_sampling = scfg.Value('soft2')
>>> cls = ExampleDataConfig2
>>> print(f'cls={cls}')
>>> self = cls()
>>> print(f'self={self}')

Example

>>> from scriptconfig.dataconfig import *  # NOQA
>>> import scriptconfig as scfg
>>> @dataconf
>>> class PathologicalConfig:
>>>     default0 = scfg.Value((256, 256), help='chip size')
>>>     default = scfg.Value((256, 256), help='chip size')
>>>     keys = [1, 2, 3]
>>>     __default__ = {
>>>         'argparse': 3.3,
>>>         'keys': [4, 5],
>>>     }
>>>     default = None
>>>     time_sampling = scfg.Value('soft2')
>>>     def foobar(self):
>>>         ...
>>> self = PathologicalConfig(1, 2, 3)
>>> print(f'self={self}')

# FIXME: xdoctest problem. Need to be able to simulate a module global scope # Example: # >>> # Using inheritance and the decorator lets you pickle the object # >>> from scriptconfig.dataconfig import * # NOQA # >>> import scriptconfig as scfg # >>> @dataconf # >>> class PathologicalConfig2(scfg.DataConfig): # >>> default0 = scfg.Value((256, 256), help=’chip size’) # >>> default2 = scfg.Value((256, 256), help=’chip size’) # >>> #keys = [1, 2, 3] : Too much # >>> __default__3 = { # >>> ‘argparse’: 3.3, # >>> ‘keys2’: [4, 5], # >>> } # >>> default2 = None # >>> time_sampling = scfg.Value(‘soft2’) # >>> config = PathologicalConfig2() # >>> import pickle # >>> serial = pickle.dumps(config) # >>> recon = pickle.loads(serial) # >>> assert ‘locals’ not in str(PathologicalConfig2)

class scriptconfig.dataconfig.MetaDataConfig(name, bases, namespace, *args, **kwargs)[source]

Bases: MetaConfig

This metaclass allows us to call dataconf when a new subclass is defined without the extra boilerplate.

class scriptconfig.dataconfig.DataConfig(*args, **kwargs)[source]

Bases: Config

Valid options: []

Parameters:
  • *args – positional arguments for this data config

  • **kwargs – keyword arguments for this data config

classmethod legacy(cmdline=False, data=None, default=None, strict=False)[source]

Calls the original “load” way of creating non-dataclass config objects. This may be refactored in the future.

classmethod parse_args(args=None, namespace=None)[source]

Mimics argparse.ArgumentParser.parse_args

classmethod parse_known_args(args=None, namespace=None)[source]

Mimics argparse.ArgumentParser.parse_known_args

default = {}
classmethod _register_main(func)[source]

Register a function as the main method for this dataconfig CLI