Retrieve Issue items¶
Selected libCellML classes contain a Logger whose job it is to curate any issues encountered within the class, and return them to the user when asked.
The classes are:
the
Parserclass;the
Validatorclass;the
Printerclass;the
Analyserclass;the
Importerclass; andthe
Generatorclass.
Individual issues can be retrieved from the parent class by their index, an integer between 0 and issueCount()-1.
Each issue contains a severity level indicator, one of four levels (ERROR, WARNING, HINT, or MESSAGE):
ERRORlevel indicates issues that must be resolved before the model is valid and runnable;
WARNINGlevel indicates a non-fatal issue, but one that may cause hidden or unintended consequences;
HINTlevel indicates a commonly encountered valid-but-nonsense situation; and
MESSAGElevel is for your information but does not require action.
Issues can also be retrieved from subgroups based on their severity, as shown in the examples below.
See C++ example
// Iterate through all the issues in a Validator, regardless of level, and print to the terminal.
for (size_t i = 0; i < validator->issueCount(); ++i) {
// Retrieve the i-th issue and store it in the variable "myIssue".
libcellml::IssuePtr myIssue = validator->issue(i);
// Print the issue's description:
std::cout << myIssue->description() << std::endl;
// Print the issue's URL. This is a URL at which more
// information could be found about the cause and corrections
// are needed to avoid it.
std::cout << myIssue->url() << std::endl;
// Validator only: Print the issue's reference. This is
// the heading reference in the normative specification which
// relates to this issue.
std::cout << myIssue->referenceHeading() << std::endl;
}
// Retrieve the second ERROR level issue from a Printer. Note indexing from 0.
auto secondError = printer->error(1);
// Retrieve the last WARNING level issue from a Parser.
auto lastWarning = parser->warning(parser->warningCount()-1);
// Iterate through all HINT level issues in a Generator.
for (size_t h = 0; h < generator->hintCount(); ++h) {
// Retrieve the h-th hint and store it in the variable "myHint".
auto myHint = generator->hint(h);
}
See Python example
# Iterate through all the issues in a Validator, regardless of level, and print to the terminal.
for i in range(0, validator.issueCount()):
# Retrieve the i-th issue and store it in the variable "my_issue".
my_issue = validator.issue(i)
# Print the issue's description:
print(my_issue.description())
# Print the issue's URL. This is a URL at which more
# information could be found about the cause and corrections
# are needed to avoid it.
print(my_issue.url())
# Validator only: Print the issue's reference. This is
# the heading reference in the normative specification which
# relates to this issue.
print(my_issue.referenceHeading())
# Retrieve the second ERROR level issue from a Printer. Note indexing from 0.
second_error = printer.error(1)
# Retrieve the last WARNING level issue from a Parser.
last_warning = parser.warning(parser.warningCount() - 1)
# Iterate through all HINT level issues in a Generator.
for h in range(0, generator.hintCount()):
# Retrieve the h-th hint and store it in the variable "my_hint".
my_hint = generator.hint(h)
Each Issue also contains the following attributes:
A description: a brief statement about the problem and how it might be fixed;
A reference heading: a chapter number pertaining to the formal CellML 2.0 Specification document, for issues related to formatting and specification;
A URL: a web address at which more detailed information and examples pertaining to the issue are available;
A cause: an
enumwhich reports the type of item responsible for the issue. This is one of the enums:
COMPONENT,CONNECTION,ENCAPSULATION,IMPORT,MAP_VARIABLES,MATHML,MODEL,RESET,RESET_VALUE,TEST_VALUE,UNDEFINED,UNIT,UNITS,VARIABLE, andXML.
See C++ examples
// Retrieve and print the description of the issue.
std::cout << issue->description() << std::endl;
// Retrieve and print the reference heading number, if related to CellML2.0 specification and format.
std::cout << issue->referenceHeading() << std::endl;
// Retrieve and print the URL for more help and information about the issue.
std::cout << issue->url() << std::endl;
// Retrieve the item type - a libcellml::CellmlElementType enum - for the issue.
auto myType = issue->CellmlElementType();
// Retrieve the level - a libcellml::Issue::LEVEL enum - for the issue.
auto myLevel = issue->level();
See Python examples
# Retrieve and print the description of the issue.
print(issue.description())
# Retrieve and print the reference heading number, if related to CellML2.0 specification and format.
print(issue.referenceHeading())
# Retrieve and print the URL for more help and information about the issue.
print(issue.url())
# Retrieve the cause - a libcellml.CellmlElementType enum - for the issue.
my_type = issue.cellmlElementType()
# Retrieve the level - a libcellml.Issue.LEVEL enum - for the issue.
my_level = issue.level()
Useful functions for dealing with issues¶
Utility functions to retrieve issues
void printIssues(const libcellml::LoggerPtr &item) {
// Get the number of issues attached to the logger item. Note that this will
// return issues of all levels. To retrieve the total number of a specific level
// of issues, use the errorCount(), warningCount(), hintCount(), or messageCount() functions.
size_t num = item->issueCount();
std::cout << "Recorded " << num << " issues";
if (num != 0) {
std::cout << ":" << std::endl;
for (size_t i = 0; i < num; ++i) {
// Retrieve the issue at index i. Note that this is agnostic as to the level of issue.
// Specific issue levels can be retrieved using the functions item->error(i), item->warning(i)
// etc, where the index must be within appropriate limits.
libcellml::IssuePtr issue = item->issue(i);
// Issues created by the Validator class contain a reference heading number, which indicates
// the section reference within the normative specification relevant to the issue.
std::string errorReference = issue->referenceHeading();
// The level of an issue is retrieved using the level() function as an enum value.
std::cout << "Issue " << i << " is " << getIssueLevelFromEnum(issue->level()) << ":" << std::endl;
// Each issue has a descriptive text field, accessible through the description() function.
std::cout << " description: " << issue->description() << std::endl;
if (errorReference != "") {
std::cout << " see section " << errorReference
<< " in the CellML specification." << std::endl;
}
// An optional URL is given for some issues which directs the user to more detailed information.
if(!issue->url().empty()){
std::cout << " more information at: " <<issue->url() << std::endl;
}
// Each issue is associated with an item. In order to properly deal with the item stored, its type is
// recorded too in an enumeration.
std::cout << " stored item type: " << getCellmlElementTypeFromEnum(issue->cellmlElementType()) << std::endl;
}
std::cout << std::endl << std::endl;
}
else {
std::cout << "!" << std::endl << std::endl;
}
}
std::map<libcellml::CellmlElementType, std::string> itemTypeToString =
{{libcellml::CellmlElementType::COMPONENT, "COMPONENT"},
{libcellml::CellmlElementType::COMPONENT_REF, "COMPONENT_REF"},
{libcellml::CellmlElementType::CONNECTION, "CONNECTION"},
{libcellml::CellmlElementType::ENCAPSULATION, "ENCAPSULATION" },
{libcellml::CellmlElementType::IMPORT, "IMPORT"},
{libcellml::CellmlElementType::MAP_VARIABLES, "MAP_VARIABLES"},
{libcellml::CellmlElementType::MATH, "MATH"},
{libcellml::CellmlElementType::MODEL, "MODEL"},
{libcellml::CellmlElementType::RESET, "RESET"},
{libcellml::CellmlElementType::RESET_VALUE, "RESET_VALUE"},
{libcellml::CellmlElementType::TEST_VALUE, "TEST_VALUE"},
{libcellml::CellmlElementType::UNDEFINED, "UNDEFINED"},
{libcellml::CellmlElementType::UNIT, "UNIT"},
{libcellml::CellmlElementType::UNITS, "UNITS"},
{libcellml::CellmlElementType::VARIABLE, "VARIABLE"}};
std::string getCellmlElementTypeFromEnum(libcellml::CellmlElementType t) {
return itemTypeToString.at(t);
}
std::string getIssueLevelFromEnum(libcellml::Issue::Level myLevel)
{
std::string myTypeAsString = "dunno";
switch (myLevel) {
case libcellml::Issue::Level::ERROR:
myTypeAsString = "an ERROR";
break;
case libcellml::Issue::Level::WARNING:
myTypeAsString = "a WARNING";
break;
case libcellml::Issue::Level::HINT:
myTypeAsString = "a HINT";
break;
case libcellml::Issue::Level::MESSAGE:
myTypeAsString = "a MESSAGE";
break;
}
return myTypeAsString;
}
Full context: utilities.cpp
def print_issues(item):
# Get the number of issues attached to the logger item. Note that this will
# return issues of all levels. To retrieve the total number of a specific level
# of issues, use the errorCount(), warningCount(), hintCount(), or messageCount() functions.
number_of_issues = item.issueCount()
if number_of_issues != 0:
print("\nThe {t} has found {n} issues:".format(
t=type(item).__name__,
n=number_of_issues)
)
for e in range(0, number_of_issues):
# Retrieve the issue at index i. Note that this is agnostic as to the level of issue.
# Specific issue levels can be retrieved using the functions item.error(e), item.warning(e)
# etc, where the index must be within appropriate limits.
i = item.issue(e)
# The level of an issue is retrieved using the level() function as an enum value.
level = i.level()
print(" {l}[{e}]:".format(
l=level_as_string[level],
e=e))
# Each issue has a descriptive text field, accessible through the description() function.
print(" Description: {d}".format(
d=i.description()))
# Issues created by the Validator class contain a reference heading number, which indicates
# the section reference within the normative specification relevant to the issue.
specification = i.referenceHeading()
if specification != "":
print(" See section {s} in the CellML specification.".format(
s=specification))
# An optional URL is given for some issues which directs the user to more detailed information.
url = i.url()
if url != "":
print(" More information is available at {url}".format(
url=url))
# Each issue is associated with an item. In order to properly deal with the item stored, its type is
# recorded too in an enumeration.
print(" Stored item type: {}".format(get_cellml_element_type_from_enum(i.cellmlElementType())))
else:
print("\nThe {t} has not found any issues!".format(
t=type(item).__name__)
)
def get_cellml_element_type_from_enum(my_cause):
my_type_as_string = "dunno"
if my_cause == CellmlElementType.COMPONENT:
my_type_as_string = "COMPONENT"
elif my_cause == CellmlElementType.COMPONENT_REF:
my_type_as_string = "COMPONENT_REf"
elif my_cause == CellmlElementType.CONNECTION:
my_type_as_string = "CONNECTION"
elif my_cause == CellmlElementType.ENCAPSULATION:
my_type_as_string = "ENCAPSULATION"
elif my_cause == CellmlElementType.IMPORT:
my_type_as_string = "IMPORT"
elif my_cause == CellmlElementType.MATH:
my_type_as_string = "MATH"
elif my_cause == CellmlElementType.MAP_VARIABLES:
my_type_as_string = "MAP_VARIABLES"
elif my_cause == CellmlElementType.MODEL:
my_type_as_string = "MODEL"
elif my_cause == CellmlElementType.RESET:
my_type_as_string = "RESET"
elif my_cause == CellmlElementType.RESET_VALUE:
my_type_as_string = "RESET_VALUE"
elif my_cause == CellmlElementType.TEST_VALUE:
my_type_as_string = "TEST_VALUE"
elif my_cause == CellmlElementType.UNDEFINED:
my_type_as_string = "UNDEFINED"
elif my_cause == CellmlElementType.UNIT:
my_type_as_string = "UNIT"
elif my_cause == CellmlElementType.UNITS:
my_type_as_string = "UNITS"
elif my_cause == CellmlElementType.VARIABLE:
my_type_as_string = "VARIABLE"
return my_type_as_string
def get_issue_level_from_enum(my_level):
my_type_as_string = "dunno"
if my_level == Issue.Level.ERROR:
my_type_as_string = "ERROR"
elif my_level == Issue.Level.WARNING:
my_type_as_string = "WARNING"
elif my_level == Issue.Level.HINT:
my_type_as_string = "HINT"
elif my_level == Issue.Level.MESSAGE:
my_type_as_string = "MESSAGE"
return my_type_as_string
Full context: utilities.py