Anyconfig First Look
python-anyconfig is a MIT licensed python library provides common APIs to load and dump configuration files in various formats with some useful features such as contents merge, templates, query, schema validation and generation support.
This notebook demonstrates some features of anyconfig
for loading and dumping data. We raise a comparsion to traitlets.config
at the end where a backend for python config files is created.
import anyconfig, pydantic, munch, json, toolz
anyconfig
can load to multiple formats.
config = anyconfig.loads("""a: 10""", ac_parser='yaml')
config.update(anyconfig.loads("""{"b": 10}""", ac_parser='json'))
anyconfig.loads("""a.q=10""", ac_parser='toml')
{'a': {'q': 10}}
anyconfig
allows jinja2
templates.
anyconfig.loads("a: \n", ac_parser='yaml', ac_template=True)
{'a': 'aaa'}
anyconfig.loads("a: \n", ac_parser='yaml', ac_template=True, ac_context={'a': 3})
{'a': 3}
anyconfig
can dump to multiple formats.
print(anyconfig.dumps(config, 'json'))
{"a": 10, "b": 10}
print(anyconfig.dumps(config, 'yaml'))
a: 10
b: 10
anyconfig
provides jsonschema
validation. We’ll use pydantic
to generate schema.
class Schema(pydantic.BaseModel): a: int; b: int
valid, _ = anyconfig.validate(config, Schema.schema())
assert Schema and valid
class BadSchema(pydantic.BaseModel): a: int; b: str
valid, errors = anyconfig.validate(config, BadSchema.schema())
assert not valid
print(errors)
10 is not of type 'string'
Failed validating 'type' in schema['properties']['b']:
{'title': 'B', 'type': 'string'}
On instance['b']:
10
In traitlets
we could load configurations from python files. Below we add similar functionality to anyconfig
for a python backend.
def load(object, **c):
if hasattr(object, 'read'): object = object.read()
c['c'] = c.get('c', munch.Munch())
return exec(object, c, c) or c['c']
class Python(anyconfig.backend.base.StringStreamFnParser):
_cid = "python"
_type = "python"
_extensions = ["python"]
_ordered = True
_load_opts = _dump_opts = _dict_opts = ["_dict"]
_load_from_string_fn = anyconfig.backend.base.to_method(load)
_load_from_stream_fn = anyconfig.backend.base.to_method(load)
_dump_to_string_fn = anyconfig.backend.base.to_method(toolz.compose('c = '.__add__, json.dumps))
_dump_to_stream_fn = anyconfig.backend.base.to_method(json.dump)
Loading a python config.
data = anyconfig.loads("""c.a = list(range(10))""", ac_parser=Python); data
{'a': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
Writing a python config.
anyconfig.dumps(data, ac_parser=Python)
'c = {"a": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}'