diff options
Diffstat (limited to 'dodai/config/sections.py')
-rw-r--r-- | dodai/config/sections.py | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/dodai/config/sections.py b/dodai/config/sections.py new file mode 100644 index 0000000..feb59be --- /dev/null +++ b/dodai/config/sections.py | |||
@@ -0,0 +1,172 @@ | |||
1 | # Copyright (C) 2010 Leonard Thomas | ||
2 | # | ||
3 | # This file is part of Dodai. | ||
4 | # | ||
5 | # Dodai is free software: you can redistribute it and/or modify | ||
6 | # it under the terms of the GNU General Public License as published by | ||
7 | # the Free Software Foundation, either version 3 of the License, or | ||
8 | # (at your option) any later version. | ||
9 | # | ||
10 | # Dodai is distributed in the hope that it will be useful, | ||
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | # GNU General Public License for more details. | ||
14 | # | ||
15 | # You should have received a copy of the GNU General Public License | ||
16 | # along with Dodai. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | import unicodedata | ||
19 | |||
20 | class ConfigSections(object): | ||
21 | """ | ||
22 | An iterable object that contains ConfigSection objects | ||
23 | |||
24 | """ | ||
25 | |||
26 | def __init__(self, string_object = None): | ||
27 | """ | ||
28 | Iterable object that handles the conversion of a config | ||
29 | parser object to a list of section objects. | ||
30 | |||
31 | |||
32 | string_object: This is an object (non instantiated or | ||
33 | callable) that the results of the config's | ||
34 | sections, and options will be stored in. | ||
35 | This enables you to store your values as a | ||
36 | custom object. A good object to use is the | ||
37 | dodai.tools.himo Himo object. If the | ||
38 | string_object is not given the default python | ||
39 | str() object will be used. | ||
40 | |||
41 | """ | ||
42 | self._string_object = string_object or None | ||
43 | self._sections = {} | ||
44 | |||
45 | def __call__(self, parser): | ||
46 | """ | ||
47 | Parses the given parser object into this object's sections. | ||
48 | |||
49 | parser: The actual parser object that is used to | ||
50 | get the sections. This object must have | ||
51 | the sections(), options() and get() | ||
52 | methods. A good object to use is the native | ||
53 | ConfigParse object. However, you can create | ||
54 | your own | ||
55 | |||
56 | """ | ||
57 | self._build_sections(parser) | ||
58 | |||
59 | def _build_sections(self, parser): | ||
60 | # Builds ConfigSection objects from the parser object | ||
61 | |||
62 | for section_name in parser.sections(): | ||
63 | section = self.get_section(section_name) | ||
64 | self._build_options(parser, section_name, section) | ||
65 | |||
66 | def _build_options(self, parser, section_name, section): | ||
67 | # Adds the options to the section object | ||
68 | |||
69 | for key in parser.options(section_name): | ||
70 | key = unicode(self._build_string_object(key)) | ||
71 | value = self._build_string_object(parser.get(section_name, key)) | ||
72 | setattr(section, key, value) | ||
73 | |||
74 | def _build_string_object(self, data): | ||
75 | if self._string_object: | ||
76 | return self._string_object(data) | ||
77 | else: | ||
78 | return data | ||
79 | |||
80 | def get_section(self, section_name): | ||
81 | """ | ||
82 | Returns a ConfigSection object from this object's section | ||
83 | dictionary or creates a new ConfigSection object, which is | ||
84 | stored int this object's section dictionary then is returned | ||
85 | |||
86 | """ | ||
87 | section_name = unicode(self._build_string_object(section_name)) | ||
88 | if section_name in self._sections: | ||
89 | return self._sections[section_name] | ||
90 | else: | ||
91 | section = ConfigSection(section_name) | ||
92 | self._sections[section_name] = section | ||
93 | return section | ||
94 | |||
95 | def __getitem__(self, key): | ||
96 | key = normalize_key(key) | ||
97 | return self._sections[key] | ||
98 | |||
99 | def __getattr__(self, key): | ||
100 | key = normalize_key(key) | ||
101 | try: | ||
102 | out = self._sections[key] | ||
103 | except KeyError: | ||
104 | return getattr(self._sections, key) | ||
105 | else: | ||
106 | return out | ||
107 | |||
108 | def __iter__(self, *args, **kargs): | ||
109 | return self._sections.__iter__(*args, **kargs) | ||
110 | |||
111 | |||
112 | def __len__(self): | ||
113 | return len(self._sections) | ||
114 | |||
115 | class ConfigSection(object): | ||
116 | """ | ||
117 | A generic object to hold keys and values primarily from a config file | ||
118 | |||
119 | """ | ||
120 | def __init__(self, title): | ||
121 | """ | ||
122 | Holds keys and values primarily from a section of a config file | ||
123 | |||
124 | title: The title of the section of the config file | ||
125 | |||
126 | """ | ||
127 | self.___title___ = title | ||
128 | self.___options___ = {} | ||
129 | |||
130 | |||
131 | def get_title(self): | ||
132 | """ | ||
133 | Returns the title of the section | ||
134 | |||
135 | """ | ||
136 | return self.___title___ | ||
137 | |||
138 | |||
139 | def __setattr__(self, key, value): | ||
140 | if key.startswith('___') and key.endswith('___'): | ||
141 | object.__setattr__(self, key, value) | ||
142 | else: | ||
143 | key = normalize_key(key) | ||
144 | if self.___options___.has_key(key): | ||
145 | self.___options___[key] = value | ||
146 | else: | ||
147 | dict.__setitem__(self.___options___, key, value) | ||
148 | |||
149 | def __getattr__(self, key): | ||
150 | if key.startswith('___') and key.endswith('___'): | ||
151 | return self.__dict__[key] | ||
152 | else: | ||
153 | key = normalize_key(key) | ||
154 | try: | ||
155 | out = self.___options___[key] | ||
156 | except KeyError: | ||
157 | return getattr(self.___options___, key) | ||
158 | else: | ||
159 | return out | ||
160 | |||
161 | def __getitem__(self, key): | ||
162 | key = normalize_key(key) | ||
163 | return self.___options___[key] | ||
164 | |||
165 | def __iter__(self, *args, **kargs): | ||
166 | return self.___options___.__iter__(*args, **kargs) | ||
167 | |||
168 | |||
169 | def normalize_key(key): | ||
170 | key = unicode(key) | ||
171 | key = unicodedata.normalize('NFC', key) | ||
172 | return key | ||