1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
"""
Abstract models and classes for the config
"""
import json
import os
from abc import abstractmethod, ABC
from typing import Type, Union, AnyStr, TextIO
from configlib.util import snake_case
class InvalidConfigEscapeException(Exception):
"""
Some config uses an invalid escape like `$invalidescapecode:argument`
"""
class InvalidConfigTypingException(Exception):
"""
The typing found in the given class is missing arguments.
Example:
>>> import typing
>>> someting: typing.List[str, int]
is illegal since :class:`typing.List` only takes one argument.
"""
class ConfigValueMissingException(Exception):
"""
The given config file is missing an argument
"""
class Config(ABC):
"""
Base class for a Config. Do NOT extend this. use :class:`configlib.BaseConfig` instead.
"""
@classmethod
@abstractmethod
def get_name(cls) -> str:
"""
Get the name for a config
:return: the name
"""
@classmethod
@abstractmethod
def parse_dict(cls: Type['Config'], data: dict) -> 'Config':
"""
For the given data return the config instance.
:param data: the loaded data dict
:return: a loaded config
"""
@classmethod
def load(cls: Type['Config'], file: Union[AnyStr, TextIO]) -> 'Config':
"""
Load a specified config file
:param file: the file object or file path
:return: the parsed config according to :func:`.parse_dict`
"""
if hasattr(file, 'read'):
return cls.loads(file.read())
with open(file) as file_pointer:
return cls.load(file_pointer)
@classmethod
def loads(cls: Type['Config'], text: str) -> 'Config':
"""
Load data from text
:param text: the text data
:return: the parsed config
"""
return cls.parse_dict(json.loads(text))
@classmethod
def get_instance(cls: Type['Config']) -> 'Config':
"""
get a Config instance according to the matching environment variable
:return: the parsed config
"""
name = os.environ.get(snake_case(cls.get_name()), '').strip()
return cls.get_instance_for_env(name)
@classmethod
def get_instance_for_env(cls: Type['Config'], env: str) -> 'Config':
"""
get a Config instance for a given environment
:param env: the wanted environment
:return: the parsed config
"""
if env:
env = '-' + env
return cls.load('config/' + snake_case(cls.get_name()) + env + '.json')
|