Mercurial > hg > config
comparison python/simpleini.py @ 113:44534594f402
add variable interpolation
| author | Jeff Hammel <jhammel@mozilla.com> |
|---|---|
| date | Thu, 02 Dec 2010 13:04:54 -0800 |
| parents | e85298a35998 |
| children | 9b193312ceba |
comparison
equal
deleted
inserted
replaced
| 112:e85298a35998 | 113:44534594f402 |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 | 2 |
| 3 import os | 3 import os |
| 4 | 4 |
| 5 def read(fp, comments=';#', separators=('=', ':')): | 5 def read(fp, variables=None, default='DEFAULT', |
| 6 comments=';#', separators=('=', ':'), strict=True): | |
| 7 """ | |
| 8 read an .ini file and return a list of [(section, values)] | |
| 9 - fp : file pointer or name to read | |
| 10 - variables : default set of variables | |
| 11 - default : name of the section for the default section | |
| 12 - comments : characters that if they start a line denote a comment | |
| 13 - separators : strings that denote key, value separation in order | |
| 14 - strict : whether to be strict about parsing | |
| 15 """ | |
| 16 | |
| 17 if variables is None: | |
| 18 variables = {} | |
| 19 variables = variables.copy() # no reason to overwrite the originals | |
| 6 | 20 |
| 7 if isinstance(fp, basestring): | 21 if isinstance(fp, basestring): |
| 8 fp = file(fp) | 22 fp = file(fp) |
| 9 | 23 |
| 10 sections = [] | 24 sections = [] |
| 11 key = value = None | 25 key = value = None |
| 12 | 26 section_names = set([]) |
| 27 | |
| 28 # read the lines | |
| 13 for line in fp.readlines(): | 29 for line in fp.readlines(): |
| 14 | 30 |
| 15 stripped = line.strip() | 31 stripped = line.strip() |
| 16 | 32 |
| 17 # ignore blank lines | 33 # ignore blank lines |
| 18 if not stripped: | 34 if not stripped: |
| 35 # XXX should probably reset key and value to avoid continuation lines | |
| 36 key = value = None | |
| 19 continue | 37 continue |
| 20 | 38 |
| 21 # ignore comment lines | 39 # ignore comment lines |
| 22 if stripped[0] in comments: | 40 if stripped[0] in comments: |
| 23 continue | 41 continue |
| 24 | 42 |
| 25 # check for a new section | 43 # check for a new section |
| 26 if len(stripped) > 2 and stripped[0] == '[' and stripped[-1] == ']': | 44 if len(stripped) > 2 and stripped[0] == '[' and stripped[-1] == ']': |
| 27 section = stripped[1:-1].strip() | 45 section = stripped[1:-1].strip() |
| 28 sections.append((section, {})) | |
| 29 key = value = None | 46 key = value = None |
| 30 # TODO: should probably make sure this section doesn't already exist | 47 |
| 48 # deal with DEFAULT section | |
| 49 if section.lower() == default.lower(): | |
| 50 if strict: | |
| 51 assert default not in section_names | |
| 52 section_names.add(default) | |
| 53 current_section = variables | |
| 54 continue | |
| 55 | |
| 56 if strict: | |
| 57 # make sure this section doesn't already exist | |
| 58 assert section not in section_names | |
| 59 | |
| 60 section_names.add(section) | |
| 61 | |
| 62 current_section = {} | |
| 63 sections.append((section, current_section)) | |
| 31 continue | 64 continue |
| 32 | 65 |
| 33 # if there aren't any sections yet, something bad happen | 66 # if there aren't any sections yet, something bad happen |
| 34 if not sections: | 67 if not section_names: |
| 35 raise Exception('No sections yet :(') | 68 raise Exception('No sections yet :(') |
| 36 | 69 |
| 37 # (key, value) pair | 70 # (key, value) pair |
| 38 for separator in separators: | 71 for separator in separators: |
| 39 if separator in stripped: | 72 if separator in stripped: |
| 40 key, value = stripped.split(separator, 1) | 73 key, value = stripped.split(separator, 1) |
| 41 key = key.strip() | 74 key = key.strip() |
| 42 value = value.strip() | 75 value = value.strip() |
| 43 sections[-1][1][key] = value | 76 |
| 44 # TODO: should probably make sure this key isn't already in the section | 77 if strict: |
| 78 # make sure this key isn't already in the section or empty | |
| 79 assert key | |
| 80 if current_section is not variables: | |
| 81 assert key not in current_section | |
| 82 | |
| 83 current_section[key] = value | |
| 45 break | 84 break |
| 46 else: | 85 else: |
| 47 # continuation line ? | 86 # continuation line ? |
| 48 if line[0].isspace() and key: | 87 if line[0].isspace() and key: |
| 49 value = '%s%s%s' % (value, os.linesep, stripped) | 88 value = '%s%s%s' % (value, os.linesep, stripped) |
| 50 sections[-1][1][key] = value | 89 current_section[key] = value |
| 51 else: | 90 else: |
| 52 # something bad happen! | 91 # something bad happen! |
| 53 raise Exception("Not sure what you're trying to do") | 92 raise Exception("Not sure what you're trying to do") |
| 54 | 93 |
| 94 # interpret the variables | |
| 95 def interpret_variables(global_dict, local_dict): | |
| 96 variables = global_dict.copy() | |
| 97 variables.update(local_dict) | |
| 98 # TODO: string intepolation | |
| 99 return variables | |
| 100 | |
| 101 sections = [(i, interpret_variables(variables, j)) for i, j in sections] | |
| 55 return sections | 102 return sections |
| 56 | 103 |
| 57 if __name__ == '__main__': | 104 if __name__ == '__main__': |
| 58 import sys | 105 import sys |
| 59 for i in sys.argv[1:]: | 106 for i in sys.argv[1:]: |
