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