Skip to content

Commit bca5f78

Browse files
committed
Merge branch 'glob_safe_config_parser' of github.com:wayfair/beaver into wayfair-glob_safe_config_parser
Conflicts: requirements/base.txt
2 parents 91557a7 + 2488c92 commit bca5f78

File tree

5 files changed

+101
-3
lines changed

5 files changed

+101
-3
lines changed

beaver/config.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from conf_d import Configuration
99
from beaver.utils import eglob
10-
10+
from beaver.glob_safe_config_parser import GlobSafeConfigParser
1111

1212
class BeaverConfig():
1313

@@ -148,6 +148,7 @@ def __init__(self, args, logger=None):
148148
}
149149

150150
self._configfile = args.config
151+
self._config_parser = GlobSafeConfigParser
151152
self._globbed = []
152153
self._parse(args)
153154
for key in self._beaver_config:
@@ -434,7 +435,8 @@ def _section_parser(config, raise_exceptions=True):
434435
section_defaults=self._section_defaults,
435436
main_parser=_main_parser,
436437
section_parser=_section_parser,
437-
path_from_main='confd_path'
438+
path_from_main='confd_path',
439+
config_parser=self._config_parser
438440
)
439441

440442
config = conf.raw()

beaver/glob_safe_config_parser.py

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# -*- coding: utf-8 -*-
2+
import ConfigParser
3+
import re
4+
5+
"""
6+
Allows use of square brackets in .ini section names, which are used in some globs.
7+
Based off of python 2.6 ConfigParser.RawConfigParser source code with a few modifications.
8+
http://hg.python.org/cpython/file/8c4d42c0dc8e/Lib/configparser.py
9+
"""
10+
class GlobSafeConfigParser(ConfigParser.RawConfigParser):
11+
12+
OPTCRE = re.compile(
13+
r'(?P<option>[^:=\s][^:=]*)'
14+
r'\s*(?P<vi>[:=])\s*'
15+
r'(?P<value>.*)$'
16+
)
17+
18+
def _read(self, fp, fpname):
19+
cursect = None
20+
optname = None
21+
lineno = 0
22+
e = None
23+
while True:
24+
line = fp.readline()
25+
if not line:
26+
break
27+
lineno = lineno + 1
28+
if line.strip() == '' or line[0] in '#;':
29+
continue
30+
if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
31+
continue
32+
if line[0].isspace() and cursect is not None and optname:
33+
value = line.strip()
34+
if value:
35+
cursect[optname] = "%s\n%s" % (cursect[optname], value)
36+
else:
37+
try:
38+
value = line[:line.index(';')].strip()
39+
except ValueError:
40+
value = line.strip()
41+
42+
if value[0]=='[' and value[-1]==']' and len(value)>2:
43+
sectname = value[1:-1]
44+
if sectname in self._sections:
45+
cursect = self._sections[sectname]
46+
elif sectname == "DEFAULT":
47+
cursect = self._defaults
48+
else:
49+
cursect = self._dict()
50+
cursect['__name__'] = sectname
51+
self._sections[sectname] = cursect
52+
optname = None
53+
elif cursect is None:
54+
raise MissingSectionHeaderError(fpname, lineno, line)
55+
else:
56+
mo = self.OPTCRE.match(line)
57+
if mo:
58+
optname, vi, optval = mo.group('option', 'vi', 'value')
59+
if vi in ('=', ':') and ';' in optval:
60+
pos = optval.find(';')
61+
if pos != -1 and optval[pos-1].isspace():
62+
optval = optval[:pos]
63+
optval = optval.strip()
64+
if optval == '""':
65+
optval = ''
66+
optname = self.optionxform(optname.rstrip())
67+
cursect[optname] = optval
68+
else:
69+
if not e:
70+
e = ParsingError(fpname)
71+
e.append(lineno, repr(line))
72+
if e:
73+
raise e

beaver/tests/test_glob_sections.py

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# -*- coding: utf-8 -*-
2+
import unittest
3+
import os
4+
import glob
5+
from beaver.config import BeaverConfig
6+
7+
class ConfigTests(unittest.TestCase):
8+
9+
def setUp(self):
10+
self.config = lambda: None
11+
self.config.config = 'tests/square_bracket_sections.ini'
12+
self.config.mode = 'bind'
13+
self.beaver_config = BeaverConfig(self.config)
14+
15+
def test_globs(self):
16+
files = [os.path.realpath(x) for x in glob.glob('tests/logs/0x[0-9]*.log')]
17+
for file in self.beaver_config.getfilepaths():
18+
self.assertTrue(file in files)
19+
20+
if __name__ == '__main__':
21+
unittest.main()

requirements/base.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
boto>=2.8.0
2-
conf_d>=0.0.3
2+
conf_d>=0.0.4
33
glob2==0.3
44
mosquitto>=1.1
55
msgpack-pure>=0.1.3

tests/square_bracket_sections.ini

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[./tests/logs/0x[0-9]*.log] ; paths are relative to your current path
2+
type: logs

0 commit comments

Comments
 (0)