Skip to content

Presets

duho.presets

Pre-configured argument classes for common patterns.

__all__ = ['ConfigArgs', 'LoggingArgs', 'OutputArgs'] module-attribute

ConfigArgs(**kwargs)

Bases: Args

A data mixin that adds --config FILE (-c) and reads that file.

The file's values become defaults under the command line, and its format is chosen by its suffix (see duho.config). ConfigArgs sets _config_field_, so list it BEFORE Cli, which declares that name as None: class App(ConfigArgs, LoggingArgs, Cli).

Source code in src/duho/args/_argsclass.py
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
def __init__(self, /, **kwargs: object) -> None:
    # Seed each declared field's effective default when absent, so a direct
    # instance has the attribute surface of a parsed one (e.g. a `store_true`
    # bool). Passed kwargs win; a required field (NOT_DEFINED) stays unset.
    # Not `super().__init__(**kwargs)`: a field named `self` would collide.
    super().__init__()
    for key, value in kwargs.items():
        setattr(self, key, value)
    if "_passthrough_" not in vars(self):
        self._passthrough_ = []
    seeded: dict[str, object] = {}
    for builder in type(self)._getargs_():
        name = builder.name
        # `vars(self)`, not `hasattr`: a class-level default is `hasattr`-true
        # by inheritance, so the instance would share, and mutations would
        # leak through, the class attribute.
        if name in kwargs or name in vars(self):
            continue
        default = builder._effective_default_()
        if default is not NOT_DEFINED:
            setattr(self, name, default)
            seeded[name] = _copy.copy(default)
    # Record which fields THIS CALL passed, outside vars(self). A class that
    # is not weak-referenceable is untracked, and `duho.parse(instance)`
    # then treats every attribute as explicit.
    try:
        _key = id(self)
        _duho_explicit_instance_fields[_key] = frozenset(kwargs)
        _duho_seeded_instance_values[_key] = seeded
        _weakref.finalize(self, _duho_explicit_instance_fields.pop, _key, None)
        _weakref.finalize(self, _duho_seeded_instance_values.pop, _key, None)
    except TypeError:
        pass

config = None class-attribute instance-attribute

__init_subclass__(**kwargs)

Source code in src/duho/presets.py
243
244
245
246
247
248
249
250
def __init_subclass__(cls, **kwargs: _ty.Any) -> None:
    super().__init_subclass__(**kwargs)
    # A class that sets `_config_field_ = None` itself turned the flag off.
    if cls._config_field_ is None and "_config_field_" not in vars(cls):
        raise TypeError(
            f"{cls.__qualname__}: ConfigArgs must come before Cli in the base "
            "classes, or Cli's _config_field_ = None hides the --config field"
        )

LoggingArgs(**kwargs)

Bases: Args

Args subclass with built-in -v/-q and --loglevel support.

LoggingArgs is a data mixin (verbosity fields + _set_loglevels_ + the _logger_ property); it defines no __call__ and is NOT itself runnable. Since the Args/Cmd split, combine it with Cmd to get a runnable command with logging::

class MyApp(LoggingArgs, Cmd):
    _version_ = "1.2.3"

    def __call__(self):
        self._logger_.info("running")
        return 0

Recommended base order: (LoggingArgs, Cmd) -- data mixin first, executable base last (reads "add logging to a command"). Both orders resolve correctly because LoggingArgs overrides no Cmd member; _logger_/_set_loglevels_ come from LoggingArgs and __call__ from Cmd regardless of order.

Set a class attr _version_ to opt into a --version flag; no separate preset class is needed. --version prints "%(prog)s 1.2.3" and exits 0. It is skipped if a version-dest action already exists (e.g. supplied by a parent parser).

Source code in src/duho/args/_argsclass.py
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
def __init__(self, /, **kwargs: object) -> None:
    # Seed each declared field's effective default when absent, so a direct
    # instance has the attribute surface of a parsed one (e.g. a `store_true`
    # bool). Passed kwargs win; a required field (NOT_DEFINED) stays unset.
    # Not `super().__init__(**kwargs)`: a field named `self` would collide.
    super().__init__()
    for key, value in kwargs.items():
        setattr(self, key, value)
    if "_passthrough_" not in vars(self):
        self._passthrough_ = []
    seeded: dict[str, object] = {}
    for builder in type(self)._getargs_():
        name = builder.name
        # `vars(self)`, not `hasattr`: a class-level default is `hasattr`-true
        # by inheritance, so the instance would share, and mutations would
        # leak through, the class attribute.
        if name in kwargs or name in vars(self):
            continue
        default = builder._effective_default_()
        if default is not NOT_DEFINED:
            setattr(self, name, default)
            seeded[name] = _copy.copy(default)
    # Record which fields THIS CALL passed, outside vars(self). A class that
    # is not weak-referenceable is untracked, and `duho.parse(instance)`
    # then treats every attribute as explicit.
    try:
        _key = id(self)
        _duho_explicit_instance_fields[_key] = frozenset(kwargs)
        _duho_seeded_instance_values[_key] = seeded
        _weakref.finalize(self, _duho_explicit_instance_fields.pop, _key, None)
        _weakref.finalize(self, _duho_seeded_instance_values.pop, _key, None)
    except TypeError:
        pass

loglevels = {} class-attribute instance-attribute

quiet = 0 class-attribute instance-attribute

verbose = 0 class-attribute instance-attribute

OutputArgs(**kwargs)

Bases: Args

A data mixin that adds --format {text,json} and --json, and _output_.

self._output_(value, text=None) prints value as the user asked: indented JSON for --json or --format json, else text (a str, or a callable taking value and returning one) or, with no text, duho's own rendering of value. Nothing is printed implicitly. A class that declares a format or a json field of its own, or inherits one, cannot use this mixin (TypeError).

Source code in src/duho/args/_argsclass.py
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
def __init__(self, /, **kwargs: object) -> None:
    # Seed each declared field's effective default when absent, so a direct
    # instance has the attribute surface of a parsed one (e.g. a `store_true`
    # bool). Passed kwargs win; a required field (NOT_DEFINED) stays unset.
    # Not `super().__init__(**kwargs)`: a field named `self` would collide.
    super().__init__()
    for key, value in kwargs.items():
        setattr(self, key, value)
    if "_passthrough_" not in vars(self):
        self._passthrough_ = []
    seeded: dict[str, object] = {}
    for builder in type(self)._getargs_():
        name = builder.name
        # `vars(self)`, not `hasattr`: a class-level default is `hasattr`-true
        # by inheritance, so the instance would share, and mutations would
        # leak through, the class attribute.
        if name in kwargs or name in vars(self):
            continue
        default = builder._effective_default_()
        if default is not NOT_DEFINED:
            setattr(self, name, default)
            seeded[name] = _copy.copy(default)
    # Record which fields THIS CALL passed, outside vars(self). A class that
    # is not weak-referenceable is untracked, and `duho.parse(instance)`
    # then treats every attribute as explicit.
    try:
        _key = id(self)
        _duho_explicit_instance_fields[_key] = frozenset(kwargs)
        _duho_seeded_instance_values[_key] = seeded
        _weakref.finalize(self, _duho_explicit_instance_fields.pop, _key, None)
        _weakref.finalize(self, _duho_seeded_instance_values.pop, _key, None)
    except TypeError:
        pass

format = 'text' class-attribute instance-attribute

json = False class-attribute instance-attribute

__init_subclass__(**kwargs)

Source code in src/duho/presets.py
275
276
277
278
279
280
281
282
283
284
285
def __init_subclass__(cls, **kwargs: _ty.Any) -> None:
    super().__init_subclass__(**kwargs)
    for klass in cls.__mro__:
        if klass is OutputArgs:
            continue
        clash = sorted(_OUTPUT_FIELDS.intersection(_own_annotations(klass)))
        if clash:
            raise TypeError(
                f"{cls.__qualname__}: OutputArgs adds the field {clash[0]!r}, "
                f"which {klass.__qualname__} already declares"
            )