Skip to content

convoke.configs

Tools for parsing configuration values from the environment

convoke.configs.env_field

Define a field that pulls config values from the environment.

Fields with missing defaults will be assumed to be required, and if missing will produce an error.

Parameters:

Name Type Description Default
default Any

the default value to use, if any, of the expected type. If this is omitted, the field will be required.

MISSING
doc str

a docstring describing the use of the configuration value, used in generating .env files

''
Source code in src/convoke/configs.py
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
def env_field(
    *,
    default=dc.MISSING,
    init=True,
    repr=True,
    hash=None,
    compare=True,
    metadata=None,
    kw_only=dc.MISSING,
    doc="",
):
    """Define a field that pulls config values from the environment.

    Fields with missing defaults will be assumed to be required, and if missing will produce an error.

    :param Any default: the default value to use, if any, of the expected type. If this is omitted, the field will be required.
    :param str doc: a docstring describing the use of the configuration value, used in generating .env files

    """
    return ConfigField(default, init, repr, hash, compare, metadata, kw_only, doc)

convoke.configs.Secret

Bases: str

A string value that should not be revealed in logs, tracebacks, etc.

Source code in src/convoke/configs.py
25
26
27
28
29
30
class Secret(str):
    """A string value that should not be revealed in logs, tracebacks, etc."""

    def __repr__(self) -> str:
        class_name = self.__class__.__name__
        return f"{class_name}('**********')"

convoke.configs.BaseConfig

Base settings common to all configurations

Source code in src/convoke/configs.py
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
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
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
class BaseConfig(metaclass=BaseConfigMeta):
    """Base settings common to all configurations"""

    DEBUG: bool = env_field(default=False, doc="Development mode?")
    TESTING: bool = env_field(default=False, doc="Testing mode?")

    env_field = env_field

    @classmethod
    def from_config(cls: Type[T], config: "BaseConfig") -> T:
        """Derive an instance of this config class from another configuration.

        This is really only useful if the passed configuration has
        overridden (non-environment-derived) values.

        """
        valid_params = set(inspect.signature(cls).parameters)
        kwargs = {k: v for k, v in dc.asdict(config).items() if k in valid_params}
        return cls(**kwargs)

    @classmethod
    def gather_settings(cls) -> dict:
        """Gather settings from all loaded configurations."""
        base = BaseConfig.report_settings()
        base_settings = set(base["settings"].keys())
        all_settings = {f"{BaseConfig.__module__}.{BaseConfig.__name__}": base}
        for config in cls.plugins_by_name.values():
            settings = config.report_settings()
            all_settings[f"{config.__module__}.{config.__name__}"] = {
                "doc": settings["doc"],
                "settings": omit(settings["settings"], base_settings),
            }

        return all_settings

    @classmethod
    def report_settings(cls) -> dict:
        """Prepare a datastructure reporting on this configuration class's settings."""
        return {
            "doc": format_object_docstring(cls),
            "settings": {
                fd.name: {
                    "type": fd.type,
                    "default": (
                        UNDEFINED
                        if (default := getattr(fd, "__config_default__", dc.MISSING)) is dc.MISSING
                        else default
                    ),
                    "doc": getattr(fd, "__doc__", ""),
                }
                for fd in dc.fields(cls)
            },
        }

    def __getitem__(self, name: str) -> str:
        if hasattr(self, name):
            return getattr(self, name)

        return os.environ[name]

    def get(self, name: str, default: Any = UNDEFINED, caster: Union[Type, TUndefined] = UNDEFINED) -> Any:
        """Return the named configuration environment value, optionally casting it as specified.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already the expected type.
        :param Type caster: A type to cast the string value to, if any.
        """
        if caster is UNDEFINED:
            caster = identity
        else:
            caster = get_casting_type(name, caster)
        try:
            value = self[name]
        except KeyError:
            if default is UNDEFINED:
                raise
            else:
                value = default

        return caster(value)

    def asdict(self, keys=()) -> dict:
        """Return a dictionary with the defined settings"""
        if keys:
            return fn.project(dc.asdict(self), keys)
        else:
            return dc.asdict(self)

    def get_tuple(
        self, name: str, default: Union[tuple[Any], TUndefined] = UNDEFINED, caster: Type = tuple[str]
    ) -> tuple[Any]:
        """Return the named configuration environment value as a sequence, optionally casting internal values as specified.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already the expected type.
        :param Type caster: A type to cast the internal string values to, if any.
        """
        return self.get(name, default=default, caster=caster)

    def as_secret(self, name: str, default: Secret = UNDEFINED) -> Secret:
        """Return the named configuration environment value as a Secret string.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already a Secret.
        """
        return self.get(name, default=default, caster=Secret)

    def as_secret_tuple(self, name: str, default: Union[tuple[Secret], TUndefined] = UNDEFINED) -> tuple[Secret]:
        """Return the named configuration environment value as a sequence of Secret strings.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already a tuple of Secrets.
        """
        return self.get_tuple(name, default=default, caster=tuple[Secret])

    def as_bool(self, name: str, default: Union[bool, TUndefined] = UNDEFINED) -> bool:
        """Return the named configuration environment value as a boolean value.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already a boolean.
        """
        return self.get(name, default=default, caster=bool)

    def as_bool_tuple(self, name: str, default: Union[tuple[bool], TUndefined] = UNDEFINED) -> tuple[bool]:
        """Return the named configuration environment value as a tuple of boolean values.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already a tuple of booleans.
        """
        return self.get_tuple(name, default=default, caster=tuple[bool])

    def as_int(self, name: str, default: Union[int, TUndefined] = UNDEFINED) -> int:
        """Return the named configuration environment value as an int.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already an int.
        """
        return self.get(name, default=default, caster=int)

    def as_int_tuple(self, name: str, default: Union[tuple[int], TUndefined] = UNDEFINED) -> tuple[int]:
        """Return the named configuration environment value as a tuple of ints.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already a tuple of ints.
        """
        return self.get_tuple(name, default=default, caster=tuple[int])

    def as_float(self, name: str, default: Union[float, TUndefined] = UNDEFINED) -> float:
        """Return the named configuration environment value as a float.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already a float.
        """
        return self.get(name, default=default, caster=float)

    def as_float_tuple(self, name: str, default: Union[tuple[float], TUndefined] = UNDEFINED) -> tuple[float]:
        """Return the named configuration environment value as a tuple of floats.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already a tuple of floats.
        """
        return self.get_tuple(name, default=default, caster=tuple[float])

    def as_path(self, name: str, default: Union[Path, TUndefined] = UNDEFINED) -> Path:
        """Return the named configuration environment value as a Path.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already a Path.
        """
        return self.get(name, default=default, caster=Path)

    def as_path_tuple(self, name: str, default: Union[tuple[float], TUndefined] = UNDEFINED) -> tuple[Path]:
        """Return the named configuration environment value as a tuple of Paths.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already a tuple of Paths.
        """
        return self.get(name, default=default, caster=tuple[Path])

    def as_package_import(self, name: str, default: Union[Any, TUndefined] = UNDEFINED) -> Any:
        """Return the named configuration environment value as an imported module.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already a module.
        """
        path = self.get(name, default=default)
        return importlib.import_module(path)

    def as_package_import_tuple(self, name: str, default: Union[tuple[Any], TUndefined] = UNDEFINED) -> tuple[Any]:
        """Return the named configuration environment value as a tuple of imported modules.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already a tuple of modules.
        """
        paths = self.get_tuple(name, default=default)
        return tuple(importlib.import_module(path) for path in paths)

    def as_object_import(self, name: str, default: Union[Any, TUndefined] = UNDEFINED) -> Any:
        """Return the named configuration environment value as an imported object.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already an object.
        """
        path = self.get(name, default=default)
        return import_object(path)

    def as_object_import_tuple(self, name: str, default: Union[tuple[Any], TUndefined] = UNDEFINED):
        """Return the named configuration environment value as a tuple of imported objects.

        :param str name: The name of the configuration value, as defined on this object or in the environment.
        :param Any default: A default value, already a tuple of objects.
        """
        paths = self.get_tuple(name, default=default)
        return tuple(import_object(path) for path in paths)

as_bool(name, default=UNDEFINED)

Return the named configuration environment value as a boolean value.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already a boolean.

UNDEFINED
Source code in src/convoke/configs.py
361
362
363
364
365
366
367
def as_bool(self, name: str, default: Union[bool, TUndefined] = UNDEFINED) -> bool:
    """Return the named configuration environment value as a boolean value.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already a boolean.
    """
    return self.get(name, default=default, caster=bool)

as_bool_tuple(name, default=UNDEFINED)

Return the named configuration environment value as a tuple of boolean values.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already a tuple of booleans.

UNDEFINED
Source code in src/convoke/configs.py
369
370
371
372
373
374
375
def as_bool_tuple(self, name: str, default: Union[tuple[bool], TUndefined] = UNDEFINED) -> tuple[bool]:
    """Return the named configuration environment value as a tuple of boolean values.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already a tuple of booleans.
    """
    return self.get_tuple(name, default=default, caster=tuple[bool])

as_float(name, default=UNDEFINED)

Return the named configuration environment value as a float.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already a float.

UNDEFINED
Source code in src/convoke/configs.py
393
394
395
396
397
398
399
def as_float(self, name: str, default: Union[float, TUndefined] = UNDEFINED) -> float:
    """Return the named configuration environment value as a float.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already a float.
    """
    return self.get(name, default=default, caster=float)

as_float_tuple(name, default=UNDEFINED)

Return the named configuration environment value as a tuple of floats.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already a tuple of floats.

UNDEFINED
Source code in src/convoke/configs.py
401
402
403
404
405
406
407
def as_float_tuple(self, name: str, default: Union[tuple[float], TUndefined] = UNDEFINED) -> tuple[float]:
    """Return the named configuration environment value as a tuple of floats.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already a tuple of floats.
    """
    return self.get_tuple(name, default=default, caster=tuple[float])

as_int(name, default=UNDEFINED)

Return the named configuration environment value as an int.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already an int.

UNDEFINED
Source code in src/convoke/configs.py
377
378
379
380
381
382
383
def as_int(self, name: str, default: Union[int, TUndefined] = UNDEFINED) -> int:
    """Return the named configuration environment value as an int.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already an int.
    """
    return self.get(name, default=default, caster=int)

as_int_tuple(name, default=UNDEFINED)

Return the named configuration environment value as a tuple of ints.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already a tuple of ints.

UNDEFINED
Source code in src/convoke/configs.py
385
386
387
388
389
390
391
def as_int_tuple(self, name: str, default: Union[tuple[int], TUndefined] = UNDEFINED) -> tuple[int]:
    """Return the named configuration environment value as a tuple of ints.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already a tuple of ints.
    """
    return self.get_tuple(name, default=default, caster=tuple[int])

as_object_import(name, default=UNDEFINED)

Return the named configuration environment value as an imported object.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already an object.

UNDEFINED
Source code in src/convoke/configs.py
443
444
445
446
447
448
449
450
def as_object_import(self, name: str, default: Union[Any, TUndefined] = UNDEFINED) -> Any:
    """Return the named configuration environment value as an imported object.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already an object.
    """
    path = self.get(name, default=default)
    return import_object(path)

as_object_import_tuple(name, default=UNDEFINED)

Return the named configuration environment value as a tuple of imported objects.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already a tuple of objects.

UNDEFINED
Source code in src/convoke/configs.py
452
453
454
455
456
457
458
459
def as_object_import_tuple(self, name: str, default: Union[tuple[Any], TUndefined] = UNDEFINED):
    """Return the named configuration environment value as a tuple of imported objects.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already a tuple of objects.
    """
    paths = self.get_tuple(name, default=default)
    return tuple(import_object(path) for path in paths)

as_package_import(name, default=UNDEFINED)

Return the named configuration environment value as an imported module.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already a module.

UNDEFINED
Source code in src/convoke/configs.py
425
426
427
428
429
430
431
432
def as_package_import(self, name: str, default: Union[Any, TUndefined] = UNDEFINED) -> Any:
    """Return the named configuration environment value as an imported module.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already a module.
    """
    path = self.get(name, default=default)
    return importlib.import_module(path)

as_package_import_tuple(name, default=UNDEFINED)

Return the named configuration environment value as a tuple of imported modules.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already a tuple of modules.

UNDEFINED
Source code in src/convoke/configs.py
434
435
436
437
438
439
440
441
def as_package_import_tuple(self, name: str, default: Union[tuple[Any], TUndefined] = UNDEFINED) -> tuple[Any]:
    """Return the named configuration environment value as a tuple of imported modules.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already a tuple of modules.
    """
    paths = self.get_tuple(name, default=default)
    return tuple(importlib.import_module(path) for path in paths)

as_path(name, default=UNDEFINED)

Return the named configuration environment value as a Path.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already a Path.

UNDEFINED
Source code in src/convoke/configs.py
409
410
411
412
413
414
415
def as_path(self, name: str, default: Union[Path, TUndefined] = UNDEFINED) -> Path:
    """Return the named configuration environment value as a Path.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already a Path.
    """
    return self.get(name, default=default, caster=Path)

as_path_tuple(name, default=UNDEFINED)

Return the named configuration environment value as a tuple of Paths.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already a tuple of Paths.

UNDEFINED
Source code in src/convoke/configs.py
417
418
419
420
421
422
423
def as_path_tuple(self, name: str, default: Union[tuple[float], TUndefined] = UNDEFINED) -> tuple[Path]:
    """Return the named configuration environment value as a tuple of Paths.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already a tuple of Paths.
    """
    return self.get(name, default=default, caster=tuple[Path])

as_secret(name, default=UNDEFINED)

Return the named configuration environment value as a Secret string.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already a Secret.

UNDEFINED
Source code in src/convoke/configs.py
345
346
347
348
349
350
351
def as_secret(self, name: str, default: Secret = UNDEFINED) -> Secret:
    """Return the named configuration environment value as a Secret string.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already a Secret.
    """
    return self.get(name, default=default, caster=Secret)

as_secret_tuple(name, default=UNDEFINED)

Return the named configuration environment value as a sequence of Secret strings.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already a tuple of Secrets.

UNDEFINED
Source code in src/convoke/configs.py
353
354
355
356
357
358
359
def as_secret_tuple(self, name: str, default: Union[tuple[Secret], TUndefined] = UNDEFINED) -> tuple[Secret]:
    """Return the named configuration environment value as a sequence of Secret strings.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already a tuple of Secrets.
    """
    return self.get_tuple(name, default=default, caster=tuple[Secret])

asdict(keys=())

Return a dictionary with the defined settings

Source code in src/convoke/configs.py
327
328
329
330
331
332
def asdict(self, keys=()) -> dict:
    """Return a dictionary with the defined settings"""
    if keys:
        return fn.project(dc.asdict(self), keys)
    else:
        return dc.asdict(self)

from_config(config) classmethod

Derive an instance of this config class from another configuration.

This is really only useful if the passed configuration has overridden (non-environment-derived) values.

Source code in src/convoke/configs.py
254
255
256
257
258
259
260
261
262
263
264
@classmethod
def from_config(cls: Type[T], config: "BaseConfig") -> T:
    """Derive an instance of this config class from another configuration.

    This is really only useful if the passed configuration has
    overridden (non-environment-derived) values.

    """
    valid_params = set(inspect.signature(cls).parameters)
    kwargs = {k: v for k, v in dc.asdict(config).items() if k in valid_params}
    return cls(**kwargs)

gather_settings() classmethod

Gather settings from all loaded configurations.

Source code in src/convoke/configs.py
266
267
268
269
270
271
272
273
274
275
276
277
278
279
@classmethod
def gather_settings(cls) -> dict:
    """Gather settings from all loaded configurations."""
    base = BaseConfig.report_settings()
    base_settings = set(base["settings"].keys())
    all_settings = {f"{BaseConfig.__module__}.{BaseConfig.__name__}": base}
    for config in cls.plugins_by_name.values():
        settings = config.report_settings()
        all_settings[f"{config.__module__}.{config.__name__}"] = {
            "doc": settings["doc"],
            "settings": omit(settings["settings"], base_settings),
        }

    return all_settings

get(name, default=UNDEFINED, caster=UNDEFINED)

Return the named configuration environment value, optionally casting it as specified.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already the expected type.

UNDEFINED
caster Type

A type to cast the string value to, if any.

UNDEFINED
Source code in src/convoke/configs.py
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
def get(self, name: str, default: Any = UNDEFINED, caster: Union[Type, TUndefined] = UNDEFINED) -> Any:
    """Return the named configuration environment value, optionally casting it as specified.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already the expected type.
    :param Type caster: A type to cast the string value to, if any.
    """
    if caster is UNDEFINED:
        caster = identity
    else:
        caster = get_casting_type(name, caster)
    try:
        value = self[name]
    except KeyError:
        if default is UNDEFINED:
            raise
        else:
            value = default

    return caster(value)

get_tuple(name, default=UNDEFINED, caster=tuple[str])

Return the named configuration environment value as a sequence, optionally casting internal values as specified.

Parameters:

Name Type Description Default
name str

The name of the configuration value, as defined on this object or in the environment.

required
default Any

A default value, already the expected type.

UNDEFINED
caster Type

A type to cast the internal string values to, if any.

tuple[str]
Source code in src/convoke/configs.py
334
335
336
337
338
339
340
341
342
343
def get_tuple(
    self, name: str, default: Union[tuple[Any], TUndefined] = UNDEFINED, caster: Type = tuple[str]
) -> tuple[Any]:
    """Return the named configuration environment value as a sequence, optionally casting internal values as specified.

    :param str name: The name of the configuration value, as defined on this object or in the environment.
    :param Any default: A default value, already the expected type.
    :param Type caster: A type to cast the internal string values to, if any.
    """
    return self.get(name, default=default, caster=caster)

report_settings() classmethod

Prepare a datastructure reporting on this configuration class's settings.

Source code in src/convoke/configs.py
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
@classmethod
def report_settings(cls) -> dict:
    """Prepare a datastructure reporting on this configuration class's settings."""
    return {
        "doc": format_object_docstring(cls),
        "settings": {
            fd.name: {
                "type": fd.type,
                "default": (
                    UNDEFINED
                    if (default := getattr(fd, "__config_default__", dc.MISSING)) is dc.MISSING
                    else default
                ),
                "doc": getattr(fd, "__doc__", ""),
            }
            for fd in dc.fields(cls)
        },
    }