mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 03:24:20 +00:00
Remove royalnet.scrolls
, superseded by cfig
https://github.com/Steffo99/cfig
This commit is contained in:
parent
b170c3a5f8
commit
6da801864a
2 changed files with 0 additions and 184 deletions
|
@ -1,149 +0,0 @@
|
|||
"""
|
||||
This module defines a class that can be used to easily load configuration from a :mod:`json` or :mod:`toml` file and
|
||||
from :data:`os.environ`.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
||||
import toml
|
||||
|
||||
from royalnet.royaltyping import *
|
||||
from .exc import *
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class Scroll:
|
||||
"""
|
||||
A configuration handler that allows getting values from both the environment variables and a config file.
|
||||
"""
|
||||
|
||||
key_validator = re.compile(r"^[A-Za-z.]+$")
|
||||
"""
|
||||
A regex used to validate config keys.
|
||||
"""
|
||||
|
||||
def __init__(self, namespace: str, config: Optional[Dict[str, JSON]] = None):
|
||||
self.namespace: str = namespace
|
||||
self.config: Optional[Dict[str, JSON]] = config
|
||||
|
||||
@classmethod
|
||||
def from_toml(cls, namespace: str, file_path: os.PathLike) -> Scroll:
|
||||
"""
|
||||
Create a new :class:`.Scroll` from a :mod:`toml` file.
|
||||
|
||||
:param namespace: A string prefixed to the environment variable keys to disambiguate between multiple scroll
|
||||
objects.
|
||||
:param file_path: The path of the :mod:`toml` file to load.
|
||||
:return: The created :class:`.Scroll` object.
|
||||
"""
|
||||
with open(file_path) as file:
|
||||
config = toml.load(file)
|
||||
return cls(namespace, config)
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, namespace: str, file_path: os.PathLike) -> Scroll:
|
||||
"""
|
||||
Create a new :class:`.Scroll` from a :mod:`json` file.
|
||||
|
||||
:param namespace: A string prefixed to the environment variable keys to disambiguate between multiple scroll
|
||||
objects.
|
||||
:param file_path: The path of the :mod:`json` file to load.
|
||||
:return: The created :class:`.Scroll` object.
|
||||
"""
|
||||
with open(file_path) as file:
|
||||
config = json.load(file)
|
||||
return cls(namespace, config)
|
||||
|
||||
@classmethod
|
||||
def from_file(cls, namespace: str, file_path: os.PathLike, require_file: bool = False) -> Scroll:
|
||||
"""
|
||||
Try to guess the type of the config file and create a new :class:`.Scroll` from it.
|
||||
|
||||
:param namespace: A string prefixed to the environment variable keys to disambiguate between multiple scroll
|
||||
objects.
|
||||
:param file_path: The path of the file to load.
|
||||
:param require_file: Require the file to exist for the :class:`.Scroll` to be created.
|
||||
:raise .exc.InvalidFileType: If the file format isn't supported.
|
||||
:raise .exc.MissingConfigFile: If ``require_file`` is set to :data:`True` and the config file does not exist.
|
||||
:return: The created :class:`.Scroll` object.
|
||||
"""
|
||||
if require_file and not os.path.exists(file_path):
|
||||
raise MissingConfigFileError(f"No config file exists at path {file_path}, and require_file is set to True.")
|
||||
|
||||
_, ext = os.path.splitext(file_path)
|
||||
lext = ext.lower()
|
||||
|
||||
try:
|
||||
return cls.loaders[lext](namespace=namespace, file_path=file_path)
|
||||
except KeyError:
|
||||
raise InvalidFileType(f"Invalid extension: {lext}")
|
||||
except FileNotFoundError:
|
||||
return cls(namespace=namespace)
|
||||
|
||||
@classmethod
|
||||
def _validate_key(cls, item: str):
|
||||
check = cls.key_validator.match(item)
|
||||
if not check:
|
||||
raise InvalidFormatError()
|
||||
|
||||
def _get_from_environ(self, item: str) -> JSONScalar:
|
||||
"""Get a configuration value from the environment variables."""
|
||||
key = f"{self.namespace}_{item.replace('.', '_')}".upper()
|
||||
|
||||
try:
|
||||
j = os.environ[key]
|
||||
except KeyError:
|
||||
raise NotFoundError(f"'{key}' was not found in the environment variables.")
|
||||
|
||||
try:
|
||||
value = json.loads(j)
|
||||
except json.JSONDecodeError:
|
||||
raise ParseError(f"'{key}' contains invalid JSON: {j}")
|
||||
|
||||
return value
|
||||
|
||||
def _get_from_config(self, item: str) -> JSONScalar:
|
||||
"""Get a configuration value from the configuration file."""
|
||||
if self.config is None:
|
||||
raise NotFoundError("No config file has been loaded.")
|
||||
|
||||
chain = item.lower().split(".")
|
||||
|
||||
current = self.config
|
||||
|
||||
for element in chain:
|
||||
try:
|
||||
current = current[element]
|
||||
except KeyError:
|
||||
raise NotFoundError(f"'{item}' was unreachable: could not find '{element}'")
|
||||
|
||||
return current
|
||||
|
||||
def __getitem__(self, item: str):
|
||||
self._validate_key(item)
|
||||
try:
|
||||
return self._get_from_environ(item)
|
||||
except NotFoundError:
|
||||
return self._get_from_config(item)
|
||||
|
||||
def get(self, item: str, default: T) -> Union[JSONScalar, T]:
|
||||
try:
|
||||
return self[item]
|
||||
except NotFoundError:
|
||||
return default
|
||||
|
||||
|
||||
Scroll.loaders = {
|
||||
".json": Scroll.from_json,
|
||||
".toml": Scroll.from_toml,
|
||||
}
|
||||
"""
|
||||
An extension to deserialization function map.
|
||||
"""
|
||||
|
||||
__all__ = ("Scroll",)
|
|
@ -1,35 +0,0 @@
|
|||
from ..exc import RoyalnetException
|
||||
|
||||
|
||||
class ScrollsException(RoyalnetException):
|
||||
"""An exception raised by the scrolls module."""
|
||||
|
||||
|
||||
class NotFoundError(ScrollsException, KeyError):
|
||||
"""The requested config key was not found."""
|
||||
|
||||
|
||||
class MissingConfigFileError(ScrollsException, IOError):
|
||||
"""The config file does not exist, and ``require_file`` is set to :data:`True`."""
|
||||
|
||||
|
||||
class InvalidFormatError(ScrollsException):
|
||||
"""The requested config key is not valid."""
|
||||
|
||||
|
||||
class ParseError(ScrollsException):
|
||||
"""The config value could not be parsed correctly."""
|
||||
|
||||
|
||||
class InvalidFileType(ParseError):
|
||||
"""The type of the specified config file is not currently supported."""
|
||||
|
||||
|
||||
__all__ = (
|
||||
"ScrollsException",
|
||||
"NotFoundError",
|
||||
"MissingConfigFileError",
|
||||
"InvalidFormatError",
|
||||
"ParseError",
|
||||
"InvalidFileType",
|
||||
)
|
Loading…
Reference in a new issue