Skip to content

Commit

Permalink
Merge pull request #1 from amorison/dtc
Browse files Browse the repository at this point in the history
Rewrite API to allow definition of configuration via dataclasses

The new API allows users to define their configuration with dataclasses
instead of a dictionary. The definition is cleaner and this makes static
type checking possible where configuration values are read/written.
Additionally, the from_str/to_str mechanism introduced in this PR
makes the parsing and dumping of arbitrary-typed values much more
robust and flexible.
  • Loading branch information
amorison committed Apr 28, 2022
2 parents 6471bc1 + dc02513 commit d9efe83
Show file tree
Hide file tree
Showing 22 changed files with 713 additions and 907 deletions.
2 changes: 1 addition & 1 deletion LICENSE
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2018-2021 Adrien Morison
Copyright (c) 2018-2022 Adrien Morison

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Expand Up @@ -40,7 +40,7 @@

# -- Project information -----------------------------------------------------
project = 'loam'
copyright = '2018 - 2021, Adrien Morison'
copyright = '2018 - 2022, Adrien Morison'
author = 'Adrien Morison'

# The full version, including alpha/beta/rc tags.
Expand Down
3 changes: 2 additions & 1 deletion docs/index.rst
Expand Up @@ -16,8 +16,9 @@ Welcome to loam's documentation!
:maxdepth: 2
:caption: API Reference

sources/api/manager
sources/api/base
sources/api/cli
sources/api/parsers
sources/api/tools
sources/api/error

5 changes: 5 additions & 0 deletions docs/sources/api/base.rst
@@ -0,0 +1,5 @@
base
====

.. automodule:: loam.base
:members:
5 changes: 0 additions & 5 deletions docs/sources/api/manager.rst

This file was deleted.

5 changes: 5 additions & 0 deletions docs/sources/api/parsers.rst
@@ -0,0 +1,5 @@
parsers
=======

.. automodule:: loam.parsers
:members:
61 changes: 30 additions & 31 deletions docs/sources/firststeps.rst
Expand Up @@ -17,34 +17,33 @@ configuration object with no config file nor argument parsing management.

::

from loam.manager import ConfigurationManager, ConfOpt

# A simple dictionary define all the options and their default values.
# The first level of keys are the section names, the second level of keys
# are the option names. Note that you can have the same option name living
# in two different sections.
conf_def = {
'sectionA': {'optionA': ConfOpt('foo'),
'optionB': ConfOpt(42),
'optionC': ConfOpt('bar')},
'sectionB': {'optionD': ConfOpt(None),
'optionA': ConfOpt(3.14156)}
}

conf = ConfigurationManager.from_dict_(conf_def)

# you can access options value with attribute or item notation
assert conf.sectionA.optionA is conf.sectionA['optionA']
assert conf.sectionA is conf['sectionA']

# you can set values (with attribute or item notation)
conf.sectionA.optionA = 'baz'
# and then reset it to its default value
del conf.sectionA.optionA
assert conf.sectionA.optionA == 'foo'
# you can also reset entire sections at once
del conf.sectionA
# or even all configuration options (note that all methods of
# ConfigurationManager have a postfixed _ to minimize the risk of collision
# with your section or option names).
conf.reset_()
from dataclasses import dataclass
from typing import Optional

from loam.base import entry, Section, ConfigBase

# Dataclasses define the options and their default values.
@dataclass
class SectionA(Section):
option_a: str = "foo"
option_b: int = 42
option_c: str = "bar"

# You can attach metadata to each option, such as an explanation
@dataclass
class SectionB(Section):
option_d: int = entry(val=0, doc="some number")
# you can have the same option name living in two different sections
option_a: float = entry(val=3.14159, doc="some float")

# A ConfigBase dataclass groups the sections
@dataclass
class Config(ConfigBase):
section_a: SectionA
section_b: SectionB

conf = Config.default_()

# You can access options value and modify them
assert conf.section_a.option_a == "foo"
conf.section_b.option_d = 3
13 changes: 6 additions & 7 deletions loam/_internal.py
Expand Up @@ -10,7 +10,7 @@
if typing.TYPE_CHECKING:
from typing import Dict, Any, Tuple, Mapping, Optional, Type
from argparse import ArgumentParser, Namespace
from .manager import Section
from .base import Section


class Switch(argparse.Action):
Expand Down Expand Up @@ -46,14 +46,13 @@ def __init__(self, section: Section, options: Mapping[str, Any]):
self._old_values: Dict[str, Any] = {}

def __enter__(self) -> None:
self._old_values = {}
for option_name, new_value in self._options.items():
self._old_values[option_name] = self._section[option_name]
self._section[option_name] = new_value
self._old_values = {
opt: getattr(self._section, opt) for opt in self._options
}
self._section.update_from_dict_(self._options)

def __exit__(self, e_type: Optional[Type[BaseException]], *_: Any) -> bool:
for option_name, old_value in self._old_values.items():
self._section[option_name] = old_value
self._section.update_from_dict_(self._old_values)
return e_type is None


Expand Down

0 comments on commit d9efe83

Please sign in to comment.