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.

References CellMLToNektar.validator.check_repo().

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 447 of file validator.py.

References CellMLToNektar.validator.compare_output_files().

Referenced by CellMLToNektar.validator._characters().

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

◆ compare_output_files()

def CellMLToNektar.validator.compare_output_files (   new_stream,
  old_filename 
)

Definition at line 507 of file validator.py.

Referenced by CellMLToNektar.validator.check_repo().

507 def 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 
def compare_output_files(new_stream, old_filename)
Definition: validator.py:507

◆ 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.

Referenced by CellMLToNektar.validator.run().

554 def 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

◆ 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.

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

610 def 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
654  close_output_stream(out_s)
655  close_output_stream(err_s)
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 get_options(args)
For running as an executable #.
Definition: validator.py:554
def open_output_stream(fname)
Definition: utilities.py:298
def close_output_stream(stream)
Definition: utilities.py:314

◆ 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

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.