Nektar++
Classes | Functions | Variables
CellMLToNektar.validator Namespace Reference

Classes

class  CellMLValidator
 
class  LxmlRelaxngValidator
 
class  RvpRelaxngValidator
 
class  ValidatorError
 

Functions

def quit (self)
 def del(self): """ Tell our RVP process to quit. More...
 
def validate (self, stream)
 
def get_validation_errors (self)
 
def _error_found (self, line, col, msg)
 
def _start_tag_open (self, cur, name)
 
def _attribute (self, cur, name, val)
 
def _start_tag_close (self, cur, name)
 
def _end_tag (self, cur, name)
 
def _textonly (self, cur, text)
 
def _mixed (self, cur, text)
 
def _start (self, grammar='0')
 
def _send (self, s)
 
def _recv (self)
 
def _resp (self)
 
def _flush_text (self)
 
def _start_element (self, name, attrs)
 
def _end_element (self, name)
 
def _characters (self, data)
 
def check_repo (repo_dir='../../models/all_from_repository', model_suffix='xml', invalid_if_warnings=False, compare=True)
 Convenience functions #. More...
 
def compare_output_files (new_stream, old_filename)
 
def get_options (args)
 For running as an executable #. More...
 
def run ()
 

Variables

 pycml_path = os.path.dirname(os.path.realpath(__file__))
 
list __version__ = "$Revision: 25790 $"[11:-2]
 
string profile_name = '/tmp/pycml-profile-%f-%d' % (time.time(), os.getpid())
 
 _text
 
 _error_messages
 
 _prevcol
 
 _pat
 
 _parser
 
 _errors
 
 _ismixed
 

Detailed Description

Copyright (c) 2005-2016, University of Oxford.
All rights reserved.

University of Oxford means the Chancellor, Masters and Scholars of the
University of Oxford, having an administrative office at Wellington
Square, Oxford OX1 2JD, UK.

This file is part of Chaste.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
 * Neither the name of the University of Oxford nor the names of its
   contributors may be used to endorse or promote products derived from this
   software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Function Documentation

◆ _attribute()

def CellMLToNektar.validator._attribute (   self,
  cur,
  name,
  val 
)
private

Definition at line 339 of file validator.py.

339 def _attribute(self, cur, name, val):
340 self._send('attribute '+cur+' '+name+' '+val)
341 return self._resp()
def _attribute(self, cur, name, val)
Definition: validator.py:339

◆ _characters()

def CellMLToNektar.validator._characters (   self,
  data 
)
private

Definition at line 432 of file validator.py.

432 def _characters(self, data):
433 self._text = self._text + data
434
435
436
437
438
439
def _characters(self, data)
Definition: validator.py:432

◆ _end_element()

def CellMLToNektar.validator._end_element (   self,
  name 
)
private

Definition at line 428 of file validator.py.

428 def _end_element(self, name):
429 self._flush_text()
430 self._pat = self._end_tag(self._pat, name)
431 self._ismixed = True
def _end_element(self, name)
Definition: validator.py:428

◆ _end_tag()

def CellMLToNektar.validator._end_tag (   self,
  cur,
  name 
)
private

Definition at line 345 of file validator.py.

345 def _end_tag(self, cur, name):
346 self._send('end-tag '+cur+' '+name)
347 return self._resp()
def _end_tag(self, cur, name)
Definition: validator.py:345

◆ _error_found()

def CellMLToNektar.validator._error_found (   self,
  line,
  col,
  msg 
)
private

Definition at line 330 of file validator.py.

330 def _error_found(self, line, col, msg):
331 report = "%d,%d:%s" % (line, col, msg.strip())
332 logging.getLogger('validator').error(report)
333 self._error_messages.append(report)
334
def _error_found(self, line, col, msg)
Definition: validator.py:330

◆ _flush_text()

def CellMLToNektar.validator._flush_text (   self)
private
Apparently Expat doesn't concatenate text nodes, so we do it
manually; the CharDataHandler collects the text, and this
method passes it to the validator.

Definition at line 408 of file validator.py.

408 def _flush_text(self):
409 """
410 Apparently Expat doesn't concatenate text nodes, so we do it
411 manually; the CharDataHandler collects the text, and this
412 method passes it to the validator.
413 """
414 if self._text:
415 if self._ismixed:
416 self._pat = self._mixed(self._pat, self._text)
417 else:
418 self._pat = self._textonly(self._pat, self._text)
419 self._text = ''

◆ _mixed()

def CellMLToNektar.validator._mixed (   self,
  cur,
  text 
)
private
In mixed content, whitespace is discarded, and any non-whitespace
is counted as equal.

Definition at line 351 of file validator.py.

351 def _mixed(self, cur, text):
352 """
353 In mixed content, whitespace is discarded, and any non-whitespace
354 is counted as equal.
355 """
356 if self._ws.search(text):
357 self._send('mixed '+cur+' .')
358 return self._resp()
359 else:
360 return cur
def _mixed(self, cur, text)
Definition: validator.py:351

◆ _recv()

def CellMLToNektar.validator._recv (   self)
private
Receive a zero-terminated response from RVP; drop zero byte.

Definition at line 371 of file validator.py.

371 def _recv(self):
372 """
373 Receive a zero-terminated response from RVP; drop zero byte.
374 """
375 s = ''
376 while True:
377 # 16 is a good buffer length for ok responses; errors
378 # should be rare
379 s = s + os.read(self._rvpout, 16)
380 if s[-1] == '\0': break
381 return s[:-1]

◆ _resp()

def CellMLToNektar.validator._resp (   self)
private
Get a reply from RVP.
If an error occurs, log the message.
Return the current pattern value.

Definition at line 382 of file validator.py.

382 def _resp(self):
383 """
384 Get a reply from RVP.
385 If an error occurs, log the message.
386 Return the current pattern value.
387 """
388 r = self._recv().split(' ', 3)
389 if r[0] == 'ok': return r[1]
390 if r[0] == 'error':
391 self._errors = True
392 if r[3] != '': # Only report if we have a message
393 line = self._parser.CurrentLineNumber
394 col = self._parser.CurrentColumnNumber
395 if line != self._prevline or col != self._prevcol:
396 # One report per file position
397 self._error_found(line, col, r[3])
398 self._prevline, self._prevcol = line, col
399 return r[1]
400 if r[0] == 'er':
401 self._errors = True
402 return r[1]
403 # Unknown response
404 raise self.RvpProtocolError, "unexpected response '"+r[0]+"'"
405
406

◆ _send()

def CellMLToNektar.validator._send (   self,
  s 
)
private
Terminate string with zero, encode in UTF-8 and send to RVP.

Definition at line 366 of file validator.py.

366 def _send(self, s):
367 """
368 Terminate string with zero, encode in UTF-8 and send to RVP.
369 """
370 os.write(self._rvpin, s.encode('UTF-8') + '\0')

◆ _start()

def CellMLToNektar.validator._start (   self,
  grammar = '0' 
)
private

Definition at line 361 of file validator.py.

361 def _start(self, grammar = '0'):
362 self._send('start '+grammar)
363 return self._resp()
364
def _start(self, grammar='0')
Definition: validator.py:361

◆ _start_element()

def CellMLToNektar.validator._start_element (   self,
  name,
  attrs 
)
private

Definition at line 420 of file validator.py.

420 def _start_element(self, name, attrs):
421 self._ismixed = True
422 self._flush_text()
423 self._pat = self._start_tag_open(self._pat, name)
424 self._ismixed = False
425 for n, v in attrs.items():
426 self._pat = self._attribute(self._pat, n, v)
427 self._pat = self._start_tag_close(self._pat, name)
def _start_element(self, name, attrs)
Definition: validator.py:420

◆ _start_tag_close()

def CellMLToNektar.validator._start_tag_close (   self,
  cur,
  name 
)
private

Definition at line 342 of file validator.py.

342 def _start_tag_close(self, cur, name):
343 self._send('start-tag-close '+cur+' '+name)
344 return self._resp()
def _start_tag_close(self, cur, name)
Definition: validator.py:342

◆ _start_tag_open()

def CellMLToNektar.validator._start_tag_open (   self,
  cur,
  name 
)
private

Definition at line 336 of file validator.py.

336 def _start_tag_open(self, cur, name):
337 self._send('start-tag-open '+cur+' '+name)
338 return self._resp()
def _start_tag_open(self, cur, name)
Definition: validator.py:336

◆ _textonly()

def CellMLToNektar.validator._textonly (   self,
  cur,
  text 
)
private

Definition at line 348 of file validator.py.

348 def _textonly(self, cur, text):
349 self._send('text '+cur+' '+text)
350 return self._resp()
def _textonly(self, cur, text)
Definition: validator.py:348

◆ check_repo()

def CellMLToNektar.validator.check_repo (   repo_dir = '../../models/all_from_repository',
  model_suffix = 'xml',
  invalid_if_warnings = False,
  compare = True 
)

Convenience functions #.

Validate every model in the CellML repository, and return a list
of invalid models.

If compare is False, writes errors & warnings to log files in the
same folder as the models, otherwise compares the output to log
files already present, and notes differences.

Displays total run time.

Definition at line 444 of file validator.py.

447 compare=True):
448 """
449 Validate every model in the CellML repository, and return a list
450 of invalid models.
451
452 If compare is False, writes errors & warnings to log files in the
453 same folder as the models, otherwise compares the output to log
454 files already present, and notes differences.
455
456 Displays total run time.
457 """
458 def close_log_file(stream, filename):
459 stream.close()
460 try:
461 size = os.path.getsize(filename)
462 if size == 0:
463 os.remove(filename)
464 except OSError:
465 pass
466 import glob, time, gc
467 start_time = time.time()
468 v = CellMLValidator()
469 invalid = []
470 files = glob.glob(repo_dir + '/*.' + model_suffix)
471 files.sort()
472 for filename in files:
473 model = os.path.basename(filename)[:-4]
474 fn = os.path.splitext(filename)[0]
475 warnfn, errfn = fn + '_warnings.log', fn + '_errors.log'
476 if compare:
477 warn_stream = StringIO()
478 err_stream = StringIO()
479 else:
480 warn_stream = open(warnfn, 'w')
481 err_stream = open(errfn, 'w')
482 print "Checking model",model,"at",time.strftime("%X %x"),
483 sys.stdout.flush()
484 valid = v.validate(filename, error_stream=err_stream,
485 warning_stream=warn_stream,
486 invalid_if_warnings=invalid_if_warnings)
487 if not valid:
488 print max(1,4 - (5+len(model))//8) * '\t', "X"
489 else:
490 print
491 if compare:
492 compare_output_files(warn_stream, warnfn)
493 compare_output_files(err_stream, errfn)
494 else:
495 close_log_file(err_stream, errfn)
496 close_log_file(warn_stream, warnfn)
497 if not valid:
498 invalid.append(model)
499 gc.collect()
500 elapsed_time = time.time() - start_time
501 mins,secs = int(elapsed_time//60), int(elapsed_time%60)
502 print len(files),"models checked in",mins,"minutes",secs,"seconds."
503 print len(invalid),"invalid"
504 v.quit()
505 return invalid
506
def compare_output_files(new_stream, old_filename)
Definition: validator.py:507

References CellMLToNektar.validator.compare_output_files().

◆ compare_output_files()

def CellMLToNektar.validator.compare_output_files (   new_stream,
  old_filename 
)

Definition at line 507 of file validator.py.

507def compare_output_files(new_stream, old_filename):
508 def save_new_output():
509 nfp = open(old_filename + '-new', 'w')
510 nfp.write(new_stream.getvalue())
511 nfp.close()
512 new_stream.seek(0, 2)
513 new_len = new_stream.tell()
514 try:
515 fp = open(old_filename, 'r')
516 except IOError:
517 if new_len > 0:
518 print "Log file", old_filename, "doesn't exist,", \
519 "but we have new output"
520 try:
521 ofp = open(os.path.join(os.path.dirname(old_filename),
522 'new'), 'a')
523 print >>ofp, "Log file", old_filename, "doesn't exist,", \
524 "but we have new output"
525 ofp.close()
526 except IOError:
527 pass
528 save_new_output()
529 return
530 new_stream.seek(0)
531 new_lines = set(new_stream.readlines())
532 old_lines = set(fp.readlines())
533 if old_lines != new_lines:
534 print "Output set differs from log file", old_filename
535 print "Lines added:", new_lines - old_lines
536 print "Lines removed:", old_lines - new_lines
537 try:
538 ofp = open(os.path.join(os.path.dirname(old_filename), 'new'), 'a')
539 print >>ofp, "Output set differs from log file", old_filename
540 print >>ofp, "Lines added:", new_lines - old_lines
541 print >>ofp, "Lines removed:", old_lines - new_lines, "\n"
542 ofp.close()
543 except IOError:
544 pass
545 save_new_output()
546 new_stream.close()
547 fp.close()
548 return
549

Referenced by CellMLToNektar.validator.check_repo().

◆ get_options()

def CellMLToNektar.validator.get_options (   args)

For running as an executable #.

get_options(args):
Process our command-line options.

args is a list of options & positional arguments.

Definition at line 554 of file validator.py.

554def get_options(args):
555 """get_options(args):
556 Process our command-line options.
557
558 args is a list of options & positional arguments.
559 """
560 usage = 'usage: %prog [options] <cellml file or URI> ...'
561 parser = optparse.OptionParser(version="%%prog %s" % __version__,
562 usage=usage)
563 parser.add_option('-o', dest='outfilename', metavar='OUTFILE',
564 help='write *all* output to OUTFILE (overrides -e and -w)')
565 parser.add_option('-e', '--error-file',
566 dest='errfilename', metavar='ERRFILE',
567 default='stderr',
568 help='write errors to ERRFILE [default %default]')
569 parser.add_option('-w', '--warning-file',
570 dest='warnfilename', metavar='WARNFILE',
571 default='stderr',
572 help='write warnings to WARNFILE [default %default]')
573 parser.add_option('-q', '--quiet',
574 dest='quiet', action='store_true', default=False,
575 help="don't display any output, just set exit status")
576 parser.add_option('--no-warnings', '--only-errors',
577 dest='show_warnings', action='store_false',
578 default=True,
579 help="don't display warning messages")
580 parser.add_option('-s', '--space-messages',
581 dest='space_errors', action='store_true',
582 default=False,
583 help="print a blank line after every warning/error message")
584 parser.add_option('-x', '--xml-context',
585 dest='xml_context', action='store_true', default=False,
586 help="display the MathML tree of any expression with invalid units")
587 parser.add_option('-u', '--warn-on-unit-conversions',
588 action='store_true', default=False,
589 help="generate a warning if unit conversions are required")
590 parser.add_option('--Wu', '--warn-on-units-errors',
591 action='store_true', default=False,
592 dest='warn_on_units_errors',
593 help="give a warning instead of an error for"
594 " dimensional inconsistencies")
595 parser.add_option('-i', '--interactive',
596 action='store_true', default=False,
597 help="use with python -i to enter an interactive session"
598 " after validation")
599 parser.add_option('-d', '--debug', action='store_true', default=False,
600 help="output debug info to stderr")
601 parser.add_option('--profile', action='store_true', default=False,
602 help="turn on profiling of PyCml")
603
604 options, args = parser.parse_args(args)
605 if len(args) < 1:
606 parser.error("an input CellML file must be specified")
607 return options, args
608
609
def get_options(args)
For running as an executable #.
Definition: validator.py:554

Referenced by CellMLToNektar.validator.run().

◆ get_validation_errors()

def CellMLToNektar.validator.get_validation_errors (   self)
Return the list of all errors found while validating
the current file.

Definition at line 323 of file validator.py.

323 def get_validation_errors(self):
324 """
325 Return the list of all errors found while validating
326 the current file.
327 """
328 return self._error_messages
329
def get_validation_errors(self)
Definition: validator.py:323

◆ quit()

def CellMLToNektar.validator.quit (   self)

def del(self): """ Tell our RVP process to quit.

This doesn't work well, since del isn't necessarily called at program exit. Hence, there is a manual quit() method. """ self.quit()

Call this method when the validator is finished with.
It terminates the associated RVP process cleanly.
Failure to do so will probably result in an error when your program exits.

Definition at line 288 of file validator.py.

288 def quit(self):
289 """Call this method when the validator is finished with.
290 It terminates the associated RVP process cleanly.
291 Failure to do so will probably result in an error when your program exits.
292 """
293 self._send('quit')
294 return self._resp()
295
def quit(self)
def del(self): """ Tell our RVP process to quit.
Definition: validator.py:288

◆ run()

def CellMLToNektar.validator.run ( )

Definition at line 610 of file validator.py.

610def run():
611 # Validate all files specified on the command line
612 options, files = get_options(sys.argv[1:])
613 validator = CellMLValidator()
614
615 # Open output streams
616 if not options.outfilename is None:
617 out_s = open_output_stream(options.outfilename)
618 err_s = warn_s = out_s
619 else:
620 out_s = sys.stdout
621 err_s = open_output_stream(options.errfilename)
622 warn_s = open_output_stream(options.warnfilename)
623
624 # Keyword arguments for validator
625 kwargs = {'show_warnings': options.show_warnings,
626 'warning_stream': warn_s,
627 'show_errors': not options.quiet,
628 'error_stream': err_s,
629 'space_errors': options.space_errors,
630 'xml_context': options.xml_context,
631 'warn_on_units_errors': options.warn_on_units_errors,
632 'check_for_units_conversions': options.warn_on_unit_conversions}
633
634 if options.debug:
635 formatter = logging.Formatter(fmt="%(name)s %(asctime)s: %(message)s")
636 handler = logging.StreamHandler(sys.stderr)
637 handler.setFormatter(formatter)
638 handler.addFilter(OnlyDebugFilter())
639 logging.getLogger().addHandler(handler)
640 logging.getLogger().setLevel(logging.DEBUG)
641 kwargs['loglevel'] = logging.DEBUG
642
643 # Validate files
644 result = True
645 for f in files:
646 if not options.quiet:
647 print >>out_s, "Validating file", f, "against CellML 1.0"
648 res = validator.validate(f, **kwargs)
649 if not options.quiet:
650 print >>out_s, "File is%s valid CellML 1.0" % ((' NOT','')[res])
651 result = result and res
652
653 # Close output streams
656 close_output_stream(warn_s)
657
658 # Tidy up validator
659 validator.quit()
660
661 # Set exit status
662 if not options.interactive:
663 sys.exit(not result)
664
665
def open_output_stream(fname)
Definition: utilities.py:298
def close_output_stream(stream)
Definition: utilities.py:314

References CellMLToNektar.utilities.close_output_stream(), CellMLToNektar.validator.get_options(), and CellMLToNektar.utilities.open_output_stream().

◆ validate()

def CellMLToNektar.validator.validate (   self,
  stream 
)
Validate an XML document, returning a boolean.

stream should be a file-like object containing the document to
be validated.
Returns True iff the document was valid.

Definition at line 296 of file validator.py.

296 def validate(self, stream):
297 """Validate an XML document, returning a boolean.
298
299 stream should be a file-like object containing the document to
300 be validated.
301 Returns True iff the document was valid.
302 """
303 # Initialise
304 self._text = ''
305 self._errors, self._error_messages = False, []
306 self._prevline, self._prevcol = -1, -1
307 self._pat = self._start()
308 # Create parser
309 parser = self.expat.ParserCreate(namespace_separator=':')
310 parser.StartElementHandler = self._start_element
311 parser.EndElementHandler = self._end_element
312 parser.CharacterDataHandler = self._characters
313 self._parser = parser
314 # Parse & validate
315 try:
316 self._parser.ParseFile(stream)
317 except self.expat.ExpatError, e:
318 self._errors = True
319 self._error_found(e.lineno, e.offset, str(e))
320 # Any errors
321 return not self._errors
322
def validate(self, stream)
Definition: validator.py:296

Referenced by CellMLToNektar.translators.CellMLTranslator.translate().

Variable Documentation

◆ __version__

list CellMLToNektar.validator.__version__ = "$Revision: 25790 $"[11:-2]
private

Definition at line 56 of file validator.py.

◆ _error_messages

CellMLToNektar.validator._error_messages
private

Definition at line 305 of file validator.py.

◆ _errors

CellMLToNektar.validator._errors
private

Definition at line 318 of file validator.py.

◆ _ismixed

CellMLToNektar.validator._ismixed
private

Definition at line 421 of file validator.py.

◆ _parser

CellMLToNektar.validator._parser
private

Definition at line 313 of file validator.py.

◆ _pat

CellMLToNektar.validator._pat
private

Definition at line 307 of file validator.py.

◆ _prevcol

CellMLToNektar.validator._prevcol
private

Definition at line 306 of file validator.py.

◆ _text

CellMLToNektar.validator._text
private

Definition at line 304 of file validator.py.

◆ profile_name

string CellMLToNektar.validator.profile_name = '/tmp/pycml-profile-%f-%d' % (time.time(), os.getpid())

Definition at line 669 of file validator.py.

◆ pycml_path

CellMLToNektar.validator.pycml_path = os.path.dirname(os.path.realpath(__file__))

Definition at line 49 of file validator.py.