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