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