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

Annotation of /trunk/contrib/diff_formed.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 394 - (hide annotations)
Thu Aug 12 10:00:47 2010 UTC (14 years, 6 months ago) by torsten
File MIME type: text/x-python
File size: 8643 byte(s)
Improved script. Added more options

1 torsten 393 # -*- 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 torsten 394 def perform(self, elements=None, subtree=None, fields=None, check_attributes=False):
76     log.info('Only checking %s elements' % ",".join(elements or ['all']))
77 torsten 393 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 torsten 394 if subtree:
83     needle = '//*[@name="%s"]//%s' % (subtree, element)
84     else:
85     needle = '//%s' % (element)
86     log.debug("Searching for %s" % needle)
87     for e in self.old_xml_doc.findall(needle):
88     if fields is not None:
89     name = e.attrib.get('name')
90     if str(name ) not in fields:
91     log.debug('Old: Not found %s in %s' % (name, fields))
92     continue
93 torsten 393 self.elements_old[element].append(e)
94 torsten 394 for e in self.new_xml_doc.findall(needle):
95     if fields is not None:
96     name = e.attrib.get('name')
97     if str(name )not in fields:
98     log.debug('New: Not found %s in %s' % (name, fields))
99     continue
100 torsten 393 self.elements_new[element].append(e)
101     self.diff_element(element, check_attributes)
102    
103     def diff_element(self, element, check_attributes):
104     log.debug('Checking %s elements' % element)
105     out = []
106    
107     # Search for old field in new
108     for o in self.elements_old.get(element):
109     error = []
110     name = o.attrib.get('name')
111     found = False
112     for n in self.elements_new.get(element):
113     if name == n.attrib.get('name'):
114     found = True
115     try:
116     if check_attributes:
117     self.diff_attributes(o, n)
118     except AttributeChangeException, e:
119     error.append("Attributes changed for '%s': %s" % (name, e.message))
120     if element == 'choice':
121     error.extend(self.diff_choicelist(o, n, check_attributes))
122     break
123     if not found:
124     error.append("Deleted")
125    
126     if error:
127     out.append("Field: %s (%s)" % (name, element))
128     out.append('---')
129     out.append('Changes:')
130     for num, err in enumerate(error):
131     out.append('%s. %s' % (num, err))
132     out.append('===')
133    
134     # Searching for new fields in old
135     for o in self.elements_new.get(element):
136     error = []
137     name = o.attrib.get('name')
138     # Search for element in new
139     found = False
140     for n in self.elements_old.get(element):
141     if name == n.attrib.get('name'):
142     found = True
143     break
144     if not found:
145     error.append("New")
146 torsten 394 if element == 'choice':
147     error.extend(self.diff_choicelist(None, o, check_attributes))
148 torsten 393
149     if error:
150     out.append("Field: %s (%s)" % (name, element))
151     out.append('---')
152     out.append('Changes:')
153     for num, err in enumerate(error):
154     out.append('%s. %s' % (num, err))
155     out.append('===')
156    
157     for o in out:
158     print unicode(o).encode("utf-8")
159    
160     def diff_choicelist(self, o, n, check_attributes):
161     old = {}
162     new = {}
163     errors = []
164 torsten 394 if o is not None:
165     for c in o.findall('.//bool'):
166     old[c.attrib.get('value')] = c
167     if n is not None:
168     for c in n.findall('.//bool'):
169     new[c.attrib.get('value')] = c
170 torsten 393
171     for key in old.keys():
172     if new.has_key(key):
173     try:
174     if check_attributes:
175     self.diff_attributes(old.get(key), new.get(key))
176     except AttributeChangeException, e:
177     errors.append("Attributes changed for '%s': %s " % (key, e.message) )
178     else:
179     errors.append("Deleted option: '%s' value: '%s'" % (old.get(key).attrib.get('description'), key))
180     for key in new.keys():
181     if not old.has_key(key):
182     errors.append("New option: '%s' value: '%s'" % (new.get(key).attrib.get('description'), key))
183    
184     return errors
185    
186     def diff_attributes(self, o, n):
187     ok = False
188     new = []
189     changed = []
190     deleted = []
191     for key, value in o.attrib.iteritems():
192     if n.attrib.has_key(key):
193     if n.get(key) == value:
194     pass #Ok
195     else:
196     changed.append(key)
197     else:
198     deleted.append(key)
199     for key, value in n.attrib.iteritems():
200     if not o.attrib.has_key(key):
201     new.append(key)
202    
203     if len(new) > 0 or len(changed) > 0 or len(deleted) > 0:
204     raise AttributeChangeException(new, changed, deleted)
205    
206     def usage(code, msg=''):
207     print >> sys.stderr, __doc__
208     if msg:
209     print >> sys.stderr, msg
210     sys.exit(code)
211    
212     def main():
213     try:
214 torsten 394 opts, args = getopt.getopt(sys.argv[1:], 'hvVe:s:f:',
215     ['elements=', 'check-attributes', 'subtree=', 'fields='])
216 torsten 393
217     except getopt.error, msg:
218     usage(1, msg)
219    
220     elements = None
221 torsten 394 subtree = None
222     fields = None
223 torsten 393 check_attributes = False
224     for opt, arg in opts:
225     if opt in ('-v'):
226     log.setLevel(logging.INFO)
227     if opt in ('-V'):
228     log.setLevel(logging.DEBUG)
229     if opt in ('-h', '--help'):
230     usage(0)
231     if opt in ('-e', '--elements'):
232     elements = arg.split(',')
233     log.debug('Elements: %s' % elements)
234 torsten 394 if opt in ('-s', '--subtree'):
235     subtree = arg
236     log.debug('Subtree: %s' % subtree)
237     if opt in ('-f', '--fields'):
238     fields = arg.split(',')
239     log.debug('Fields: %s' % fields)
240 torsten 393 if opt in ('--check-attributes'):
241     check_attributes = True
242     if len(args) < 2:
243     usage(1)
244    
245     ins = Inspector(args[0], args[1])
246 torsten 394 ins.perform(elements, subtree, fields, check_attributes)
247 torsten 393
248     if __name__ == '__main__':
249     main()

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26