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

Annotation of /trunk/contrib/diff_formed.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 393 - (hide 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 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     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