Skip to content

Commit

Permalink
cleaned up pathdict.py
Browse files Browse the repository at this point in the history
  • Loading branch information
nfearnley committed May 21, 2024
1 parent 4233ee1 commit 6b07f3b
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 19 deletions.
21 changes: 11 additions & 10 deletions sizebot/conf.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from __future__ import annotations
from typing import Any
from collections.abc import Callable

import toml

from sizebot.lib import paths
from sizebot.lib.attrdict import AttrDict
from sizebot.lib.pathdict import PathDict
from sizebot.lib.pathdict import get_by_path, set_by_path


SENTINEL = object()
Expand All @@ -20,7 +21,7 @@ def __init__(self,
var: str,
path: str,
*,
type: callable[[Any], Any] = lambda v: v,
type: Callable[[Any], Any] = lambda v: v,
default: Any = SENTINEL,
initdefault: Any = SENTINEL):
self.var = var
Expand All @@ -29,20 +30,20 @@ def __init__(self,
self.initdefault = initdefault
self.type = type

def load(self, config: Config, configDict: PathDict):
def load(self, config: Config, configDict: dict):
if self.default is not SENTINEL:
val = configDict.get(self.path, SENTINEL)
val = get_by_path(configDict, self.path, SENTINEL)
if val is SENTINEL:
val = self.default
else:
val = self.type(val)
config[self.var] = val
else:
config[self.var] = self.type(configDict[self.path])
config[self.var] = get_by_path(configDict, self.path)

def init(self, configDict: PathDict):
def init(self, configDict: dict):
if self.initdefault is not SENTINEL:
configDict[self.path] = self.initdefault
set_by_path(configDict, self.path, self.initdefault)


class Config(AttrDict):
Expand All @@ -54,7 +55,7 @@ def __init__(self, fields: list[ConfigField]):

def load(self):
try:
configDict = PathDict(toml.load(paths.confpath))
configDict = toml.load(paths.confpath)
except FileNotFoundError as e:
raise ConfigError(f"Configuration file not found: {e.filename}")

Expand All @@ -69,11 +70,11 @@ def init(self):
raise FileExistsError(f"Configuration file already exists: {paths.confpath}")
paths.confpath.parent.mkdir(parents=True, exist_ok=True)

configDict = PathDict()
configDict = {}
for f in self._fields:
f.init(configDict)
with open(paths.confpath, "w") as f:
toml.dump(configDict.toDict(), f)
toml.dump(configDict, f)


conf = Config([
Expand Down
30 changes: 21 additions & 9 deletions sizebot/lib/pathdict.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class BadPathException(Exception):
pass


def parse_component(component: str) -> int | str:
def _parse_component(component: str) -> int | str:
index_match = RE_INDEX.match(component)
if index_match:
return int(index_match[1])
Expand All @@ -22,8 +22,7 @@ def parse_component(component: str) -> int | str:
raise BadPathException


# TODO: CamelCase
def buildPath(components: list[int | str]) -> str:
def _build_path(components: list[int | str]) -> str:
path = ""
for c in components:
if isinstance(c, int):
Expand All @@ -37,10 +36,9 @@ def buildPath(components: list[int | str]) -> str:
return path


# TODO: CamelCase
def parsePath(path: str) -> list[int | str]:
components = [parse_component(c) for c in RE_COMPONENT.findall(path)]
if path != buildPath(components):
def _parse_path(path: str) -> list[int | str]:
components = [_parse_component(c) for c in RE_COMPONENT.findall(path)]
if path != _build_path(components):
raise BadPathException
return components

Expand All @@ -53,7 +51,7 @@ def __getitem__(self, path: str) -> Any:
"""value = PathDict[path]"""
branch = self._values
try:
components = parsePath(path)
components = _parse_path(path)
except BadPathException:
raise BadPathException(f"Bad Path: {path}")

Expand All @@ -70,7 +68,7 @@ def __getitem__(self, path: str) -> Any:
def __setitem__(self, path: str, value: Any):
"""PathDict[path] = value"""
branch = self._values
components = parsePath(path)
components = _parse_path(path)
last = components.pop()

for c in components:
Expand All @@ -97,3 +95,17 @@ def __str__(self) -> str:

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


SENTINEL = object()


def get_by_path(data: dict, path: str, default: Any = SENTINEL) -> Any:
if default is SENTINEL:
return PathDict(data)[path]
else:
return PathDict(data).get(path, default)


def set_by_path(data: dict, path: str, value: Any):
PathDict(data)[path] = value

0 comments on commit 6b07f3b

Please sign in to comment.