Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Validation changes #389

Merged
merged 16 commits into from
May 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions odml/doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from . import dtypes
from . import format as fmt
from . import terminology
from . import validation
from .tools.doc_inherit import inherit_docstring, allow_inherit_docstring


Expand Down Expand Up @@ -152,6 +153,14 @@ def finalize(self):
if sec._include is not None:
sec.include = sec._include

def validate(self):
"""
Runs a validation on itself and returns the Validation object.

:return: odml.Validation
"""
return validation.Validation(self)

@inherit_docstring
def get_terminology_equivalent(self):
if self.repository is None:
Expand Down
12 changes: 9 additions & 3 deletions odml/property.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@ def name(self, new_name):
if self.name == new_name:
return

# Make sure name cannot be set to None or empty
if not new_name:
self._name = self._id
return

curr_parent = self.parent
if hasattr(curr_parent, "properties") and new_name in curr_parent.properties:

Expand Down Expand Up @@ -569,11 +574,12 @@ def _values_cardinality_validation(self):
is respected and prints a warning message otherwise.
"""
valid = validation.Validation(self)
val_id = validation.IssueID.property_values_cardinality

# Make sure to display only warnings of the current property
res = [curr for curr in valid.errors if self.id == curr.obj.id]
for err in res:
print("%s: %s" % (err.rank.capitalize(), err.msg))
for curr in valid.errors:
if curr.validation_id == val_id and self.id == curr.obj.id:
print("%s: %s" % (curr.rank.capitalize(), curr.msg))

def set_values_cardinality(self, min_val=None, max_val=None):
"""
Expand Down
21 changes: 15 additions & 6 deletions odml/section.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,11 @@ def name(self, new_value):
if self.name == new_value:
return

# Make sure name cannot be set to None or empty
if not new_value:
self._name = self._id
return

curr_parent = self.parent
if hasattr(curr_parent, "sections") and new_value in curr_parent.sections:
raise KeyError("Object with the same name already exists!")
Expand Down Expand Up @@ -416,10 +421,12 @@ def _sections_cardinality_validation(self):
is respected and prints a warning message otherwise.
"""
valid = validation.Validation(self)
val_id = validation.IssueID.section_sections_cardinality

# Make sure to display only warnings of the current section
res = [curr for curr in valid.errors if self.id == curr.obj.id]
for err in res:
print("%s: %s" % (err.rank.capitalize(), err.msg))
for curr in valid.errors:
if curr.validation_id == val_id and self.id == curr.obj.id:
print("%s: %s" % (curr.rank.capitalize(), curr.msg))

@property
def prop_cardinality(self):
Expand Down Expand Up @@ -469,10 +476,12 @@ def _properties_cardinality_validation(self):
is respected and prints a warning message otherwise.
"""
valid = validation.Validation(self)
val_id = validation.IssueID.section_properties_cardinality

# Make sure to display only warnings of the current section
res = [curr for curr in valid.errors if self.id == curr.obj.id]
for err in res:
print("%s: %s" % (err.rank.capitalize(), err.msg))
for curr in valid.errors:
if curr.validation_id == val_id and self.id == curr.obj.id:
print("%s: %s" % (curr.rank.capitalize(), curr.msg))

@inherit_docstring
def get_terminology_equivalent(self):
Expand Down
65 changes: 64 additions & 1 deletion odml/tools/odmlparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import datetime
import json
import sys
import warnings

from os.path import basename

Expand Down Expand Up @@ -61,11 +62,18 @@ def write_file(self, odml_document, filename):
msg = ""
for err in validation.errors:
if err.is_error:
msg += "\n\t- %s %s: %s" % (err.obj, err.rank, err.msg)
# msg += "\n\t- %s %s: %s" % (err.obj, err.rank, err.msg)
msg += "\n- %s" % err
if msg != "":
msg = "Resolve document validation errors before saving %s" % msg
raise ParserException(msg)

report = validation.report()
if report:
msg += "The saved Document contains unresolved issues."
msg += " Run the Documents 'validate' method to access them.\n%s" % report
warnings.warn(msg)

with open(filename, 'w') as file:
# Add XML header to support odML stylesheets.
if self.parser == 'XML':
Expand Down Expand Up @@ -153,6 +161,13 @@ def __init__(self, parser='XML', show_warnings=True):
self.show_warnings = show_warnings
self.warnings = []

def _validation_warning(self):
report = Validation(self.doc).report()
if report:
msg = "The loaded Document contains unresolved issues."
msg += " Run the Documents 'validate' method to access them.\n%s" % report
warnings.warn(msg)

def from_file(self, file, doc_format=None):
"""
Loads an odML document from a file. The ODMLReader.parser specifies the
Expand All @@ -171,6 +186,11 @@ def from_file(self, file, doc_format=None):
show_warnings=self.show_warnings)
self.warnings = par.warnings
self.doc = par.from_file(file)

# Print validation warnings after parsing
if self.show_warnings:
self._validation_warning()

return self.doc

if self.parser == 'YAML':
Expand All @@ -188,6 +208,11 @@ def from_file(self, file, doc_format=None):
self.doc = par.to_odml(self.parsed_doc)
# Provide original file name via the in memory document
self.doc.origin_file_name = basename(file)

# Print validation warnings after parsing
if self.show_warnings:
self._validation_warning()

return self.doc

if self.parser == 'JSON':
Expand All @@ -202,13 +227,27 @@ def from_file(self, file, doc_format=None):
self.doc = par.to_odml(self.parsed_doc)
# Provide original file name via the in memory document
self.doc.origin_file_name = basename(file)

# Print validation warnings after parsing
if self.show_warnings:
self._validation_warning()

return self.doc

if self.parser == 'RDF':
if not doc_format:
raise ValueError("Format of the rdf file was not specified")

# Importing from an RDF graph can return multiple documents
self.doc = RDFReader().from_file(file, doc_format)

for doc in self.doc:
report = Validation(doc).report()
if report:
msg = "The loaded Document contains unresolved issues."
msg += " Run the Documents 'validate' method to access them.\n%s" % report
warnings.warn(msg)

return self.doc

def from_string(self, string, doc_format=None):
Expand All @@ -227,6 +266,11 @@ def from_string(self, string, doc_format=None):

if self.parser == 'XML':
self.doc = xmlparser.XMLReader().from_string(string)

# Print validation warnings after parsing
if self.show_warnings:
self._validation_warning()

return self.doc

if self.parser == 'YAML':
Expand All @@ -237,6 +281,11 @@ def from_string(self, string, doc_format=None):
return

self.doc = DictReader().to_odml(self.parsed_doc)

# Print validation warnings after parsing
if self.show_warnings:
self._validation_warning()

return self.doc

if self.parser == 'JSON':
Expand All @@ -247,13 +296,27 @@ def from_string(self, string, doc_format=None):
return

self.doc = DictReader().to_odml(self.parsed_doc)

# Print validation warnings after parsing
if self.show_warnings:
self._validation_warning()

return self.doc

if self.parser == 'RDF':
if not doc_format:
raise ValueError("Format of the rdf file was not specified")

# Importing from an RDF graph can return multiple documents
self.doc = RDFReader().from_string(string, doc_format)

for doc in self.doc:
report = Validation(doc).report()
if report:
msg = "The loaded Document contains unresolved issues."
msg += " Run the Documents 'validate' method to access them.\n%s" % report
warnings.warn(msg)

return self.doc


Expand Down
Loading