Skip to content

Commit b484c23

Browse files
committed
Initial commit
0 parents  commit b484c23

File tree

15 files changed

+758
-0
lines changed

15 files changed

+758
-0
lines changed

CHANGES.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Changelog
2+
=========
3+
4+
0.0.1 (2013-04-13)
5+
------------------
6+
7+
- Initial commit

LICENSE.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Copyright (c) 2013 Jose Diaz-Gonzalez
2+
3+
Permission is hereby granted, free of charge, to any person obtaining
4+
a copy of this software and associated documentation files (the
5+
"Software"), to deal in the Software without restriction, including
6+
without limitation the rights to use, copy, modify, merge, publish,
7+
distribute, sublicense, and/or sell copies of the Software, and to
8+
permit persons to whom the Software is furnished to do so, subject to
9+
the following conditions:
10+
11+
The above copyright notice and this permission notice shall be
12+
included in all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

MANIFEST.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
include *.txt
2+
include *.rst

README.rst

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
======
2+
conf_d
3+
======
4+
5+
read configuration files, conf.d style
6+
7+
Requirements
8+
============
9+
10+
* Python 2.6+
11+
12+
Installation
13+
============
14+
15+
Using PIP:
16+
17+
From Github::
18+
19+
pip install git+git://github.com/josegonzalez/conf_d.git#egg=conf_d
20+
21+
From PyPI::
22+
23+
pip install conf_d==0.0.1
24+
25+
Usage
26+
=====
27+
28+
usage::
29+
30+
# in your /etc/derp/conf file
31+
[derp]
32+
no: sleep
33+
til: brooklyn
34+
35+
[herp]
36+
sleep: 1
37+
wait: 5.0
38+
timeout: seventy
39+
40+
# From your fictional derp module
41+
from conf_d import Configuration
42+
43+
def digitize(config):
44+
for key in config:
45+
if not config[key].isdigit():
46+
try:
47+
config[key] = float(config[key])
48+
except ValueError:
49+
pass
50+
else:
51+
try:
52+
config[key] = int(config[key])
53+
except ValueError:
54+
pass
55+
56+
return config
57+
58+
# All defaults must be strings
59+
conf = Configuration(
60+
name="derp",
61+
path="/etc/derp/conf",
62+
main_defaults={
63+
"no": "one",
64+
"expected": "the spanish inquisition",
65+
"cats": "1",
66+
},
67+
section_parser=digitize
68+
)
69+
70+
what_not_to_do = conf.get(section='derp', key='no', default="jumping")
71+
# "sleep"
72+
73+
until_when = conf.get(section='derp', key='til')
74+
# "brooklyn"
75+
76+
cats = conf.get(section='derp', key='cats')
77+
# "1"
78+
79+
dogs = conf.get(section='derp', key='dogs')
80+
# None
81+
82+
sleep = conf.get(section='herp', key='sleep')
83+
# 1
84+
85+
wait = conf.get(section='herp', key='wait')
86+
# 5.0
87+
88+
timeout = conf.get(section='herp', key='timeout')
89+
# "seventy"
90+
91+
section_exists = conf.has(section='derp')
92+
# True
93+
94+
section_exists = conf.has(section='derp', key='no')
95+
# True
96+
97+
raw_data = conf.raw()
98+
# {
99+
# 'sections': {
100+
# 'herp': {
101+
# 'sleep': 1,
102+
# 'wait': 5.0,
103+
# 'timeout': 'seventy'
104+
# }
105+
# },
106+
# 'derp': {
107+
# 'expected': 'the spanish inquisition',
108+
# 'til': 'brooklyn',
109+
# 'cats': '1',
110+
# 'no': 'sleep'
111+
# }
112+
# }

conf_d/__init__.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# -*- coding: utf-8 -*-
2+
import ConfigParser
3+
import os
4+
5+
__version__ = '0.0.1'
6+
7+
8+
class Configuration():
9+
10+
def __init__(self, name, path, parse=True, confd_path=None, conf_ext=None, main_defaults={}, section_defaults={}, main_parser=None, section_parser=None):
11+
self._conf_ext = conf_ext
12+
self._config_sections = {}
13+
self._confd_path = confd_path
14+
self._main_config = {}
15+
self._main_defaults = main_defaults
16+
self._main_parser = main_parser
17+
self._name = name
18+
self._path = path
19+
self._section_defaults = section_defaults
20+
self._section_parser = section_parser
21+
22+
if self._conf_ext:
23+
self._conf_ext = '.' + conf_ext.strip(".")
24+
25+
if parse:
26+
self.parse()
27+
28+
def get(self, section, key=None, default=None):
29+
if section == self._name:
30+
if key is None:
31+
return self._main_config
32+
return self._main_config.get(key, default)
33+
34+
if section in self._config_sections:
35+
if key is None:
36+
return self._config_sections[section]
37+
return self._config_sections[section].get(key, default)
38+
39+
raise KeyError("Invalid section")
40+
41+
def has(self, section, key=None):
42+
if section in self._config_sections:
43+
if key is None:
44+
return True
45+
46+
return key in self._config_sections[section]
47+
48+
if section == self._name:
49+
if key is None:
50+
return True
51+
52+
return key in self._main_config
53+
54+
return False
55+
56+
def raw(self, section=None):
57+
if section:
58+
if not self.has(section):
59+
raise KeyError("Invalid section")
60+
61+
if section == self._name:
62+
return self._main_config
63+
64+
return self._config_sections[section]
65+
66+
return {
67+
self._name: self._main_config,
68+
'sections': self._config_sections
69+
}
70+
71+
def parse(self):
72+
configs = self._parse_section(path=self._path, defaults=self._main_defaults, parser=self._main_parser, only_section=self._name)
73+
self._main_config = configs[self._name]
74+
75+
self._config_sections = self._parse_section(path=self._path, defaults=self._section_defaults, parser=self._section_parser, remove_section=self._name)
76+
if self._confd_path:
77+
for f in sorted(os.listdir(self._confd_path)):
78+
path = os.path.realpath(os.path.join(self._confd_path, f))
79+
if not os.path.isfile(path):
80+
continue
81+
82+
if self._conf_ext and not path.endswith(self._conf_ext):
83+
continue
84+
85+
configs = self._parse_section(path=path, defaults=self._section_defaults, parser=self._section_parser, remove_section=self._name)
86+
self._config_sections.update(configs)
87+
88+
def _parse_section(self, path, defaults={}, parser=None, only_section=None, remove_section=None):
89+
config_parser = ConfigParser.ConfigParser(defaults)
90+
91+
if not path:
92+
raise IOError('No path specified: "%s"' % path)
93+
94+
path = os.path.realpath(path)
95+
96+
if len(config_parser.read(path)) != 1:
97+
raise IOError('Could not parse config file "%s"' % path)
98+
99+
configs = {}
100+
for section in config_parser.sections():
101+
if remove_section and remove_section == section:
102+
continue
103+
104+
if only_section and only_section != section:
105+
continue
106+
107+
config = dict((x[0], x[1]) for x in config_parser.items(section))
108+
if hasattr(parser, '__call__'):
109+
config = parser(config)
110+
111+
configs[section] = config
112+
113+
return configs

conf_d/tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# -*- coding: utf-8 -*-

0 commit comments

Comments
 (0)