Skip to content

Commit

Permalink
Avoid squashing config settings with downstream defaults
Browse files Browse the repository at this point in the history
  • Loading branch information
khaeru committed Jul 27, 2022
1 parent 5c289c6 commit 8f6ae3b
Showing 1 changed file with 17 additions and 14 deletions.
31 changes: 17 additions & 14 deletions ixmp/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,25 +82,24 @@ def __getitem__(self, name):
def __setitem__(self, name, value):
setattr(self, name.replace(" ", "_"), value)

def add_field(self, name, type_, default=None):
def add_field(self, name, type_, default, **kwargs):
# Check `name`
name = name.replace(" ", "_")
if name in self.__dataclass_fields__:
if (
name in self.__dataclass_fields__
and "auto" not in self.__dataclass_fields__[name].metadata
):
raise ValueError(f"configuration key {repr(name)} already defined")

# Create a new data class with an additional field
new_cls = make_dataclass(
"Values", [(name, type_, field(default=default))], bases=(self.__class__,)
"Values",
[(name, type_, field(default=default, **kwargs))],
bases=(self.__class__,),
)

# Re-use current values and any defaults for the new fields
data = asdict(self)
try:
data[name] = getattr(self, name)
except AttributeError:
pass

return new_cls, new_cls(**data)
return new_cls, new_cls(**asdict(self))

def delete_field(self, name):
# Check `name`
Expand Down Expand Up @@ -249,9 +248,11 @@ def read(self):
# Parse JSON and set values
for key, value in data.items():
try:
self.set(key, value, _strict=True) # Cast type for registered keys
self.set(key, value) # Cast type for registered keys
except KeyError:
self.set(key, value, _strict=False) # Tolerate unregistered keys
# Automatically register new values
self.register(key, type(value), default=None, metadata=dict(auto=True))
self.set(key, value)

# Public methods

Expand All @@ -263,7 +264,7 @@ def keys(self) -> Tuple[str, ...]:
"""Return the names of all registered configuration keys."""
return self.values.keys()

def register(self, name: str, type_: type, default: Any = None):
def register(self, name: str, type_: type, default: Any = None, **kwargs):
"""Register a new configuration key.
Parameters
Expand All @@ -281,7 +282,9 @@ def register(self, name: str, type_: type, default: Any = None):
ValueError
if the key `name` is already registered.
"""
self._ValuesClass, self.values = self.values.add_field(name, type_, default)
self._ValuesClass, self.values = self.values.add_field(
name, type_, default, **kwargs
)

def unregister(self, name: str) -> None:
"""Unregister and clear the configuration key `name`."""
Expand Down

0 comments on commit 8f6ae3b

Please sign in to comment.