2021-02-15 18:29:27 -08:00

66 lines
1.5 KiB
Python

from abc import ABC, abstractmethod
from typing import List, IO
from pydantic import BaseModel, ValidationError
from contextlib import contextmanager
import re
class ConfigModel(BaseModel):
class Config:
extra = "allow"
class DynamicTypedConfig(ConfigModel):
type: str
class MetaError(Exception):
"""A base class for all meta exceptions"""
class ConfigurationError(MetaError):
"""A configuration error has happened"""
class ConfigurationMechanism(ABC):
@abstractmethod
def load_config(self, config_fp: IO) -> dict:
pass
class AllowDenyPattern(BaseModel):
""" A class to store allow deny regexes"""
allow: List[str] = [".*"]
deny: List[str] = []
@classmethod
def allow_all(cls):
return AllowDenyPattern()
def allowed(self, string: str) -> bool:
for deny_pattern in self.deny:
if re.match(deny_pattern, string):
return False
for allow_pattern in self.allow:
if re.match(allow_pattern, string):
return True
return False
@contextmanager
def nicely_formatted_validation_errors():
try:
yield
except ValidationError as e:
messages = []
for err in e.errors():
location = ".".join((str(x) for x in err["loc"]))
reason = err["msg"]
messages.append(f" - {location}: {reason}")
msg = "\n".join(messages)
raise ConfigurationError(f"Invalid value in configuration: \n{msg}") from e