/
constants.py
144 lines (128 loc) · 3.9 KB
/
constants.py
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
"""
constant.Constants - The simple way to deal with environment constants.
"""
import os
try:
import ConfigParser as configparser
except ImportError:
import configparser
import warnings
import logging
import functools
logger = logging.getLogger(__name__)
def debug(function):
"""
logging debug decorator
"""
@functools.wraps(function)
def wrapper(*args, **kvargs):
"""
wrap method call
"""
logger.debug('begin %s %s',
args,
kvargs,
extra={'method': function.__name__})
result = function(*args, **kvargs)
logger.debug('end %s', result, extra={'method': function.__name__})
return result
return wrapper
VARIABLE = '__CONSTANTS__'
FILENAME = 'constants.ini'
class Constants(object):
"""
Environement sensitive application constants class
"""
@debug
def __init__(self, variable=VARIABLE, filename=FILENAME):
"""
variable is the name of the environment variable to read the
environment / config section from default to __CONSTANTS__
filename is the config filename
"""
object.__setattr__(self, 'dict', {})
self.variable = variable
self.filename = filename
self.load()
@debug
def load(self):
"""
load the section self.variable from the config file self.filename
"""
self.get_environment()
self.read_config()
self.load_dict()
@debug
def get_environment(self):
"""
returns the value of the environment variable self.variable
"""
self.environment = os.environ[self.variable]
@debug
def read_config(self):
"""
returns a ConfigParser instance from self.filename
"""
self.config = configparser.ConfigParser()
with open(self.filename) as config_file:
self.config.readfp(config_file)
@debug
def load_dict(self):
"""
load the config items into self.dict
"""
self.dict = dict (self.config.items(self.environment))
logger.info('variable: %s, filename: %s, environment: %s, constants: %s',
self.variable,
self.filename,
self.environment,
self.dict,
extra={'method': 'load'})
@debug
def __getitem__(self, item):
"""
access to environment specific constants in a dictionary manner
casts to int, float or keep as string
"""
return self.cast(self.dict[item])
@debug
def __getattr__(self, item):
"""
syntactic sugar, .item rather than ['item']
"""
return self[item]
@staticmethod
@debug
def cast(string):
"""
cast string to int, float or keep as string
"""
if hasattr(string, 'startswith') and string.startswith('0'):
return string
try:
return int(string)
except ValueError:
pass
try:
return float(string)
except ValueError:
pass
return string
@debug
def __setitem__(self, item, value):
"""
dict like assignment - warns when a constant is changed
"""
if item in self.dict:
warnings.warn('{0} changed to {1}'.format(item, value))
self.dict[item] = value
@debug
def __setattr__(self, name, value):
"""
attribute assignment - warns when a constant is changed
"""
if hasattr(self, 'dict') and name in self.dict:
warnings.warn('{0} changed to {1}'.format(name, value))
self.dict[name] = value
else:
object.__setattr__(self, name, value)