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

Annotation of /trunk/contrib/diff_formed.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 395 - (hide annotations)
Thu Aug 12 10:03:17 2010 UTC (14 years, 6 months ago) by torsten
File MIME type: text/x-python
File size: 8772 byte(s)
Updated help

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26