Skip to content

Commit

Permalink
various updates
Browse files Browse the repository at this point in the history
  • Loading branch information
mih committed Sep 25, 2024
1 parent f37cf4d commit be353c7
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 61 deletions.
10 changes: 1 addition & 9 deletions datasalad/settings/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@

import logging

from datasalad.settings.setting import (
DynamicSetting,
Setting,
)
from datasalad.settings.setting import Setting
from datasalad.settings.source import InMemorySettings

lgr = logging.getLogger('datasalad.settings')
Expand All @@ -18,11 +15,6 @@ class Defaults(InMemorySettings):
only one instance of this class, and it is then the true source of the
information by itself.
"""

def __getitem__(self, key: str) -> Setting:
item = super().__getitem__(key)
return item.eval() if isinstance(item, DynamicSetting) else item

def __setitem__(self, key: str, value: Setting) -> None:
if key in self:
# resetting is something that is an unusual event.
Expand Down
61 changes: 25 additions & 36 deletions datasalad/settings/setting.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,56 +16,45 @@ def __init__(
value: Any | UnsetValue = UnsetValue,
*,
coercer: Callable | None = None,
lazy: bool = False,
):
self._value = value
self._coercer = coercer
self._lazy = lazy

@property
def value(self) -> Any:
val = self._value() if self._lazy else self._value
if self._coercer:
return self._coercer(self._value)
return self._value
return self._coercer(val)
return val

@property
def coercer(self) -> Callable | None:
return self._coercer

@property
def is_lazy(self) -> bool:
return self._lazy

def update(self, item: Setting) -> None:
for attr, unset in (
('_value', UnsetValue),
('_coercer', None),
):
val = getattr(item, attr, unset)
if val is unset:
continue
setattr(self, attr, val)
if item._value is not UnsetValue:
self._value = item._value
# we also need to syncronize the lazy eval flag
# so we can do the right thing (TM) with the
# new value
self._lazy = item._lazy

if item._coercer:
self._coercer = item._coercer

def __str__(self) -> str:
return str(self.value)
# wrap the value in the classname to make clear that
# the actual object type is different from the value
return f'{self.__class__.__name__}({self.value})'

def __repr__(self) -> str:
return repr(self.value)


class DynamicSetting(Setting):
def __init__(
self,
value: Callable,
*,
coercer: Callable | None = None,
):
super().__init__(
value=value,
coercer=coercer,
)

@property
def value(self) -> Any:
return self.eval().value

def eval(self) -> Setting:
return Setting(
# do the dynamic evaluation
self._value(),
coercer=self.coercer,
)
# wrap the value in the classname to make clear that
# the actual object type is different from the value
# TODO: report other props
return f'{self.__class__.__name__}({self.value!r})'
20 changes: 15 additions & 5 deletions datasalad/settings/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

from itertools import chain
from types import MappingProxyType
from typing import TYPE_CHECKING
from typing import (
TYPE_CHECKING,
Any,
)

from datasalad.settings.setting import Setting

if TYPE_CHECKING: # pragma: nocover
from datasalad.setttings import (
Setting,
Source,
)
from datasalad.setttings import Source


class Settings:
Expand Down Expand Up @@ -75,3 +77,11 @@ def __contains__(self, key):

def keys(self) -> set[str]:
return set(chain.from_iterable(s.keys() for s in self._sources.values()))

def get(self, key: str, default: Any = None) -> Setting:
try:
return self[key]
except KeyError:
if isinstance(default, Setting):
return default
return Setting(value=default)
6 changes: 3 additions & 3 deletions datasalad/settings/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def __setitem__(self, key: str, value: Setting) -> None:
""" """

@abstractmethod
def get(self, key, default: Any = None) -> Setting:
def get(self, key: str, default: Any = None) -> Setting:
""" """

@abstractmethod
Expand Down Expand Up @@ -132,10 +132,10 @@ def get(self, key, default: Any = None) -> Setting:
return Setting(value=default)

def __repr__(self) -> str:
return self._items.__repr__()
return f'{self.__class__.__name__}({self._items})'

def __str__(self) -> str:
return f'CachedSettings({self._items})'
return f'{self.__class__.__name__}({self._items!r})'


class InMemorySettings(CachingSource):
Expand Down
10 changes: 3 additions & 7 deletions datasalad/settings/tests/test_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
from os.path import dirname

from ..defaults import Defaults
from ..setting import (
DynamicSetting,
Setting,
)
from ..setting import Setting


def test_defaultsrc(caplog):
Expand Down Expand Up @@ -44,14 +41,13 @@ def test_defaultsrc(caplog):
def test_defaultsrc_dynamic():
d = Defaults()
target_key = 'some.key'
dynset = DynamicSetting(
dynset = Setting(
lambda: sys.executable,
coercer=dirname,
lazy=True,
)
assert dynset.value == dirname(sys.executable)

d[target_key] = dynset
item = d[target_key]
assert isinstance(item, Setting)
assert not isinstance(item, DynamicSetting)
assert item.value == dirname(sys.executable)
12 changes: 12 additions & 0 deletions datasalad/settings/tests/test_settings.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest
import sys

from ..defaults import Defaults
from ..setting import Setting
Expand Down Expand Up @@ -32,3 +33,14 @@ def test_settings():
item = man[target_key]
assert item.value == coerced_target
assert item.coercer == float

assert man.get('idonotexist').value is None
assert man.get(
'idonotexist',
# makes little actual sense, but exercises a lazy
# default setting
Setting(
lambda: sys.executable,
lazy=True,
)
).value is sys.executable
2 changes: 1 addition & 1 deletion datasalad/settings/tests/test_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ def test_inmemorysrc():
def test_cachingsource():
ds = DummyCachingSource()
ds['mike'] = Setting('one')
assert str(ds) == "CachedSettings({'mike': 'one'})"
assert str(ds) == "DummyCachingSource({'mike': Setting('one')})"

0 comments on commit be353c7

Please sign in to comment.