7
7
8
8
"""
9
9
10
- import yaml
11
10
import json
11
+ import yaml
12
+
12
13
from .. import format
14
+ from ..info import FORMAT_VERSION
13
15
from . import xmlparser
14
16
15
- # FIX ME: Version should not be hardcoded here. Import from odML module after
16
- # fixing the circular imports issue.
17
- odml_version = '1'
18
-
19
17
allowed_parsers = ['ODML' , 'XML' , 'YAML' , 'JSON' ]
20
18
21
19
20
+ class ParserException (Exception ):
21
+ pass
22
+
23
+
22
24
class ODMLWriter :
23
- '''
25
+ """
24
26
A generic odML document writer, for XML, YAML and JSON.
25
27
26
28
Usage:
27
29
xml_writer = ODMLWriter(parser='XML')
28
30
xml_writer.write_file(odml_document, filepath)
29
- '''
31
+ """
30
32
31
33
def __init__ (self , parser = 'XML' ):
32
34
self .doc = None # odML document
@@ -55,7 +57,6 @@ def to_dict(self, odml_document):
55
57
self .parsed_doc = parsed_doc
56
58
57
59
def get_sections (self , section_list ):
58
-
59
60
section_seq = []
60
61
61
62
for section in section_list :
@@ -81,7 +82,6 @@ def get_sections(self, section_list):
81
82
return section_seq
82
83
83
84
def get_properties (self , props_list ):
84
-
85
85
props_seq = []
86
86
87
87
for prop in props_list :
@@ -100,7 +100,7 @@ def get_properties(self, props_list):
100
100
prop_dict [attr ] = t
101
101
102
102
props_seq .append (prop_dict )
103
-
103
+
104
104
return props_seq
105
105
106
106
def get_values (self , value_list ):
@@ -122,6 +122,17 @@ def get_values(self, value_list):
122
122
return value_seq
123
123
124
124
def write_file (self , odml_document , filename ):
125
+ # Write document only if it does not contain validation errors.
126
+ from ..validation import Validation # disgusting import problems
127
+ validation = Validation (odml_document )
128
+ msg = ""
129
+ for e in validation .errors :
130
+ if e .is_error :
131
+ msg += "\n \t - %s %s: %s" % (e .obj , e .type , e .msg )
132
+ if msg != "" :
133
+ msg = "Resolve document validation errors before saving %s" % msg
134
+ raise ParserException (msg )
135
+
125
136
file = open (filename , 'w' )
126
137
file .write (self .to_string (odml_document ))
127
138
file .close ()
@@ -135,7 +146,7 @@ def to_string(self, odml_document):
135
146
self .to_dict (odml_document )
136
147
odml_output = {}
137
148
odml_output ['Document' ] = self .parsed_doc
138
- odml_output ['odml-version' ] = odml_version
149
+ odml_output ['odml-version' ] = FORMAT_VERSION
139
150
140
151
if self .parser == 'YAML' :
141
152
string_doc = yaml .dump (odml_output , default_flow_style = False )
@@ -150,8 +161,8 @@ class ODMLReader:
150
161
based on the given data exchange format, like XML, YAML or JSON.
151
162
152
163
Usage:
153
- yaml_odml_doc = ODMLReader(parser='YAML').fromFile(open( "odml_doc.yaml") )
154
- json_odml_doc = ODMLReader(parser='JSON').fromFile(open( "odml_doc.json") )
164
+ yaml_odml_doc = ODMLReader(parser='YAML').from_file( "odml_doc.yaml")
165
+ json_odml_doc = ODMLReader(parser='JSON').from_file( "odml_doc.json")
155
166
"""
156
167
157
168
def __init__ (self , parser = 'XML' ):
@@ -162,18 +173,29 @@ def __init__(self, parser='XML'):
162
173
if parser not in allowed_parsers :
163
174
raise NotImplementedError ("'%s' odML parser does not exist!" % parser )
164
175
self .parser = parser
176
+ self .warnings = []
165
177
166
178
def is_valid_attribute (self , attr , fmt ):
167
179
if attr in fmt ._args :
168
180
return attr
169
181
if fmt .revmap (attr ):
170
182
return attr
171
- print ("Invalid element <%s> inside <%s> tag" % (attr , fmt .__class__ .__name__ ))
183
+ msg = "Invalid element <%s> inside <%s> tag" % (attr , fmt .__class__ .__name__ )
184
+ print (msg )
185
+ self .warnings .append (msg )
172
186
return None
173
187
174
188
def to_odml (self ):
175
-
176
- self .odml_version = self .parsed_doc .get ('odml-version' , odml_version )
189
+ # Parse only odML documents of supported format versions.
190
+ if 'odml-version' not in self .parsed_doc :
191
+ raise ParserException ("Invalid odML document: Could not find odml-version." )
192
+ elif self .parsed_doc .get ('odml-version' ) != FORMAT_VERSION :
193
+ msg = ("Cannot read file: invalid odML document format version '%s'. \n "
194
+ "This package supports odML format versions: '%s'."
195
+ % (self .parsed_doc .get ('odml-version' ), FORMAT_VERSION ))
196
+ raise ParserException (msg )
197
+
198
+ self .odml_version = self .parsed_doc .get ('odml-version' )
177
199
self .parsed_doc = self .parsed_doc ['Document' ]
178
200
179
201
doc_attrs = {}
@@ -193,7 +215,6 @@ def to_odml(self):
193
215
return self .doc
194
216
195
217
def parse_sections (self , section_list ):
196
-
197
218
odml_sections = []
198
219
199
220
for section in section_list :
@@ -218,7 +239,6 @@ def parse_sections(self, section_list):
218
239
219
240
return odml_sections
220
241
221
-
222
242
def parse_properties (self , props_list ):
223
243
odml_props = []
224
244
@@ -257,52 +277,54 @@ def parse_values(self, value_list):
257
277
258
278
return odml_values
259
279
260
-
261
280
def from_file (self , file ):
262
281
263
282
if self .parser == 'XML' or self .parser == 'ODML' :
264
- odml_doc = xmlparser .XMLReader ().fromFile (file )
283
+ par = xmlparser .XMLReader (ignore_errors = True )
284
+ self .warnings = par .warnings
285
+ odml_doc = par .fromFile (file )
265
286
self .doc = odml_doc
266
287
return odml_doc
267
288
268
289
elif self .parser == 'YAML' :
269
- try :
270
- self . parsed_doc = yaml . load ( file )
271
- except yaml . parser . ParserError as e :
272
- print ( e )
273
- return
274
- finally :
275
- file . close ()
290
+ with open ( file ) as yaml_data :
291
+ try :
292
+ self . parsed_doc = yaml . load ( yaml_data )
293
+ except yaml . parser . ParserError as e :
294
+ print ( e )
295
+ return
296
+
276
297
return self .to_odml ()
277
298
278
299
elif self .parser == 'JSON' :
279
- try :
280
- self .parsed_doc = json .load (file )
281
- except json .decoder .JSONDecodeError as e :
282
- print (e )
283
- return
284
- finally :
285
- file .close ()
286
- return self .to_odml ()
300
+ with open (file ) as json_data :
301
+ try :
302
+ self .parsed_doc = json .load (json_data )
303
+ except ValueError as e : # Python 2 does not support JSONDecodeError
304
+ print ("JSON Decoder Error: %s" % e )
305
+ return
287
306
307
+ return self .to_odml ()
288
308
289
309
def from_string (self , string ):
290
310
291
311
if self .parser == 'XML' or self .parser == 'ODML' :
292
312
odml_doc = xmlparser .XMLReader ().fromString (string )
293
313
self .doc = odml_doc
294
314
return self .doc
315
+
295
316
elif self .parser == 'YAML' :
296
317
try :
297
- odml_doc = yaml .load (string )
318
+ self . parsed_doc = yaml .load (string )
298
319
except yaml .parser .ParserError as e :
299
320
print (e )
300
321
return
301
322
return self .to_odml ()
323
+
302
324
elif self .parser == 'JSON' :
303
325
try :
304
- odml_doc = json .loads (string )
305
- except json . decoder . JSONDecodeError as e :
306
- print (e )
326
+ self . parsed_doc = json .loads (string )
327
+ except ValueError as e : # Python 2 does not support JSONDecodeError
328
+ print ("JSON Decoder Error: %s" % e )
307
329
return
308
330
return self .to_odml ()
0 commit comments