2Copyright (C) 2016, Digium, Inc.
4This program is free software, distributed under the terms of
5the GNU General Public License Version 2.
12from astdicts
import OrderedDict
13from astdicts
import MultiOrderedDict
17 """Merges values from right into left."""
18 if isinstance(left, list):
21 vals0 = left[key]
if key
in left
else []
22 vals1 = right[key]
if key
in right
else []
24 return vals0 + [i
for i
in vals1
if i
not in vals0]
31 A Section is a MultiOrderedDict itself that maintains a list of
32 key/value options. However,
in the case of an Asterisk config
33 file a section may have other defaults sections that
is can pull
34 data
from (i.e. templates). So when an option
is looked up by key
35 it first checks the base section
and if not found looks
in the
36 added default sections. If
not found at that point then a
'KeyError'
41 def __init__(self, defaults=None, templates=None):
42 MultiOrderedDict.__init__(self)
45 self.
id = Section.count
46 self.
_defaults = []
if defaults
is None else defaults
47 self.
_templates = []
if templates
is None else templates
51 Use self.id as means of determining equality
53 return (self.
id > other.id) - (self.
id < other.id)
57 Use self.id as means of determining equality
59 return self.
id == other.id
63 Use self.id as means of determining equality
65 return self.
id < other.id
69 Use self.id as means of determining equality
71 return self.
id > other.id
75 Use self.id as means of determining equality
77 return self.
id <= other.id
81 Use self.id as means of determining equality
83 return self.
id >= other.id
85 def get(self, key, from_self=True, from_templates=True,
88 Get the values corresponding to a given key. The parameters to this
89 function form a hierarchy that determines priority of the search.
90 from_self takes priority over from_templates, and from_templates takes
91 priority over from_defaults.
94 from_self - If
True, search within the given section.
95 from_templates - If
True, search
in this section
's templates.
96 from_defaults - If True, search within this section
's defaults.
98 if from_self
and key
in self:
99 return MultiOrderedDict.__getitem__(self, key)
108 return t.get(key,
True, from_templates, from_defaults)
115 return d.get(key,
True, from_templates, from_defaults)
123 Get the value for the given key. If it
is not found
in the
'self'
124 then check inside templates
and defaults before declaring raising
125 a KeyError exception.
129 def keys(self, self_only=False):
131 Get the keys from this section. If self_only
is True, then
132 keys
from this section
's defaults and templates are not
133 included in the returned value
135 res = MultiOrderedDict.keys(self)
152 Add a list of defaults to the section. Defaults are
153 sections such as 'general'
161 Add a list of templates to the section.
168 """Return a list of values for a given key merged from default(s)"""
192DEFAULTSECT =
'general'
196 """Remove any commented elements from the line."""
198 return line, is_comment
201 part = line.partition(COMMENT_END)
207 part = line.partition(COMMENT_START)
208 if part[1]
and not part[2].startswith(
'-'):
211 has_comment = part[0].partition(COMMENT)
214 return has_comment[0],
False
220 return part[0].strip(),
True
223 return ''.join([part[0].strip(),
' ', line]).rstrip(),
False
226 match = re.match(
r'.*?([^\\];)', line)
230 line = line[0:(match.end()-1)]
231 if line.startswith(
";"):
235 return line.replace(
"\\",
"").strip(),
False
239 Checks to see if the given line
is an include. If so
return the
240 included filename, otherwise
None.
243 match = re.match('^#include\s*([^;]+).*$', line)
245 trimmed = match.group(1).rstrip()
246 quoted = re.match(
'^"([^"]+)"$', trimmed)
248 return quoted.group(1)
249 bracketed = re.match(
'^<([^>]+)>$', trimmed)
251 return bracketed.group(1)
258 Checks to see if the given line
is a section. If so
return the section
259 name, otherwise
return 'None'.
262 if not line.startswith(
'['):
263 return None,
False, []
265 section, delim, templates = line.partition(
']')
267 return section[1:],
False, []
270 templates = templates.replace(
'(',
"").
replace(
')',
"").split(
',')
272 templates = [i.strip()
for i
in templates]
274 templates.remove(
'!')
275 return section[1:],
True, templates
277 return section[1:],
False, templates
281 """Parses the line as an option, returning the key/value pair."""
282 data = re.split(
'=>?', line, 1)
284 return data[0].rstrip(), data[1].lstrip()
291 Given a list of mult-dicts, return the multi-dict that contains
292 the given key/value pair.
296 return key
in d
and val
in d[key]
299 return [d
for d
in mdicts
if found(d)][0]
301 raise LookupError(
"Dictionary not located for key = %s, value = %s"
306 """Write the contents of the mdicts to the specified config file"""
307 for section, sect_list
in mdicts.iteritems():
309 for sect
in sect_list:
310 config_file.write(
"[%s]\n" % section)
311 for key, val_list
in sect.iteritems():
316 key_val +=
" = " +
str(v)
317 config_file.write(
"%s\n" % (key_val))
318 config_file.write(
"\n")
331 """Given a list of sections, try to find value(s) for the given key."""
333 sections.sort(reverse=
True)
337 return s.get(key, from_defaults=
False)
346 return s.get(key, from_self=
False, from_templates=
False)
356 """Retrieves a list of dictionaries for a default section."""
361 Adds a default section to defaults, returning the
362 default Section object.
364 if template_keys
is None:
372 """Retrieves a list of dictionaries for a section."""
377 Retrieve a list of sections that have values for the given key.
378 The attr parameter can be used to control what part of the parser
379 to retrieve values
from.
386 sections = getattr(self, attr)
387 res = sections[key]
if key
in sections
else []
388 searched.append(self)
390 res.extend(list(itertools.chain(*[
391 incl.get_sections(key, attr, searched)
392 for incl
in self.
_includes.itervalues()])))
399 Retrieve a list of defaults that have values for the given key.
405 Create a new section in the configuration. The name of the
406 new section
is the
'key' parameter.
408 if template_keys
is None:
413 for t
in template_keys:
416 mdicts.insert(0, key, res)
433 def get(self, section, key):
434 """Retrieves the list of values from a section for a key."""
446 raise LookupError(
"key %r not found for section %r"
451 Retrieves the list of values from a section
for a list of keys.
452 This method
is intended to be used
for equivalent keys. Thus,
as soon
453 as any match
is found
for any key
in the key_list, the match
is
454 returned. This does
not concatenate the lookups of all of the keys
459 return self.
get(section, i)
464 raise LookupError(
"keys %r not found for section %r" %
467 def set(self, section, key, val):
468 """Sets an option in the given section."""
472 self.
section(section)[0][key] = val
474 self.
defaults(section)[0][key] = val
476 def read(self, filename, sect=None):
477 """Parse configuration information from a file"""
479 with open(filename,
'rt')
as config_file:
480 self.
_read(config_file, sect)
482 print(
"Could not open file " + filename +
" for reading")
484 def _read(self, config_file, sect):
485 """Parse configuration information from the config_file"""
487 for line
in config_file:
495 for incl
in sorted(glob.iglob(include_name)):
497 parser.read(incl, sect)
500 section, is_template, templates =
try_section(line)
502 if section == DEFAULTSECT
or is_template:
510 raise Exception(
"Section not defined before assignment")
514 """Write configuration information out to a file"""
516 for key, val
in self.
_includes.iteritems():
518 config_file.write(
'#include "%s"\n' % key)
520 config_file.write(
'\n')
525 with open(config_file,
'wt')
as fp:
528 print(
"Could not open file " + config_file +
" for writing")
def get_defaults(self, key)
def write(self, config_file)
def add_include(self, filename, parser=None)
def __init__(self, parent=None)
def add_default(self, key, template_keys=None)
def read(self, filename, sect=None)
def get_sections(self, key, attr='_sections', searched=None)
def find_value(self, sections, key)
def multi_get(self, section, key_list)
def _read(self, config_file, sect)
def add_section(self, key, template_keys=None, mdicts=None)
def get(self, section, key)
def set(self, section, key, val)
def __init__(self, defaults=None, templates=None)
def keys(self, self_only=False)
def add_defaults(self, defaults)
def get_merged(self, key)
def __getitem__(self, key)
def add_templates(self, templates)
def get(self, key, from_self=True, from_templates=True, from_defaults=True)
def insert(self, i, key, val)
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
def write_dicts(config_file, mdicts)
def remove_comment(line, is_comment)
def find_dict(mdicts, key, val)
def merge_values(left, right, key)