-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathxmlhandler.py
More file actions
executable file
·348 lines (290 loc) · 12.7 KB
/
Copy pathxmlhandler.py
File metadata and controls
executable file
·348 lines (290 loc) · 12.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
##############################################################################
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU LGPL License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# See the files gpl.txt and lgpl.txt packaged with this file.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
__author__ = "Mike Rightmire"
__copyright__ = "BioCom Software"
__license__ = "LGPLv3"
__license_file__= "lgpl.txt"
__version__ = "0.9.0.0"
__maintainer__ = "Mike Rightmire"
__email__ = "Mike.Rightmire@BiocomSoftware.com"
__status__ = "Development"
##############################################################################
from BiocomCommon.checks import Checks
from BiocomCommon.confighandler import ConfigHandler
from BiocomCommon.loghandler import log
import inspect
import re
import xml.etree.cElementTree as ET
class XMLHandler(object):
""""""
def __init__(self, *args, **kwargs):
self.checks = Checks()
self.config = ConfigHandler()
self.source = kwargs.pop('source', None)
""" PROPERTIES ========================================================="""
@property
def source(self):
try:
return self._SOURCE
except AttributeError as e:
return None
@source.setter
def source(self, value):
""""""
if value is None:
log.debug("xmlhandler.source has been set to None.")
self._SOURCE = None
self._TREE = None
self._ROOT = None
return
_value = str(value)
if not self.checks.pathExists(_value):
err = ''.join(["xmlhandler.source.setter: ", "The source path '", _value, "' appears invalid. "])
raise ValueError(err)
self._TREE = ET.parse(_value)
self._ROOT = self._TREE.getroot()
self._SOURCE = _value
log.debug(''.join(["xmlhandler.source has been set to '", _value, "'."]))
@source.deleter
def source(self):
self._SOURCE = None
self._TREE = None
self._ROOT = None
@property
def tree(self):
try:
return self._TREE
except AttributeError as e:
return None
@tree.setter
def tree(self, value):
err = ''.join(["xmlhandler.tree.setter: The 'tree' parameter cannot be manually set. Please set 'source' value instead."])
raise NotImplementedError(err)
@tree.deleter
def tree(self):
del source
@property
def root(self):
try:
return self._ROOT
except AttributeError as e:
return None
@root.setter
def root(self, value):
err = ''.join(["xmlhandler.root.setter: The 'root' parameter cannot be manually set. Please set 'source' value instead."])
raise NotImplementedError(err)
@root.deleter
def root(self):
del source
@property
def elements(self):
try:
return self._ELEMENTS
except (AttributeError, NameError) as e:
self._ELEMENTS = []
return self._ELEMENTS
@elements.setter
def elements(self, value):
"""
value must be a string, in the format of an ElementTree findall
statement.
Currently, no string checks are performed. Screw up at your own risk.
"""
# For now, does no check on the value string...so we assume the user
# knows what the hell s/he's doing.
self._ELEMENTS = self.root.findall(value)
@elements.deleter
def elements(self):
self._ELEMENTS = []
@property
def element(self):
try:
return self._ELEMENT
except (AttributeError, NameError) as e:
self._ELEMENT = None
return self._ELEMENT
@element.setter
def element(self, value):
"""
"""
err = ''.join([self.__class__.__name__, ".", inspect.stack()[0][3], ": " ])
def _passed_element(value):
self._ELEMENT = value
def _passed_tuple(value):
if ( (len(value) < 2) or (len(value) > 3) ):
_err = ''.join([err, "Tuple must contain 2 or 3 values in the format (attrib_name, attrib_value, number_of_matched_instance). "])
raise ValueError(_err)
# Get found instance number _end_count
try: _end_count = value[2]
except IndexError: _end_count = 1
# Search elements
_count = 0
for elem in self.dump():
try:
if elem.attrib[value[0]] == value[1]:
# Check which numbered match this is
_count += 1 # Increment match
if _count == _end_count:
self._ELEMENT = elem
return
# KeyError when there is no elem.attrib[value[0]]
except KeyError:
continue
# If here, nothing got found, or the Nth (_count_end) match was not found
self._ELEMENT = None
return False
"""BEGIN"""
# if isinstance(value, xml.etree.ElementTree.Element): # Doesnt work. I dont know why
# Element passed in...just set
if str(type(value)) == "<type 'Element'>": return _passed_element(value)
# assumes first instance of elem.attrib[]'name'
elif isinstance(value, str) : return _passed_tuple( ('name', value) )
# Finds (elem-attrib-name, elem-attrib-value, number of found instance)
elif isinstance(value, tuple) : return _passed_tuple(value)
# Invalid input
else:
err = ''.join([err, "Value '", str(value), "' is not a valid object. ", "\n'value' must be a Name String, an ElementTree Element object, or a tupl containing a (attrib, value, instance) pair. "])
raise ValueError(err)
@element.deleter
def element(self):
self._ELEMENT = None
""" PRIVATE METHODS ===================================================="""
""" PUBLIC METHODS ===================================================="""
@classmethod
def isXMLHandler(self, XML):
# Try to load the file as xml
if isinstance(XML, XMLHandler):
return XML
else:
# If source is not a valid xml file, this will error.
try:
return XMLHandler(source = XML)
except Exception as e:
stack = inspect.stack()
_class = stack[1][0].f_locals["self"].__class__
err = ''.join([_class, ".isXMLHandler:", "Parameter must be an XMLHandler object, or a full-path string to an XML file. (Value = '", str(XML), "'."])
raise ValueError(err)
def write(self, dest = None):
"""
:NAME:
write([dest = String])
:PARAMETERS:
dest = (OPTIONAL) The full file path to which the XML output will
be written. If not supplied, the destination file will be
the original source file (WARNING: THIS WILL OVERWRITE THE
SOURCE FILE!)
"""
err = ''.join([self.__class__.__name__, ".", inspect.stack()[0][3], ": " ])
if dest is None: dest is self.source
try:
self.tree.write(dest, encoding='ISO-8859-1', xml_declaration=True)
except Exception as e:
msg = ''.join([err, "An unknown error occurred trying to export XML. (", str(e), ")."])
log.error(msg)
return False
msg = ''.join(["Tree successfully exported to '", dest, "'. "])
log.info(msg)
return True
def dump(self, _elem = None):
"""
:NAME:
:RETURNS:
A list of cElementTree Elements.
"""
if _elem is None:
return self.root.getiterator()
elif str(type(_elem)) == "<type 'Element'>":
return _elem.getiterator()
else:
err = ''.join([self.__class__.__name__, ".", inspect.stack()[0][3], ": " ])
err = ''.join([err, "Value passed in is not a valid cElement"])
raise ValueError(err)
if __name__ == '__main__':
# _xml = XMLHandler(source = '/Users/mikes/Documents/tmp/DeMIX.toppas')
# _xml = XMLHandler(source = '/Users/mikes/Documents/tmp/FeatureFinderCentroided5.ini')
_xml = XMLHandler(source = '/Users/mikes/Documents/tmp/Workflow.bpwf')
_xml.element = 'bioproximity'
print '_xml.element =', _xml.element.attrib
for i in _xml.element.findall('*'): print i.attrib
#===============================================================================
# _xml.element = _xml.element.find("*[@name='0']")
# print '_xml.element =', _xml.element.attrib
#
# _xml.element = _xml.element.find("NODE[@name='parameters']")
# print '_xml.element =', _xml.element.attrib
#===============================================================================
# log.debug(str(xml), log_level = 10, screendump = True)
# xml.write('/Users/mikes/Documents/tmp/TESTXMLOUTPUT.xml')
#===========================================================================
#===============================================================================
# import inspect
# import time
# from Bioproximity.common.openms_bridge import OpenMSBridge
# OPENMS = OpenMSBridge()
#
# log.debug("Starting xmlhandler test...",
# logfile = 'syslog',
# screendump = True,
# log_level = 10,
# )
# xml = XMLHandler(source = "/Users/mikes/Documents/tmp/DeMix.top")
# xml = XMLHandler(source = "/Users/mikes/Documents/tmp/DeMix.toppas")
# # xml = XMLHandler(source = "nope")
# print "xml.source:", xml.source
# print "xml.tree:", xml.tree
# print "xml.root:", xml.root
# print "xml.elements:", xml.elements
# print "xml.tree.getroot():", xml.tree.getroot
# print inspect.getmembers(xml, predicate=inspect.ismethod)
# # for i in [elem.attrib for elem in xml.root.iter()]:
# # print i
# #===========================================================================
# # elem = xml.root.findall("NODE[@name='veices']")
# # print 'elem=', elem
# #===========================================================================
# elem = [elem.attrib['name'] for elem in xml.root.findall("NODE")]
# print 'elem:', elem
# time.sleep(.1)
# exes = OPENMS.methods('installed')
# print 'exes:', exes
# print [i for e in elem for i in exes if e in i]
# # for elem in xml.root.iter():
# # try:
# # if ((elem.attrib['name'] == 'toppas_type') and (elem.attrib['value'] =="tool") ):
# # print; print '============'
# # print elem
# # except: pass
#===============================================================================
#===============================================================================
# for elem in xml.root.findall("NODE[@name='0']"):
# print '----'
# print elem, ':', elem.attrib
# # print "xml.root.findall(NODE[@name='vertices']).elem.attrib =", elem.attrib
# # for i in elem: print i
#===============================================================================
#===========================================================================
# for node in xml.root:
# print node, node.attrib['name']
#
# raw_input('Press enter...')
#===========================================================================
#===============================================================================
# for i in xml.elements:
# print 'i:', i
# print "i.attrib:", i.attrib
# print "i.attrib['name']:", i.attrib['name']
# print '------------------------------------'
# # for parent in xml.tree.getiterator():
# # for child in parent:
# # print child.attrib['name']
#===============================================================================