Skip to content

Commit

Permalink
Code changes to make MyPy happier and include some more sanity checks
Browse files Browse the repository at this point in the history
  • Loading branch information
LobaDK committed Aug 19, 2024
1 parent d4b0c63 commit d3dd516
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 22 deletions.
13 changes: 6 additions & 7 deletions settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
Generic,
TypeVar,
)
from types import MappingProxyType
from json import load, dump
from configparser import ConfigParser
from atexit import register
Expand Down Expand Up @@ -61,10 +60,10 @@ def __init__(
self._settings: T
self._default_settings: T = deepcopy(x=default_settings)

self._safe_load: Optional[Callable[[IO], Dict[str, Any]]] = None
self._safe_dump: Optional[Callable[[Dict[str, Any], IO], None]] = None
self._toml_load: Optional[Callable[[IO], Dict[str, Any]]] = None
self._toml_dump: Optional[Callable[[Dict[str, Any], IO], None]] = None
self._safe_load = None
self._safe_dump = None
self._toml_load = None
self._toml_dump = None

logger.debug(
msg=f"\n=========== Initializing SettingsManager ===========\nSystem info: {system()} {version()} {architecture()[0]} Python {python_version()}\n"
Expand Down Expand Up @@ -343,7 +342,7 @@ def sanitize_settings(self) -> None:
def _sanitize_settings(
self,
settings: Dict[str, Any],
default_settings: MappingProxyType[str, Any],
default_settings: Dict[str, Any],
dict_path: str,
) -> Tuple[List[str], Dict[str, Any]]:

Expand Down Expand Up @@ -448,7 +447,7 @@ def valid_ini_format(data: Dict[str, Any]) -> bool:
return True

@abstractmethod
def _to_dict(self, obj: object) -> Dict[str, Any]:
def _to_dict(self, obj: Any) -> Dict[str, Any]:
"""
Converts the settings object to a dictionary.
Expand Down
20 changes: 12 additions & 8 deletions settings/settings_manager.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from __future__ import annotations
from json import dumps, loads
from settings.base import SettingsManagerBase


from dacite import from_dict
from dataclasses import asdict
from typing import Any, Dict, TypeVar, TYPE_CHECKING, Union


from dataclasses import asdict
from typing import Any, Dict, TypeVar
from settings.base import SettingsManagerBase

if TYPE_CHECKING:
from _typeshed import DataclassInstance

T = TypeVar("T")

Expand All @@ -22,7 +23,7 @@ def __init__(self, dict: dict) -> None:


class SettingsManagerWithDataclass(SettingsManagerBase[T]):
def _to_dict(self, obj: object) -> Dict[str, Any]:
def _to_dict(self, obj: "DataclassInstance") -> Dict[str, Any]:
"""
Converts the settings object to a dictionary using dataclasses.asdict.
Expand Down Expand Up @@ -58,7 +59,10 @@ def _to_dict(self, obj: object) -> Dict[str, Any]:
Returns:
Dict[str, Any]: _description_
"""
return self._class_to_dict(obj=obj)
new_dict = self._class_to_dict(obj=obj)
if not isinstance(new_dict, dict):
raise TypeError("Settings object must be a dictionary.")
return new_dict

def _from_dict(self, data: Dict[str, Any]) -> T:
"""
Expand All @@ -72,7 +76,7 @@ def _from_dict(self, data: Dict[str, Any]) -> T:
"""
return loads(s=dumps(obj=data), object_hook=TemplateSettings)

def _class_to_dict(self, obj: object) -> dict | list | dict[str, Any] | object:
def _class_to_dict(self, obj: object) -> Union[dict, list, Dict[str, Any], object]:
"""
Recursively converts a given object to a dictionary representation.
Expand Down
19 changes: 12 additions & 7 deletions settings/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from types import FrameType
from typing import Dict, Optional, overload, Tuple, TypeVar
from pathlib import Path
from inspect import FrameInfo, stack, getmembers, currentframe
Expand Down Expand Up @@ -92,7 +93,7 @@ def set_format(
'json'
"""
format: str = None
format: Optional[str] = None
if config_format:
if logger:
logger.info(msg=f"User specified format: {config_format}.")
Expand Down Expand Up @@ -170,7 +171,7 @@ def _determine_format_from_file_extension(
)


def composite_toggle(composite: bool, options: T) -> T:
def composite_toggle(composite: bool, options: Tuple[bool, ...]) -> Tuple[bool, ...]:
"""
Uses the composite flag to determine if all individual toggles should be set to True.
Expand Down Expand Up @@ -251,25 +252,29 @@ def get_caller_stack(instance: Optional[object] = None) -> str:

frame_length: int = len(_stack) - 1
caller_stack: str = ""
current_frame: Optional[FrameType] = currentframe()
current_function_name: Optional[str] = None

if current_frame:
current_function_name = current_frame.f_code.co_name

for index, frame in enumerate(iterable=_stack[2:frame_length]):
func_name: str = frame.function
# If the function name is a dunder method, skip it.
if func_name.startswith("__"):
continue
# if the function name is not in the list of local methods (if provided) and is not the current function, assume we've found the caller and return the stack.
elif (
func_name not in method_names and func_name != currentframe().f_code.co_name
):
elif func_name not in method_names and func_name != current_function_name:
caller_stack += func_name
return caller_stack
break
# If we've reached the end of the stack, return what we managed to find.
elif index >= frame_length:
logger.debug(
msg=f"Did not have enough frames to find non-local caller name. Last frame: {func_name}."
)
if func_name:
caller_stack += func_name
return caller_stack if caller_stack else "Unknown"
break
else:
caller_stack += f"{func_name} -> "
return caller_stack

0 comments on commit d3dd516

Please sign in to comment.