]> git.phdru.name Git - m_lib.git/blob - m_lib/flad/fladw.py
Fix exceptions for Py3 compatibility
[m_lib.git] / m_lib / flad / fladw.py
1 """
2    Flat ASCII Database to load WIN.INI-like files.
3 """
4
5
6 import re
7 from m_lib.flad import flad
8
9
10 from .flad import checking_error
11 class error(checking_error):
12     pass
13
14 class section_error(checking_error):
15     pass
16
17
18 re_section = re.compile("^ *\[(.+)\] *$")
19
20
21 class Flad_WIni(flad.Flad):
22    """
23       FLAD database is a list of records, where every record is
24       a tuple (section_name, keys, section_dictionary).
25       Sounds similary to Flad? But it is Flad! The only difference is that
26       Flad_WIni has section names and keys (i.e. list of keys and comments
27       in every section to preserve comments and desired order of keys).
28    """
29    def __init__(self):
30       flad.Flad.__init__(self, key_sep = '=')
31       self.first_section = 1
32
33
34    def __parse_line(self, record, line): # Internal function
35       match = re_section.match(line) # Record separator is section name
36       if match:
37          return match.group(1) # Signal to stop filling the record (section) and start a new one
38
39       if self.first_section:
40          if line.strip() != '':
41             raise error("non-empty line before 1st section")
42
43       elif (line.strip() == '') or (line.lstrip()[0] == ';') : # Empty line or comment
44          record[0].append(line)
45
46       else:
47          key, value = self.split_key(line)
48          if key in record[1].keys(): # This have to be done with check_record
49                                   # but the record is not complete now,
50                                   # so it is not ready to be checked :(
51                                   # And, of course, two keys with the same name
52                                   # cannot be added to dictionary
53             raise KeyError("field key \"" + key + "\" already in record")
54
55          record[0].append(key)
56          record[1][key] = value
57
58       return 0
59
60
61    def create_new_record(self):
62       return ([], {})
63
64
65    def feed(self, record, line):
66       if line:
67          section = self.__parse_line(record, line)
68          if section:
69             if not self.first_section:
70                self.append((self.section, record[0], record[1]))
71                self.section = section
72
73                return 1 # Section filled - create new section
74             else:
75                self.first_section = 0
76                self.section = section
77
78          else:
79             if self.first_section and (line.strip() != ''):
80                raise error("non-empty line before 1st section")
81             # else: line had been appended to section in __parse_line()
82
83       else: # This called after last line of the source file
84          self.append((self.section, record[0], record[1]))
85          del self.section, self.first_section
86
87          # Now remove last empty line in every section
88          for record in self:
89             klist = record[1]
90             if klist:
91                l = len(klist) - 1
92                if klist[l].strip() == '':
93                   del klist[l]
94
95       return 0
96
97
98    def store_to_file(self, f):
99       if type(f) == type(''): # If f is string - use it as file's name
100          outfile = open(f, 'w')
101       else:
102          outfile = f          # else assume it is opened file (fileobject) or
103                               # "compatible" object (must has write() method)
104
105       flush_section = 0 # Do not close 1st section
106
107       for record in self:
108          if flush_section:
109             outfile.write('\n') # Close section
110          else:
111             flush_section = 1    # Set flag for all but 1st section
112
113          outfile.write('[' + record[0] + ']\n') # Section
114
115          if record[1]:
116             for key in record[1]:
117                if key.strip() == '' or key.lstrip()[0] == ';' :
118                   outfile.write(key)
119                else:
120                   outfile.write(key + self.key_sep + record[2][key] + '\n')
121
122       if type(f) == type(''): # If f was opened - close it
123          outfile.close()
124
125
126    def find_section(self, section):
127       for i in range(0, len(self)):
128          record = self[i]
129          if record[0] == section:
130             return i
131
132       return -1
133
134
135    def add_section(self, section):
136       rec_no = self.find_section(section)
137       if rec_no >= 0:
138          raise section_error("section [%s] already exists" % section)
139
140       self.append((section, [], {}))
141
142
143    def del_section(self, section):
144       rec_no = self.find_section(section)
145       if rec_no < 0:
146          raise section_error("section [%s] does not exists" % section)
147
148       del self[rec_no]
149
150
151    def set_keyvalue(self, section, key, value):
152       rec_no = self.find_section(section)
153       if rec_no < 0:
154          record = (section, [key], {key: value})
155          self.append(record)
156
157       else:
158          record = self[rec_no]
159          if key not in record[1]:
160             record[1].append(key)
161          record[2][key] = value
162
163
164    def get_keyvalue(self, section, key):
165       rec_no = self.find_section(section)
166       if rec_no < 0:
167          raise section_error("section [%s] does not exists" % section)
168
169       record = self[rec_no]
170       if key not in record[1]:
171          raise KeyError("section [%s] does not has `%s' key" % (section, key))
172
173       return record[2][key]
174
175
176    def get_keydefault(self, section, key, default):
177       rec_no = self.find_section(section)
178       if rec_no < 0:
179          return default
180
181       record = self[rec_no]
182       if key not in record[1]:
183          return default
184
185       return record[2][key]
186
187
188    def del_key(self, section, key):
189       rec_no = self.find_section(section)
190       if rec_no < 0:
191          raise section_error("section [%s] does not exists" % section)
192
193       record = self[rec_no]
194       if key not in record[1]:
195          raise KeyError("section [%s] does not has `%s' key" % (section, key))
196
197       klist = record[1]
198       del klist[klist.index(key)]
199       del record[2][key]
200
201
202 def load_file(f):
203    db = Flad_WIni()
204    db.load_file(f)
205
206    return db
207
208
209 def load_from_file(f):
210    db = Flad_WIni()
211    db.load_from_file(f)
212
213    return db