def _test_make_imports(self, tppath):
        """
        Tests the "make imports" build task.

        tppath: The path of the test OntoPilot project.
        """
        args = [self.execpath, 'make', 'imports']
        retval = subprocess.call(args, cwd=tppath)
        self.assertEqual(0, retval)

        # Check that the compiled import module exists.
        im_path = os.path.join(tppath, 'imports/bfo_test_import_module.owl')
        self.assertTrue(os.path.isfile(im_path))

        im_ont = Ontology(im_path)
        owlont = im_ont.getOWLOntology()

        # Confirm that it contains the single imported class.
        self.assertIsNotNone(im_ont.getExistingClass("'continuant'"))
        self.assertEqual(
            1, owlont.getClassesInSignature(Imports.EXCLUDED).size()
        )

        # Confirm that it contains the proper source annotation.
        bfo_verIRI = IRI.create('http://purl.obolibrary.org/obo/bfo/2.0/bfo.owl')
        found_src_annot = False
        for ont_annot in owlont.getAnnotations():
            if ont_annot.getProperty().getIRI().equals(Ontology.SOURCE_ANNOT_IRI):
                if ont_annot.getValue().asIRI().isPresent():
                    sourceIRI = ont_annot.getValue().asIRI().get()
                    if sourceIRI.equals(bfo_verIRI):
                        found_src_annot = True

        self.assertTrue(found_src_annot)
예제 #2
0
    def test_checkEntailmentErrors(self):
        # Check on ontology that is both consistent and coherent.
        report = self.ont.checkEntailmentErrors()
        self.assertTrue(report['is_consistent'])
        self.assertEqual(0, len(report['unsatisfiable_classes']))

        # Check an ontology that is both inconsistent and incoherent.
        testont = Ontology('test_data/inconsistent.owl')
        report = testont.checkEntailmentErrors()
        self.assertFalse(report['is_consistent'])
        self.assertEqual(0, len(report['unsatisfiable_classes']))

        # The ReasonerManager should ensure that reasoner instances track
        # ontology changes, so the following line should not be needed.
        #testont.getReasonerManager().disposeReasoners()

        # Check an ontology that is incoherent but not inconsistent.
        # Remove the instance of the unsatisfiable class 'test class 2' to make
        # the ontology consistent.
        individual = testont.getExistingIndividual('obo:OBTO_9000')
        testont.removeEntity(individual)
        unsatisfiable = testont.getExistingClass(
            'obo:OBTO_0011').getOWLAPIObj()
        report = testont.checkEntailmentErrors()
        self.assertTrue(report['is_consistent'])
        self.assertEqual(1, len(report['unsatisfiable_classes']))
        self.assertTrue(
            unsatisfiable.equals(report['unsatisfiable_classes'][0]))
예제 #3
0
class Test_BasicShortFormProvider(unittest.TestCase):
    """
    Tests the _BasicShortFormProvider "private" helper class.
    """
    def setUp(self):
        self.test_ont = Ontology('test_data/ontology.owl')
        self.bsfp = _BasicShortFormProvider()

    def test_getShortForm(self):
        entity = self.test_ont.getExistingClass('OBTO:0010').getOWLAPIObj()

        self.assertEqual('OBTO_0010', self.bsfp.getShortForm(entity))
    def _test_make_ont_merged(self, tppath):
        """
        Tests the "make ontology --merge" build task.

        tppath: The path of the test OntoPilot project.
        """
        args = [self.execpath, 'make', 'ontology', '--merge']
        retval = subprocess.call(args, cwd=tppath)
        self.assertEqual(0, retval)

        # Check that the compiled ontology exists.
        ont_path = os.path.join(tppath, 'ontology/test-merged.owl')
        self.assertTrue(os.path.isfile(ont_path))

        ont = Ontology(ont_path)
        owlont = ont.getOWLOntology()

        # There should not be any imports.
        self.assertTrue(owlont.getImports().isEmpty())

        # Confirm that the ontology contains the expected object property,
        # classes, and individual, and nothing else.

        self.assertIsNotNone(ont.getExistingClass("'test class'"))
        self.assertIsNotNone(ont.getExistingClass("'continuant'"))
        self.assertEqual(
            2, owlont.getClassesInSignature(Imports.EXCLUDED).size()
        )

        self.assertIsNotNone(ont.getExistingObjectProperty("'test property'"))
        self.assertEqual(
            1, owlont.getObjectPropertiesInSignature(Imports.EXCLUDED).size()
        )

        self.assertIsNotNone(ont.getExistingIndividual("'test individual'"))
        self.assertEqual(
            1, owlont.getIndividualsInSignature(Imports.EXCLUDED).size()
        )

        self.assertEqual(
            0, owlont.getDataPropertiesInSignature(Imports.EXCLUDED).size()
        )
    def _test_make_ont(self, tppath):
        """
        Tests the basic "make ontology" build task.

        tppath: The path of the test OntoPilot project.
        """
        args = [self.execpath, 'make', 'ontology']
        retval = subprocess.call(args, cwd=tppath)
        self.assertEqual(0, retval)

        # Check that the compiled ontology exists.
        ont_path = os.path.join(tppath, 'ontology/test-raw.owl')
        self.assertTrue(os.path.isfile(ont_path))

        ont = Ontology(ont_path)
        owlont = ont.getOWLOntology()

        # Confirm that it contains the expected object property, class, and
        # individual, and nothing else.

        self.assertIsNotNone(ont.getExistingClass("'test class'"))
        # There are two classes in the signature because BFO:'continuant' is
        # used in a "subclass of" axiom.
        self.assertEqual(
            2, owlont.getClassesInSignature(Imports.EXCLUDED).size()
        )

        self.assertIsNotNone(ont.getExistingObjectProperty("'test property'"))
        self.assertEqual(
            1, owlont.getObjectPropertiesInSignature(Imports.EXCLUDED).size()
        )

        self.assertIsNotNone(ont.getExistingIndividual("'test individual'"))
        self.assertEqual(
            1, owlont.getIndividualsInSignature(Imports.EXCLUDED).size()
        )

        self.assertEqual(
            0, owlont.getDataPropertiesInSignature(Imports.EXCLUDED).size()
        )
예제 #6
0
class TestManchesterSyntaxParserHelper(unittest.TestCase):
    """
    Tests the ManchesterSyntaxParserHelper class.  This also indirectly tests
    the functionality of _MoreAdvancedEntityChecker.
    """
    def setUp(self):
        self.test_ont = Ontology('test_data/ontology.owl')

        self.msph = ManchesterSyntaxParserHelper(self.test_ont)

    def test_parseLiteral(self):
        litval = self.msph.parseLiteral('"test"')
        self.assertTrue(litval.isRDFPlainLiteral())
        self.assertEqual('test', litval.getLiteral())

        litval = self.msph.parseLiteral('"test"^^xsd:string')
        self.assertTrue(litval.getDatatype().isString())
        self.assertEqual('test', litval.getLiteral())

        litval = self.msph.parseLiteral('1')
        self.assertTrue(litval.isInteger())
        self.assertEqual(1, litval.parseInteger())

        litval = self.msph.parseLiteral('"1"^^xsd:float')
        self.assertTrue(litval.isFloat())
        self.assertEqual(1.0, litval.parseFloat())

        litval = self.msph.parseLiteral('1.0f')
        self.assertTrue(litval.getDatatype().isFloat())
        self.assertEqual(1.0, litval.parseFloat())

        litval = self.msph.parseLiteral('true')
        self.assertTrue(litval.isBoolean())
        self.assertTrue(litval.parseBoolean())

    def test_parseDataRange(self):
        drange = self.msph.parseDataRange('xsd:integer')
        self.assertTrue(drange.isDatatype())
        self.assertTrue(drange.asOWLDatatype().isInteger())

        drange = self.msph.parseDataRange('xsd:integer[>0]')
        self.assertFalse(drange.isDatatype())
        self.assertEqual(DataRangeType.DATATYPE_RESTRICTION,
                         drange.getDataRangeType())

        drange = self.msph.parseDataRange('{1,2,3}')
        self.assertFalse(drange.isDatatype())
        self.assertEqual(DataRangeType.DATA_ONE_OF, drange.getDataRangeType())

    def test_parseClassExpressions(self):
        """
        Tests parsing strings that contain MS class expressions.
        """
        # Test strings containing simple, single-class expressions that all
        # refer to the same class.
        test_exps = [
            "'test class 1'", "obo:'test class 1'", "OBTO:'test class 1'",
            'obo:OBTO_0010', 'http://purl.obolibrary.org/obo/OBTO_0010',
            '<http://purl.obolibrary.org/obo/OBTO_0010>', 'OBTO:0010'
        ]
        expIRI = self.test_ont.getExistingClass('OBTO:0010').getIRI()

        for test_exp in test_exps:
            cl_exp = self.msph.parseClassExpression(test_exp)
            # Make sure the returned class expression is correct.
            self.assertFalse(cl_exp.isAnonymous())
            self.assertTrue(cl_exp.asOWLClass().getIRI().equals(expIRI))

        # Test a more complex expression.  In this case, we just verify that
        # the call completes and returns a value.  The check could be more
        # thorough at some point, but that is probably not necessary for now
        # since the correctness of the return value depends mostly on the
        # correctness of the OWL API.
        exps_str = "'test class 1' AND 'imported test class 1'"
        actual = self.msph.parseClassExpression(exps_str)
        self.assertIsNotNone(actual)
예제 #7
0
class Test_Ontology(unittest.TestCase):
    """
    Tests the Ontology convenience class.
    """
    def setUp(self):
        self.ont = Ontology('test_data/ontology.owl')
        self.owlont = self.ont.getOWLOntology()

    def test_getExistingClass(self):
        self.assertIsNotNone(self.ont.getExistingClass(CLASS_IRI))

        # Check a class in the imports closure.
        self.assertIsNotNone(
            self.ont.getExistingClass(
                'http://purl.obolibrary.org/obo/OBITO_0001'))

        # Verify that a non-existent entity is not found.
        self.assertIsNone(self.ont.getExistingClass(NULL_IRI))

        # Verify that an existent entity of the wrong type is not returned.
        self.assertIsNone(self.ont.getExistingClass(OBJPROP_IRI))

    def test_getExistingDataProperty(self):
        self.assertIsNotNone(self.ont.getExistingDataProperty(DATAPROP_IRI))

        # Verify that a non-existent entity is not found.
        self.assertIsNone(self.ont.getExistingDataProperty(NULL_IRI))

        # Verify that an existent entity of the wrong type is not returned.
        self.assertIsNone(self.ont.getExistingDataProperty(OBJPROP_IRI))

    def test_getExistingObjectProperty(self):
        self.assertIsNotNone(self.ont.getExistingObjectProperty(OBJPROP_IRI))

        # Verify that a non-existent entity is not found.
        self.assertIsNone(self.ont.getExistingObjectProperty(NULL_IRI))

        # Verify that an existent entity of the wrong type is not returned.
        self.assertIsNone(self.ont.getExistingObjectProperty(DATAPROP_IRI))

    def test_getExistingAnnotationProperty(self):
        self.assertIsNotNone(
            self.ont.getExistingAnnotationProperty(ANNOTPROP_IRI))

        # Verify that a non-existent entity is not found.
        self.assertIsNone(self.ont.getExistingAnnotationProperty(NULL_IRI))

        # Verify that an existent entity of the wrong type is not returned.
        self.assertIsNone(self.ont.getExistingAnnotationProperty(OBJPROP_IRI))

    def test_getExistingProperty(self):
        # Check each property type.
        self.assertIsNotNone(self.ont.getExistingProperty(OBJPROP_IRI))
        self.assertIsNotNone(self.ont.getExistingProperty(DATAPROP_IRI))
        self.assertIsNotNone(self.ont.getExistingProperty(ANNOTPROP_IRI))

        # Verify that a non-existent entity is not found.
        self.assertIsNone(self.ont.getExistingProperty(NULL_IRI))

        # Verify that an existent entity of the wrong type is not returned.
        self.assertIsNone(self.ont.getExistingProperty(CLASS_IRI))

    def test_getExistingEntity(self):
        # Check each entity type.
        self.assertIsNotNone(self.ont.getExistingEntity(OBJPROP_IRI))
        self.assertIsNotNone(self.ont.getExistingEntity(DATAPROP_IRI))
        self.assertIsNotNone(self.ont.getExistingEntity(ANNOTPROP_IRI))
        self.assertIsNotNone(self.ont.getExistingEntity(CLASS_IRI))
        self.assertIsNotNone(self.ont.getExistingEntity(INDIVIDUAL_IRI))

        # Verify that a non-existent entity is not found.
        self.assertIsNone(self.ont.getExistingEntity(NULL_IRI))

    def test_getExistingIndividual(self):
        self.assertIsNotNone(self.ont.getExistingIndividual(INDIVIDUAL_IRI))

        # Verify that a non-existent entity is not found.
        self.assertIsNone(self.ont.getExistingIndividual(NULL_IRI))

        # Verify that an existent entity of the wrong type is not returned.
        self.assertIsNone(self.ont.getExistingIndividual(CLASS_IRI))

    def test_createNewClass(self):
        entIRI = NULL_IRI

        self.assertIsNone(self.ont.getExistingEntity(entIRI))

        self.ont.createNewClass(entIRI)

        self.assertIsNotNone(self.ont.getExistingClass(entIRI))

    def test_createNewDataProperty(self):
        entIRI = NULL_IRI

        self.assertIsNone(self.ont.getExistingEntity(entIRI))

        self.ont.createNewDataProperty(entIRI)

        self.assertIsNotNone(self.ont.getExistingDataProperty(entIRI))

    def test_createNewObjectProperty(self):
        entIRI = NULL_IRI

        self.assertIsNone(self.ont.getExistingEntity(entIRI))

        self.ont.createNewObjectProperty(entIRI)

        self.assertIsNotNone(self.ont.getExistingObjectProperty(entIRI))

    def test_createNewAnnotationProperty(self):
        entIRI = NULL_IRI

        self.assertIsNone(self.ont.getExistingEntity(entIRI))

        self.ont.createNewAnnotationProperty(entIRI)

        self.assertIsNotNone(self.ont.getExistingAnnotationProperty(entIRI))

    def test_createNewIndividual(self):
        entIRI = NULL_IRI

        self.assertIsNone(self.ont.getExistingEntity(entIRI))

        self.ont.createNewIndividual(entIRI)

        self.assertIsNotNone(self.ont.getExistingIndividual(entIRI))

    def test_removeEntity(self):
        classobj = self.ont.getExistingClass(CLASS_IRI)
        self.assertIsNotNone(classobj)

        # First, delete the class but not its annotations.
        self.ont.removeEntity(classobj.getOWLAPIObj(), False)

        # Make sure the class has been deleted.
        self.assertIsNone(self.ont.getExistingClass(CLASS_IRI))

        # Make sure annotations for the target entity have not been deleted.
        IRIobj = IRI.create(CLASS_IRI)
        annot_ax_set = self.owlont.getAnnotationAssertionAxioms(IRIobj)
        self.assertEqual(2, annot_ax_set.size())

        # Run the deletion command again, this time deleting annotations.
        # Also, this time, use the _OntologyEntity object directly instead of
        # the OWL API object to make sure entity deletion works either way.
        self.ont.removeEntity(classobj, True)

        # Make sure annotations for the target entity have been deleted.
        IRIobj = IRI.create(CLASS_IRI)
        annot_ax_set = self.owlont.getAnnotationAssertionAxioms(IRIobj)
        self.assertTrue(annot_ax_set.isEmpty())

    def test_hasImport(self):
        import_iri = 'https://github.com/stuckyb/ontopilot/raw/master/python-src/test/test_data/ontology-import.owl'

        self.assertFalse(self.ont.hasImport('http://not.an.import/iri'))
        self.assertTrue(self.ont.hasImport(import_iri))

    def test_getImports(self):
        expected = [
            'https://github.com/stuckyb/ontopilot/raw/master/python-src/test/test_data/ontology-import.owl'
        ]
        imports_IRI_strs = [iri.toString() for iri in self.ont.getImports()]
        self.assertEqual(expected, imports_IRI_strs)

    def test_addImport(self):
        importIRI = IRI.create('file:/local/path/ont.owl')

        # Verify that the import is not yet included in the ontology.
        self.assertFalse(
            self.owlont.getDirectImportsDocuments().contains(importIRI))

        self.ont.addImport(importIRI, False)

        # Verify that the import declaration was added.
        self.assertTrue(
            self.owlont.getDirectImportsDocuments().contains(importIRI))

    def test_updateImportIRI(self):
        old_iri = 'https://github.com/stuckyb/ontopilot/raw/master/python-src/test/test_data/ontology-import.owl'
        new_iri = 'http://a.new.iri/replacement'

        self.assertTrue(self.ont.hasImport(old_iri))
        self.assertFalse(self.ont.hasImport(new_iri))

        self.ont.updateImportIRI(old_iri, new_iri)

        self.assertFalse(self.ont.hasImport(old_iri))
        self.assertTrue(self.ont.hasImport(new_iri))

        # Verify that an attempt to update an IRI for which there is not an
        # import statement is correctly handled.
        with self.assertRaisesRegexp(RuntimeError,
                                     'the import IRI could not be updated'):
            self.ont.updateImportIRI('http://iri.with.no/import', old_iri)

    def test_getImportedFromAnnotations(self):
        axioms = self.owlont.getAxioms(ImportsEnum.EXCLUDED)

        if_axioms = self.ont._getImportedFromAnnotations(axioms, self.owlont)

        # Define the IRIs of the entities that should be annotated.
        baseIRI = 'http://purl.obolibrary.org/obo/OBTO_'
        idnums = ('0001', '0020', '0030', '0010', '0011', '0012', '8000',
                  '8001')
        ent_IRIs = set([baseIRI + idnum for idnum in idnums])

        self.assertEqual(len(ent_IRIs), len(if_axioms))

        ontIRI = self.owlont.getOntologyID().getOntologyIRI().get()

        res_IRIs = set()
        for if_axiom in if_axioms:
            # Check the annotation property and value of each axiom.
            self.assertTrue(
                Ontology.IMPORTED_FROM_IRI.equals(
                    if_axiom.getProperty().getIRI()))

            self.assertTrue(ontIRI.equals(if_axiom.getValue().asIRI().get()))

            res_IRIs.add(if_axiom.getSubject().toString())

        # Check all of the annotation subjects.
        self.assertEqual(ent_IRIs, res_IRIs)

    def test_mergeOntology(self):
        mergeiri_str = 'https://github.com/stuckyb/ontopilot/raw/master/python-src/test/test_data/ontology-import.owl'
        mergeIRI = IRI.create(mergeiri_str)

        mergeclassiri_str = 'http://purl.obolibrary.org/obo/OBITO_0001'
        mergeclassIRI = IRI.create(mergeclassiri_str)
        mergeclass = self.ont.df.getOWLClass(mergeclassIRI)

        # Verify that the source IRI is in the target ontology's imports list
        # and that the class defined in the source ontology is not in the
        # target ontology.
        self.assertTrue(
            self.owlont.getDirectImportsDocuments().contains(mergeIRI))
        self.assertFalse(
            self.owlont.isDeclared(mergeclass, ImportsEnum.EXCLUDED))

        # Merge the axioms from the source ontology.
        self.ont.mergeOntology(mergeiri_str)

        # Verify that the source IRI is *not* in the target ontology's imports
        # list and that the class defined in the source ontology *is* in the
        # target ontology.
        self.assertFalse(
            self.owlont.getDirectImportsDocuments().contains(mergeIRI))
        self.assertTrue(
            self.owlont.isDeclared(mergeclass, ImportsEnum.EXCLUDED))

    def test_checkEntailmentErrors(self):
        # Check on ontology that is both consistent and coherent.
        report = self.ont.checkEntailmentErrors()
        self.assertTrue(report['is_consistent'])
        self.assertEqual(0, len(report['unsatisfiable_classes']))

        # Check an ontology that is both inconsistent and incoherent.
        testont = Ontology('test_data/inconsistent.owl')
        report = testont.checkEntailmentErrors()
        self.assertFalse(report['is_consistent'])
        self.assertEqual(0, len(report['unsatisfiable_classes']))

        # The ReasonerManager should ensure that reasoner instances track
        # ontology changes, so the following line should not be needed.
        #testont.getReasonerManager().disposeReasoners()

        # Check an ontology that is incoherent but not inconsistent.
        # Remove the instance of the unsatisfiable class 'test class 2' to make
        # the ontology consistent.
        individual = testont.getExistingIndividual('obo:OBTO_9000')
        testont.removeEntity(individual)
        unsatisfiable = testont.getExistingClass(
            'obo:OBTO_0011').getOWLAPIObj()
        report = testont.checkEntailmentErrors()
        self.assertTrue(report['is_consistent'])
        self.assertEqual(1, len(report['unsatisfiable_classes']))
        self.assertTrue(
            unsatisfiable.equals(report['unsatisfiable_classes'][0]))

    def test_setOntologyID(self):
        ont_iri = 'http://a.test.iri/main'
        ver_iri = 'http://a.test.iri/version'

        self.ont.setOntologyID(ont_iri)
        ontid = self.owlont.getOntologyID()
        self.assertEqual(ont_iri, str(ontid.getOntologyIRI().get()))
        self.assertIsNone(ontid.getVersionIRI().orNull())

        self.ont.setOntologyID(ont_iri, ver_iri)
        ontid = self.owlont.getOntologyID()
        self.assertEqual(ont_iri, str(ontid.getOntologyIRI().get()))
        self.assertEqual(ver_iri, str(ontid.getVersionIRI().get()))
예제 #8
0
class Test_ModuleExtractor(unittest.TestCase):
    """
    Tests the ModuleExtractor class.
    """
    def setUp(self):
        self.ont = Ontology('test_data/ontology.owl')
        self.owlont = self.ont.getOWLOntology()

        self.me = ModuleExtractor(self.ont)

    def test_getSignatureSize(self):
        self.assertEqual(0, self.me.getSignatureSize())

        self.me.addEntity('OBTO:0001', me_methods.SINGLE)
        self.me.addEntity('OBTO:0010', me_methods.SINGLE)
        self.me.addEntity('OBTO:0001', me_methods.LOCALITY)
        self.assertEqual(3, self.me.getSignatureSize())

        # Confirm that adding entities already in the signature does not
        # increase the signature size.
        self.me.addEntity('OBTO:0010', me_methods.SINGLE)
        self.assertEqual(3, self.me.getSignatureSize())

    def test_getPropertyCharacteristicsAxioms(self):
        # Test object property characteristics.
        ent = self.ont.getExistingObjectProperty('OBTO:0001')
        owlent = ent.getOWLAPIObj()

        axioms = self.me._getPropertyCharacteristicsAxioms(owlent)
        self.assertEqual(0, len(axioms))

        ent.makeFunctional()
        ent.makeInverseFunctional()
        ent.makeReflexive()
        ent.makeIrreflexive()
        ent.makeSymmetric()
        ent.makeAsymmetric()
        ent.makeTransitive()

        axioms = self.me._getPropertyCharacteristicsAxioms(owlent)
        self.assertEqual(7, len(axioms))
        for axiom in axioms:
            self.assertTrue(
                isinstance(axiom, OWLObjectPropertyCharacteristicAxiom))
            self.assertTrue(axiom.getProperty().equals(owlent))

        # Test data property characteristics.
        ent = self.ont.getExistingDataProperty('OBTO:0020')
        owlent = ent.getOWLAPIObj()

        axioms = self.me._getPropertyCharacteristicsAxioms(owlent)
        self.assertEqual(0, len(axioms))

        ent.makeFunctional()

        axioms = self.me._getPropertyCharacteristicsAxioms(owlent)
        self.assertEqual(1, len(axioms))
        for axiom in axioms:
            self.assertTrue(isinstance(axiom, OWLFunctionalDataPropertyAxiom))
            self.assertTrue(axiom.getProperty().equals(owlent))

    def _compareEntitySets(self, ent_list, result):
        """
        Compares a list of expected entities to a result set of OWLEntity
        instances.  The list should contain entity ID strings.
        """
        expset = set()
        for ent_id in ent_list:
            ent = self.ont.getExistingEntity(ent_id)
            expset.add(ent.getOWLAPIObj())

        self.assertEqual(expset, result)

    def test_getDirectlyRelatedComponents(self):
        # Define a set of related axiom types for ancestors and descendants.
        relatives = {rel_axiom_types.ANCESTORS, rel_axiom_types.DESCENDANTS}

        #--------
        # Tests for classes.
        #--------

        # Create a parent class for OBITO:0001.  This results in an explicit
        # class hierarchy that is 3 levels deep (starting from OBTO:9999).
        ent = self.ont.getExistingClass('OBITO:0001')
        owlent = ent.getOWLAPIObj()
        self.ont.createNewClass('OBTO:9999')
        ent.addSuperclass('OBTO:9999')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, relatives)
        self._compareEntitySets(
            ['OBTO:9999', 'OBTO:0010', 'OBTO:0011', 'OBTO:0012'], entset)
        self.assertEqual(4, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(axiom.isOfType(AxiomType.SUBCLASS_OF))
            self.assertTrue(axiom.containsEntityInSignature(owlent))

        # Test a disjointness relationship.
        owlent = self.ont.getExistingClass('OBTO:0010').getOWLAPIObj()

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.DISJOINTS})

        self._compareEntitySets(['OBTO:0011'], entset)
        self.assertEqual(1, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(axiom.isOfType(AxiomType.DISJOINT_CLASSES))
            self.assertTrue(axiom.contains(owlent))

        # Test equivalency relationships, and verify that the pairwise
        # equivalency axioms are properly analyzed.
        ent = self.ont.getExistingClass('OBTO:0010')
        owlent = ent.getOWLAPIObj()
        self.ont.createNewClass('OBTO:0013')
        self.ont.createNewClass('OBTO:0014')
        ent.addEquivalentTo('OBTO:0013')
        ent.addEquivalentTo('OBTO:0014')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.EQUIVALENTS})

        self._compareEntitySets(['OBTO:0013', 'OBTO:0014'], entset)
        self.assertEqual(2, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(axiom.isOfType(AxiomType.EQUIVALENT_CLASSES))
            self.assertTrue(axiom.contains(owlent))

        #--------
        # Tests for object properties.
        #--------

        # Create a superproperty for 'test object property 1'.
        ent = self.ont.getExistingObjectProperty('OBTO:0001')
        owlent = ent.getOWLAPIObj()
        self.ont.createNewObjectProperty('OBTO:0002')
        ent.addSuperproperty('OBTO:0002')

        # Create a subproperty for 'test object property 1'.
        newent = self.ont.createNewObjectProperty('OBTO:0003')
        newent.addSuperproperty('OBTO:0001')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, relatives)

        self._compareEntitySets(['OBTO:0002', 'OBTO:0003'], entset)
        self.assertEqual(2, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(axiom.isOfType(AxiomType.SUB_OBJECT_PROPERTY))
            self.assertTrue(axiom.containsEntityInSignature(owlent))

        # Test an equivalency relationship.
        self.ont.createNewObjectProperty('OBTO:0004')
        ent.addEquivalentTo('OBTO:0004')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.EQUIVALENTS})

        self._compareEntitySets(['OBTO:0004'], entset)
        self.assertEqual(1, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(
                axiom.isOfType(AxiomType.EQUIVALENT_OBJECT_PROPERTIES))
            self.assertTrue(axiom.getProperties().contains(owlent))

        # Test a disjointness relationship.
        self.ont.createNewObjectProperty('OBTO:0005')
        ent.addDisjointWith('OBTO:0005')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.DISJOINTS})

        self._compareEntitySets(['OBTO:0005'], entset)
        self.assertEqual(1, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(
                axiom.isOfType(AxiomType.DISJOINT_OBJECT_PROPERTIES))
            self.assertTrue(axiom.getProperties().contains(owlent))

        # Test an inverse relationship.
        self.ont.createNewObjectProperty('OBTO:0006')
        ent.addInverse('OBTO:0006')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.INVERSES})

        self._compareEntitySets(['OBTO:0006'], entset)
        self.assertEqual(1, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(axiom.isOfType(
                AxiomType.INVERSE_OBJECT_PROPERTIES))
            self.assertTrue(axiom.getProperties().contains(owlent))

        # Test a domain axiom.
        ent.addDomain('OBTO:0010')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.DOMAINS})

        self._compareEntitySets(['OBTO:0010'], entset)
        self.assertEqual(1, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(axiom.isOfType(AxiomType.OBJECT_PROPERTY_DOMAIN))
            self.assertTrue(axiom.getProperty().equals(owlent))

        # Test a range axiom.
        ent.addRange('OBTO:0011')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.RANGES})

        self._compareEntitySets(['OBTO:0011'], entset)
        self.assertEqual(1, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(axiom.isOfType(AxiomType.OBJECT_PROPERTY_RANGE))
            self.assertTrue(axiom.getProperty().equals(owlent))

        #--------
        # Tests for data properties.
        #--------

        # Create a superproperty for 'test data property 1'.
        ent = self.ont.getExistingDataProperty('OBTO:0020')
        owlent = ent.getOWLAPIObj()
        self.ont.createNewDataProperty('OBTO:0021')
        ent.addSuperproperty('OBTO:0021')

        # Create a subproperty for 'test data property 1'.
        newent = self.ont.createNewDataProperty('OBTO:0022')
        newent.addSuperproperty('OBTO:0020')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, relatives)

        self._compareEntitySets(['OBTO:0021', 'OBTO:0022'], entset)
        self.assertEqual(2, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(axiom.isOfType(AxiomType.SUB_DATA_PROPERTY))
            self.assertTrue(axiom.containsEntityInSignature(owlent))

        # Test an equivalency relationship.
        self.ont.createNewDataProperty('OBTO:0023')
        ent.addEquivalentTo('OBTO:0023')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.EQUIVALENTS})

        self._compareEntitySets(['OBTO:0023'], entset)
        self.assertEqual(1, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(
                axiom.isOfType(AxiomType.EQUIVALENT_DATA_PROPERTIES))
            self.assertTrue(axiom.getProperties().contains(owlent))

        # Test a disjointness relationship.
        self.ont.createNewDataProperty('OBTO:0024')
        ent.addDisjointWith('OBTO:0024')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.DISJOINTS})

        self._compareEntitySets(['OBTO:0024'], entset)
        self.assertEqual(1, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(axiom.isOfType(AxiomType.DISJOINT_DATA_PROPERTIES))
            self.assertTrue(axiom.getProperties().contains(owlent))

        # Test a domain axiom.
        ent.addDomain('OBTO:0010')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.DOMAINS})

        self._compareEntitySets(['OBTO:0010'], entset)
        self.assertEqual(1, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(axiom.isOfType(AxiomType.DATA_PROPERTY_DOMAIN))
            self.assertTrue(axiom.getProperty().equals(owlent))

        # Test a range axiom.
        ent.addRange('xsd:string')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.RANGES})

        self.assertEqual(0, len(entset))
        self.assertEqual(1, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(axiom.isOfType(AxiomType.DATA_PROPERTY_RANGE))
            self.assertTrue(axiom.getProperty().equals(owlent))

        #--------
        # Tests for annotation properties.
        #--------

        # Create a superproperty for 'annotation property 1'.
        ent = self.ont.getExistingAnnotationProperty('OBTO:0030')
        owlent = ent.getOWLAPIObj()
        self.ont.createNewAnnotationProperty('OBTO:0031')
        ent.addSuperproperty('OBTO:0031')

        # Create a subproperty for 'annotation property 1'.
        newent = self.ont.createNewAnnotationProperty('OBTO:0032')
        newent.addSuperproperty('OBTO:0030')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, relatives)

        self._compareEntitySets(['OBTO:0031', 'OBTO:0032'], entset)
        self.assertEqual(2, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(
                axiom.isOfType(AxiomType.SUB_ANNOTATION_PROPERTY_OF))
            self.assertTrue(axiom.containsEntityInSignature(owlent))

        #--------
        # Tests for named individuals.
        #--------

        # Test a class assertion (type).
        ent = self.ont.createNewIndividual('OBTO:0042')
        owlent = ent.getOWLAPIObj()
        ent.addType('OBTO:0010')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.TYPES})

        self._compareEntitySets(['OBTO:0010'], entset)
        self.assertEqual(1, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(axiom.isOfType(AxiomType.CLASS_ASSERTION))
            self.assertTrue(axiom.getIndividual().equals(owlent))

        # Test an object property assertion.
        self.ont.createNewIndividual('OBTO:0043')
        ent.addObjectPropertyFact('OBTO:0001', 'OBTO:0043')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.PROPERTY_ASSERTIONS})

        self._compareEntitySets(['OBTO:0001', 'OBTO:0043'], entset)
        self.assertEqual(1, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(axiom.isOfType(
                AxiomType.OBJECT_PROPERTY_ASSERTION))
            self.assertTrue(axiom.getSubject().equals(owlent))

        # Test a negative object property assertion.
        ent = self.ont.createNewIndividual('OBTO:0044')
        self.ont.createNewIndividual('OBTO:0045')
        owlent = ent.getOWLAPIObj()
        ent.addObjectPropertyFact('OBTO:0001', 'OBTO:0045', is_negative=True)

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.PROPERTY_ASSERTIONS})

        self._compareEntitySets(['OBTO:0001', 'OBTO:0045'], entset)
        self.assertEqual(1, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(
                axiom.isOfType(AxiomType.NEGATIVE_OBJECT_PROPERTY_ASSERTION))
            self.assertTrue(axiom.getSubject().equals(owlent))

        # Test a data property assertion.
        ent = self.ont.createNewIndividual('OBTO:0046')
        owlent = ent.getOWLAPIObj()
        ent.addDataPropertyFact('OBTO:0020', '"literal"^^xsd:string')

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.PROPERTY_ASSERTIONS})

        self._compareEntitySets(['OBTO:0020'], entset)
        self.assertEqual(1, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(axiom.isOfType(AxiomType.DATA_PROPERTY_ASSERTION))
            self.assertTrue(axiom.getSubject().equals(owlent))

        # Test a negative data property assertion.
        ent = self.ont.createNewIndividual('OBTO:0047')
        owlent = ent.getOWLAPIObj()
        ent.addDataPropertyFact('OBTO:0020',
                                '"literal"^^xsd:string',
                                is_negative=True)

        entset, axiomset = self.me.getDirectlyRelatedComponents(
            owlent, {rel_axiom_types.PROPERTY_ASSERTIONS})

        self._compareEntitySets(['OBTO:0020'], entset)
        self.assertEqual(1, len(axiomset))
        for axiom in axiomset:
            self.assertTrue(
                axiom.isOfType(AxiomType.NEGATIVE_DATA_PROPERTY_ASSERTION))
            self.assertTrue(axiom.getSubject().equals(owlent))

    def test_getRelatedComponents(self):
        # Create a subclass for 'test class 2'.  This results in an explicit
        # class hierarchy that is 3 levels deep and includes a node with
        # multiple child classes, all of which should provide a good test case
        # for the traversal algorithm.  The class structure should be as
        # follows:
        #
        # OBITO:0001
        # |--- OBTO:0010
        # |--- OBTO:0011
        # |    |--- OBTO:9999
        # |--- OBTO:0012
        newent = self.ont.createNewClass('OBTO:9999')
        newent.addSuperclass('OBTO:0011')

        # Test class descendant retrieval.
        ent = self.ont.getExistingClass('OBITO:0001').getOWLAPIObj()
        entset, axiomset = self.me.getRelatedComponents(
            ent, {rel_axiom_types.DESCENDANTS})

        self._compareEntitySets(
            ['OBITO:0001', 'OBTO:0010', 'OBTO:0011', 'OBTO:0012', 'OBTO:9999'],
            entset)
        self.assertEqual(4, len(axiomset))

        # Make a cyclic parent/child relationship for 'test class 2'.  The
        # class structure should be as follows:
        #
        # OBITO:0001
        # |--- OBTO:0010
        # |--- OBTO:0011
        # |    |--- OBTO:9999
        # |         |--- OBTO:0011
        # |--- OBTO:0012
        ent = self.ont.getExistingClass('OBTO:0011')
        ent.addSuperclass('OBTO:9999')

        # Verify that the cycle is correctly handled.
        ent = self.ont.getExistingClass('OBTO:0011').getOWLAPIObj()
        entset, axiomset = self.me.getRelatedComponents(
            ent, {rel_axiom_types.DESCENDANTS})

        self._compareEntitySets(['OBTO:0011', 'OBTO:9999'], entset)
        self.assertEqual(2, len(axiomset))

        # Create a polyhierarchy by making OBITO:0010 a parent class of
        # OBTO:0011.  The class structure should now be as follows:
        #
        # OBITO:0001
        # |--- OBTO:0010
        # |    |--- OBTO:0011
        # |         |--- OBTO:9999
        # |              |--- OBTO:0011
        # |--- OBTO:0011
        # |    |-- OBTO:9999
        # |        |--- OBTO:0011
        # |--- OBTO:0012
        ent = self.ont.getExistingClass('OBTO:0011')
        ent.addSuperclass('OBTO:0010')

        ent = self.ont.getExistingClass('OBITO:0001').getOWLAPIObj()
        entset, axiomset = self.me.getRelatedComponents(
            ent, {rel_axiom_types.DESCENDANTS})

        self._compareEntitySets(
            ['OBITO:0001', 'OBTO:0010', 'OBTO:0011', 'OBTO:0012', 'OBTO:9999'],
            entset)
        self.assertEqual(6, len(axiomset))

    def test_extractSingleTerms(self):
        """
        Tests building an import module using only the single-term extraction
        method.
        """
        # Create a parent class for OBITO:0001.  This results in an explicit
        # class hierarchy that is 3 levels deep (starting from OBTO:0010),
        # which should provide a good test case for the traversal algorithm.
        ent = self.ont.getExistingClass('OBITO:0001')
        self.ont.createNewClass('OBTO:9999')
        ent.addSuperclass('OBTO:9999')

        #--------
        # Create a new module to test adding single terms without any ancestors
        # or descendants.
        #--------

        # Add 'test class 1'.
        self.me.addEntity('OBTO:0010', me_methods.SINGLE)
        # Add 'test object property 1'.
        self.me.addEntity('OBTO:0001', me_methods.SINGLE)

        # Make 'test object property 1' transitive.
        prop = self.ont.getExistingObjectProperty('OBTO:0001')
        prop.makeTransitive()

        module = self.me.extractModule('http://test.mod/id')

        # Verify that all expected entities are present in the module.  Use at
        # least one label reference to verify that labels are mapped correctly
        # in the module ontology.
        self.assertIsNotNone(module.getExistingClass("'test class 1'"))
        self.assertIsNotNone(module.getExistingObjectProperty('OBTO:0001'))
        self.assertIsNotNone(module.getExistingAnnotationProperty('OBTO:0030'))

        # Verify that 'test object property 1' is transitive.
        owlprop = module.getExistingObjectProperty('OBTO:0001').getOWLAPIObj()
        owlmod = module.getOWLOntology()
        axioms = owlmod.getTransitiveObjectPropertyAxioms(owlprop)
        self.assertEqual(1, len(axioms))
        for axiom in axioms:
            self.assertTrue(isinstance(axiom,
                                       OWLTransitiveObjectPropertyAxiom))
            self.assertTrue(axiom.getProperty().equals(owlprop))

        # Verify that there are no unexpected entities.  Note that the
        # annotation properties in the signature will include rdfs:label and
        # dc:source.
        owlont = module.getOWLOntology()
        self.assertEqual(1, owlont.getClassesInSignature(True).size())
        self.assertEqual(1, owlont.getObjectPropertiesInSignature(True).size())
        self.assertEqual(0, owlont.getDataPropertiesInSignature(True).size())
        self.assertEqual(
            3,
            owlont.getAnnotationPropertiesInSignature(False).size())
        self.assertEqual(0, owlont.getIndividualsInSignature(True).size())

        #--------
        # Create a new module to test adding single terms with their
        # descendants.
        #--------

        self.me.clearSignatures()

        # Define a set of related axiom types for descendants.
        descendants = {rel_axiom_types.DESCENDANTS}

        # Add 'imported test class 1'.
        self.me.addEntity('OBITO:0001', me_methods.SINGLE, descendants)
        # Add 'test object property 1'.
        self.me.addEntity('OBTO:0001', me_methods.SINGLE, descendants)

        module = self.me.extractModule('http://test.mod/id2')

        # Verify that all expected entities are present in the module.  Use at
        # least one label reference to verify that labels are mapped correctly
        # in the module ontology.
        self.assertIsNotNone(module.getExistingClass('OBITO:0001'))
        self.assertIsNotNone(module.getExistingClass('OBTO:0010'))
        self.assertIsNotNone(module.getExistingClass('OBTO:0011'))
        self.assertIsNotNone(module.getExistingClass('OBTO:0012'))
        self.assertIsNotNone(module.getExistingObjectProperty('OBTO:0001'))
        self.assertIsNotNone(module.getExistingAnnotationProperty('OBTO:0030'))

        # Verify that there are no unexpected entities.  Note that the
        # annotation properties in the signature will include rdfs:label and
        # dc:source.
        owlont = module.getOWLOntology()
        self.assertEqual(4, owlont.getClassesInSignature(True).size())
        self.assertEqual(1, owlont.getObjectPropertiesInSignature(True).size())
        self.assertEqual(0, owlont.getDataPropertiesInSignature(True).size())
        self.assertEqual(
            3,
            owlont.getAnnotationPropertiesInSignature(False).size())
        self.assertEqual(0, owlont.getIndividualsInSignature(True).size())

        # Verify that the parent/child axioms are present.
        ent = module.getExistingClass('OBITO:0001')
        axioms = owlont.getSubClassAxiomsForSuperClass(ent.getOWLAPIObj())
        self.assertEqual(3, axioms.size())

        #--------
        # Create a new module to test adding single terms with their
        # descendants and ancestors.
        #--------

        self.me.clearSignatures()

        # Define a set of related axiom types for ancestors and descendants.
        relatives = {rel_axiom_types.ANCESTORS, rel_axiom_types.DESCENDANTS}

        # Add 'imported test class 1'.
        self.me.addEntity('OBITO:0001', me_methods.SINGLE, relatives)
        # Add 'test class 3'.  This should already be part of the signature
        # thanks to the preceding call, but we add it again here to verify that
        # repeated entities are not somehow duplicated in the extracted module.
        self.me.addEntity('OBTO:0012', me_methods.SINGLE)
        # Add 'test object property 1'.
        self.me.addEntity('OBTO:0001', me_methods.SINGLE, relatives)

        module = self.me.extractModule('http://test.mod/id3')

        # Verify that all expected entities are present in the module.
        self.assertIsNotNone(module.getExistingClass('OBTO:9999'))
        self.assertIsNotNone(module.getExistingClass('OBITO:0001'))
        self.assertIsNotNone(module.getExistingClass('OBTO:0010'))
        self.assertIsNotNone(module.getExistingClass('OBTO:0011'))
        self.assertIsNotNone(module.getExistingClass('OBTO:0012'))
        self.assertIsNotNone(module.getExistingObjectProperty('OBTO:0001'))
        self.assertIsNotNone(module.getExistingAnnotationProperty('OBTO:0030'))

        # Verify that there are no unexpected entities.  Note that the
        # annotation properties in the signature will include rdfs:label and
        # dc:source.
        owlont = module.getOWLOntology()
        self.assertEqual(5, owlont.getClassesInSignature(True).size())
        self.assertEqual(1, owlont.getObjectPropertiesInSignature(True).size())
        self.assertEqual(0, owlont.getDataPropertiesInSignature(True).size())
        self.assertEqual(
            3,
            owlont.getAnnotationPropertiesInSignature(False).size())
        self.assertEqual(0, owlont.getIndividualsInSignature(True).size())

        # Verify that the parent/child axioms are present.
        ent = module.getExistingClass('OBITO:0001')
        axioms = owlont.getSubClassAxiomsForSuperClass(ent.getOWLAPIObj())
        self.assertEqual(3, axioms.size())
        axioms = owlont.getSubClassAxiomsForSubClass(ent.getOWLAPIObj())
        self.assertEqual(1, axioms.size())

        #--------
        # Create a new module to test adding single terms combined with
        # explicitly excluding some entities.
        #--------

        self.me.clearSignatures()

        # Add 'imported test class 1', including all of its descendants and
        # ancestors, then exclude it and its descendants.
        self.me.addEntity('OBITO:0001', me_methods.SINGLE, relatives)
        self.me.excludeEntity('OBITO:0001', descendants)
        # Add 'test object property 1'.
        self.me.addEntity('OBTO:0001', me_methods.SINGLE, relatives)

        module = self.me.extractModule('http://test.mod/id4')

        # Verify that all expected entities are present in the module.
        self.assertIsNotNone(module.getExistingClass('OBTO:9999'))
        self.assertIsNotNone(module.getExistingObjectProperty('OBTO:0001'))
        self.assertIsNotNone(module.getExistingAnnotationProperty('OBTO:0030'))

        # Verify that there are no unexpected entities.  Note that the
        # annotation properties in the signature will include rdfs:label and
        # dc:source.
        owlont = module.getOWLOntology()
        self.assertEqual(1, owlont.getClassesInSignature(True).size())
        self.assertEqual(1, owlont.getObjectPropertiesInSignature(True).size())
        self.assertEqual(0, owlont.getDataPropertiesInSignature(True).size())
        self.assertEqual(
            3,
            owlont.getAnnotationPropertiesInSignature(False).size())
        self.assertEqual(0, owlont.getIndividualsInSignature(True).size())

        # Verify that no parent/child axioms are present.
        ent = module.getExistingClass('OBTO:9999')
        axioms = owlont.getSubClassAxiomsForSuperClass(ent.getOWLAPIObj())
        self.assertTrue(axioms.isEmpty())

    def test_extractLocality(self):
        """
        Tests building an import module using only the syntactic locality
        extraction method.  This test only verifies that the code runs without
        error, since the correctness of the axiom extraction depends on the OWL
        API implementation.
        """
        # Add 'test class 1'.
        self.me.addEntity('OBTO:0010', me_methods.LOCALITY)
        # Add 'test object property 1'.
        self.me.addEntity('OBTO:0001', me_methods.LOCALITY)

        module = self.me.extractModule('http://test.mod/id')
예제 #9
0
class Test_Documenter(unittest.TestCase):
    """
    Tests the Documenter class.
    """
    def setUp(self):
        self.ont = Ontology('test_data/ontology.owl')
        self.doc = Documenter(self.ont)

        self.longMessage = True

    def test_parseDocSpec(self):
        """
        This method tests the results of _parseDocSpec() by converting the
        returned Document objects to a string representation and checking the
        string.
        """
        # Define test values and results for valid specifications.
        testvals = [
            {
                'docspec': '',
                'expected': ''
            },
            {
                'docspec': ' \n',
                'expected': ''
            },
            # Only a title.
            {
                'docspec': '# Document title',
                'expected': '# Document title'
            },
            # Several headings and other non-entities text.
            {
                'docspec':
                """
# Document title

---
## Classes

 - not an entities entry
""",
                'expected':
                """
# Document title

---
## Classes

 - not an entities entry
"""
            },
            # Multiple non-empty document sections.
            {
                'docspec':
                """
## Properties
- ID: OBTO:'test data property 1'

## Classes
- ID: OBTO:0010
- ID: OBTO:0011
""",
                'expected':
                """
## Properties
Entities:
    IRI: http://purl.obolibrary.org/obo/OBTO_0020
    OBO ID: OBTO:0020
    Label: test data property 1

## Classes
Entities:
    IRI: http://purl.obolibrary.org/obo/OBTO_0010
    OBO ID: OBTO:0010
    Label: test class 1

    IRI: http://purl.obolibrary.org/obo/OBTO_0011
    OBO ID: OBTO:0011
    Label: test class 2

"""
            },
            # Multi-level nested child specifications.
            {
                'docspec':
                """
## Classes
- ID: OBITO:0001
  children:
      - ID: OBTO:0010
        children:
            - ID: OBTO:0012
      - ID: OBTO:0011
- ID: OBTO:0090
""",
                'expected':
                """
## Classes
Entities:
    IRI: http://purl.obolibrary.org/obo/OBITO_0001
    OBO ID: OBITO:0001
    Label: imported test class 1
    Children:
        IRI: http://purl.obolibrary.org/obo/OBTO_0010
        OBO ID: OBTO:0010
        Label: test class 1
        Children:
            IRI: http://purl.obolibrary.org/obo/OBTO_0012
            OBO ID: OBTO:0012
            Label: test class 3

        IRI: http://purl.obolibrary.org/obo/OBTO_0011
        OBO ID: OBTO:0011
        Label: test class 2

    IRI: http://purl.obolibrary.org/obo/OBTO_0090
    OBO ID: OBTO:0090
    Label: 

"""
            },
            # Values of "descendants" that do not result in entity retrieval.
            {
                'docspec':
                """
## Classes
- ID: OBITO:0001
  descendants: none
""",
                'expected':
                """
## Classes
Entities:
    IRI: http://purl.obolibrary.org/obo/OBITO_0001
    OBO ID: OBITO:0001
    Label: imported test class 1

"""
            },
            {
                'docspec':
                """
## Classes
- ID: OBITO:0001
  descendants: 0
""",
                'expected':
                """
## Classes
Entities:
    IRI: http://purl.obolibrary.org/obo/OBITO_0001
    OBO ID: OBITO:0001
    Label: imported test class 1

"""
            },
            # Single-level automatic descendants retrieval.
            {
                'docspec':
                """
## Classes
- ID: OBITO:0001
  descendants: 1
""",
                'expected':
                """
## Classes
Entities:
    IRI: http://purl.obolibrary.org/obo/OBITO_0001
    OBO ID: OBITO:0001
    Label: imported test class 1
    Children:
        IRI: http://purl.obolibrary.org/obo/OBTO_0010
        OBO ID: OBTO:0010
        Label: test class 1

        IRI: http://purl.obolibrary.org/obo/OBTO_0011
        OBO ID: OBTO:0011
        Label: test class 2

        IRI: http://purl.obolibrary.org/obo/OBTO_0012
        OBO ID: OBTO:0012
        Label: test class 3

"""
            },
            # Multi-level automatic descendants retrieval.
            {
                'docspec':
                """
## Classes
- ID: OBITO:0001
  descendants: all
""",
                'expected':
                """
## Classes
Entities:
    IRI: http://purl.obolibrary.org/obo/OBITO_0001
    OBO ID: OBITO:0001
    Label: imported test class 1
    Children:
        IRI: http://purl.obolibrary.org/obo/OBTO_0010
        OBO ID: OBTO:0010
        Label: test class 1
        Children:
            IRI: http://purl.obolibrary.org/obo/OBTO_0091
            OBO ID: OBTO:0091
            Label: 

        IRI: http://purl.obolibrary.org/obo/OBTO_0011
        OBO ID: OBTO:0011
        Label: test class 2

        IRI: http://purl.obolibrary.org/obo/OBTO_0012
        OBO ID: OBTO:0012
        Label: test class 3

"""
            },
            # Multi-level automatic descendants retrieval with filtering.
            {
                'docspec':
                """
## Classes
- ID: OBITO:0001
  descendants: all
  filter_by_label: " 1"
""",
                'expected':
                """
## Classes
Entities:
    IRI: http://purl.obolibrary.org/obo/OBITO_0001
    OBO ID: OBITO:0001
    Label: imported test class 1
    Children:
        IRI: http://purl.obolibrary.org/obo/OBTO_0010
        OBO ID: OBTO:0010
        Label: test class 1

"""
            },
            # Multi-level automatic descendants retrieval with both label and
            # IRI filtering.
            {
                'docspec':
                """
## Classes
- ID: OBITO:0001
  descendants: all
  filter_by_label: " 1"
  filter_by_IRI: "OBITO_"
""",
                'expected':
                """
## Classes
Entities:
    IRI: http://purl.obolibrary.org/obo/OBITO_0001
    OBO ID: OBITO:0001
    Label: imported test class 1

"""
            },
            # Multiple mixed Markdown and entities sections.
            {
                'docspec':
                """
# Document title.

Markdown paragraph.

## Classes
- ID: OBITO:0001

Another Markdown *paragraph*.

* a
* list

## Properties
- ID: OBTO:'test data property 1'
A final Markdown paragraph.
""",
                'expected':
                """
# Document title.

Markdown paragraph.

## Classes
Entities:
    IRI: http://purl.obolibrary.org/obo/OBITO_0001
    OBO ID: OBITO:0001
    Label: imported test class 1

Another Markdown *paragraph*.

* a
* list

## Properties
Entities:
    IRI: http://purl.obolibrary.org/obo/OBTO_0020
    OBO ID: OBTO:0020
    Label: test data property 1

A final Markdown paragraph.
"""
            },
            # Including literal '^- .*' in a Markdown section.
            {
                'docspec':
                r"""
 - text
-- text
\- text
\\- text
\\\- text

## Classes
- ID: OBITO:0001
""",
                'expected':
                r"""
 - text
-- text
- text
\- text
\\- text

## Classes
Entities:
    IRI: http://purl.obolibrary.org/obo/OBITO_0001
    OBO ID: OBITO:0001
    Label: imported test class 1

"""
            },
            # Test UTF-8 unicode support.
            {
                'docspec':
                """
# Document title

## Greek alpha: \xce\xb1
Other text.
""",
                'expected':
                u"""
# Document title

## Greek alpha: \u03b1
Other text.
"""
            }
        ]

        # Add some extra classes to the test ontology hierarchy.  After the
        # additions, the class structure should now be as follows:
        #
        # OBTO:0090
        # OBITO:0001
        # |--- OBTO:0010
        # |    |--- OBTO:0091
        # |--- OBTO:0011
        # |--- OBTO:0012
        newclass = self.ont.createNewClass('OBTO:0090')
        newclass = self.ont.createNewClass('OBTO:0091')
        newclass.addSuperclass('OBTO:0010')

        for testval in testvals:
            result = unicode(self.doc._parseDocSpec(testval['docspec']))
            #print result
            # When testing the result, remove the leading newline from the
            # expected results string.
            self.assertEqual(testval['expected'],
                             result,
                             msg='Input specification:"""{0}"""'.format(
                                 testval['docspec']))

        # Create a cycle in the descendant relationships by making OBITO:0001 a
        # subclass of OBTO:0091, and make a polyhierarchy by making OBTO:0010 a
        # subclass of OBTO:0011.  The class structure should look like this:
        #
        # OBTO:0090
        # OBITO:0001
        # |--- OBTO:0010
        # |    |--- OBTO:0091
        # |         |--- OBITO:0001
        # |--- OBTO:0011
        # |    |--- OBTO:0010
        # |         |--- OBTO:0091
        # |              |--- OBITO:0001
        # |--- OBTO:0012
        newclass.addSubclass('OBITO:0001')
        ent = self.ont.getExistingClass('OBTO:0011')
        ent.addSubclass('OBTO:0010')

        # Run new multi-level descendants tests to make sure the cycle doesn't
        # "trap" the algorithms and that the polyhierarchy is handled
        # correctly.
        testvals = [
            # Multi-level automatic descendants retrieval.
            {
                'docspec':
                """
## Classes
- ID: OBITO:0001
  descendants: all
""",
                'expected':
                """
## Classes
Entities:
    IRI: http://purl.obolibrary.org/obo/OBITO_0001
    OBO ID: OBITO:0001
    Label: imported test class 1
    Children:
        IRI: http://purl.obolibrary.org/obo/OBTO_0010
        OBO ID: OBTO:0010
        Label: test class 1
        Children:
            IRI: http://purl.obolibrary.org/obo/OBTO_0091
            OBO ID: OBTO:0091
            Label: 
            Children:
                IRI: http://purl.obolibrary.org/obo/OBITO_0001
                OBO ID: OBITO:0001
                Label: imported test class 1

        IRI: http://purl.obolibrary.org/obo/OBTO_0011
        OBO ID: OBTO:0011
        Label: test class 2
        Children:
            IRI: http://purl.obolibrary.org/obo/OBTO_0010
            OBO ID: OBTO:0010
            Label: test class 1
            Children:
                IRI: http://purl.obolibrary.org/obo/OBTO_0091
                OBO ID: OBTO:0091
                Label: 
                Children:
                    IRI: http://purl.obolibrary.org/obo/OBITO_0001
                    OBO ID: OBITO:0001
                    Label: imported test class 1

        IRI: http://purl.obolibrary.org/obo/OBTO_0012
        OBO ID: OBTO:0012
        Label: test class 3

"""
            },
            # Multi-level automatic descendants retrieval with filtering.  This
            # also tests duplicate deletion.
            {
                'docspec':
                """
## Classes
- ID: OBITO:0001
  descendants: all
  filter_by_label: " 1"
""",
                'expected':
                """
## Classes
Entities:
    IRI: http://purl.obolibrary.org/obo/OBITO_0001
    OBO ID: OBITO:0001
    Label: imported test class 1
    Children:
        IRI: http://purl.obolibrary.org/obo/OBTO_0010
        OBO ID: OBTO:0010
        Label: test class 1
        Children:
            IRI: http://purl.obolibrary.org/obo/OBITO_0001
            OBO ID: OBITO:0001
            Label: imported test class 1

"""
            }
        ]

        for testval in testvals:
            result = unicode(self.doc._parseDocSpec(testval['docspec']))
            #print result
            self.assertEqual(testval['expected'], result)

        # Test error conditions to make sure they are handled correctly.
        testvals = [
            # Missing entity ID.
            {
                'docspec': """
## Classes
- descendants: 1
""",
                'errorstr': 'No entity ID was provided'
            },
            # Invalid ID.
            {
                'docspec': """
## Classes
- ID: OBTO:INVALID
""",
                'errorstr': 'No entity with the ID ".*" could be found'
            },
            # Invalid "descendants" values.
            {
                'docspec': """
## Classes
- ID: OBTO:0010
  descendants: invalid
""",
                'errorstr': 'Invalid value for "descendants" directive'
            },
            {
                'docspec': """
## Classes
- ID: OBTO:0010
  descendants: -1
""",
                'errorstr': 'Invalid value for "descendants" directive'
            },
        ]

        for testval in testvals:
            with self.assertRaisesRegexp(DocumentationSpecificationError,
                                         testval['errorstr']):
                self.doc._parseDocSpec(testval['docspec'])
예제 #10
0
class Test_HTMLWriter(unittest.TestCase):
    """
    Tests the HTMLWriter class.
    """
    def setUp(self):
        self.ont = Ontology('test_data/ontology.owl')
        self.doc = Documenter(self.ont)

        self.hw = HTMLWriter()

    def test_getUniqueValue(self):
        coll = ['a', 'b', 'b-1', 'c-']

        testvals = [{
            'text': '',
            'expected': '-1'
        }, {
            'text': 'd',
            'expected': 'd'
        }, {
            'text': 'a',
            'expected': 'a-1'
        }, {
            'text': 'b',
            'expected': 'b-2'
        }, {
            'text': 'c-',
            'expected': 'c--1'
        }]

        for testval in testvals:
            self.assertEqual(testval['expected'],
                             self.hw._getUniqueValue(testval['text'], coll))

    def test_getIDText(self):
        # String conversion tests.
        testvals = [
            {
                'text': '',
                'expected': '-1'
            },
            {
                'text': '- -- \t\n',
                'expected': '-'
            },
            {
                'text': 'will-not_be-changed',
                'expected': 'will-not_be-changed'
            },
            {
                'text': '(w*&il|}[]l be\tch@anged',
                'expected': 'will-be-changed'
            },
            {
                'text': 'Case-Will-Change',
                'expected': 'case-will-change'
            },
            {
                # Includes a unicode lower-case Greek alpha.
                'text': unicode('unicode: \xce\xb1', 'utf-8'),
                'expected': 'unicode-'
            }
        ]

        for testval in testvals:
            self.assertEqual(testval['expected'],
                             self.hw._getIDText(testval['text'], set()))

        # Test unique ID generation.
        usedIDs = {
            'ida', 'idb', 'idb-1', 'idc', 'idc-2', 'idd', 'idd-1', 'idd-2'
        }

        testvals = [{
            'text': 'ide',
            'expected': 'ide'
        }, {
            'text': 'ida',
            'expected': 'ida-1'
        }, {
            'text': 'idb',
            'expected': 'idb-2'
        }, {
            'text': 'idc',
            'expected': 'idc-1'
        }, {
            'text': 'idd',
            'expected': 'idd-3'
        }]

        for testval in testvals:
            self.assertEqual(testval['expected'],
                             self.hw._getIDText(testval['text'], usedIDs))

    def _printResultsComparison(self, expected, result):
        """
        Prints a line-by-line comparison of an expected text string and a
        result text string.
        """
        for e_line, r_line in zip(expected.splitlines(), result.splitlines()):
            if e_line != r_line:
                print 'MISMATCH:'
            print 'exp: "{0}"\nres: "{1}"'.format(e_line, r_line)

    def test_write(self):
        testvals = [
            # A document specification that includes two Markdown sections with
            # h2 headers, separated by an entities section, followed by another
            # entities section.  One of the h2 headers has content that will
            # generate an ID that conflicts with a reserved ID, to verify that
            # reserved IDs are properly preserved.
            {
                'docspec':
                """
# Test documentation

## First h2 header

## main

## Properties
- ID: OBTO:0020

## Classes

- ID: OBITO:0001
  descendants: 1
""",
                'expected':
                """
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
    <meta charset="utf-8" />
    <title>Test documentation</title>
    <link rel="stylesheet" type="text/css" href="documentation_styles.css" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="navtree.js"></script>
</head>
<body>

<nav id="toc">
<h1>Table of Contents</h1>
<div id="toc_buttons">
    <div id="expand_all" class="top_toc_button">expand all</div>
    <div id="collapse_all" class="top_toc_button">collapse all</div>
</div>
<ul>
<li><a href="#first-h2-header">First h2 header</a>
</li>
<li><a href="#main-1">main</a>
</li>
<li><a href="#properties">Properties</a>
    <ul>
    <li><a href="#test-data-property-1">test data property 1</a></li>
    </ul>
</li>
<li><a href="#classes">Classes</a>
    <ul>
    <li><a href="#imported-test-class-1">imported test class 1</a>
        <ul>
        <li><a href="#test-class-1">test class 1</a></li>
        <li><a href="#test-class-2">test class 2</a></li>
        <li><a href="#test-class-3">test class 3</a></li>
        </ul>
    </li>
    </ul>
</li>
</ul>
</nav>

<main>
<h1>Test documentation</h1>

<h2 id="first-h2-header">First h2 header</h2>

<h2 id="main-1">main</h2>

<h2 id="properties">Properties</h2>
<ul class="entity_list">
<li>
    <h3 id="test-data-property-1">test data property 1</h3>
    <p>OBO ID: OBTO:0020</p>
    <p>IRI: http://purl.obolibrary.org/obo/OBTO_0020</p>
</li>
</ul>

<h2 id="classes">Classes</h2>
<ul class="entity_list">
<li>
    <h3 id="imported-test-class-1">imported test class 1</h3>
    <p>OBO ID: OBITO:0001</p>
    <p>IRI: http://purl.obolibrary.org/obo/OBITO_0001</p>
    <ul class="entity_list">
    <li>
        <h3 id="test-class-1">test class 1</h3>
        <p>OBO ID: OBTO:0010</p>
        <p>IRI: http://purl.obolibrary.org/obo/OBTO_0010</p>
    </li>
    <li>
        <h3 id="test-class-2">test class 2</h3>
        <p>OBO ID: OBTO:0011</p>
        <p>IRI: http://purl.obolibrary.org/obo/OBTO_0011</p>
    </li>
    <li>
        <h3 id="test-class-3">test class 3</h3>
        <p>OBO ID: OBTO:0012</p>
        <p>IRI: http://purl.obolibrary.org/obo/OBTO_0012</p>
    </li>
    </ul>
</li>
</ul>

</main>
</body>
</html>"""
            },
            # A document specification that includes UTF-8 non-ASCI text.
            {
                'docspec':
                """
## UTF-8 Greek alpha: \xce\xb1
""",
                'expected':
                """
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
    <meta charset="utf-8" />
    <title></title>
    <link rel="stylesheet" type="text/css" href="documentation_styles.css" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="navtree.js"></script>
</head>
<body>

<nav id="toc">
<h1>Table of Contents</h1>
<div id="toc_buttons">
    <div id="expand_all" class="top_toc_button">expand all</div>
    <div id="collapse_all" class="top_toc_button">collapse all</div>
</div>
<ul>
<li><a href="#utf-8-greek-alpha-">UTF-8 Greek alpha: \xce\xb1</a>
</li>
</ul>
</nav>

<main>
<h2 id="utf-8-greek-alpha-">UTF-8 Greek alpha: \xce\xb1</h2>
</main>
</body>
</html>"""
            }
        ]

        self.doc.setWriter(HTMLWriter())

        for testval in testvals:
            docspec = testval['docspec']
            expected = testval['expected']

            strbuf = StringIO.StringIO()
            self.doc.document(docspec, strbuf)
            result = strbuf.getvalue()
            strbuf.close()

            #self._printResultsComparison(expected[1:], result)

            self.assertEqual(expected[1:], result)

        # Create a cycle in the descendant relationships by making OBITO:0001 a
        # subclass of OBTO:0010, and make a polyhierarchy by making OBTO:0012 a
        # subclass of OBTO:0011.  The class structure should look like this:
        #
        # OBTO:0090
        # OBITO:0001
        # |--- OBTO:0010
        # |    |--- OBITO:0001
        # |--- OBTO:0011
        # |    |--- OBTO:0012
        # |--- OBTO:0012
        ent = self.ont.getExistingClass('OBTO:0010')
        ent.addSubclass('OBITO:0001')
        ent = self.ont.getExistingClass('OBTO:0011')
        ent.addSubclass('OBTO:0012')

        # Make sure the cycle doesn't "trap" the documentation generating
        # algorithms and that the polyhierarchy is handled correctly.
        docspec = """
## Classes
- ID: OBITO:0001
  descendants: all
"""
        expected = """
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
    <meta charset="utf-8" />
    <title></title>
    <link rel="stylesheet" type="text/css" href="documentation_styles.css" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="navtree.js"></script>
</head>
<body>

<nav id="toc">
<h1>Table of Contents</h1>
<div id="toc_buttons">
    <div id="expand_all" class="top_toc_button">expand all</div>
    <div id="collapse_all" class="top_toc_button">collapse all</div>
</div>
<ul>
<li><a href="#classes">Classes</a>
    <ul>
    <li><a href="#imported-test-class-1">imported test class 1</a>
        <ul>
        <li><a href="#test-class-1">test class 1</a>
            <ul>
            <li><a href="#imported-test-class-1">imported test class 1</a></li>
            </ul>
        </li>
        <li><a href="#test-class-2">test class 2</a>
            <ul>
            <li><a href="#test-class-3">test class 3</a></li>
            </ul>
        </li>
        <li><a href="#test-class-3">test class 3</a></li>
        </ul>
    </li>
    </ul>
</li>
</ul>
</nav>

<main>
<h2 id="classes">Classes</h2>
<ul class="entity_list">
<li>
    <h3 id="imported-test-class-1">imported test class 1</h3>
    <p>OBO ID: OBITO:0001</p>
    <p>IRI: http://purl.obolibrary.org/obo/OBITO_0001</p>
    <ul class="entity_list">
    <li>
        <h3 id="test-class-1">test class 1</h3>
        <p>OBO ID: OBTO:0010</p>
        <p>IRI: http://purl.obolibrary.org/obo/OBTO_0010</p>
        <ul class="entity_list">
        <li>
            <h3>imported test class 1</h3>
            <p>OBO ID: OBITO:0001</p>
            <p>IRI: http://purl.obolibrary.org/obo/OBITO_0001</p>
        </li>
        </ul>
    </li>
    <li>
        <h3 id="test-class-2">test class 2</h3>
        <p>OBO ID: OBTO:0011</p>
        <p>IRI: http://purl.obolibrary.org/obo/OBTO_0011</p>
        <ul class="entity_list">
        <li>
            <h3 id="test-class-3">test class 3</h3>
            <p>OBO ID: OBTO:0012</p>
            <p>IRI: http://purl.obolibrary.org/obo/OBTO_0012</p>
        </li>
        </ul>
    </li>
    <li>
        <h3>test class 3</h3>
        <p>OBO ID: OBTO:0012</p>
        <p>IRI: http://purl.obolibrary.org/obo/OBTO_0012</p>
    </li>
    </ul>
</li>
</ul>

</main>
</body>
</html>"""

        strbuf = StringIO.StringIO()
        self.doc.document(docspec, strbuf)
        result = strbuf.getvalue()
        strbuf.close()

        #self._printResultsComparison(expected[1:], result)

        self.assertEqual(expected[1:], result)