65 lines
1.5 KiB
Python
Raw Normal View History

2021-01-31 22:40:30 -08:00
from abc import ABC, abstractmethod
2021-02-11 19:12:43 -08:00
from typing import TypeVar, Type, List, IO
2021-01-31 22:40:30 -08:00
from pydantic import BaseModel, ValidationError
from pathlib import Path
2021-02-11 19:12:43 -08:00
from contextlib import contextmanager
import re
2021-01-31 22:40:30 -08:00
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
2021-02-11 19:12:43 -08:00
def load_config(self, config_fp: IO) -> dict:
2021-01-31 22:40:30 -08:00
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
2021-02-11 19:12:43 -08:00
@contextmanager
def nicely_formatted_validation_errors():
2021-01-31 22:40:30 -08:00
try:
2021-02-11 19:12:43 -08:00
yield
2021-01-31 22:40:30 -08:00
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)
2021-02-11 19:12:43 -08:00
raise ConfigurationError(f"Invalid value in configuration: \n{msg}") from e