forked from jamesoff/simplemonitor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathenvconfig.py
117 lines (99 loc) · 4.05 KB
/
envconfig.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
import os
import re
import functools
import sys
if sys.version_info[0] == 2:
from ConfigParser import ConfigParser, NoSectionError, NoOptionError
else:
from configparser import ConfigParser, NoSectionError, NoOptionError
from configparser import BasicInterpolation
# Unique object, which replaces a default config value
_NO_FALLBACK = object()
if sys.version_info[0] == 2:
def with_fallback(f):
@functools.wraps(f)
def newf(*args, **kwargs):
fallback = kwargs.pop('fallback', _NO_FALLBACK)
try:
return f(*args, **kwargs)
except (NoSectionError, NoOptionError):
if fallback is _NO_FALLBACK:
raise
else:
return fallback
return newf
else:
def with_fallback(f):
return f
class EnvironmentAwareConfigParser(ConfigParser):
"""A subclass of ConfigParser which allows %env:VAR% interpolation via the
get method."""
r = re.compile('%env:([a-zA-Z0-9_]+)%')
def __init__(self, *args, **kwargs):
"""Init with our specific interpolation class (for Python 3)"""
try:
interpolation = EnvironmentAwareInterpolation()
kwargs['interpolation'] = interpolation
except Exception:
# Python 2
pass
ConfigParser.__init__(self, *args, **kwargs)
def read(self, filenames):
"""Load a config file and do environment variable interpolation on the section names."""
result = ConfigParser.read(self, filenames)
for section in self.sections():
original_section = section
matches = self.r.search(section)
while matches:
env_key = matches.group(1)
if env_key in os.environ:
section = section.replace(matches.group(0), os.environ[env_key])
else:
raise ValueError('Cannot find {0} in environment for config interpolation'.format(env_key))
matches = self.r.search(section)
if section != original_section:
self.add_section(section)
for (option, value) in self.items(original_section):
self.set(section, option, value)
self.remove_section(original_section)
return result
@with_fallback
def get(self, *args, **kwargs):
if sys.version_info[0] > 2:
return ConfigParser.get(self, *args, **kwargs)
result = ConfigParser.get(self, *args, **kwargs)
matches = self.r.search(result)
while matches:
env_key = matches.group(1)
if env_key in os.environ:
result = result.replace(matches.group(0), os.environ[env_key])
matches = self.r.match(result)
return result
if sys.version_info[0] == 2:
@with_fallback
def getint(self, *args, **kwargs):
return ConfigParser.getint(self, *args, **kwargs)
@with_fallback
def getfloat(self, *args, **kwargs):
return ConfigParser.getfloat(self, *args, **kwargs)
@with_fallback
def getboolean(self, *args, **kwargs):
return ConfigParser.getboolean(self, *args, **kwargs)
if sys.version_info[0] > 2:
class EnvironmentAwareInterpolation(BasicInterpolation):
r = re.compile('%env:([a-zA-Z0-9_]+)%')
def before_get(self, parser, section, option, value, defaults):
parser.get(section, option, raw=True, fallback=value)
matches = self.r.search(value)
old_value = value
while matches:
env_key = matches.group(1)
if env_key in os.environ:
value = value.replace(matches.group(0), os.environ[env_key])
else:
raise ValueError('Cannot find {0} in environment for config interpolation'.format(env_key))
matches = self.r.search(value)
if value == old_value:
break
old_value = value
return value