cmdkit.namespace#



Reference#


class Namespace(*args: Iterable | Mapping, **kwargs: Any)[source]#

Bases: NSCoreMixin

A dictionary with depth-first updates and factory methods.

Example:
>>> ns = Namespace({'a': {'x': 1, 'y': 2}, 'b': 3})
>>> ns.update({'a': {'x': 4, 'z': 5}})
>>> ns
Namespace({'a': {'x': 4, 'y': 2, 'z': 5}, 'b': 3})
>>> ns.to_local('config.toml')
>>> Namespace.from_local('config.toml', ignore_if_missing=True)
Namespace({'a': {'x': 4, 'y': 2, 'z': 5}, 'b': 3})

update(*args, **kwargs) None#

Depth-first update method.


classmethod from_local(filepath: str, ignore_if_missing: bool = False, ftype: str | None = None, **options) Namespace[source]#

Load from a local file.

If filepath does not exist an exception is raised as expected, unless ignore_if_missing is True and an empty Namespace is returned instead.

Supported formats currently include yaml, toml, and json. For yaml support include “yaml” extra (adds pyyaml dependency). For toml support include “toml” extra when Python < 3.11 (adds tomli dependency).

Example:
>>> Namespace.from_local('config.toml', ignore_if_missing=True)
Namespace({})
>>> Namespace({'a': {'x': 1, 'y': 2}, 'b': 3}).to_local('config.toml')
>>> Namespace.from_local('config.toml')
Namespace({'a': {'x': 1, 'y': 2}, 'b': 3})
>>> Namespace.from_local('config', ftype='toml', ignore_if_missing=True)
Namespace({})
to_local(filepath: str, ftype: str | None = None, **options) None[source]#

Output to local file. If ftype not set, format based on file extension.


classmethod from_yaml(path_or_file: str | IO, **options) Namespace[source]#

Load a namespace from a YAML file.

classmethod from_toml(path_or_file: str | IO, **options) Namespace[source]#

Load a namespace from a TOML file.

classmethod from_json(path_or_file: str | IO, **options) Namespace[source]#

Load a namespace from a JSON file.


to_yaml(path_or_file: str | IO, encoding: str = 'utf-8', **kwargs) None[source]#

Output to YAML file.

to_toml(path_or_file: str | IO, encoding: str = 'utf-8', **kwargs) None[source]#

Output to TOML file.

to_json(path_or_file: str | IO, encoding: str = 'utf-8', indent: int = 4, **kwargs) None[source]#

Output to JSON file.


classmethod from_env(prefix: str | None = None, defaults: Dict[str, Any] | None = None) Environ[source]#

Create a Namespace from os.environ, optionally filtering variables based on their name using prefix.

Args:
prefix (str):

An optional prefix to filter the environment variables. The results will be any variable that starts with this prefix.

defaults (dict):

An existing Namespace of defaults to be overriden if present in the environment.

Example:
>>> Namespace.from_env(prefix='MYAPP', defaults={'MYAPP_LOGGING_LEVEL': 'WARNING', })
Environ({'MYAPP_LOGGING_LEVEL': 'WARNING', 'MYAPP_COUNT': '42'})
See Also:

Environ: adds expand() method

to_env() Environ[source]#

Translate namespace to an Environ namespace.


duplicates() Dict[str, List[Tuple[str, ...]]][source]#

Find all the repeated leaves.

Example:
>>> ns = Namespace({'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'z': 4}})
>>> ns
Namespace({'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'z': 4}})
>>> ns.duplicates()
{'x': [('a',), ('b',)]}

whereis(leaf: str, value: ~typing.Callable[[~cmdkit.namespace.T], bool] | ~cmdkit.namespace.T = <function Namespace.<lambda>>) List[Tuple[str, ...]][source]#

Find paths to leaf, optionally filtered on value.

Example:
>>> ns = Namespace({'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'z': 4}})
>>> ns
Namespace({'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'z': 4}})
>>> ns.whereis('x')
[('a',), ('b',)]
>>> ns.whereis('x', 1)
[('a',)]
>>> ns.whereis('x', lambda v: v % 3 == 0)
[('b',)]

class Environ(prefix: str | None = None, defaults: dict | None = None)[source]#

Bases: NSCoreMixin

A Namespace initialized via from_env(). The special method expand() melts the normalized variables by splitting on underscores into a full heirarchy.

Example:
>>> env = Namespace.from_env('MYAPP')
>>> env
Environ({'MYAPP_A_X': '1', 'MYAPP_A_Y': '2', 'MYAPP_B': '3'})
>>> env.expand()
Environ({'a': {'x': 1, 'y': 2}, 'b': 3})

expand(converter: Callable[[str], Any] | None = None) Environ[source]#

De-normalize the key-value pairs into a nested dictionary. The prefix is stripped away and structure is derived by splitting on underscores.

The converter should be a function that accepts an input value and returns a new value appropriately coerced. The default converter attempts first to coerce a value to an integer if possible, then a float, except the following special values. Otherwise, the string remains.

Input Value

Output Value

'', 'null'

None

'true' / 'false'

True / False

flatten(prefix: str | None = None) Environ[source]#

Collapse a namespace down to a single level by merging keys with their parent section by underscore.

Example:
>>> env = Namespace.from_env('MYAPP')
>>> env
Environ({'MYAPP_A_X': '1', 'MYAPP_A_Y': '2', 'MYAPP_B': '3'})
>>> env.expand()
Environ({'a': {'x': 1, 'y': 2}, 'b': 3})
>>> env.expand().flatten(prefix='MYAPP')
Environ({'MYAPP_A_X': '1', 'MYAPP_A_Y': '2', 'MYAPP_B': '3'})

export(prefix: str | None = None) None[source]#

Calls flatten() before persisting members to os.environ.