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 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821
|
#!/usr/bin/env python3
# =============================================================================
# @file writeErrorTable.py
# @brief Write documentation for SBML error codes
# @author Sarah Keating
# @author Michael Hucka
# =============================================================================
#
# This Python program interrogates the currently-installed libSBML library to
# generate documentation about the libSBML diagnostic codes, and generate
# output used in several contexts. The output produced by this program is
# controlled by the first command-line argument given to it:
#
# * Given --doc, it will generate a table suitable for use in the libSBML
# API documentation as it appears in the header of SBMLError.h. The file
# it produces is meant to replace src/sbml/common/common-sbmlerror-codes.h.
# In other words, do the following:
#
# writeErrorTable.py --doc ../../../src/sbml/common/common-sbmlerror-codes.h
#
# * Given --enum, it will generate the SBMLErrorCode_t enum for SBMLError.h.
# (The output needs to be manually copied and pasted into SBMLError.h.)
#
# * Given --web, it will generate output used in the table in the web page at
# http://sbml.org/Facilities/Documentation/Error_Categories.
#
# Here is a typical way of using this program:
#
# 1) Make any desired updates to the text of the diagnostic messages in
# src/sbml/SBMLErrorTable.h.
#
# 2) Rebuild and install libSBML on your computer, with the Python bindings
# enabled. This is necessary because this program (writeErrorTable.py)
# uses the libSBML Python bindings to do its work.
#
# 3) Configure your PYTHONPATH environment variable to encompass this newly-
# installed copy of libSBML. Double-check that your Python executable
# is in fact picking up the copy of libSBML you think it is.
#
# 4) Run this program 3 times, as following
#
# ./writeErrorTable.py --doc doc-fragment.txt
# ./writeErrorTable.py --enum enum.txt
# ./writeErrorTable.py --web sbmlerror-table.html
#
# 5) Replace sbmlerror-table.html on sbml.org, and edit SBMLError.h to
# insert the contents of doc-fragment.txt and enum.txt in the appropriate
# places.
#
#<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# This file is part of libSBML. Please visit http://sbml.org for more
# information about SBML, and the latest version of libSBML.
#
# Copyright (C) 2013-2018 jointly by the following organizations:
# 1. California Institute of Technology, Pasadena, CA, USA
# 2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK
# 3. University of Heidelberg, Heidelberg, Germany
#
# Copyright (C) 2009-2013 jointly by the following organizations:
# 1. California Institute of Technology, Pasadena, CA, USA
# 2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK
#
# Copyright (C) 2006-2008 by the California Institute of Technology,
# Pasadena, CA, USA
#
# Copyright (C) 2002-2005 jointly by the following organizations:
# 1. California Institute of Technology, Pasadena, CA, USA
# 2. Japan Science and Technology Agency, Japan
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation. A copy of the license agreement is provided
# in the file named "LICENSE.txt" included with this software distribution
# and also available online as http://sbml.org/software/libsbml/license.html
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
import re, os, sys
from types import *
from imp import *
from string import *
from libsbml import *
# -----------------------------------------------------------------------------
# Globals.
# -----------------------------------------------------------------------------
# The currently-known SBML Levels and Versions.
sbml_levels_versions = [[1, 1], [1, 2],
[2, 1], [2, 2], [2, 3], [2, 4],
[3, 1], [3, 2]]
# Set of error codes that we ignore for purposes of documentation.
ignored_error_codes = {9999, 10599, 20905, 21112, 29999, 90000, 90501, 99502,
99503, 99504, 99994, 99995, 99999}
# Package error code ranges. The numbers are the low end start values.
package_codes = [['comp', 1000000],
['fbc', 2000000],
['qual', 3000000],
['groups', 4000000],
['layout', 6000000]]
# Our approach to finding error codes starts with numbers and then rummages
# through the list of symbols in the libSBML Python module to find the symbol
# that corresponds to each number. That works well enough for our purposes
# when the number is above 100, but for lower numbers, we have collisions
# because there are many short enumerations in libSBML. We don't care about
# numbers lower than 10000 when doing --enum or --doc, but we do for --web,
# where we try to list all error codes. All of those enumerations turn into
# the same numbers starting from 0, so if you grab a symbol from the Python
# module and examine its value and find that it, say, "3", you can't tell
# which enumeration it came from. You can only do that if you know the
# symbol names you care about ahead of time. Since we don't want to
# hard-code all possible libSBML error codes here (avoiding that scenario is
# the point of this program!), we have to find some other way to distinguish
# the cases. The approach taken here is to only worry about the numbers
# below 1000 using a table that enumerates the symbols we care about; when we
# iterate over all error numbers, we always explicitly map the numbers to the
# following codes.
low_numbered_errors = { 0 : 'XMLUnknownError',
1 : 'XMLOutOfMemory',
2 : 'XMLFileUnreadable',
3 : 'XMLFileUnwritable',
4 : 'XMLFileOperationError',
5 : 'XMLNetworkAccessError',
101 : 'InternalXMLParserError',
102 : 'UnrecognizedXMLParserCode',
103 : 'XMLTranscoderError' }
# Fragments for the table used in the documentation for SBMLError.h.
doc_table_start_fragment = '''/**
* @class doc_sbml_error_table
*
* @par
<table id="sbmlerror-table"
class="text-table small-font alt-row-colors"
width="95%" cellspacing="1" cellpadding="2" border="0">
<tr style="background: lightgray" class="normal-font">
<th valign="bottom"><strong>Enumerator</strong></th>
<th valign="bottom"><strong>Meaning</strong></th>
<th align="center" width="10">L1 V1</th>
<th align="center" width="10">L1 V2</th>
<th align="center" width="10">L2 V1</th>
<th align="center" width="10">L2 V2</th>
<th align="center" width="10">L2 V3</th>
<th align="center" width="10">L2 V4</th>
<th align="center" width="10">L3 V1</th>
<th align="center" width="10">L3 V2</th>
</tr>
'''
doc_table_end_fragment = '''</table>
*/
'''
# Templates and fragments used for the enum.
enum_start_fragment = '''/**
* @enum SBMLErrorCode_t
* Codes for all SBML-level errors and warnings from the core specification.
*
* @copydetails doc_sbml_error_code_ranges
*/
typedef enum
{
'''
enum_end_fragment = '''} SBMLErrorCode_t;
'''
# Templates and fragments used for the web page.
web_css_fragment = '''<style type='text/css'>
/*<![CDATA[*/
table {
margin-bottom: 2em;
border: 1px solid #ccc;
border-spacing: 0;
}
td, th {
border: none;
}
th {
border-bottom: 1px solid #ccc;
}
td {
border-bottom: 1px solid white;
}
tr:last-child > td {
border-bottom: none;
}
td.s-fatal {
font-size: 7pt;
color: white;
background-color: darkred;
font-weight: bold;
text-align: center;
letter-spacing: -1px;
padding: 2px;
}
td.s-fatal:before {
content: "F";
}
td.s-error {
font-size: 7pt;
background-color: #dc143c;
font-weight: bold;
text-align: center;
letter-spacing: -1px;
padding: 2px;
}
td.s-error:before {
content: "E";
}
td.s-warning {
font-size: 7pt;
background-color: gold;
font-weight: bold;
text-align: center;
letter-spacing: -1px;
padding: 2px;
}
td.s-warning:before {
content: "W";
}
td.s-na {
font-size: 7pt;
font-weight: bold;
text-align: center;
letter-spacing: -1px;
padding: 2px;
}
td.s-na:before {
content: "NA";
}
tr.headers {
background: lightgray;
}
th.levels {
text-align: center;
width: 1%;
padding: 2px;
letter-spacing: -1px;
}
th.errorid {
width: 12ex;
vertical-align: bottom;
}
th.errorid strong {
color: #333;
}
td.code {
font-size: 8pt;
font-family: -webkit-monospace, monospace;
color: #000;
text-align: center;
letter-spacing: -1px;
}
th.errorname {
width: 20%;
}
td.errorname {
font-size: 8pt;
font-family: -webkit-monospace, monospace;
color: #000;
height: 26px; /* to equalize heights of all table rows. */
}
th.meaning {
font-size: 8pt;
font-style: italic;
vertical-align: bottom;
letter-spacing: -1px;
}
th.meaning strong {
color: #333;
}
td.meaning code {
font-size: 8pt;
}
.s-warning
{
background-color: gold;
padding: .1em .5em;
color: black;
}
.s-error
{
background-color: #D23D24;
padding: .1em .5em;
color: white;
}
.s-fatal
{
background-color: darkred;
padding: .1em .5em;
color: white;
}
.table-pkg-separator {
text-align: center;
background-color: #ffefd5;
font-style: italic;
font-weight: bold;
line-height: 160%;
}
/*]]>*/
</style>
'''
web_toc_start_fragment = '''
<table style='margin-top: 2pt' id="toc" class="toc" summary="Contents">
<tr><td>
<div style="text-align:left">
<a name="TOC"/></a>
'''
web_toc_end_fragment = '''</div>
</td></tr>
</table>
'''
page_intro_template = '''
<p>This page lists all error, warning and informational diagnostic codes
and messages produced by <a
href="http://sbml.org/Software/libSBML">libSBML</a>, the software
underlying the <a
href="http://sbml.org/Facilities/Validator">Online SBML Validator</a>.
The diagnostics whose code numbers are
between 10000 and 90000 are defined in the <a
href="http://sbml.org/Documents/Specifications">SBML specification documents</a>;
the ones with numbers below 10000 and above 90000 are specific to libSBML or
this validation system and are not defined by the SBML specifications. The
groups below provide finer-grained divisions in the diagnostics, for better
comprehensibility.</p>
<p>
In the tables below, the right-hand columns titled "L1V1", "L1V2", etc. refer
to Levels and Versions of the SBML specifications, and the entries in
each column refer to the severity of the condition in that
particular Level and Version of SBML. The codes have the following
meanings:</p>
<p>
<table class="normal-font borderless-table gray-border sm-padding"
width="200px" cellspacing="1" cellpadding="2" border="0"
style="margin-left: 2em">
<tr><th style="text-align: center">Symbol</th><th style="text-align: left">Meaning</th></tr>
<tr><td class="s-warning gray-border"></td><td>Warning</td></tr>
<tr><td class="s-error"></td><td>Error</td></tr>
<tr><td class="s-fatal"></td><td>Fatal</td></tr>
<tr><td class="s-na" style="border: none"></td><td>Not applicable</td></tr>
</table>
<p>For more information about the meanings of diagnostics numbered between
10000 and 90000, please consult the <a
href="http://sbml.org/Documents/Specifications">SBML specification documents</a>
relevant to the particularl Level and Version combination in question.</p>
'''
web_error_table_start_fragment = '''<center>
<table class="sm-padding sm-font alt-row-colors"
width="100%" cellspacing="1" cellpadding="2" border="0">
<tr class="headers">
<th class="errorid">Error code</th>
<th class="errorname">LibSBML name</th>
<th class="errormeaning">Meaning</th>
<th class="levels">L1 V1</th>
<th class="levels">L1 V2</th>
<th class="levels">L2 V1</th>
<th class="levels">L2 V2</th>
<th class="levels">L2 V3</th>
<th class="levels">L2 V4</th>
<th class="levels">L3 V1</th>
<th class="levels">L3 V2</th>
</tr>
'''
web_error_table_end_fragment = '''</table>
</center>
'''
error_groups = [["Internal", # HTML anchor
[LIBSBML_CAT_INTERNAL], # category code(s)
"Internal errors", # section title
'''This group of errors concerns problems involving the libSBML software
itself, or the underlying XML parser being used. This almost certainly
indicates a software defect (i.e., bug) in libSBML. <strong>Please
<a href='https://sourceforge.net/p/sbml/libsbml/new/'>report</a>
occurrences of these errors to the libSBML developers.</strong>'''
], # section intro text
["OS",
[LIBSBML_CAT_SYSTEM],
"Operating system errors",
'''This group of diagnostic codes refers to problems that can be reported
by the operating system where libSBML is running. This indicates something
that is not a libSBML error, but rather, is outside of the control of libSBML.'''
],
["XML",
[LIBSBML_CAT_XML],
"XML errors",
'''This group of diagnostic codes refers to problems with the XML content of
the SBML file or data stream. This usually arises from malformed XML, and is
detected at a very low level in the XML parsing system. Further interpretation
of SBML is aborted if this type of error is encountered.'''
],
["Overall-sbml",
[LIBSBML_CAT_SBML],
"Overall SBML conformance issues",
'''This group of diagnostic codes is concerned with general and overall issues
of conformance to the relevant SBML specifications.'''
],
["General",
[LIBSBML_CAT_GENERAL_CONSISTENCY],
"General SBML consistency issues",
'''This group of diagnostic codes concerns the correct use of SBML constructs
according to the relevant SBML specifications.'''
],
["Identifier",
[LIBSBML_CAT_IDENTIFIER_CONSISTENCY],
"SBML identifier consistency issues",
'''This group of diagnostic codes concerns general SBML issues related to
the identifiers used in SBML documents. For convenience and greater control
during validation procedures, they are separated from the set of diagnostics
for general SBML consistency.'''
],
["Units",
[LIBSBML_CAT_UNITS_CONSISTENCY],
"Units consistency issues",
'''This group of diagnostic codes is concerned with the consistency of units
of measurement associated with quantities specified in an SBML model. For
convenience and greater control during validation procedures, they are
separated from the set of diagnostics for general SBML consistency.'''
],
["MathML",
[LIBSBML_CAT_MATHML_CONSISTENCY],
"MathML issues",
'''This group of diagnostic codes concerns possible problems that can arise
with the MathML constructs used in an SBML document.'''
],
["SBO",
[LIBSBML_CAT_SBO_CONSISTENCY],
"Systems Biology Ontology (SBO) issues",
'''This group of diagnostic codes concerns possible problems that can arise
with the MathML constructs used in an SBML document. For
convenience and greater control during validation procedures, they are
separated from the set of diagnostics for general SBML consistency.'''
],
# The errors previously categorized as LIBSBML_CAT_OVERDETERMINED_MODEL in
# libSBML now seem to be categorized as general SBML spec consistency errors.
#
# ["Over",
# [LIBSBML_CAT_OVERDETERMINED_MODEL],
# "Overdetermined models",
# '''This group of diagnostic codes is concerned with problems encountered
# while testing for overdetermined models; that is, a model where the system is
# overdetermined, therefore violating a tenet of proper SBML.'''
# ],
["Practice",
[LIBSBML_CAT_MODELING_PRACTICE],
"Modeling practice issues",
'''This group of diagnostic codes is concerned with matters of good modeling
practices involving SBML and computational modeling. These are tests
performed by libSBML and do not have equivalent SBML validation rules.
For convenience and greater control during validation procedures, they are
separated from the set of diagnostics for general SBML consistency.'''
],
["Internal-consistency",
[LIBSBML_CAT_INTERNAL_CONSISTENCY],
"Internal SBML consistency issues",
'''This set of diagnostics is concerned with problems that can occur while
validating the libSBML internal representation of SBML constructs. These
are tests performed by libSBML and do not have equivalent SBML validation
rules. For convenience and greater control during validation procedures, they
are separated from the set of diagnostics for general SBML consistency.'''
],
# 2014-05-14: We decided not to show the conversion codes in the online table.
#
# ["conversion",
# [LIBSBML_CAT_SBML_L1_COMPAT,
# LIBSBML_CAT_SBML_L2V1_COMPAT,
# LIBSBML_CAT_SBML_L2V1_COMPAT,
# LIBSBML_CAT_SBML_L2V2_COMPAT,
# LIBSBML_CAT_SBML_L2V3_COMPAT,
# LIBSBML_CAT_SBML_L2V4_COMPAT,
# LIBSBML_CAT_SBML_L3V1_COMPAT],
# "Problems in converting models",
# '''This group of diagnostic codes is concerned with problems encountered
# during conversion of an SBML document from one SBML Level+Version combination
# to another.'''
# ],
]
# -----------------------------------------------------------------------------
# Main code for --doc.
# -----------------------------------------------------------------------------
def write_doc(stream, module):
stream.write(doc_table_start_fragment)
for errNum in sorted(get_numeric_constants(module) - ignored_error_codes):
stream.write(make_doc_row_text(errNum, module))
stream.write(doc_table_end_fragment)
def make_doc_row_text(errNum, module):
s = get_symbol(module, errNum)
output = '<tr>'
output += '<td class="code">@sbmlconstant{' + s + ', SBMLErrorCode_t}</td>\n'
if errNum < 99999:
e = SBMLError(errNum, 1, 1)
if not e.isValid():
return ''
output += '<td class="meaning">{}</td>\n'.format(to_html(e.getShortMessage()))
for lv in sbml_levels_versions:
e = SBMLError(errNum, lv[0], lv[1])
output += '<td class="{}"></td>\n'.format(get_severity_class(e.getSeverity()))
else:
for package in package_codes:
pkg_name = package[0]
pkg_start = package[1]
pkg_end = pkg_start + 1000000
if errNum > pkg_start and errNum < pkg_end:
# Packages are only possible in SBML Level 3.
# Check existence in some L/V combination.
elist = []
for lv in sbml_levels_versions:
if lv[0] < 3:
continue
elist.append(SBMLError(errNum, lv[0], lv[1], '', 0, 0, 0, 0, pkg_name, 1))
if all(not e.isValid() for e in elist):
return ''
first_e = next(e for e in elist if e.isValid())
output += '<td class="meaning">{}</td>\n'.format(to_html(first_e.getShortMessage()))
for lv in sbml_levels_versions:
if lv[0] < 3:
output += '<td class="{}"></td>\n'.format(get_severity_class(0))
continue
e = SBMLError(errNum, lv[0], lv[1], '', 0, 0, 0, 0, pkg_name, 1)
output += '<td class="{}"></td>\n'.format(get_severity_class(e.getSeverity()))
break
output += '</tr>\n'
print_progress()
return output
# -----------------------------------------------------------------------------
# Main code for --web.
# -----------------------------------------------------------------------------
def write_web(stream, module):
stream.write(web_css_fragment)
stream.write(make_web_toc())
stream.write(page_intro_template.format(LIBSBML_DOTTED_VERSION))
for entry in error_groups:
anchor = entry[0]
categories = entry[1]
title = entry[2]
intro = entry[3]
stream.write('<a name="{}"><h3>{}</h3></a>\n'.format(anchor, title))
stream.write('<p>' + intro + '</p>\n')
stream.write(web_error_table_start_fragment)
for errNum in sorted(get_numeric_constants(module, 0, 100000) - ignored_error_codes):
e = SBMLError(errNum, 1, 1)
if not e.isValid():
continue
if not e.getCategory() in categories:
continue
stream.write(make_web_row_text(errNum, module))
for package in package_codes:
pkg_name = package[0]
pkg_start = package[1]
pkg_end = pkg_start + 1000000
printed_separator = False
for errNum in sorted(get_numeric_constants(module, pkg_start, pkg_end)):
e = SBMLError(errNum, 3, 1, '', 0, 0, 0, 0, pkg_name, 1)
msg = e.getShortMessage()
if not msg:
continue
if not e.getCategory() in categories:
continue
if not printed_separator:
stream.write(make_web_table_pkg_separator(pkg_name))
printed_separator = True
stream.write(make_web_row_pkg_text(e, errNum, pkg_name, pkg_start, module))
print_progress("Writing '" + title + "' \n")
stream.write(web_error_table_end_fragment)
def make_web_toc():
output = web_toc_start_fragment
for entry in error_groups:
anchor = entry[0]
title = entry[2]
output += '<a href="#{}">{}</a><br/>\n'.format(anchor, title)
output += web_toc_end_fragment
return output
def make_web_table_pkg_separator(pkg_name):
return '<tr><td colspan="' + str(3 + len(sbml_levels_versions)) \
+ '" class="table-pkg-separator">Codes for SBML Level 3 package "' \
+ pkg_name + '"</td></tr>'
def make_web_row_text(errNum, module):
e = SBMLError(errNum, 1, 1)
if not e.isValid():
return ''
output = '<tr>'
output += '<td class="code">{0:05d}</td>'.format(errNum)
output += '<td class="errorname">{}</td>'.format(get_symbol(module, errNum))
output += '<td class="meaning">{}</td>'.format(to_html(e.getShortMessage()))
for lv in sbml_levels_versions:
e = SBMLError(errNum, lv[0], lv[1])
severity = e.getSeverity()
output += '<td class="{}"></td>'.format(get_severity_class(severity))
output += '</tr>\n'
return output
def make_web_row_pkg_text(err, errNum, pkg_name, pkg_start, module):
output = '<tr>'
output += '<td class="code">{0}-{1:05d}</td>'.format(pkg_name, errNum-pkg_start)
output += '<td class="errorname">{}</td>'.format(get_symbol(module, errNum))
output += '<td class="meaning">{}</td>'.format(to_html(err.getShortMessage()))
for lv in range(0, len(sbml_levels_versions) - 1):
output += '<td class="{}"></td>'.format(get_severity_class(0))
output += '<td class="{}"></td>'.format(get_severity_class(err.getSeverity()))
output += '</tr>\n'
return output
# -----------------------------------------------------------------------------
# Main code for --enum.
# -----------------------------------------------------------------------------
def write_enum(stream, module):
stream.write(enum_start_fragment)
for errNum in sorted(get_numeric_constants(module, 0, 100000)):
e = SBMLError(errNum, 1, 1)
if e.isValid():
if errNum == 10000:
stream.write(" ")
else:
stream.write(", ")
stream.write("%s = %s" %(ljust(get_symbol(module, errNum), 37), str(errNum)))
msg = e.getShortMessage()
if msg != '':
if msg[-1] != '.':
maybe_period = '.'
else:
maybe_period = ''
stream.write(" /*!< " + to_html(msg) + maybe_period + " */")
stream.write("\n")
print_progress()
stream.write(enum_end_fragment)
# -----------------------------------------------------------------------------
# Helper functions.
# -----------------------------------------------------------------------------
def get_module():
fp, pathname, description = find_module("libsbml")
return load_module('_libsbml', fp, pathname, description)
def get_numeric_constants(module, low=0, high=90000000):
constants = set()
for symbol in dir(module):
try: # Some symbols don't have a value,
value = eval(symbol) # so we have to guard against that.
if isinstance(value, int) and low <= value and value <= high:
constants.add(value)
except:
continue
return constants
def get_symbol(module, number):
# This is an inefficient way of getting the string corresponding to a
# given error number, but we don't care because this application isn't
# performance-critical. The algorithm is also fragile, but if we're
# careful about the range of values attempted (i.e., numbers from 10000
# to 100000), it should be okay. Unfortunately, values below 100 hits
# a number of small enumerations in libSBML, so we have to special-case
# that. Really, this whole thing is just awful.
#
if number in low_numbered_errors.keys():
return low_numbered_errors[number]
symbols = dir(module)
attributes = [None]*len(symbols)
for i in range(0, len(symbols)):
attributes[i] = getattr(module, symbols[i])
for i in range(0, len(symbols)):
if isinstance(attributes[i], int) == True and attributes[i] == number:
return symbols[i]
def get_severity_class(severity):
if (severity == 3): return "s-fatal"
elif (severity == 2): return "s-error"
elif (severity == 1): return "s-warning"
else: return "s-na"
def to_html(text):
text = text.replace('<', '<')
text = text.replace('>', '>')
text = text.replace('<', '<code><')
text = text.replace('>', '></code>')
return text
def print_progress(marker="."):
# Echo to terminal to show progress.
sys.stdout.write(marker)
sys.stdout.flush()
# -----------------------------------------------------------------------------
# Main.
# -----------------------------------------------------------------------------
def main (args):
"""Usage:
writeErrorTable.py [--doc | --enum | --web] OUTPUTFILE
The first argument must one of --doc, --enum or --web.
* Given --doc, it will generate a table suitable for use in the libSBML
API documentation as it appears in the header of SBMLError.h.
* Given --enum, it will generate the SBMLErrorCode_t enum for SBMLError.h.
* Given --web, it will generate output used in the table in the web page at
http://sbml.org/Facilities/Documentation/Error_Categories.
It will write its output to OUTPUTFILE. Note that the name of the file
will be used as given; no file name extension will be added. Callers are
assumed to supply the full name desired.
"""
# Start with some sanity-checking.
if len(args) != 3 or (args[1] not in ['--doc', '--enum', '--web']):
print(main.__doc__)
sys.exit(1)
# OK, let's do this thing.
module = get_module()
print('Writing output to ' + args[2])
stream = open(args[2], 'w')
if args[1] == '--doc':
write_doc(stream, module)
elif args[1] == '--enum':
write_enum(stream, module)
else:
write_web(stream, module)
stream.close()
print 'Done.'
if __name__ == '__main__':
main(sys.argv)
|