/[formed]/trunk/contrib/diff_formed.py
ViewVC logotype

Contents of /trunk/contrib/diff_formed.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 393 - (show annotations)
Tue Aug 10 15:53:42 2010 UTC (14 years, 6 months ago) by torsten
File MIME type: text/x-python
File size: 7405 byte(s)
Added helper script to diff to given formedtree files.

1 # -*- coding: utf-8 -*-
2 #!/usr/bin/python
3 """\n
4 Diffs to given formedtrees. Note that currently no checks on external choice
5 lists are done. Furter checks on Repeatgroups are very simple for now.
6 Warning: If a field with the same name is moved from master_tbl into a RG, it will not be
7 noticed, as we do not diff strutural changes.
8
9 Usage: diff_formed.py old new
10
11 Options:
12 -h / --help Print this message and exit.
13 -e / --elements comma-seperated list of elements to check
14 --check-attributes Check changes in attributes (changed descriptions, target...)
15
16 """
17 # 20100810 Torsten Irlaender <[email protected]>
18 #
19 # This program is free software under the GNU GPL (>=v2)
20 # Read the file COPYING coming with the software for details.
21
22
23 import sys
24 import getopt
25 import logging
26
27 from lxml import etree
28
29 logging.basicConfig(level=logging.ERROR)
30 log = logging.getLogger('diff_formed')
31
32 class AttributeChangeException(Exception):
33 def __init__(self, n, c, d):
34 self.new = n
35 self.changed = c
36 self.deleted = d
37
38 msg = []
39 if self.new:
40 msg.append('New: %s' % ",".join(self.new))
41 if self.changed:
42 msg.append('Changed: %s' % ",".join(self.changed))
43 if self.deleted:
44 msg.append('Deleted: %s' % ",".join(self.deleted))
45 self.message = " | ".join(msg)
46
47 class Inspector():
48
49 def __init__(self, filename_old, filename_new):
50
51 self.old_xml_doc = None
52 self.new_xml_doc = None
53 self.elements_old = {}
54 self.elements_new = {}
55 self.elements = ['choice', 'text', 'textarea', 'repeat']
56
57 # Open files and load xml
58 try:
59 f1 = None
60 f2 = None
61 log.debug('Old: %s'% filename_old)
62 f1 = open(filename_old, "r")
63 log.debug('New: %s'% filename_new)
64 f2 = open(filename_new, "r")
65 self.old_xml_doc = etree.parse(f1)
66 self.new_xml_doc = etree.parse(f2)
67 except:
68 log.exception('Error while opening file')
69 finally:
70 if f1 is not None:
71 f1.close()
72 if f2 is not None:
73 f2.close()
74
75 def perform(self, elements=None, check_attributes=False):
76 log.info('Only checking %s elements' % ",".join(elements))
77 for element in self.elements:
78 if elements is not None:
79 if element not in elements: continue
80 self.elements_old[element] = []
81 self.elements_new[element] = []
82 for e in self.old_xml_doc.findall("//%s" % element):
83 self.elements_old[element].append(e)
84 for e in self.new_xml_doc.findall("//%s" % element):
85 self.elements_new[element].append(e)
86 self.diff_element(element, check_attributes)
87
88 def diff_element(self, element, check_attributes):
89 log.debug('Checking %s elements' % element)
90 out = []
91
92 # Search for old field in new
93 for o in self.elements_old.get(element):
94 error = []
95 name = o.attrib.get('name')
96 found = False
97 for n in self.elements_new.get(element):
98 if name == n.attrib.get('name'):
99 found = True
100 try:
101 if check_attributes:
102 self.diff_attributes(o, n)
103 except AttributeChangeException, e:
104 error.append("Attributes changed for '%s': %s" % (name, e.message))
105 if element == 'choice':
106 error.extend(self.diff_choicelist(o, n, check_attributes))
107 break
108 if not found:
109 error.append("Deleted")
110
111 if error:
112 out.append("Field: %s (%s)" % (name, element))
113 out.append('---')
114 out.append('Changes:')
115 for num, err in enumerate(error):
116 out.append('%s. %s' % (num, err))
117 out.append('===')
118
119 # Searching for new fields in old
120 for o in self.elements_new.get(element):
121 error = []
122 name = o.attrib.get('name')
123 # Search for element in new
124 found = False
125 for n in self.elements_old.get(element):
126 if name == n.attrib.get('name'):
127 found = True
128 break
129 if not found:
130 error.append("New")
131
132 if error:
133 out.append("Field: %s (%s)" % (name, element))
134 out.append('---')
135 out.append('Changes:')
136 for num, err in enumerate(error):
137 out.append('%s. %s' % (num, err))
138 out.append('===')
139
140 for o in out:
141 print unicode(o).encode("utf-8")
142
143 def diff_choicelist(self, o, n, check_attributes):
144 old = {}
145 new = {}
146 errors = []
147 for c in o.getchildren():
148 old[c.attrib.get('value')] = c
149 for c in n.getchildren():
150 new[c.attrib.get('value')] = c
151
152 for key in old.keys():
153 if new.has_key(key):
154 try:
155 if check_attributes:
156 self.diff_attributes(old.get(key), new.get(key))
157 except AttributeChangeException, e:
158 errors.append("Attributes changed for '%s': %s " % (key, e.message) )
159 else:
160 errors.append("Deleted option: '%s' value: '%s'" % (old.get(key).attrib.get('description'), key))
161 for key in new.keys():
162 if not old.has_key(key):
163 errors.append("New option: '%s' value: '%s'" % (new.get(key).attrib.get('description'), key))
164
165 return errors
166
167 def diff_attributes(self, o, n):
168 ok = False
169 new = []
170 changed = []
171 deleted = []
172 for key, value in o.attrib.iteritems():
173 if n.attrib.has_key(key):
174 if n.get(key) == value:
175 pass #Ok
176 else:
177 changed.append(key)
178 else:
179 deleted.append(key)
180 for key, value in n.attrib.iteritems():
181 if not o.attrib.has_key(key):
182 new.append(key)
183
184 if len(new) > 0 or len(changed) > 0 or len(deleted) > 0:
185 raise AttributeChangeException(new, changed, deleted)
186
187 def usage(code, msg=''):
188 print >> sys.stderr, __doc__
189 if msg:
190 print >> sys.stderr, msg
191 sys.exit(code)
192
193 def main():
194 try:
195 opts, args = getopt.getopt(sys.argv[1:], 'hvVe:',
196 ['elements=', 'check-attributes'])
197
198 except getopt.error, msg:
199 usage(1, msg)
200
201 elements = None
202 check_attributes = False
203 for opt, arg in opts:
204 if opt in ('-v'):
205 log.setLevel(logging.INFO)
206 if opt in ('-V'):
207 log.setLevel(logging.DEBUG)
208 if opt in ('-h', '--help'):
209 usage(0)
210 if opt in ('-e', '--elements'):
211 elements = arg.split(',')
212 log.debug('Elements: %s' % elements)
213 if opt in ('--check-attributes'):
214 check_attributes = True
215 if len(args) < 2:
216 usage(1)
217
218 ins = Inspector(args[0], args[1])
219 ins.perform(elements, check_attributes)
220
221 if __name__ == '__main__':
222 main()

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26