Skip to content

Commit

Permalink
Merge pull request #300 from tcmitchell/205-write-validate
Browse files Browse the repository at this point in the history
Add optional validation to Document.write()
  • Loading branch information
tcmitchell authored Jun 18, 2020
2 parents 0e7a213 + 7fa485f commit 15177db
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 24 deletions.
2 changes: 1 addition & 1 deletion dev/hooks/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fi
# Run style checker
MAX_VIOLATIONS=23
echo "Checking style..."
pycodestyle sbol2 test > style.txt
pycodestyle sbol2 test examples > style.txt
result=$(cat style.txt | wc -l)
if [ "$result" -gt $MAX_VIOLATIONS ]; then
cat <<EOF
Expand Down
11 changes: 11 additions & 0 deletions sbol2/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging
import os
import posixpath
import time
from typing import Any, Dict, Mapping, Union
import warnings

Expand Down Expand Up @@ -395,6 +396,16 @@ def write(self, filename):
or empty string if validation is disabled.
"""
self.doc_serialize_rdf2xml(filename)
# Optionally validate
result = 'Validation disabled. To enable use of the online validation tool, use'
result += ' Config.setOption(ConfigOptions.VALIDATE, True)'
if Config.getOption(ConfigOptions.VALIDATE):
t_start = time.time()
result = self.validate()
if Config.getOption(ConfigOptions.VERBOSE):
t_end = time.time()
print(f'Validation request took {t_end - t_start} seconds')
return result

def read(self, filename):
"""
Expand Down
32 changes: 32 additions & 0 deletions test/test_document.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import io
import locale
import os
import tempfile
import unittest
import unittest.mock

import rdflib

Expand Down Expand Up @@ -544,6 +547,35 @@ def test_idempotent_read(self):
cd = doc.componentDefinitions[cd_uri]
self.assertEqual(1, len(cd.roles))

def test_write_validation(self):
# Test that write performs validation if requested
# and skips validation if requested.
doc = sbol2.Document()
doc.moduleDefinitions.create('md1')
validate = sbol2.Config.getOption(sbol2.ConfigOptions.VALIDATE)
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE, True)
verbose = sbol2.Config.getOption(sbol2.ConfigOptions.VERBOSE)
sbol2.Config.setOption(sbol2.ConfigOptions.VERBOSE, True)
with tempfile.TemporaryDirectory() as tmpdirname:
test_file = os.path.join(tmpdirname, 'test.xml')
with unittest.mock.patch('sys.stdout', new=io.StringIO()) as fake_out:
# Write to disk
result = doc.write(test_file)
self.assertEqual('Valid.', result)
# Expect timing output
output = fake_out.getvalue().strip()
self.assertTrue(output.startswith('Validation request took'))
self.assertTrue(output.endswith('seconds'))
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE, False)
with tempfile.TemporaryDirectory() as tmpdirname:
test_file = os.path.join(tmpdirname, 'test.xml')
# Write to disk
result = doc.write(test_file)
self.assertTrue(result.startswith('Validation disabled.'))
# Reset validate to its original value
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE, validate)
sbol2.Config.setOption(sbol2.ConfigOptions.VERBOSE, verbose)


if __name__ == '__main__':
unittest.main()
3 changes: 3 additions & 0 deletions test/test_roundtrip.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ class TestRoundTripSBOL2(unittest.TestCase):
def setUp(self):
# Create temp directory
self.temp_out_dir = tempfile.mkdtemp()
# Disable validation to avoid unnecessary round trips
# to the online validator
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE, False)
self.logger = logging.getLogger('sbol2.test')
if not self.logger.hasHandlers():
logging.basicConfig()
Expand Down
43 changes: 20 additions & 23 deletions test/test_sequence.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import os
import sys
import tempfile
import unittest

import rdflib

import sbol2 as sbol
import sbol2

MODULE_LOCATION = os.path.dirname(os.path.abspath(__file__))
CRISPR_EXAMPLE = os.path.join(MODULE_LOCATION, 'resources', 'crispr_example.xml')
Expand All @@ -14,23 +11,23 @@
class TestSequence(unittest.TestCase):

def testAddSequence(self):
test_seq = sbol.Sequence("R0010", "ggctgca")
doc = sbol.Document()
test_seq = sbol2.Sequence("R0010", "ggctgca")
doc = sbol2.Document()
doc.addSequence(test_seq)
seq = doc.sequences.get("R0010").elements

self.assertEqual(seq, 'ggctgca')

def testRemoveSequence(self):
test_seq = sbol.Sequence("R0010", "ggctgca")
doc = sbol.Document()
test_seq = sbol2.Sequence("R0010", "ggctgca")
doc = sbol2.Document()
doc.addSequence(test_seq)
doc.sequences.remove(0)
with self.assertRaises(sbol.SBOLError):
with self.assertRaises(sbol2.SBOLError):
doc.sequences.get("R0010")

def testSeqDisplayId(self):
doc = sbol.Document()
doc = sbol2.Document()
doc.read(CRISPR_EXAMPLE)

# List of displayIds
Expand All @@ -41,15 +38,15 @@ def testSeqDisplayId(self):
self.assertCountEqual(listseq_read, listseq)

def testSequenceEncoding(self):
doc = sbol.Document()
doc = sbol2.Document()
doc.read(CRISPR_EXAMPLE)
seq = doc.sequences.get('CRP_b_seq')
self.assertEqual(seq.encoding, sbol.SBOL_ENCODING_IUPAC)
self.assertEqual(seq.encoding, sbol2.SBOL_ENCODING_IUPAC)

def testSequenceElement(self):
sbol.setHomespace('http://sbols.org/CRISPR_Example')
sbol.Config.setOption('sbol_typed_uris', False)
doc = sbol.Document()
sbol2.setHomespace('http://sbols.org/CRISPR_Example')
sbol2.Config.setOption('sbol_typed_uris', False)
doc = sbol2.Document()
doc.read(CRISPR_EXAMPLE)
# Sequence to test against
seq = ('GCTCCGAATTTCTCGACAGATCTCATGTGATTACGCCAAGCTACGGGCGGAGTACTGTCCTC'
Expand All @@ -62,9 +59,9 @@ def testSequenceElement(self):
self.assertEqual(seq_read, seq)

def testUpdateSequenceElement(self):
sbol.setHomespace('http://sbols.org/CRISPR_Example')
sbol.Config.setOption('sbol_typed_uris', False)
doc = sbol.Document()
sbol2.setHomespace('http://sbols.org/CRISPR_Example')
sbol2.Config.setOption('sbol_typed_uris', False)
doc = sbol2.Document()
doc.read(CRISPR_EXAMPLE)
# Sequence to test against
seq = 'AAAAA'
Expand All @@ -74,14 +71,14 @@ def testUpdateSequenceElement(self):

# File I/O Tests
def testUpdateWrite(self):
sbol.setHomespace('http://sbols.org/CRISPR_Example')
sbol.Config.setOption('sbol_typed_uris', False)
doc = sbol.Document()
sbol2.setHomespace('http://sbols.org/CRISPR_Example')
sbol2.Config.setOption('sbol_typed_uris', False)
doc = sbol2.Document()
doc.read(CRISPR_EXAMPLE)
# Sequence to test against
seq = 'AAAAA'
doc.sequences.get('CRP_b_seq').elements = seq
doc2 = sbol.Document() # Document to compare for equality
doc2 = sbol2.Document() # Document to compare for equality
with tempfile.TemporaryDirectory() as tmpdirname:
test_file = os.path.join(tmpdirname, 'test.xml')
# Write to disk
Expand All @@ -92,5 +89,5 @@ def testUpdateWrite(self):
self.assertEqual(seq_read, seq)

def test_bool(self):
seq = sbol.Sequence()
seq = sbol2.Sequence()
self.assertTrue(seq)

0 comments on commit 15177db

Please sign in to comment.