From cc6b6298b1c4aa0af63640948d82168765a81144 Mon Sep 17 00:00:00 2001 From: lambdamusic Date: Sun, 19 Sep 2021 23:03:50 +0100 Subject: [PATCH 01/16] entity_display_title --- ontospy/core/entities.py | 46 ++++++++++++++++----- ontospy/core/ontospy.py | 88 +++++++++++++++++++++++++++------------- 2 files changed, 95 insertions(+), 39 deletions(-) diff --git a/ontospy/core/entities.py b/ontospy/core/entities.py index 23d97342..e23bb58c 100755 --- a/ontospy/core/entities.py +++ b/ontospy/core/entities.py @@ -37,7 +37,9 @@ def __init__(self, rdftype=None, namespaces=None, ext_model=False, - is_Bnode=False): + is_Bnode=False, + entity_display_title="qname", + ): """ Init ontology object. Load the graph in memory, then setup all necessary attributes. @@ -53,6 +55,7 @@ def __init__(self, self.locale = inferURILocalSymbol(self.uri)[0] self.ext_model = ext_model self.is_Bnode = is_Bnode + self.entity_display_title = entity_display_title self.slug = None self.rdftype = rdftype self.triples = None @@ -215,6 +218,25 @@ def bestDescription(self, prefLanguage="en", quotes=False): return "" + def display_title(self): + """Entity title - used for display purposes only. + Can be set by user once ontospy is created. + Values allowed: 'qname' or 'label' + + Defaults to 'qname'. + """ + + if self.entity_display_title == "qname": + out = self.qname + elif self.entity_display_title == "": + out = self.bestLabel() + else: + return self.qname + + return out + + + class Ontology(RDF_Entity): """ Pythonic representation of an OWL ontology @@ -228,11 +250,13 @@ def __init__(self, rdftype=None, namespaces=None, prefPrefix="", - ext_model=False): + ext_model=False, + entity_display_title="qname", + ): """ Init ontology object. Load the graph in memory, then setup all necessary attributes. """ - super(Ontology, self).__init__(uri, rdftype, namespaces, ext_model) + super(Ontology, self).__init__(uri, rdftype, namespaces, ext_model, entity_display_title) # self.uri = uri # rdflib.Uriref self.prefix = prefPrefix self.slug = "ontology-" + slugify(self.qname) @@ -280,11 +304,11 @@ class OntoClass(RDF_Entity): ] """ - def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False): + def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, entity_display_title="qname",): """ ... """ - super(OntoClass, self).__init__(uri, rdftype, namespaces, ext_model) + super(OntoClass, self).__init__(uri, rdftype, namespaces, ext_model, entity_display_title) self.slug = "class-" + slugify(self.qname) self.domain_of = [] @@ -357,11 +381,11 @@ class OntoProperty(RDF_Entity): """ - def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False): + def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, entity_display_title="qname",): """ ... """ - super(OntoProperty, self).__init__(uri, rdftype, namespaces, ext_model) + super(OntoProperty, self).__init__(uri, rdftype, namespaces, ext_model, entity_display_title) self.slug = "prop-" + slugify(self.qname) self.rdftype = inferMainPropertyType(rdftype) @@ -402,12 +426,12 @@ class OntoSKOSConcept(RDF_Entity): """ - def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False): + def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, entity_display_title="qname",): """ ... """ super(OntoSKOSConcept, self).__init__(uri, rdftype, namespaces, - ext_model) + ext_model, entity_display_title) self.slug = "concept-" + slugify(self.qname) self.instance_of = [] self.ontology = None @@ -442,11 +466,11 @@ class OntoShape(RDF_Entity): """ - def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False): + def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, entity_display_title="qname",): """ ... """ - super(OntoShape, self).__init__(uri, rdftype, namespaces, ext_model) + super(OntoShape, self).__init__(uri, rdftype, namespaces, ext_model, entity_display_title) self.slug = "shape-" + slugify(self.qname) self.ontology = None self.targetClasses = [] diff --git a/ontospy/core/ontospy.py b/ontospy/core/ontospy.py index 105db0c6..08aa8a4f 100755 --- a/ontospy/core/ontospy.py +++ b/ontospy/core/ontospy.py @@ -65,10 +65,39 @@ def __init__(self, hide_implicit_preds=True, sparql_endpoint=None, credentials=None, - build_all=True): - """ - Load the graph in memory, then setup all necessary attributes. + build_all=True, + entity_display_title="qname", + ): + """Load the graph in memory, then setup all necessary attributes. + + Parameters + ---------- + uri_or_path : [type], optional + [description], by default None + data : [type], optional + [description], by default None + file_obj : [type], optional + [description], by default None + rdf_format : str, optional + [description], by default "" + verbose : bool, optional + [description], by default False + hide_base_schemas : bool, optional + [description], by default True + hide_implicit_types : bool, optional + [description], by default True + hide_implicit_preds : bool, optional + [description], by default True + sparql_endpoint : [type], optional + [description], by default None + credentials : [type], optional + [description], by default None + build_all : bool, optional + [description], by default True + entity_display_title : str, optional + How to display entities by default. Two options accepted: "qname" (default) or "label" for rdfs:label. """ + super(Ontospy, self).__init__() self.rdflib_graph = None @@ -76,6 +105,7 @@ def __init__(self, self.credentials = None # tuple: auth credentials for endpoint if needed self.sources = None self.sparqlHelper = None + self.entity_display_title = entity_display_title self.namespaces = [] # entities buckets start with 'all_' self.all_ontologies = [] @@ -95,18 +125,17 @@ def __init__(self, # finally: if uri_or_path or data or file_obj: - self.load_rdf(uri_or_path, data, file_obj, rdf_format, verbose, - hide_base_schemas, hide_implicit_types, - hide_implicit_preds) + self.load_rdf(uri_or_path, data, file_obj, rdf_format, verbose) if build_all: self.build_all( verbose=verbose, hide_base_schemas=hide_base_schemas, hide_implicit_types=hide_implicit_types, - hide_implicit_preds=hide_implicit_preds) + hide_implicit_preds=hide_implicit_preds, + entity_display_title=entity_display_title + ) elif sparql_endpoint: # by default entities are not extracted - self.load_sparql(sparql_endpoint, verbose, hide_base_schemas, - hide_implicit_types, hide_implicit_preds, credentials) + self.load_sparql(sparql_endpoint, verbose, credentials) else: pass @@ -129,10 +158,7 @@ def load_rdf(self, data=None, file_obj=None, rdf_format="", - verbose=False, - hide_base_schemas=True, - hide_implicit_types=True, - hide_implicit_preds=True): + verbose=False): """Load an RDF source into an ontospy/rdflib graph""" loader = RDFLoader(verbose=verbose) loader.load(uri_or_path, data, file_obj, rdf_format) @@ -144,9 +170,7 @@ def load_rdf(self, def load_sparql(self, sparql_endpoint, verbose=False, - hide_base_schemas=True, - hide_implicit_types=True, - hide_implicit_preds=True, credentials=None): + credentials=None): """ Set up a SPARQLStore backend as a virtual ontospy graph @@ -186,7 +210,9 @@ def build_all(self, verbose=False, hide_base_schemas=True, hide_implicit_types=True, - hide_implicit_preds=True): + hide_implicit_preds=True, + entity_display_title='qname', + ): """ Extract all ontology entities from an RDF graph and construct Python representations of them. """ @@ -254,7 +280,7 @@ def build_ontologies(self, exclude_BNodes=False, return_string=False): checkDC_ID = [x for x in self.rdflib_graph.objects( candidate[0], rdflib.namespace.DC.identifier)] if checkDC_ID: - out += [Ontology(checkDC_ID[0], namespaces=self.namespaces), ] + out += [Ontology(checkDC_ID[0], namespaces=self.namespaces, entity_display_title=self.entity_display_title), ] else: vannprop = rdflib.URIRef( "http://purl.org/vocab/vann/preferredNamespaceUri") @@ -268,12 +294,15 @@ def build_ontologies(self, exclude_BNodes=False, return_string=False): if checkDC_prefix: out += [Ontology(checkDC_ID[0], namespaces=self.namespaces, - prefPrefix=checkDC_prefix[0])] + prefPrefix=checkDC_prefix[0], + entity_display_title=self.entity_display_title, + ) + ] else: - out += [Ontology(checkDC_ID[0], namespaces=self.namespaces)] + out += [Ontology(checkDC_ID[0], namespaces=self.namespaces, entity_display_title=self.entity_display_title)] else: - out += [Ontology(candidate[0], namespaces=self.namespaces)] + out += [Ontology(candidate[0], namespaces=self.namespaces, entity_display_title=self.entity_display_title)] else: pass @@ -318,7 +347,7 @@ def build_classes(self, hide_base_schemas=True, hide_implicit_types=True): test_existing_cl = self.get_class(uri=_uri) if not test_existing_cl: # create it - ontoclass = OntoClass(_uri, _type, self.namespaces) + ontoclass = OntoClass(_uri, _type, self.namespaces, entity_display_title=self.entity_display_title) self.all_classes += [ontoclass] else: # if OWL.Class over RDFS.Class - update it @@ -389,7 +418,7 @@ def build_properties(self, hide_implicit_preds=True): test_existing_prop = self.get_property(uri=candidate[0]) if not test_existing_prop: # create it - self.all_properties += [OntoProperty(candidate[0], candidate[1], self.namespaces)] + self.all_properties += [OntoProperty(candidate[0], candidate[1], self.namespaces, entity_display_title=self.entity_display_title)] else: # update it if candidate[1] and (test_existing_prop.rdftype == rdflib.RDF.Property): @@ -458,7 +487,7 @@ def build_skos_concepts(self): test_existing_cl = self.get_skos(uri=candidate[0]) if not test_existing_cl: # create it - self.all_skos_concepts += [OntoSKOSConcept(candidate[0], None, self.namespaces)] + self.all_skos_concepts += [OntoSKOSConcept(candidate[0], None, self.namespaces, entity_display_title=self.entity_display_title)] else: pass # print("concepts created") @@ -520,7 +549,7 @@ def build_shapes(self): test_existing_cl = self.get_any_entity(uri=candidate[0]) if not test_existing_cl: # create it - self.all_shapes += [OntoShape(candidate[0], None, self.namespaces)] + self.all_shapes += [OntoShape(candidate[0], None, self.namespaces, entity_display_title=self.entity_display_title)] else: pass @@ -575,7 +604,10 @@ def build_entity_from_uri(self, uri, ontospyClass=None): pass qres = self.sparqlHelper.entityTriples(uri) if qres: - entity = ontospyClass(rdflib.URIRef(uri), None, self.namespaces) + entity = ontospyClass(rdflib.URIRef(uri), + None, + self.namespaces, + entity_display_title=self.entity_display_title) entity.triples = qres entity._buildGraph() # force construction of mini graph # try to add class info @@ -614,7 +646,7 @@ def __buildDomainRanges(self, aProp): aClass.domain_of += [aProp] else: # edge case: it's not an OntoClass instance - aProp.domains += [OntoClass(x, None, self.namespaces, ext_model=True)] + aProp.domains += [OntoClass(x, None, self.namespaces, ext_model=True, entity_display_title=self.entity_display_title)] for x in ranges: if isBlankNode(x): @@ -628,7 +660,7 @@ def __buildDomainRanges(self, aProp): # eg a DataType property has xsd:STRING # here we're storing an ontospy entities but not adding it to # the main index - aProp.ranges += [OntoClass(x, None, self.namespaces, ext_model=True)] + aProp.ranges += [OntoClass(x, None, self.namespaces, ext_model=True, entity_display_title=self.entity_display_title)] def __computeTopLayer(self): """ From bf6cb35ddb748cbe9dde5beadab1047639c72dcc Mon Sep 17 00:00:00 2001 From: lambdamusic Date: Tue, 21 Sep 2021 10:19:14 +0100 Subject: [PATCH 02/16] pref_title and pref_language --- ontospy/core/entities.py | 57 +- ontospy/core/ontospy.py | 2311 +++++++++++++++++---------------- ontospy/tests/test_methods.py | 28 +- ontospy/tests/test_quick.py | 71 +- 4 files changed, 1277 insertions(+), 1190 deletions(-) diff --git a/ontospy/core/entities.py b/ontospy/core/entities.py index e23bb58c..36b8687b 100755 --- a/ontospy/core/entities.py +++ b/ontospy/core/entities.py @@ -38,7 +38,8 @@ def __init__(self, namespaces=None, ext_model=False, is_Bnode=False, - entity_display_title="qname", + pref_title="qname", + pref_language="en", ): """ Init ontology object. Load the graph in memory, then setup all necessary attributes. @@ -55,7 +56,10 @@ def __init__(self, self.locale = inferURILocalSymbol(self.uri)[0] self.ext_model = ext_model self.is_Bnode = is_Bnode - self.entity_display_title = entity_display_title + self._pref_title = pref_title + self._pref_language = pref_language + print("RDF_Entity (received)", pref_title) + print("RDF_Entity (set)", self._pref_title) self.slug = None self.rdftype = rdftype self.triples = None @@ -172,7 +176,7 @@ def getValuesForProperty(self, aPropURIRef): aPropURIRef = rdflib.URIRef(aPropURIRef) return list(self.rdflib_graph.objects(None, aPropURIRef)) - def bestLabel(self, prefLanguage="en", qname_allowed=True, quotes=False): + def bestLabel(self, prefLanguage="", qname_allowed=True, quotes=False): """ facility for extrating the best available label for an entity @@ -182,6 +186,9 @@ def bestLabel(self, prefLanguage="en", qname_allowed=True, quotes=False): test = self.getValuesForProperty(rdflib.RDFS.label) out = "" + if not prefLanguage: + prefLanguage = self._pref_language + if test: out = firstStringInList(test, prefLanguage) else: @@ -197,7 +204,7 @@ def bestLabel(self, prefLanguage="en", qname_allowed=True, quotes=False): else: return out - def bestDescription(self, prefLanguage="en", quotes=False): + def bestDescription(self, prefLanguage="", quotes=False): """ facility for extracting a human readable description for an entity """ @@ -207,6 +214,9 @@ def bestDescription(self, prefLanguage="en", quotes=False): rdflib.namespace.DC.description, rdflib.namespace.SKOS.definition ] + if not prefLanguage: + prefLanguage = self._pref_language + for pred in test_preds: test = self.getValuesForProperty(pred) # printDebug(str(test), "red") @@ -217,18 +227,19 @@ def bestDescription(self, prefLanguage="en", quotes=False): return joinStringsInList(test, prefLanguage) return "" - - def display_title(self): + @property + def title(self): """Entity title - used for display purposes only. Can be set by user once ontospy is created. Values allowed: 'qname' or 'label' Defaults to 'qname'. """ + print("in attribute: ", self._pref_title) - if self.entity_display_title == "qname": + if self._pref_title == "qname": out = self.qname - elif self.entity_display_title == "": + elif self._pref_title == "label": out = self.bestLabel() else: return self.qname @@ -249,16 +260,17 @@ def __init__(self, uri, rdftype=None, namespaces=None, - prefPrefix="", + pref_prefix="", ext_model=False, - entity_display_title="qname", + pref_title="qname", + pref_language="en", ): """ Init ontology object. Load the graph in memory, then setup all necessary attributes. """ - super(Ontology, self).__init__(uri, rdftype, namespaces, ext_model, entity_display_title) + super(Ontology, self).__init__(uri, rdftype, namespaces, ext_model, pref_title=pref_title, pref_language=pref_language) # self.uri = uri # rdflib.Uriref - self.prefix = prefPrefix + self.prefix = pref_prefix self.slug = "ontology-" + slugify(self.qname) self.all_classes = [] self.all_properties = [] @@ -304,13 +316,15 @@ class OntoClass(RDF_Entity): ] """ - def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, entity_display_title="qname",): + def __init__(self, uri, rdftype=None, namespaces=None, + ext_model=False, pref_title="qname", pref_language="en"): """ ... """ - super(OntoClass, self).__init__(uri, rdftype, namespaces, ext_model, entity_display_title) + print("OntoClass (sender) =>", pref_title) + super().__init__(uri, rdftype, namespaces, ext_model, + pref_title=pref_title, pref_language=pref_language) self.slug = "class-" + slugify(self.qname) - self.domain_of = [] self.range_of = [] self.domain_of_inferred = [] @@ -381,11 +395,12 @@ class OntoProperty(RDF_Entity): """ - def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, entity_display_title="qname",): + def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, + pref_title="qname", pref_language="en"): """ ... """ - super(OntoProperty, self).__init__(uri, rdftype, namespaces, ext_model, entity_display_title) + super(OntoProperty, self).__init__(uri, rdftype, namespaces, ext_model, pref_title=pref_title, pref_language=pref_language) self.slug = "prop-" + slugify(self.qname) self.rdftype = inferMainPropertyType(rdftype) @@ -426,12 +441,12 @@ class OntoSKOSConcept(RDF_Entity): """ - def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, entity_display_title="qname",): + def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, pref_title="qname", pref_language="en"): """ ... """ super(OntoSKOSConcept, self).__init__(uri, rdftype, namespaces, - ext_model, entity_display_title) + ext_model, pref_title=pref_title, pref_language=pref_language) self.slug = "concept-" + slugify(self.qname) self.instance_of = [] self.ontology = None @@ -466,11 +481,11 @@ class OntoShape(RDF_Entity): """ - def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, entity_display_title="qname",): + def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, pref_title="qname", pref_language="en"): """ ... """ - super(OntoShape, self).__init__(uri, rdftype, namespaces, ext_model, entity_display_title) + super(OntoShape, self).__init__(uri, rdftype, namespaces, ext_model, pref_title=pref_title, pref_language=pref_language) self.slug = "shape-" + slugify(self.qname) self.ontology = None self.targetClasses = [] diff --git a/ontospy/core/ontospy.py b/ontospy/core/ontospy.py index 08aa8a4f..90aa7717 100755 --- a/ontospy/core/ontospy.py +++ b/ontospy/core/ontospy.py @@ -8,18 +8,8 @@ """ from __future__ import print_function - -import sys -import os -import time -import optparse from itertools import chain -try: - import urllib2 -except ImportError: - import urllib.request as urllib2 - import rdflib from .utils import * @@ -29,1129 +19,1178 @@ class Ontospy(object): - """ - Object that extracts schema definitions (aka 'ontologies') from an rdf graph. - - In [3]: import ontospy - - In [5]: o = ontospy.Ontospy() - - In [7]: o.load_rdf("foaf.rdf") - - In [11]: o.build_all() - - In [13]: o.stats() - Out[13]: - [('Ontologies', 1), - ('Triples', 630), - ('Classes', 15), - ('Properties', 67), - ('Annotation Properties', 7), - ('Object Properties', 34), - ('Datatype Properties', 26), - ('Skos Concepts', 0), - ('Data Sources', 1)] - - """ - - def __init__(self, - uri_or_path=None, - data=None, - file_obj=None, - rdf_format="", - verbose=False, - hide_base_schemas=True, - hide_implicit_types=True, - hide_implicit_preds=True, - sparql_endpoint=None, - credentials=None, - build_all=True, - entity_display_title="qname", - ): - """Load the graph in memory, then setup all necessary attributes. - - Parameters - ---------- - uri_or_path : [type], optional - [description], by default None - data : [type], optional - [description], by default None - file_obj : [type], optional - [description], by default None - rdf_format : str, optional - [description], by default "" - verbose : bool, optional - [description], by default False - hide_base_schemas : bool, optional - [description], by default True - hide_implicit_types : bool, optional - [description], by default True - hide_implicit_preds : bool, optional - [description], by default True - sparql_endpoint : [type], optional - [description], by default None - credentials : [type], optional - [description], by default None - build_all : bool, optional - [description], by default True - entity_display_title : str, optional - How to display entities by default. Two options accepted: "qname" (default) or "label" for rdfs:label. - """ - - super(Ontospy, self).__init__() - - self.rdflib_graph = None - self.sparql_endpoint = None - self.credentials = None # tuple: auth credentials for endpoint if needed - self.sources = None - self.sparqlHelper = None - self.entity_display_title = entity_display_title - self.namespaces = [] - # entities buckets start with 'all_' - self.all_ontologies = [] - self.all_classes = [] - self.all_properties = [] - self.all_properties_annotation = [] - self.all_properties_object = [] - self.all_properties_datatype = [] - self.all_skos_concepts = [] - self.all_shapes = [] - # self.all_individuals = [] - self.toplayer_classes = [] - self.toplayer_properties = [] - self.toplayer_skos = [] - self.toplayer_shapes = [] - self.OWLTHING = OntoClass(rdflib.OWL.Thing, rdflib.OWL.Class, self.namespaces) - - # finally: - if uri_or_path or data or file_obj: - self.load_rdf(uri_or_path, data, file_obj, rdf_format, verbose) - if build_all: - self.build_all( - verbose=verbose, - hide_base_schemas=hide_base_schemas, - hide_implicit_types=hide_implicit_types, - hide_implicit_preds=hide_implicit_preds, - entity_display_title=entity_display_title - ) - elif sparql_endpoint: # by default entities are not extracted - self.load_sparql(sparql_endpoint, verbose, credentials) - else: - pass - - def __repr__(self): - """ - Return some info for the ontospy instance. - - note: if it's a sparql backend, limit the info returned to avoid long queries (tip: a statement like `if self.rdflib_graph` on a sparql endpoint is enough to cause a long query!) - - """ - if self.sparql_endpoint and self.rdflib_graph != None: - return "<Ontospy Graph (sparql endpoint = <%s>)>" % self.sparql_endpoint - elif self.rdflib_graph != None: - return "<Ontospy Graph (%d triples)>" % (len(self.rdflib_graph)) - else: - return "<Ontospy object created but not initialized (use the `load_rdf` method to load an rdf schema)>" - - def load_rdf(self, - uri_or_path=None, - data=None, - file_obj=None, - rdf_format="", - verbose=False): - """Load an RDF source into an ontospy/rdflib graph""" - loader = RDFLoader(verbose=verbose) - loader.load(uri_or_path, data, file_obj, rdf_format) - self.rdflib_graph = loader.rdflib_graph - self.sources = loader.sources_valid - self.sparqlHelper = SparqlHelper(self.rdflib_graph) - self.namespaces = sorted(self.rdflib_graph.namespaces()) - - def load_sparql(self, - sparql_endpoint, - verbose=False, - credentials=None): - """ - Set up a SPARQLStore backend as a virtual ontospy graph - - Note: we're using a 'SPARQLUpdateStore' backend instead of 'SPARQLStore' cause otherwise authentication fails (https://github.com/RDFLib/rdflib/issues/755) - - @TODO this error seems to be fixed in upcoming rdflib versions - https://github.com/RDFLib/rdflib/pull/744 - - """ - try: - # graph = rdflib.Graph('SPARQLStore') - # graph = rdflib.ConjunctiveGraph('SPARQLStore') - graph = rdflib.ConjunctiveGraph('SPARQLUpdateStore') - - if credentials and type(credentials) == tuple: - # https://github.com/RDFLib/rdflib/issues/343 - graph.store.setCredentials(credentials[0], credentials[1]) - # graph.store.setHTTPAuth('BASIC') # graph.store.setHTTPAuth('DIGEST') - - graph.open(sparql_endpoint) - self.rdflib_graph = graph - self.sparql_endpoint = sparql_endpoint - self.sources = [sparql_endpoint] - self.sparqlHelper = SparqlHelper(self.rdflib_graph, self.sparql_endpoint) - self.namespaces = sorted(self.rdflib_graph.namespaces()) - except: - printDebug("Error trying to connect to Endpoint.") - raise - # don't extract entities by default.. - - - # ------------ - # === methods to build python objects === # - # ------------ - - def build_all(self, - verbose=False, - hide_base_schemas=True, - hide_implicit_types=True, - hide_implicit_preds=True, - entity_display_title='qname', - ): - """ - Extract all ontology entities from an RDF graph and construct Python representations of them. - """ - if verbose: - printDebug("Scanning entities...", "green") - printDebug("----------", "comment") - - self.build_ontologies() - if verbose: - printDebug("Ontologies.........: %d" % len(self.all_ontologies), "comment") - - self.build_classes(hide_base_schemas, hide_implicit_types) - if verbose: - printDebug("Classes............: %d" % len(self.all_classes), "comment") - - self.build_properties(hide_implicit_preds) - if verbose: - printDebug("Properties.........: %d" % len(self.all_properties), "comment") - if verbose: - printDebug("..annotation.......: %d" % len(self.all_properties_annotation), "comment") - if verbose: - printDebug("..datatype.........: %d" % len(self.all_properties_datatype), "comment") - if verbose: - printDebug("..object...........: %d" % len(self.all_properties_object), "comment") - - self.build_skos_concepts() - if verbose: - printDebug("Concepts (SKOS)....: %d" % len(self.all_skos_concepts), "comment") - - self.build_shapes() - if verbose: - printDebug("Shapes (SHACL).....: %d" % len(self.all_shapes), "comment") - - # self.__computeTopLayer() - - self.__computeInferredProperties() - - if verbose: - printDebug("----------", "comment") - - def build_ontologies(self, exclude_BNodes=False, return_string=False): - """ - Extract ontology instances info from the graph, then creates python objects for them. - - Note: often ontology info is nested in structures like this: - - [ a owl:Ontology ; - vann:preferredNamespacePrefix "bsym" ; - vann:preferredNamespaceUri "http://bsym.bloomberg.com/sym/" ] - - Hence there is some logic to deal with these edge cases. - """ - out = [] - - qres = self.sparqlHelper.getOntology() - - if qres: - # NOTE: SPARQL returns a list of rdflib.query.ResultRow (~ tuples..) - - for candidate in qres: - if isBlankNode(candidate[0]): - if exclude_BNodes: - continue - else: - checkDC_ID = [x for x in self.rdflib_graph.objects( - candidate[0], rdflib.namespace.DC.identifier)] - if checkDC_ID: - out += [Ontology(checkDC_ID[0], namespaces=self.namespaces, entity_display_title=self.entity_display_title), ] - else: - vannprop = rdflib.URIRef( - "http://purl.org/vocab/vann/preferredNamespaceUri") - vannpref = rdflib.URIRef( - "http://purl.org/vocab/vann/preferredNamespacePrefix") - checkDC_ID = [x for x in self.rdflib_graph.objects( - candidate[0], vannprop)] - if checkDC_ID: - checkDC_prefix = [ - x for x in self.rdflib_graph.objects(candidate[0], vannpref)] - if checkDC_prefix: - out += [Ontology(checkDC_ID[0], - namespaces=self.namespaces, - prefPrefix=checkDC_prefix[0], - entity_display_title=self.entity_display_title, - ) - ] - else: - out += [Ontology(checkDC_ID[0], namespaces=self.namespaces, entity_display_title=self.entity_display_title)] - - else: - out += [Ontology(candidate[0], namespaces=self.namespaces, entity_display_title=self.entity_display_title)] - - else: - pass - # printDebug("No owl:Ontologies found") - - # finally... add all annotations/triples - self.all_ontologies = out - for onto in self.all_ontologies: - onto.triples = self.sparqlHelper.entityTriples(onto.uri) - onto._buildGraph() # force construction of mini graph - - # - # RDFS:class vs OWL:class cf. http://www.w3.org/TR/owl-ref/ section 3.1 - # - - def build_classes(self, hide_base_schemas=True, hide_implicit_types=True): - """ - 2015-06-04: removed sparql 1.1 queries - 2015-05-25: optimized via sparql queries in order to remove BNodes - 2015-05-09: new attempt - - Note: sparqlHelper.getAllClasses() returns a list of tuples, - (class, classRDFtype) - so in some cases there are duplicates if a class is both RDFS.CLass and OWL.Class - In this case we keep only OWL.Class as it is more informative. - """ - - self.all_classes = [] # @todo: keep adding? - - qres = self.sparqlHelper.getAllClasses(hide_base_schemas, - hide_implicit_types) - # print("rdflib query done") - - for class_tuple in qres: - - _uri = class_tuple[0] - try: - _type = class_tuple[1] - except: - _type = "" - - test_existing_cl = self.get_class(uri=_uri) - if not test_existing_cl: - # create it - ontoclass = OntoClass(_uri, _type, self.namespaces, entity_display_title=self.entity_display_title) - self.all_classes += [ontoclass] - else: - # if OWL.Class over RDFS.Class - update it - if _type == rdflib.OWL.Class: - test_existing_cl.rdftype = rdflib.OWL.Class - - # print("classes created") - - # add more data - for aClass in self.all_classes: - # print("enriching class", aClass) - aClass.triples = self.sparqlHelper.entityTriples(aClass.uri) - aClass._buildGraph() # force construction of mini graph - - aClass.sparqlHelper = self.sparqlHelper - - # attach to an ontology - for uri in aClass.getValuesForProperty(rdflib.RDFS.isDefinedBy): - onto = self.get_ontology(uri=str(uri)) - if onto: - onto.all_classes += [aClass] - aClass.ontology = onto - - # add direct Supers - directSupers = self.sparqlHelper.getClassDirectSupers(aClass.uri) - - for x in directSupers: - superclass = self.get_class(uri=x[0]) - # note: extra condition to avoid recursive structures - if superclass and superclass.uri != aClass.uri: - aClass._parents.append(superclass) - - # add inverse relationships (= direct subs for superclass) - if aClass not in superclass.children(): - superclass._children.append(aClass) - - # sort alphabetically - self.all_classes = sorted(self.all_classes, key=lambda x: x.qname) - - # compute top layer - # print("calc toplayer") - exit = [] - for c in self.all_classes: - if not c.parents(): - exit += [c] - self.toplayer_classes = exit # sorted(exit, key=lambda x: x.id) # doesnt work - - def build_properties(self, hide_implicit_preds=True): - """ - 2015-06-04: removed sparql 1.1 queries - 2015-06-03: analogous to get classes - - # instantiate properties making sure duplicates are pruned - # but the most specific rdftype is kept - # eg OWL:ObjectProperty over RDF:property - - """ - self.all_properties = [] # @todo: keep adding? - self.all_properties_annotation = [] - self.all_properties_object = [] - self.all_properties_datatype = [] - - qres = self.sparqlHelper.getAllProperties(hide_implicit_preds) - # print("rdflib query done") - - for candidate in qres: - - test_existing_prop = self.get_property(uri=candidate[0]) - if not test_existing_prop: - # create it - self.all_properties += [OntoProperty(candidate[0], candidate[1], self.namespaces, entity_display_title=self.entity_display_title)] - else: - # update it - if candidate[1] and (test_existing_prop.rdftype == rdflib.RDF.Property): - test_existing_prop.rdftype = inferMainPropertyType(candidate[1]) - # print("properties created") - - # add more data - for aProp in self.all_properties: - # print("enriching prop..", aProp) - if aProp.rdftype == rdflib.OWL.DatatypeProperty: - self.all_properties_datatype += [aProp] - elif aProp.rdftype == rdflib.OWL.AnnotationProperty: - self.all_properties_annotation += [aProp] - elif aProp.rdftype == rdflib.OWL.ObjectProperty: - self.all_properties_object += [aProp] - else: - pass - - aProp.triples = self.sparqlHelper.entityTriples(aProp.uri) - aProp._buildGraph() # force construction of mini graph - - # attach to an ontology [2015-06-15: no property type distinction yet] - for uri in aProp.getValuesForProperty(rdflib.RDFS.isDefinedBy): - onto = self.get_ontology(uri=str(uri)) - if onto: - onto.all_properties += [aProp] - aProp.ontology = onto - - self.__buildDomainRanges(aProp) - - # add direct Supers - directSupers = self.sparqlHelper.getPropDirectSupers(aProp.uri) - - for x in directSupers: - superprop = self.get_property(uri=x[0]) - # note: extra condition to avoid recursive structures - if superprop and superprop.uri != aProp.uri: - aProp._parents.append(superprop) - - # add inverse relationships (= direct subs for superprop) - if aProp not in superprop.children(): - superprop._children.append(aProp) - - # sort alphabetically - self.all_properties = sorted(self.all_properties, key=lambda x: x.qname) - - # computer top layer for properties - # print("calc toplayer") - exit = [] - for c in self.all_properties: - if not c.parents(): - exit += [c] - self.toplayer_properties = exit # sorted(exit, key=lambda x: x.id) # doesnt work - - def build_skos_concepts(self): - """ - 2015-08-19: first draft - """ - self.all_skos_concepts = [] # @todo: keep adding? - - qres = self.sparqlHelper.getSKOSInstances() - # print("rdflib query done") - - for candidate in qres: - - test_existing_cl = self.get_skos(uri=candidate[0]) - if not test_existing_cl: - # create it - self.all_skos_concepts += [OntoSKOSConcept(candidate[0], None, self.namespaces, entity_display_title=self.entity_display_title)] - else: - pass - # print("concepts created") - # add more data - skos = rdflib.Namespace('http://www.w3.org/2004/02/skos/core#') - - for aConcept in self.all_skos_concepts: - # print("enriching concept...", aConcept) - aConcept.rdftype = skos['Concept'] - aConcept.triples = self.sparqlHelper.entityTriples(aConcept.uri) - aConcept._buildGraph() # force construction of mini graph - - aConcept.sparqlHelper = self.sparqlHelper - - # attach to an ontology - for uri in aConcept.getValuesForProperty(rdflib.RDFS.isDefinedBy): - onto = self.get_ontology(uri=str(uri)) - if onto: - onto.all_skos_concepts += [aConcept] - aConcept.ontology = onto - - # add direct Supers - directSupers = self.sparqlHelper.getSKOSDirectSupers(aConcept.uri) - - for x in directSupers: - superclass = self.get_skos(uri=x[0]) - # note: extra condition to avoid recursive structures - if superclass and superclass.uri != aConcept.uri: - aConcept._parents.append(superclass) - - # add inverse relationships (= direct subs for superclass) - if aConcept not in superclass.children(): - superclass._children.append(aConcept) - - # sort alphabetically - self.all_skos_concepts = sorted(self.all_skos_concepts, key=lambda x: x.qname) - - # compute top layer for skos - exit = [] - for c in self.all_skos_concepts: - if not c.parents(): - exit += [c] - self.toplayer_skos = exit # sorted(exit, key=lambda x: x.id) # doesnt work - - def build_shapes(self): - """ - Extract SHACL data shapes from the rdf graph. - <http://www.w3.org/ns/shacl#> - - Instatiate the Shape Python objects and relate it to existing classes, - if available. - """ - self.all_shapes = [] # @todo: keep adding? - - qres = self.sparqlHelper.getShapes() - - for candidate in qres: - - test_existing_cl = self.get_any_entity(uri=candidate[0]) - if not test_existing_cl: - # create it - self.all_shapes += [OntoShape(candidate[0], None, self.namespaces, entity_display_title=self.entity_display_title)] - else: - pass - - # add more data - shacl = rdflib.Namespace('http://www.w3.org/ns/shacl#') - - for aShape in self.all_shapes: - - aShape.rdftype = shacl['Shape'] - aShape.triples = self.sparqlHelper.entityTriples(aShape.uri) - aShape._buildGraph() # force construction of mini graph - - aShape.sparqlHelper = self.sparqlHelper - - # attach to a class - for uri in aShape.getValuesForProperty(shacl['targetClass']): - aclass = self.get_class(str(uri)) - if aclass: - aShape.targetClasses += [aclass] - aclass.all_shapes += [aShape] - for propertyUri in aShape.getValuesForProperty(shacl['path']): #add shaped properties of this class. later can be used for ontodocs - propType = self.get_property(str(propertyUri)) - if propType: - aclass.shapedProperties += [{'shape': aShape, 'property': propType}] - - - - # sort alphabetically - self.all_shapes = sorted(self.all_shapes, key=lambda x: x.qname) - - # compute top layer - exit = [] - for c in self.all_shapes: - if not c.parents(): - exit += [c] - self.toplayer_shapes = exit # sorted(exit, key=lambda x: x.id) # doesnt work - - def build_entity_from_uri(self, uri, ontospyClass=None): - """ - Extract RDF statements having a URI as subject, then instantiate the RDF_Entity Python object so that it can be queried further. - - Passing <ontospyClass> allows to instantiate a user-defined RDF_Entity subclass. - - NOTE: the entity is not attached to any index. In future version we may create an index for these (individuals?) keeping into account that any existing model entity could be (re)created this way. - """ - if not ontospyClass: - ontospyClass = RDF_Entity - elif not issubclass(ontospyClass, RDF_Entity): - click.secho("Error: <%s> is not a subclass of ontospy.RDF_Entity" % str(ontospyClass)) - return None - else: - pass - qres = self.sparqlHelper.entityTriples(uri) - if qres: - entity = ontospyClass(rdflib.URIRef(uri), - None, - self.namespaces, - entity_display_title=self.entity_display_title) - entity.triples = qres - entity._buildGraph() # force construction of mini graph - # try to add class info - test = entity.getValuesForProperty(rdflib.RDF.type) - if test: - entity.rdftype = test - entity.rdftype_qname = [entity._build_qname(x) for x in test] - return entity - else: - return None - - # ------------ - # === methods to refine the ontology structure === # - # ------------ - - def __buildDomainRanges(self, aProp): - """ - extract domain/range details and add to Python objects - """ - - domains = chain(aProp.rdflib_graph.objects( - None, rdflib.term.URIRef(u'http://schema.org/domainIncludes')), aProp.rdflib_graph.objects( - None, rdflib.RDFS.domain)) - - ranges = chain(aProp.rdflib_graph.objects( - None, rdflib.term.URIRef(u'http://schema.org/rangeIncludes')), aProp.rdflib_graph.objects( - None, rdflib.RDFS.range)) - - for x in domains: - if isBlankNode(x): - aProp.domains += [RDF_Entity(x, None, self.namespaces, is_Bnode=True)] - else: - aClass = self.get_class(uri=str(x)) - if aClass: - aProp.domains += [aClass] - aClass.domain_of += [aProp] - else: - # edge case: it's not an OntoClass instance - aProp.domains += [OntoClass(x, None, self.namespaces, ext_model=True, entity_display_title=self.entity_display_title)] - - for x in ranges: - if isBlankNode(x): - aProp.domains += [RDF_Entity(x, None, self.namespaces, is_Bnode=True)] - else: - aClass = self.get_class(uri=str(x)) - if aClass: - aProp.ranges += [aClass] - aClass.range_of += [aProp] - else: - # eg a DataType property has xsd:STRING - # here we're storing an ontospy entities but not adding it to - # the main index - aProp.ranges += [OntoClass(x, None, self.namespaces, ext_model=True, entity_display_title=self.entity_display_title)] - - def __computeTopLayer(self): - """ - deprecated: now this is calculated when entities get extracted - """ - - exit = [] - for c in self.all_classes: - if not c.parents(): - exit += [c] - self.toplayer_classes = exit # sorted(exit, key=lambda x: x.id) # doesnt work - - # properties - exit = [] - for c in self.all_properties: - if not c.parents(): - exit += [c] - self.toplayer_properties = exit # sorted(exit, key=lambda x: x.id) # doesnt work - - # skos - exit = [] - for c in self.all_skos_concepts: - if not c.parents(): - exit += [c] - self.toplayer_skos = exit # sorted(exit, key=lambda x: x.id) # doesnt work - - def __computeInferredProperties(self): - """ - - :return: attach a list of dicts to each class, detailing valid props up the subsumption tree - """ - exit = [] - for c in self.all_classes: - c.domain_of_inferred = self.getInferredPropertiesForClass(c, "domain_of") - c.range_of_inferred = self.getInferredPropertiesForClass(c, "range_of") - - def getInferredPropertiesForClass(self, aClass, rel="domain_of"): - """ - returns all properties valid for a class (as they have it in their domain) - recursively ie traveling up the descendants tree - Note: results in a list of dicts including itself - Note [2]: all properties with no domain info are added at the top as [None, props] - - :return: - [{<Class *http://xmlns.com/foaf/0.1/Person*>: - [<Property *http://xmlns.com/foaf/0.1/currentProject*>,<Property *http://xmlns.com/foaf/0.1/familyName*>, - etc....]}, - {<Class *http://www.w3.org/2003/01/geo/wgs84_pos#SpatialThing*>: - [<Property *http://xmlns.com/foaf/0.1/based_near*>, etc...]}, - ] - """ - _list = [] - - if rel == "domain_of": - _list.append({aClass: aClass.domain_of}) - for x in aClass.ancestors(): - if x.domain_of: - _list.append({x: x.domain_of}) - - # add properties from Owl:Thing ie the inference layer - - topLevelProps = [p for p in self.all_properties if p.domains == []] - if topLevelProps: - _list.append({self.OWLTHING: topLevelProps}) - - elif rel == "range_of": - _list.append({aClass: aClass.range_of}) - for x in aClass.ancestors(): - if x.domain_of: - _list.append({x: x.range_of}) - - # add properties from Owl:Thing ie the inference layer - - topLevelProps = [p for p in self.all_properties if p.ranges == []] - if topLevelProps: - _list.append({self.OWLTHING: topLevelProps}) - - return _list - - - - # =============== - # methods for retrieving objects - # ================ - - def get_class(self, id=None, uri=None, match=None): - """ - get the saved-class with given ID or via other methods... - - Note: it tries to guess what is being passed.. - - In [1]: g.get_class(uri='http://www.w3.org/2000/01/rdf-schema#Resource') - Out[1]: <Class *http://www.w3.org/2000/01/rdf-schema#Resource*> - - In [2]: g.get_class(10) - Out[2]: <Class *http://purl.org/ontology/bibo/AcademicArticle*> - - In [3]: g.get_class(match="person") - Out[3]: - [<Class *http://purl.org/ontology/bibo/PersonalCommunicationDocument*>, - <Class *http://purl.org/ontology/bibo/PersonalCommunication*>, - <Class *http://xmlns.com/foaf/0.1/Person*>] - - """ - - if not id and not uri and not match: - return None - - if type(id) == type("string"): - uri = id - id = None - if not is_http(uri): - match = uri - uri = None - if match: - if type(match) != type("string"): - return [] - res = [] - if ":" in match: # qname - for x in self.all_classes: - if match.lower() in x.qname.lower(): - res += [x] - else: - for x in self.all_classes: - if match.lower() in x.uri.lower(): - res += [x] - return res - else: - for x in self.all_classes: - if id and x.id == id: - return x - if uri and x.uri.lower() == uri.lower(): - return x - return None - - def get_property(self, id=None, uri=None, match=None): - """ - get the saved-class with given ID or via other methods... - - Note: analogous to getClass method - """ - - if not id and not uri and not match: - return None - - if type(id) == type("string"): - uri = id - id = None - if not is_http(uri): - match = uri - uri = None - if match: - if type(match) != type("string"): - return [] - res = [] - if ":" in match: # qname - for x in self.all_properties: - if match.lower() in x.qname.lower(): - res += [x] - else: - for x in self.all_properties: - if match.lower() in x.uri.lower(): - res += [x] - return res - else: - for x in self.all_properties: - if id and x.id == id: - return x - if uri and x.uri.lower() == uri.lower(): - return x - return None - - def get_skos(self, id=None, uri=None, match=None): - """ - get the saved skos concept with given ID or via other methods... - - Note: it tries to guess what is being passed as above - """ - - if not id and not uri and not match: - return None - - if type(id) == type("string"): - uri = id - id = None - if not is_http(uri): - match = uri - uri = None - if match: - if type(match) != type("string"): - return [] - res = [] - if ":" in match: # qname - for x in self.all_skos_concepts: - if match.lower() in x.qname.lower(): - res += [x] - else: - for x in self.all_skos_concepts: - if match.lower() in x.uri.lower(): - res += [x] - return res - else: - for x in self.all_skos_concepts: - if id and x.id == id: - return x - if uri and x.uri.lower() == uri.lower(): - return x - return None - - def get_any_entity(self, id=None, uri=None, match=None): - """ - get a generic entity with given ID or via other methods... - """ - - if not id and not uri and not match: - return None - - if type(id) == type("string"): - uri = id - id = None - if not is_http(uri): - match = uri - uri = None - if match: - if type(match) != type("string"): - return [] - res = [] - if ":" in match: # qname - for x in self.all_classes: - if match.lower() in x.qname.lower(): - res += [x] - for x in self.all_properties: - if match.lower() in x.qname.lower(): - res += [x] - else: - for x in self.all_classes: - if match.lower() in x.uri.lower(): - res += [x] - for x in self.all_properties: - if match.lower() in x.uri.lower(): - res += [x] - return res - else: - for x in self.all_classes: - if id and x.id == id: - return x - if uri and x.uri.lower() == uri.lower(): - return x - for x in self.all_properties: - if id and x.id == id: - return x - if uri and x.uri.lower() == uri.lower(): - return x - return None - - def get_ontology(self, id=None, uri=None, match=None): - """ - get the saved-ontology with given ID or via other methods... - """ - - if not id and not uri and not match: - return None - - if type(id) == type("string"): - uri = id - id = None - if not is_http(uri): - match = uri - uri = None - if match: - if type(match) != type("string"): - return [] - res = [] - for x in self.all_ontologies: - if match.lower() in x.uri.lower(): - res += [x] - return res - else: - for x in self.all_ontologies: - if id and x.id == id: - return x - if uri and x.uri.lower() == uri.lower(): - return x - return None - - def nextClass(self, classuri): - """Returns the next class in the list of classes. If it's the last one, returns the first one.""" - if classuri == self.all_classes[-1].uri: - return self.all_classes[0] - flag = False - for x in self.all_classes: - if flag == True: - return x - if x.uri == classuri: - flag = True - return None - - def nextProperty(self, propuri): - """Returns the next property in the list of properties. If it's the last one, returns the first one.""" - if propuri == self.all_properties[-1].uri: - return self.all_properties[0] - flag = False - for x in self.all_properties: - if flag == True: - return x - if x.uri == propuri: - flag = True - return None - - def nextConcept(self, concepturi): - """Returns the next skos concept in the list of concepts. If it's the last one, returns the first one.""" - if concepturi == self.all_skos_concepts[-1].uri: - return self.all_skos_concepts[0] - flag = False - for x in self.all_skos_concepts: - if flag == True: - return x - if x.uri == concepturi: - flag = True - return None - - def ontologyClassTree(self): - """ - Returns a dict representing the ontology tree - Top level = {0:[top classes]} - Multi inheritance is represented explicitly - """ - treedict = {} - if self.all_classes: - treedict[0] = self.toplayer_classes - for element in self.all_classes: - if element.children(): - treedict[element] = element.children() - return treedict - return treedict - - def ontologyPropTree(self): - """ - Returns a dict representing the ontology tree - Top level = {0:[top properties]} - Multi inheritance is represented explicitly - """ - treedict = {} - if self.all_properties: - treedict[0] = self.toplayer_properties - for element in self.all_properties: - if element.children(): - treedict[element] = element.children() - return treedict - return treedict - - def ontologyConceptTree(self): - """ - Returns a dict representing the skos tree - Top level = {0:[top concepts]} - Multi inheritance is represented explicitly - """ - treedict = {} - if self.all_skos_concepts: - treedict[0] = self.toplayer_skos - for element in self.all_skos_concepts: - if element.children(): - treedict[element] = element.children() - return treedict - return treedict - - def ontologyShapeTree(self): - """ - Returns a dict representing the ontology tree - Top level = {0:[top properties]} - Multi inheritance is represented explicitly - """ - treedict = {} - if self.all_shapes: - treedict[0] = self.toplayer_shapes - for element in self.all_shapes: - if element.children(): - treedict[element] = element.children() - return treedict - return treedict - - - # ------------ - # === utils === # - # ------------ - - - def rdf_source(self, format="turtle"): - """ - Wrapper for rdflib serializer method. - Valid options are: xml, n3, turtle, nt, pretty-xml, json-ld [trix not working out of the box] - """ - s = self.rdflib_graph.serialize(format=format) - if isinstance(s, bytes): - s = s.decode('utf-8') - return s - - - def serialize(self, format="turtle"): - "for backward compatibility" - return self.rdf_source(format) - - def query(self, stringa): - """SPARQL query / wrapper for rdflib sparql query method """ - qres = self.rdflib_graph.query(stringa) - return list(qres) - def sparql(self, stringa): - "SPARQL query / replacement for query" - return self.query(stringa) - - def stats(self): - """ shotcut to pull out useful info for a graph""" - out = [] - out += [("Ontologies", len(self.all_ontologies))] - out += [("Triples", self.triplesCount())] - out += [("Classes", len(self.all_classes))] - out += [("Properties", len(self.all_properties))] - out += [("Annotation Properties", len(self.all_properties_annotation))] - out += [("Object Properties", len(self.all_properties_object))] - out += [("Datatype Properties", len(self.all_properties_datatype))] - out += [("Skos Concepts", len(self.all_skos_concepts))] - out += [("Data Shapes", len(self.all_shapes))] - # out += [("Individuals", len(self.individuals))] @TODO - out += [("Data Sources", len(self.sources))] - return out - - def triplesCount(self): - """ - - 2016-08-18 the try/except is a dirty solution to a problem - emerging with counting graph length on cached Graph objects.. - """ - # @todo investigate what's going on.. - # click.secho(unicode(type(self.rdflib_graph)), fg="red") - try: - return len(self.rdflib_graph) - except: - click.secho("Ontospy: error counting graph length..", fg="red") - return 0 - - - def printClassTree(self, element=None, showids=False, labels=False, showtype=False): - """ - Print nicely into stdout the class tree of an ontology - - Note: indentation is made so that ids up to 3 digits fit in, plus a space. - [123]1-- - [1]123-- - [12]12-- - """ - TYPE_MARGIN = 11 # length for owl:class etc.. - - if not element: # first time - for x in self.toplayer_classes: - printGenericTree(x, 0, showids, labels, showtype, TYPE_MARGIN) - - else: - printGenericTree(element, 0, showids, labels, showtype, TYPE_MARGIN) - - def printPropertyTree(self, element=None, showids=False, labels=False, showtype=False): - """ - Print nicely into stdout the property tree of an ontology - - Note: indentation is made so that ids up to 3 digits fit in, plus a space. - [123]1-- - [1]123-- - [12]12-- - """ - TYPE_MARGIN = 18 # length for owl:AnnotationProperty etc.. - - if not element: # first time - for x in self.toplayer_properties: - printGenericTree(x, 0, showids, labels, showtype, TYPE_MARGIN) - - else: - printGenericTree(element, 0, showids, labels, showtype, TYPE_MARGIN) - - def printSkosTree(self, element=None, showids=False, labels=False, showtype=False): - """ - Print nicely into stdout the SKOS tree of an ontology - - Note: indentation is made so that ids up to 3 digits fit in, plus a space. - [123]1-- - [1]123-- - [12]12-- - """ - TYPE_MARGIN = 13 # length for skos:concept - - if not element: # first time - for x in self.toplayer_skos: - printGenericTree(x, 0, showids, labels, showtype, TYPE_MARGIN) - - else: - printGenericTree(element, 0, showids, labels, showtype, TYPE_MARGIN) + """ + Object that extracts schema definitions (aka 'ontologies') from an rdf graph. + + In [3]: import ontospy + + In [5]: o = ontospy.Ontospy() + + In [7]: o.load_rdf("foaf.rdf") + + In [11]: o.build_all() + + In [13]: o.stats() + Out[13]: + [('Ontologies', 1), + ('Triples', 630), + ('Classes', 15), + ('Properties', 67), + ('Annotation Properties', 7), + ('Object Properties', 34), + ('Datatype Properties', 26), + ('Skos Concepts', 0), + ('Data Sources', 1)] + + """ + + def __init__(self, + uri_or_path=None, + data=None, + file_obj=None, + rdf_format="", + verbose=False, + hide_base_schemas=True, + hide_implicit_types=True, + hide_implicit_preds=True, + sparql_endpoint=None, + credentials=None, + build_all=True, + pref_entities_title="qname", + pref_language="en", + ): + """Load the graph in memory, then setup all necessary attributes. + + Parameters + ---------- + uri_or_path : [type], optional + [description], by default None + data : [type], optional + [description], by default None + file_obj : [type], optional + [description], by default None + rdf_format : str, optional + [description], by default "" + verbose : bool, optional + [description], by default False + hide_base_schemas : bool, optional + [description], by default True + hide_implicit_types : bool, optional + [description], by default True + hide_implicit_preds : bool, optional + [description], by default True + sparql_endpoint : [type], optional + [description], by default None + credentials : [type], optional + [description], by default None + build_all : bool, optional + [description], by default True + pref_entities_title : str, optional + How to display entities by default. Two options accepted: "qname" (default) or "label" for rdfs:label. + pref_language : str, optional + Default: 'en' + """ + + super(Ontospy, self).__init__() + + self.rdflib_graph = None + self.sparql_endpoint = None + self.credentials = None # tuple: auth credentials for endpoint if needed + self.sources = None + self.sparqlHelper = None + self.pref_title = pref_entities_title + self.pref_language = pref_language + self.namespaces = [] + # entities buckets start with 'all_' + self.all_ontologies = [] + self.all_classes = [] + self.all_properties = [] + self.all_properties_annotation = [] + self.all_properties_object = [] + self.all_properties_datatype = [] + self.all_skos_concepts = [] + self.all_shapes = [] + # self.all_individuals = [] + self.toplayer_classes = [] + self.toplayer_properties = [] + self.toplayer_skos = [] + self.toplayer_shapes = [] + self.OWLTHING = OntoClass(rdflib.OWL.Thing, + rdflib.OWL.Class, + self.namespaces, + False, + self.pref_title, + self.pref_language) + + # finally: + if uri_or_path or data or file_obj: + self.load_rdf(uri_or_path, data, file_obj, rdf_format, verbose) + if build_all: + self.build_all( + verbose=verbose, + hide_base_schemas=hide_base_schemas, + hide_implicit_types=hide_implicit_types, + hide_implicit_preds=hide_implicit_preds, + ) + elif sparql_endpoint: # by default entities are not extracted + self.load_sparql(sparql_endpoint, verbose, credentials) + else: + pass + + def __repr__(self): + """ + Return some info for the ontospy instance. + + note: if it's a sparql backend, limit the info returned to avoid long queries (tip: a statement like `if self.rdflib_graph` on a sparql endpoint is enough to cause a long query!) + + """ + if self.sparql_endpoint and self.rdflib_graph != None: + return "<Ontospy Graph (sparql endpoint = <%s>)>" % self.sparql_endpoint + elif self.rdflib_graph != None: + return "<Ontospy Graph (%d triples)>" % (len(self.rdflib_graph)) + else: + return "<Ontospy object created but not initialized (use the `load_rdf` method to load an rdf schema)>" + + def load_rdf(self, + uri_or_path=None, + data=None, + file_obj=None, + rdf_format="", + verbose=False): + """Load an RDF source into an ontospy/rdflib graph""" + loader = RDFLoader(verbose=verbose) + loader.load(uri_or_path, data, file_obj, rdf_format) + self.rdflib_graph = loader.rdflib_graph + self.sources = loader.sources_valid + self.sparqlHelper = SparqlHelper(self.rdflib_graph) + self.namespaces = sorted(self.rdflib_graph.namespaces()) + + def load_sparql(self, + sparql_endpoint, + verbose=False, + credentials=None): + """ + Set up a SPARQLStore backend as a virtual ontospy graph + + Note: we're using a 'SPARQLUpdateStore' backend instead of 'SPARQLStore' cause otherwise authentication fails (https://github.com/RDFLib/rdflib/issues/755) + + @TODO this error seems to be fixed in upcoming rdflib versions + https://github.com/RDFLib/rdflib/pull/744 + + """ + try: + # graph = rdflib.Graph('SPARQLStore') + # graph = rdflib.ConjunctiveGraph('SPARQLStore') + graph = rdflib.ConjunctiveGraph('SPARQLUpdateStore') + + if credentials and type(credentials) == tuple: + # https://github.com/RDFLib/rdflib/issues/343 + graph.store.setCredentials(credentials[0], credentials[1]) + # graph.store.setHTTPAuth('BASIC') # graph.store.setHTTPAuth('DIGEST') + + graph.open(sparql_endpoint) + self.rdflib_graph = graph + self.sparql_endpoint = sparql_endpoint + self.sources = [sparql_endpoint] + self.sparqlHelper = SparqlHelper(self.rdflib_graph, self.sparql_endpoint) + self.namespaces = sorted(self.rdflib_graph.namespaces()) + except: + printDebug("Error trying to connect to Endpoint.") + raise + # don't extract entities by default.. + + + # ------------ + # === methods to build python objects === # + # ------------ + + def build_all(self, + verbose=False, + hide_base_schemas=True, + hide_implicit_types=True, + hide_implicit_preds=True, + ): + """ + Extract all ontology entities from an RDF graph and construct Python representations of them. + """ + if verbose: + printDebug("Scanning entities...", "green") + printDebug("----------", "comment") + + self.build_ontologies() + if verbose: + printDebug("Ontologies.........: %d" % len(self.all_ontologies), "comment") + + self.build_classes(hide_base_schemas, hide_implicit_types) + if verbose: + printDebug("Classes............: %d" % len(self.all_classes), "comment") + + self.build_properties(hide_implicit_preds) + if verbose: + printDebug("Properties.........: %d" % len(self.all_properties), "comment") + if verbose: + printDebug("..annotation.......: %d" % len(self.all_properties_annotation), "comment") + if verbose: + printDebug("..datatype.........: %d" % len(self.all_properties_datatype), "comment") + if verbose: + printDebug("..object...........: %d" % len(self.all_properties_object), "comment") + + self.build_skos_concepts() + if verbose: + printDebug("Concepts (SKOS)....: %d" % len(self.all_skos_concepts), "comment") + + self.build_shapes() + if verbose: + printDebug("Shapes (SHACL).....: %d" % len(self.all_shapes), "comment") + + # self.__computeTopLayer() + + self.__computeInferredProperties() + + if verbose: + printDebug("----------", "comment") + + def build_ontologies(self, exclude_BNodes=False, return_string=False): + """ + Extract ontology instances info from the graph, then creates python objects for them. + + Note: often ontology info is nested in structures like this: + + [ a owl:Ontology ; + vann:preferredNamespacePrefix "bsym" ; + vann:preferredNamespaceUri "http://bsym.bloomberg.com/sym/" ] + + Hence there is some logic to deal with these edge cases. + """ + out = [] + + qres = self.sparqlHelper.getOntology() + + if qres: + # NOTE: SPARQL returns a list of rdflib.query.ResultRow (~ tuples..) + + for candidate in qres: + if isBlankNode(candidate[0]): + if exclude_BNodes: + continue + else: + checkDC_ID = [x for x in self.rdflib_graph.objects( + candidate[0], rdflib.namespace.DC.identifier)] + if checkDC_ID: + out += [Ontology(checkDC_ID[0], + namespaces=self.namespaces, + pref_title=self.pref_title), + ] + else: + vannprop = rdflib.URIRef( + "http://purl.org/vocab/vann/preferredNamespaceUri") + vannpref = rdflib.URIRef( + "http://purl.org/vocab/vann/preferredNamespacePrefix") + checkDC_ID = [x for x in self.rdflib_graph.objects( + candidate[0], vannprop)] + if checkDC_ID: + checkDC_prefix = [ + x for x in self.rdflib_graph.objects(candidate[0], vannpref)] + if checkDC_prefix: + out += [Ontology(checkDC_ID[0], + namespaces=self.namespaces, + pref_prefix=checkDC_prefix[0], + pref_title=self.pref_title, + pref_language=self.pref_language, + ) + ] + else: + out += [Ontology(checkDC_ID[0], + namespaces=self.namespaces, + pref_title=self.pref_title, + pref_language=self.pref_language, + )] + + else: + out += [Ontology(candidate[0], + namespaces=self.namespaces, + pref_title=self.pref_title, + pref_language=self.pref_language, + )] + + else: + pass + # printDebug("No owl:Ontologies found") + + # finally... add all annotations/triples + self.all_ontologies = out + for onto in self.all_ontologies: + onto.triples = self.sparqlHelper.entityTriples(onto.uri) + onto._buildGraph() # force construction of mini graph + + # + # RDFS:class vs OWL:class cf. http://www.w3.org/TR/owl-ref/ section 3.1 + # + + def build_classes(self, hide_base_schemas=True, hide_implicit_types=True): + """ + 2015-06-04: removed sparql 1.1 queries + 2015-05-25: optimized via sparql queries in order to remove BNodes + 2015-05-09: new attempt + + Note: sparqlHelper.getAllClasses() returns a list of tuples, + (class, classRDFtype) + so in some cases there are duplicates if a class is both RDFS.CLass and OWL.Class + In this case we keep only OWL.Class as it is more informative. + """ + + self.all_classes = [] # @todo: keep adding? + + qres = self.sparqlHelper.getAllClasses(hide_base_schemas, + hide_implicit_types) + # print("rdflib query done") + + for class_tuple in qres: + + _uri = class_tuple[0] + try: + _type = class_tuple[1] + except: + _type = "" + + test_existing_cl = self.get_class(uri=_uri) + if not test_existing_cl: + # create it + ontoclass = OntoClass(_uri, _type, + self.namespaces, + False, + self.pref_title, + self.pref_language) + self.all_classes += [ontoclass] + else: + # if OWL.Class over RDFS.Class - update it + if _type == rdflib.OWL.Class: + test_existing_cl.rdftype = rdflib.OWL.Class + + # print("classes created") + + # add more data + for aClass in self.all_classes: + # print("enriching class", aClass) + aClass.triples = self.sparqlHelper.entityTriples(aClass.uri) + aClass._buildGraph() # force construction of mini graph + + aClass.sparqlHelper = self.sparqlHelper + + # attach to an ontology + for uri in aClass.getValuesForProperty(rdflib.RDFS.isDefinedBy): + onto = self.get_ontology(uri=str(uri)) + if onto: + onto.all_classes += [aClass] + aClass.ontology = onto + + # add direct Supers + directSupers = self.sparqlHelper.getClassDirectSupers(aClass.uri) + + for x in directSupers: + superclass = self.get_class(uri=x[0]) + # note: extra condition to avoid recursive structures + if superclass and superclass.uri != aClass.uri: + aClass._parents.append(superclass) + + # add inverse relationships (= direct subs for superclass) + if aClass not in superclass.children(): + superclass._children.append(aClass) + + # sort alphabetically + self.all_classes = sorted(self.all_classes, key=lambda x: x.qname) + + # compute top layer + # print("calc toplayer") + exit = [] + for c in self.all_classes: + if not c.parents(): + exit += [c] + self.toplayer_classes = exit # sorted(exit, key=lambda x: x.id) # doesnt work + + def build_properties(self, hide_implicit_preds=True): + """ + 2015-06-04: removed sparql 1.1 queries + 2015-06-03: analogous to get classes + + # instantiate properties making sure duplicates are pruned + # but the most specific rdftype is kept + # eg OWL:ObjectProperty over RDF:property + + """ + self.all_properties = [] # @todo: keep adding? + self.all_properties_annotation = [] + self.all_properties_object = [] + self.all_properties_datatype = [] + + qres = self.sparqlHelper.getAllProperties(hide_implicit_preds) + # print("rdflib query done") + + for candidate in qres: + + test_existing_prop = self.get_property(uri=candidate[0]) + if not test_existing_prop: + # create it + self.all_properties += [OntoProperty(candidate[0], candidate[1], + self.namespaces, + False, + self.pref_title, + self.pref_language, + )] + else: + # update it + if candidate[1] and (test_existing_prop.rdftype == rdflib.RDF.Property): + test_existing_prop.rdftype = inferMainPropertyType(candidate[1]) + # print("properties created") + + # add more data + for aProp in self.all_properties: + # print("enriching prop..", aProp) + if aProp.rdftype == rdflib.OWL.DatatypeProperty: + self.all_properties_datatype += [aProp] + elif aProp.rdftype == rdflib.OWL.AnnotationProperty: + self.all_properties_annotation += [aProp] + elif aProp.rdftype == rdflib.OWL.ObjectProperty: + self.all_properties_object += [aProp] + else: + pass + + aProp.triples = self.sparqlHelper.entityTriples(aProp.uri) + aProp._buildGraph() # force construction of mini graph + + # attach to an ontology [2015-06-15: no property type distinction yet] + for uri in aProp.getValuesForProperty(rdflib.RDFS.isDefinedBy): + onto = self.get_ontology(uri=str(uri)) + if onto: + onto.all_properties += [aProp] + aProp.ontology = onto + + self.__buildDomainRanges(aProp) + + # add direct Supers + directSupers = self.sparqlHelper.getPropDirectSupers(aProp.uri) + + for x in directSupers: + superprop = self.get_property(uri=x[0]) + # note: extra condition to avoid recursive structures + if superprop and superprop.uri != aProp.uri: + aProp._parents.append(superprop) + + # add inverse relationships (= direct subs for superprop) + if aProp not in superprop.children(): + superprop._children.append(aProp) + + # sort alphabetically + self.all_properties = sorted(self.all_properties, key=lambda x: x.qname) + + # computer top layer for properties + # print("calc toplayer") + exit = [] + for c in self.all_properties: + if not c.parents(): + exit += [c] + self.toplayer_properties = exit # sorted(exit, key=lambda x: x.id) # doesnt work + + def build_skos_concepts(self): + """ + 2015-08-19: first draft + """ + self.all_skos_concepts = [] # @todo: keep adding? + + qres = self.sparqlHelper.getSKOSInstances() + # print("rdflib query done") + + for candidate in qres: + + test_existing_cl = self.get_skos(uri=candidate[0]) + if not test_existing_cl: + # create it + self.all_skos_concepts += [OntoSKOSConcept(candidate[0], None, + self.namespaces, + None, + self.pref_title, + self.pref_language,) + ] + else: + pass + # print("concepts created") + # add more data + skos = rdflib.Namespace('http://www.w3.org/2004/02/skos/core#') + + for aConcept in self.all_skos_concepts: + # print("enriching concept...", aConcept) + aConcept.rdftype = skos['Concept'] + aConcept.triples = self.sparqlHelper.entityTriples(aConcept.uri) + aConcept._buildGraph() # force construction of mini graph + + aConcept.sparqlHelper = self.sparqlHelper + + # attach to an ontology + for uri in aConcept.getValuesForProperty(rdflib.RDFS.isDefinedBy): + onto = self.get_ontology(uri=str(uri)) + if onto: + onto.all_skos_concepts += [aConcept] + aConcept.ontology = onto + + # add direct Supers + directSupers = self.sparqlHelper.getSKOSDirectSupers(aConcept.uri) + + for x in directSupers: + superclass = self.get_skos(uri=x[0]) + # note: extra condition to avoid recursive structures + if superclass and superclass.uri != aConcept.uri: + aConcept._parents.append(superclass) + + # add inverse relationships (= direct subs for superclass) + if aConcept not in superclass.children(): + superclass._children.append(aConcept) + + # sort alphabetically + self.all_skos_concepts = sorted(self.all_skos_concepts, key=lambda x: x.qname) + + # compute top layer for skos + exit = [] + for c in self.all_skos_concepts: + if not c.parents(): + exit += [c] + self.toplayer_skos = exit # sorted(exit, key=lambda x: x.id) # doesnt work + + def build_shapes(self): + """ + Extract SHACL data shapes from the rdf graph. + <http://www.w3.org/ns/shacl#> + + Instatiate the Shape Python objects and relate it to existing classes, + if available. + """ + self.all_shapes = [] # @todo: keep adding? + + qres = self.sparqlHelper.getShapes() + + for candidate in qres: + + test_existing_cl = self.get_any_entity(uri=candidate[0]) + if not test_existing_cl: + # create it + self.all_shapes += [OntoShape(candidate[0], None, + self.namespaces, + None, + self.pref_title, + self.pref_language,) + ] + else: + pass + + # add more data + shacl = rdflib.Namespace('http://www.w3.org/ns/shacl#') + + for aShape in self.all_shapes: + + aShape.rdftype = shacl['Shape'] + aShape.triples = self.sparqlHelper.entityTriples(aShape.uri) + aShape._buildGraph() # force construction of mini graph + + aShape.sparqlHelper = self.sparqlHelper + + # attach to a class + for uri in aShape.getValuesForProperty(shacl['targetClass']): + aclass = self.get_class(str(uri)) + if aclass: + aShape.targetClasses += [aclass] + aclass.all_shapes += [aShape] + for propertyUri in aShape.getValuesForProperty(shacl['path']): #add shaped properties of this class. later can be used for ontodocs + propType = self.get_property(str(propertyUri)) + if propType: + aclass.shapedProperties += [{'shape': aShape, 'property': propType}] + + + + # sort alphabetically + self.all_shapes = sorted(self.all_shapes, key=lambda x: x.qname) + + # compute top layer + exit = [] + for c in self.all_shapes: + if not c.parents(): + exit += [c] + self.toplayer_shapes = exit # sorted(exit, key=lambda x: x.id) # doesnt work + + + def build_entity_from_uri(self, uri, ontospyClass=None): + """ + Extract RDF statements having a URI as subject, then instantiate the RDF_Entity Python object so that it can be queried further. + + Passing <ontospyClass> allows to instantiate a user-defined RDF_Entity subclass. + + NOTE: the entity is not attached to any index. In future version we may create an index for these (individuals?) keeping into account that any existing model entity could be (re)created this way. + """ + if not ontospyClass: + ontospyClass = RDF_Entity + elif not issubclass(ontospyClass, RDF_Entity): + click.secho("Error: <%s> is not a subclass of ontospy.RDF_Entity" % str(ontospyClass)) + return None + else: + pass + qres = self.sparqlHelper.entityTriples(uri) + if qres: + entity = ontospyClass(rdflib.URIRef(uri), + None, + self.namespaces, + None, + self.pref_title, + self.pref_language,) + entity.triples = qres + entity._buildGraph() # force construction of mini graph + # try to add class info + test = entity.getValuesForProperty(rdflib.RDF.type) + if test: + entity.rdftype = test + entity.rdftype_qname = [entity._build_qname(x) for x in test] + return entity + else: + return None + + # ------------ + # === methods to refine the ontology structure === # + # ------------ + + def __buildDomainRanges(self, aProp): + """ + extract domain/range details and add to Python objects + """ + + domains = chain(aProp.rdflib_graph.objects( + None, rdflib.term.URIRef(u'http://schema.org/domainIncludes')), aProp.rdflib_graph.objects( + None, rdflib.RDFS.domain)) + + ranges = chain(aProp.rdflib_graph.objects( + None, rdflib.term.URIRef(u'http://schema.org/rangeIncludes')), aProp.rdflib_graph.objects( + None, rdflib.RDFS.range)) + + for x in domains: + if isBlankNode(x): + aProp.domains += [RDF_Entity(x, None, self.namespaces, is_Bnode=True)] + else: + aClass = self.get_class(uri=str(x)) + if aClass: + aProp.domains += [aClass] + aClass.domain_of += [aProp] + else: + # edge case: it's not an OntoClass instance + aProp.domains += [OntoClass(x, None, + self.namespaces, + True, # ext_model arg + self.pref_title, + self.pref_language,)] + + for x in ranges: + if isBlankNode(x): + aProp.domains += [RDF_Entity(x, None, self.namespaces, is_Bnode=True)] + else: + aClass = self.get_class(uri=str(x)) + if aClass: + aProp.ranges += [aClass] + aClass.range_of += [aProp] + else: + # eg a DataType property has xsd:STRING + # here we're storing an ontospy entities but not adding it to + # the main index + aProp.ranges += [OntoClass(x, None, + self.namespaces, + True, + self.pref_title, + self.pref_language,)] + + def __computeTopLayer(self): + """ + deprecated: now this is calculated when entities get extracted + """ + + exit = [] + for c in self.all_classes: + if not c.parents(): + exit += [c] + self.toplayer_classes = exit # sorted(exit, key=lambda x: x.id) # doesnt work + + # properties + exit = [] + for c in self.all_properties: + if not c.parents(): + exit += [c] + self.toplayer_properties = exit # sorted(exit, key=lambda x: x.id) # doesnt work + + # skos + exit = [] + for c in self.all_skos_concepts: + if not c.parents(): + exit += [c] + self.toplayer_skos = exit # sorted(exit, key=lambda x: x.id) # doesnt work + + def __computeInferredProperties(self): + """ + + :return: attach a list of dicts to each class, detailing valid props up the subsumption tree + """ + exit = [] + for c in self.all_classes: + c.domain_of_inferred = self.getInferredPropertiesForClass(c, "domain_of") + c.range_of_inferred = self.getInferredPropertiesForClass(c, "range_of") + + def getInferredPropertiesForClass(self, aClass, rel="domain_of"): + """ + returns all properties valid for a class (as they have it in their domain) + recursively ie traveling up the descendants tree + Note: results in a list of dicts including itself + Note [2]: all properties with no domain info are added at the top as [None, props] + + :return: + [{<Class *http://xmlns.com/foaf/0.1/Person*>: + [<Property *http://xmlns.com/foaf/0.1/currentProject*>,<Property *http://xmlns.com/foaf/0.1/familyName*>, + etc....]}, + {<Class *http://www.w3.org/2003/01/geo/wgs84_pos#SpatialThing*>: + [<Property *http://xmlns.com/foaf/0.1/based_near*>, etc...]}, + ] + """ + _list = [] + + if rel == "domain_of": + _list.append({aClass: aClass.domain_of}) + for x in aClass.ancestors(): + if x.domain_of: + _list.append({x: x.domain_of}) + + # add properties from Owl:Thing ie the inference layer + + topLevelProps = [p for p in self.all_properties if p.domains == []] + if topLevelProps: + _list.append({self.OWLTHING: topLevelProps}) + + elif rel == "range_of": + _list.append({aClass: aClass.range_of}) + for x in aClass.ancestors(): + if x.domain_of: + _list.append({x: x.range_of}) + + # add properties from Owl:Thing ie the inference layer + + topLevelProps = [p for p in self.all_properties if p.ranges == []] + if topLevelProps: + _list.append({self.OWLTHING: topLevelProps}) + + return _list + + + + # =============== + # methods for retrieving objects + # ================ + + def get_class(self, id=None, uri=None, match=None): + """ + get the saved-class with given ID or via other methods... + + Note: it tries to guess what is being passed.. + + In [1]: g.get_class(uri='http://www.w3.org/2000/01/rdf-schema#Resource') + Out[1]: <Class *http://www.w3.org/2000/01/rdf-schema#Resource*> + + In [2]: g.get_class(10) + Out[2]: <Class *http://purl.org/ontology/bibo/AcademicArticle*> + + In [3]: g.get_class(match="person") + Out[3]: + [<Class *http://purl.org/ontology/bibo/PersonalCommunicationDocument*>, + <Class *http://purl.org/ontology/bibo/PersonalCommunication*>, + <Class *http://xmlns.com/foaf/0.1/Person*>] + + """ + + if not id and not uri and not match: + return None + + if type(id) == type("string"): + uri = id + id = None + if not is_http(uri): + match = uri + uri = None + if match: + if type(match) != type("string"): + return [] + res = [] + if ":" in match: # qname + for x in self.all_classes: + if match.lower() in x.qname.lower(): + res += [x] + else: + for x in self.all_classes: + if match.lower() in x.uri.lower(): + res += [x] + return res + else: + for x in self.all_classes: + if id and x.id == id: + return x + if uri and x.uri.lower() == uri.lower(): + return x + return None + + def get_property(self, id=None, uri=None, match=None): + """ + get the saved-class with given ID or via other methods... + + Note: analogous to getClass method + """ + + if not id and not uri and not match: + return None + + if type(id) == type("string"): + uri = id + id = None + if not is_http(uri): + match = uri + uri = None + if match: + if type(match) != type("string"): + return [] + res = [] + if ":" in match: # qname + for x in self.all_properties: + if match.lower() in x.qname.lower(): + res += [x] + else: + for x in self.all_properties: + if match.lower() in x.uri.lower(): + res += [x] + return res + else: + for x in self.all_properties: + if id and x.id == id: + return x + if uri and x.uri.lower() == uri.lower(): + return x + return None + + def get_skos(self, id=None, uri=None, match=None): + """ + get the saved skos concept with given ID or via other methods... + + Note: it tries to guess what is being passed as above + """ + + if not id and not uri and not match: + return None + + if type(id) == type("string"): + uri = id + id = None + if not is_http(uri): + match = uri + uri = None + if match: + if type(match) != type("string"): + return [] + res = [] + if ":" in match: # qname + for x in self.all_skos_concepts: + if match.lower() in x.qname.lower(): + res += [x] + else: + for x in self.all_skos_concepts: + if match.lower() in x.uri.lower(): + res += [x] + return res + else: + for x in self.all_skos_concepts: + if id and x.id == id: + return x + if uri and x.uri.lower() == uri.lower(): + return x + return None + + def get_any_entity(self, id=None, uri=None, match=None): + """ + get a generic entity with given ID or via other methods... + """ + + if not id and not uri and not match: + return None + + if type(id) == type("string"): + uri = id + id = None + if not is_http(uri): + match = uri + uri = None + if match: + if type(match) != type("string"): + return [] + res = [] + if ":" in match: # qname + for x in self.all_classes: + if match.lower() in x.qname.lower(): + res += [x] + for x in self.all_properties: + if match.lower() in x.qname.lower(): + res += [x] + else: + for x in self.all_classes: + if match.lower() in x.uri.lower(): + res += [x] + for x in self.all_properties: + if match.lower() in x.uri.lower(): + res += [x] + return res + else: + for x in self.all_classes: + if id and x.id == id: + return x + if uri and x.uri.lower() == uri.lower(): + return x + for x in self.all_properties: + if id and x.id == id: + return x + if uri and x.uri.lower() == uri.lower(): + return x + return None + + def get_ontology(self, id=None, uri=None, match=None): + """ + get the saved-ontology with given ID or via other methods... + """ + + if not id and not uri and not match: + return None + + if type(id) == type("string"): + uri = id + id = None + if not is_http(uri): + match = uri + uri = None + if match: + if type(match) != type("string"): + return [] + res = [] + for x in self.all_ontologies: + if match.lower() in x.uri.lower(): + res += [x] + return res + else: + for x in self.all_ontologies: + if id and x.id == id: + return x + if uri and x.uri.lower() == uri.lower(): + return x + return None + + def nextClass(self, classuri): + """Returns the next class in the list of classes. If it's the last one, returns the first one.""" + if classuri == self.all_classes[-1].uri: + return self.all_classes[0] + flag = False + for x in self.all_classes: + if flag == True: + return x + if x.uri == classuri: + flag = True + return None + + def nextProperty(self, propuri): + """Returns the next property in the list of properties. If it's the last one, returns the first one.""" + if propuri == self.all_properties[-1].uri: + return self.all_properties[0] + flag = False + for x in self.all_properties: + if flag == True: + return x + if x.uri == propuri: + flag = True + return None + + def nextConcept(self, concepturi): + """Returns the next skos concept in the list of concepts. If it's the last one, returns the first one.""" + if concepturi == self.all_skos_concepts[-1].uri: + return self.all_skos_concepts[0] + flag = False + for x in self.all_skos_concepts: + if flag == True: + return x + if x.uri == concepturi: + flag = True + return None + + def ontologyClassTree(self): + """ + Returns a dict representing the ontology tree + Top level = {0:[top classes]} + Multi inheritance is represented explicitly + """ + treedict = {} + if self.all_classes: + treedict[0] = self.toplayer_classes + for element in self.all_classes: + if element.children(): + treedict[element] = element.children() + return treedict + return treedict + + def ontologyPropTree(self): + """ + Returns a dict representing the ontology tree + Top level = {0:[top properties]} + Multi inheritance is represented explicitly + """ + treedict = {} + if self.all_properties: + treedict[0] = self.toplayer_properties + for element in self.all_properties: + if element.children(): + treedict[element] = element.children() + return treedict + return treedict + + def ontologyConceptTree(self): + """ + Returns a dict representing the skos tree + Top level = {0:[top concepts]} + Multi inheritance is represented explicitly + """ + treedict = {} + if self.all_skos_concepts: + treedict[0] = self.toplayer_skos + for element in self.all_skos_concepts: + if element.children(): + treedict[element] = element.children() + return treedict + return treedict + + def ontologyShapeTree(self): + """ + Returns a dict representing the ontology tree + Top level = {0:[top properties]} + Multi inheritance is represented explicitly + """ + treedict = {} + if self.all_shapes: + treedict[0] = self.toplayer_shapes + for element in self.all_shapes: + if element.children(): + treedict[element] = element.children() + return treedict + return treedict + + + # ------------ + # === utils === # + # ------------ + + + def rdf_source(self, format="turtle"): + """ + Wrapper for rdflib serializer method. + Valid options are: xml, n3, turtle, nt, pretty-xml, json-ld [trix not working out of the box] + """ + s = self.rdflib_graph.serialize(format=format) + if isinstance(s, bytes): + s = s.decode('utf-8') + return s + + + def serialize(self, format="turtle"): + "for backward compatibility" + return self.rdf_source(format) + + def query(self, stringa): + """SPARQL query / wrapper for rdflib sparql query method """ + qres = self.rdflib_graph.query(stringa) + return list(qres) + def sparql(self, stringa): + "SPARQL query / replacement for query" + return self.query(stringa) + + def stats(self): + """ shotcut to pull out useful info for a graph""" + out = [] + out += [("Ontologies", len(self.all_ontologies))] + out += [("Triples", self.triplesCount())] + out += [("Classes", len(self.all_classes))] + out += [("Properties", len(self.all_properties))] + out += [("Annotation Properties", len(self.all_properties_annotation))] + out += [("Object Properties", len(self.all_properties_object))] + out += [("Datatype Properties", len(self.all_properties_datatype))] + out += [("Skos Concepts", len(self.all_skos_concepts))] + out += [("Data Shapes", len(self.all_shapes))] + # out += [("Individuals", len(self.individuals))] @TODO + out += [("Data Sources", len(self.sources))] + return out + + def triplesCount(self): + """ + + 2016-08-18 the try/except is a dirty solution to a problem + emerging with counting graph length on cached Graph objects.. + """ + # @todo investigate what's going on.. + # click.secho(unicode(type(self.rdflib_graph)), fg="red") + try: + return len(self.rdflib_graph) + except: + click.secho("Ontospy: error counting graph length..", fg="red") + return 0 + + + def printClassTree(self, element=None, showids=False, labels=False, showtype=False): + """ + Print nicely into stdout the class tree of an ontology + + Note: indentation is made so that ids up to 3 digits fit in, plus a space. + [123]1-- + [1]123-- + [12]12-- + """ + TYPE_MARGIN = 11 # length for owl:class etc.. + + if not element: # first time + for x in self.toplayer_classes: + printGenericTree(x, 0, showids, labels, showtype, TYPE_MARGIN) + + else: + printGenericTree(element, 0, showids, labels, showtype, TYPE_MARGIN) + + def printPropertyTree(self, element=None, showids=False, labels=False, showtype=False): + """ + Print nicely into stdout the property tree of an ontology + + Note: indentation is made so that ids up to 3 digits fit in, plus a space. + [123]1-- + [1]123-- + [12]12-- + """ + TYPE_MARGIN = 18 # length for owl:AnnotationProperty etc.. + + if not element: # first time + for x in self.toplayer_properties: + printGenericTree(x, 0, showids, labels, showtype, TYPE_MARGIN) + + else: + printGenericTree(element, 0, showids, labels, showtype, TYPE_MARGIN) + + def printSkosTree(self, element=None, showids=False, labels=False, showtype=False): + """ + Print nicely into stdout the SKOS tree of an ontology + + Note: indentation is made so that ids up to 3 digits fit in, plus a space. + [123]1-- + [1]123-- + [12]12-- + """ + TYPE_MARGIN = 13 # length for skos:concept + + if not element: # first time + for x in self.toplayer_skos: + printGenericTree(x, 0, showids, labels, showtype, TYPE_MARGIN) + + else: + printGenericTree(element, 0, showids, labels, showtype, TYPE_MARGIN) diff --git a/ontospy/tests/test_methods.py b/ontospy/tests/test_methods.py index c9cf3b50..4770061e 100644 --- a/ontospy/tests/test_methods.py +++ b/ontospy/tests/test_methods.py @@ -25,8 +25,8 @@ class SampleCustomEntity(ontospy.RDF_Entity): - def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False): - super(SampleCustomEntity, self).__init__(uri, rdftype, namespaces, ext_model) + def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, entity_display_title="qname"): + super(SampleCustomEntity, self).__init__(uri, rdftype, namespaces, ext_model, entity_display_title) def __repr__(self): return "<SampleCustomEntity *%s*>" % ( self.uri) @@ -49,10 +49,26 @@ class TestMethods(unittest.TestCase): dir_path = os.path.dirname(os.path.realpath(__file__)) DATA_FOLDER = dir_path + "/rdf/" f = DATA_FOLDER + "pizza.ttl" - o = Ontospy(f, verbose=True) + o = Ontospy(f, verbose=True, entity_display_title="label") printDebug("\n*****\nTest: loading with local file... > %s\n*****" % str(f), "important") + def test0(self): + """ + Class methods + """ + printDebug("\n=================\nTEST 0: Checking the <class> displays", "green") + + for c in self.o.all_classes: + print("URI: ", c.uri) + print("RDFTYPE: ", c.rdftype) + print("BEST LABEL: ", c.bestLabel()) + print("TITLE DISPLAY: ", c.display_title) + print("===") + + printDebug("Test completed succesfully.\n", "green") + + def test1(self): """ Instances method @@ -62,7 +78,7 @@ def test1(self): for c in self.o.all_classes: # c.describe() if c.instances: - print("CLASS: " + c.uri) + print("CLASS: " + c.uri + " " + c.display_title) print("INSTANCES: ") for el in c.instances: print(el.uri, el.qname) @@ -79,7 +95,7 @@ def test2(self): for c in self.o.all_classes[:3]: print("CLASS: ") - print(c.uri, c.qname) + print(c.uri, c.qname, c.display_title) print("RDF:TYPE VALUES: ") print(c.getValuesForProperty("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")) @@ -95,6 +111,7 @@ def test3(self): print("URI: ", e) print("RDFTYPE: ", e.rdftype) print("BEST LABEL: ", e.bestLabel()) + print("TITLE DISPLAY: ", e.display_title) print("RDF SOURCE: ") print(e.rdf_source()) printDebug("Test completed succesfully.\n", "green") @@ -110,6 +127,7 @@ def test4(self): print("URI: ", e) print("RDFTYPE: ", e.rdftype) print("BEST LABEL: ", e.bestLabel()) + print("TITLE DISPLAY: ", e.display_title) print("OWL DISJOINT WITH: ") print("\n".join([x for x in e.disjointWith()])) printDebug("Test completed succesfully.\n", "green") diff --git a/ontospy/tests/test_quick.py b/ontospy/tests/test_quick.py index 7eb0539e..65cba09d 100644 --- a/ontospy/tests/test_quick.py +++ b/ontospy/tests/test_quick.py @@ -9,6 +9,18 @@ ./run-quick-test.sh +TIP + +# code to load resources for multiple tests + +``` +dir_path = os.path.dirname(os.path.realpath(__file__)) +DATA_FOLDER = dir_path + "/rdf/" +f = DATA_FOLDER + "pizza.ttl" +o = Ontospy(f, verbose=True) +printDebug("\n*****\nTest: loading local file... > %s\n*****" % str(f), "important") +``` + """ from __future__ import print_function @@ -23,45 +35,48 @@ class MyRDFEntity(ontospy.RDF_Entity): - def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False): - super(MyRDFEntity, self).__init__(uri, rdftype, namespaces, ext_model) + def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False): + super(MyRDFEntity, self).__init__(uri, rdftype, namespaces, ext_model) - def __repr__(self): - return "<MyRDFEntity *%s*>" % (self.uri) + def __repr__(self): + return "<MyRDFEntity *%s*>" % (self.uri) - def disjointWith(self): - """ - Example: pull out disjoint with statements - """ - pred = "http://www.w3.org/2002/07/owl#disjointWith" - return self.getValuesForProperty(pred) + def disjointWith(self): + """ + Example: pull out disjoint with statements + """ + pred = "http://www.w3.org/2002/07/owl#disjointWith" + return self.getValuesForProperty(pred) class TestQuick(unittest.TestCase): - # code to load resources for multiple tests - # dir_path = os.path.dirname(os.path.realpath(__file__)) - # DATA_FOLDER = dir_path + "/rdf/" - # f = DATA_FOLDER + "pizza.ttl" - # o = Ontospy(f, verbose=True) - # printDebug("\n*****\nTest: loading local file... > %s\n*****" % str(f), "important") + def test_quick1(self): + """ + + """ + print("=================\n*** QUICK TEST 1 ***\n=================\n") + + dir_path = os.path.dirname(os.path.realpath(__file__)) + DATA_FOLDER = dir_path + "/rdf/" + f = DATA_FOLDER + "pizza.ttl" + o = Ontospy(f, verbose=True, pref_entities_title="qname", pref_language="de") - def test_quick1(self): - """ + for c in o.all_classes: + print("URI: ", c.uri) + print("RDFTYPE: ", c.rdftype) + print("BEST LABEL: ", c.bestLabel()) + print("TITLE: ", c.title) + print("===") + - """ - print("=================\n*** QUICK TEST 1 ***\n=================\n") - from ontospy.core.rdf_loader import RDFLoader - loader = RDFLoader(verbose=True) - loader.load(uri_or_path="/Users/michele.pasin/Desktop/t.jsonld") - print(loader.rdflib_graph.serialize(format="turtle")) - # def test_quick2(self): - # """Keep adding tests like this""" - # print("=================\n*** QUICK TEST 1 ***\n=================\n") + # def test_quick2(self): + # """Keep adding tests like this""" + # print("=================\n*** QUICK TEST 1 ***\n=================\n") if __name__ == "__main__": - unittest.main() + unittest.main() From 891f7852fa032e2da9fb69e577ab55c7e9e12418 Mon Sep 17 00:00:00 2001 From: lambdamusic <michele.pasin@gmail.com> Date: Tue, 21 Sep 2021 10:22:47 +0100 Subject: [PATCH 03/16] refactor RdfEntity --- ontospy/__init__.py | 2 +- ontospy/core/entities.py | 22 +++++++++++----------- ontospy/core/ontospy.py | 14 +++++++------- ontospy/tests/test_methods.py | 16 ++++++++-------- ontospy/tests/test_quick.py | 2 +- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/ontospy/__init__.py b/ontospy/__init__.py index 82d7bad0..bda5ce72 100755 --- a/ontospy/__init__.py +++ b/ontospy/__init__.py @@ -5,4 +5,4 @@ from .VERSION import __version__, VERSION from .core.ontospy import Ontospy -from .core.entities import RDF_Entity, Ontology, OntoClass, OntoProperty, OntoSKOSConcept, OntoShape +from .core.entities import RdfEntity, Ontology, OntoClass, OntoProperty, OntoSKOSConcept, OntoShape diff --git a/ontospy/core/entities.py b/ontospy/core/entities.py index 36b8687b..9e37c4ca 100755 --- a/ontospy/core/entities.py +++ b/ontospy/core/entities.py @@ -13,7 +13,7 @@ from .utils import * -class RDF_Entity(object): +class RdfEntity(object): """ Pythonic representation of an RDF resource - normally not instantiated but used for inheritance purposes @@ -30,7 +30,7 @@ class RDF_Entity(object): _ids = count(0) def __repr__(self): - return "<Ontospy: RDF_Entity object for uri *%s*>" % (self.uri) + return "<Ontospy: RdfEntity object for uri *%s*>" % (self.uri) def __init__(self, uri, @@ -58,8 +58,8 @@ def __init__(self, self.is_Bnode = is_Bnode self._pref_title = pref_title self._pref_language = pref_language - print("RDF_Entity (received)", pref_title) - print("RDF_Entity (set)", self._pref_title) + print("RdfEntity (received)", pref_title) + print("RdfEntity (set)", self._pref_title) self.slug = None self.rdftype = rdftype self.triples = None @@ -116,7 +116,7 @@ def _buildGraph(self): for terzetto in self.triples: self.rdflib_graph.add(terzetto) - # methods added to RDF_Entity even though they apply only to some subs + # methods added to RdfEntity even though they apply only to some subs def ancestors(self, cl=None, noduplicates=True): """ returns all ancestors in the taxonomy """ @@ -248,7 +248,7 @@ def title(self): -class Ontology(RDF_Entity): +class Ontology(RdfEntity): """ Pythonic representation of an OWL ontology """ @@ -301,7 +301,7 @@ def stats(self): printDebug("Properties..: %d" % len(self.all_properties)) -class OntoClass(RDF_Entity): +class OntoClass(RdfEntity): """ Python representation of a generic class within an ontology. Includes methods for representing and querying RDFS/OWL classes @@ -346,7 +346,7 @@ def instances(self): # = all instances if self.sparqlHelper: qres = self.sparqlHelper.getClassInstances(self.uri) for uri in [x[0] for x in qres]: - instance = RDF_Entity(uri, self.uri, self.namespaces) + instance = RdfEntity(uri, self.uri, self.namespaces) instance.triples = self.sparqlHelper.entityTriples( instance.uri) instance._buildGraph() # force construction of mini graph @@ -383,7 +383,7 @@ def describe(self): # self.printGenericTree() -class OntoProperty(RDF_Entity): +class OntoProperty(RdfEntity): """ Python representation of a generic RDF/OWL property. @@ -434,7 +434,7 @@ def describe(self): # self.printGenericTree() -class OntoSKOSConcept(RDF_Entity): +class OntoSKOSConcept(RdfEntity): """ Python representation of a generic SKOS concept within an ontology. @todo: complete methods.. @@ -475,7 +475,7 @@ def describe(self): self.printGenericTree() -class OntoShape(RDF_Entity): +class OntoShape(RdfEntity): """ Python representation of a SHACL shape. diff --git a/ontospy/core/ontospy.py b/ontospy/core/ontospy.py index 90aa7717..69f8583a 100755 --- a/ontospy/core/ontospy.py +++ b/ontospy/core/ontospy.py @@ -618,16 +618,16 @@ def build_shapes(self): def build_entity_from_uri(self, uri, ontospyClass=None): """ - Extract RDF statements having a URI as subject, then instantiate the RDF_Entity Python object so that it can be queried further. + Extract RDF statements having a URI as subject, then instantiate the RdfEntity Python object so that it can be queried further. - Passing <ontospyClass> allows to instantiate a user-defined RDF_Entity subclass. + Passing <ontospyClass> allows to instantiate a user-defined RdfEntity subclass. NOTE: the entity is not attached to any index. In future version we may create an index for these (individuals?) keeping into account that any existing model entity could be (re)created this way. """ if not ontospyClass: - ontospyClass = RDF_Entity - elif not issubclass(ontospyClass, RDF_Entity): - click.secho("Error: <%s> is not a subclass of ontospy.RDF_Entity" % str(ontospyClass)) + ontospyClass = RdfEntity + elif not issubclass(ontospyClass, RdfEntity): + click.secho("Error: <%s> is not a subclass of ontospy.RdfEntity" % str(ontospyClass)) return None else: pass @@ -669,7 +669,7 @@ def __buildDomainRanges(self, aProp): for x in domains: if isBlankNode(x): - aProp.domains += [RDF_Entity(x, None, self.namespaces, is_Bnode=True)] + aProp.domains += [RdfEntity(x, None, self.namespaces, is_Bnode=True)] else: aClass = self.get_class(uri=str(x)) if aClass: @@ -685,7 +685,7 @@ def __buildDomainRanges(self, aProp): for x in ranges: if isBlankNode(x): - aProp.domains += [RDF_Entity(x, None, self.namespaces, is_Bnode=True)] + aProp.domains += [RdfEntity(x, None, self.namespaces, is_Bnode=True)] else: aClass = self.get_class(uri=str(x)) if aClass: diff --git a/ontospy/tests/test_methods.py b/ontospy/tests/test_methods.py index 4770061e..4269e1a4 100644 --- a/ontospy/tests/test_methods.py +++ b/ontospy/tests/test_methods.py @@ -23,10 +23,10 @@ -class SampleCustomEntity(ontospy.RDF_Entity): +class SampleCustomEntity(ontospy.RdfEntity): - def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, entity_display_title="qname"): - super(SampleCustomEntity, self).__init__(uri, rdftype, namespaces, ext_model, entity_display_title) + def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, pref_title="qname"): + super(SampleCustomEntity, self).__init__(uri, rdftype, namespaces, ext_model, pref_title) def __repr__(self): return "<SampleCustomEntity *%s*>" % ( self.uri) @@ -49,7 +49,7 @@ class TestMethods(unittest.TestCase): dir_path = os.path.dirname(os.path.realpath(__file__)) DATA_FOLDER = dir_path + "/rdf/" f = DATA_FOLDER + "pizza.ttl" - o = Ontospy(f, verbose=True, entity_display_title="label") + o = Ontospy(f, verbose=True, pref_entities_title="label") printDebug("\n*****\nTest: loading with local file... > %s\n*****" % str(f), "important") @@ -63,9 +63,9 @@ def test0(self): print("URI: ", c.uri) print("RDFTYPE: ", c.rdftype) print("BEST LABEL: ", c.bestLabel()) - print("TITLE DISPLAY: ", c.display_title) + print("TITLE: ", c.title) print("===") - + printDebug("Test completed succesfully.\n", "green") @@ -111,7 +111,7 @@ def test3(self): print("URI: ", e) print("RDFTYPE: ", e.rdftype) print("BEST LABEL: ", e.bestLabel()) - print("TITLE DISPLAY: ", e.display_title) + print("TITLE: ", e.title) print("RDF SOURCE: ") print(e.rdf_source()) printDebug("Test completed succesfully.\n", "green") @@ -127,7 +127,7 @@ def test4(self): print("URI: ", e) print("RDFTYPE: ", e.rdftype) print("BEST LABEL: ", e.bestLabel()) - print("TITLE DISPLAY: ", e.display_title) + print("TITLE: ", e.title) print("OWL DISJOINT WITH: ") print("\n".join([x for x in e.disjointWith()])) printDebug("Test completed succesfully.\n", "green") diff --git a/ontospy/tests/test_quick.py b/ontospy/tests/test_quick.py index 65cba09d..dc8a34e8 100644 --- a/ontospy/tests/test_quick.py +++ b/ontospy/tests/test_quick.py @@ -34,7 +34,7 @@ print("-------------------\nOntospy ", VERSION, "\n-------------------") -class MyRDFEntity(ontospy.RDF_Entity): +class MyRDFEntity(ontospy.RdfEntity): def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False): super(MyRDFEntity, self).__init__(uri, rdftype, namespaces, ext_model) From 095156f20e0a61710fd1ba5fb15041c4f19c6e80 Mon Sep 17 00:00:00 2001 From: lambdamusic <michele.pasin@gmail.com> Date: Wed, 22 Sep 2021 18:30:01 +0100 Subject: [PATCH 04/16] context typo --- ontospy/tests/rdf/periodical.jsonld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ontospy/tests/rdf/periodical.jsonld b/ontospy/tests/rdf/periodical.jsonld index 8eeb74de..545d8a3a 100644 --- a/ontospy/tests/rdf/periodical.jsonld +++ b/ontospy/tests/rdf/periodical.jsonld @@ -1,5 +1,5 @@ { - "@context": "http://schema.org", + "@context": "http://schema.org/", "@graph": [ { "@id": "#issue", From 92dcb1ec1e3a7f1ffb28a011d70d4bab9c0fc4c8 Mon Sep 17 00:00:00 2001 From: lambdamusic <michele.pasin@gmail.com> Date: Wed, 22 Sep 2021 18:30:16 +0100 Subject: [PATCH 05/16] rdflib6 --- requirements.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index d0bf204d..2e612844 100755 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@ -rdflib>=4.2.1 -rdflib-jsonld>=0.4.0 +rdflib>=6.0.0 SPARQLWrapper>=1.8.0 html5lib>=1.0.1 requests>=2.20.0 From 54650e68fc69b708fe888382f3c2c88a949c4bd6 Mon Sep 17 00:00:00 2001 From: lambdamusic <michele.pasin@gmail.com> Date: Thu, 23 Sep 2021 10:40:30 +0100 Subject: [PATCH 06/16] misc --- ontospy/core/entities.py | 35 ++++++++--------- ontospy/core/ontospy.py | 34 ++++++++--------- ontospy/core/rdf_loader.py | 4 +- ontospy/tests/rdf/multilingual.ttl | 31 +++++++++++++++ ontospy/tests/test_methods.py | 61 ++++++++++++++++++++++++++---- ontospy/tests/test_quick.py | 6 +-- 6 files changed, 122 insertions(+), 49 deletions(-) create mode 100644 ontospy/tests/rdf/multilingual.ttl diff --git a/ontospy/core/entities.py b/ontospy/core/entities.py index 9e37c4ca..e50555ed 100755 --- a/ontospy/core/entities.py +++ b/ontospy/core/entities.py @@ -39,7 +39,7 @@ def __init__(self, ext_model=False, is_Bnode=False, pref_title="qname", - pref_language="en", + pref_lang="en", ): """ Init ontology object. Load the graph in memory, then setup all necessary attributes. @@ -57,9 +57,8 @@ def __init__(self, self.ext_model = ext_model self.is_Bnode = is_Bnode self._pref_title = pref_title - self._pref_language = pref_language - print("RdfEntity (received)", pref_title) - print("RdfEntity (set)", self._pref_title) + self._pref_lang = pref_lang + self.slug = None self.rdftype = rdftype self.triples = None @@ -187,7 +186,7 @@ def bestLabel(self, prefLanguage="", qname_allowed=True, quotes=False): out = "" if not prefLanguage: - prefLanguage = self._pref_language + prefLanguage = self._pref_lang if test: out = firstStringInList(test, prefLanguage) @@ -215,7 +214,7 @@ def bestDescription(self, prefLanguage="", quotes=False): ] if not prefLanguage: - prefLanguage = self._pref_language + prefLanguage = self._pref_lang for pred in test_preds: test = self.getValuesForProperty(pred) @@ -235,7 +234,6 @@ def title(self): Defaults to 'qname'. """ - print("in <title> attribute: ", self._pref_title) if self._pref_title == "qname": out = self.qname @@ -263,12 +261,12 @@ def __init__(self, pref_prefix="", ext_model=False, pref_title="qname", - pref_language="en", + pref_lang="en", ): """ Init ontology object. Load the graph in memory, then setup all necessary attributes. """ - super(Ontology, self).__init__(uri, rdftype, namespaces, ext_model, pref_title=pref_title, pref_language=pref_language) + super().__init__(uri, rdftype, namespaces, ext_model, pref_title=pref_title, pref_lang=pref_lang) # self.uri = uri # rdflib.Uriref self.prefix = pref_prefix self.slug = "ontology-" + slugify(self.qname) @@ -317,13 +315,12 @@ class OntoClass(RdfEntity): """ def __init__(self, uri, rdftype=None, namespaces=None, - ext_model=False, pref_title="qname", pref_language="en"): + ext_model=False, pref_title="qname", pref_lang="en"): """ ... """ - print("OntoClass (sender) =>", pref_title) super().__init__(uri, rdftype, namespaces, ext_model, - pref_title=pref_title, pref_language=pref_language) + pref_title=pref_title, pref_lang=pref_lang) self.slug = "class-" + slugify(self.qname) self.domain_of = [] self.range_of = [] @@ -396,11 +393,11 @@ class OntoProperty(RdfEntity): """ def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, - pref_title="qname", pref_language="en"): + pref_title="qname", pref_lang="en"): """ ... """ - super(OntoProperty, self).__init__(uri, rdftype, namespaces, ext_model, pref_title=pref_title, pref_language=pref_language) + super().__init__(uri, rdftype, namespaces, ext_model, pref_title=pref_title, pref_lang=pref_lang) self.slug = "prop-" + slugify(self.qname) self.rdftype = inferMainPropertyType(rdftype) @@ -441,12 +438,12 @@ class OntoSKOSConcept(RdfEntity): """ - def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, pref_title="qname", pref_language="en"): + def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, pref_title="qname", pref_lang="en"): """ ... """ - super(OntoSKOSConcept, self).__init__(uri, rdftype, namespaces, - ext_model, pref_title=pref_title, pref_language=pref_language) + super().__init__(uri, rdftype, namespaces, + ext_model, pref_title=pref_title, pref_lang=pref_lang) self.slug = "concept-" + slugify(self.qname) self.instance_of = [] self.ontology = None @@ -481,11 +478,11 @@ class OntoShape(RdfEntity): """ - def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, pref_title="qname", pref_language="en"): + def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, pref_title="qname", pref_lang="en"): """ ... """ - super(OntoShape, self).__init__(uri, rdftype, namespaces, ext_model, pref_title=pref_title, pref_language=pref_language) + super().__init__(uri, rdftype, namespaces, ext_model, pref_title=pref_title, pref_lang=pref_lang) self.slug = "shape-" + slugify(self.qname) self.ontology = None self.targetClasses = [] diff --git a/ontospy/core/ontospy.py b/ontospy/core/ontospy.py index 69f8583a..3c184134 100755 --- a/ontospy/core/ontospy.py +++ b/ontospy/core/ontospy.py @@ -56,8 +56,8 @@ def __init__(self, sparql_endpoint=None, credentials=None, build_all=True, - pref_entities_title="qname", - pref_language="en", + pref_title="qname", + pref_lang="en", ): """Load the graph in memory, then setup all necessary attributes. @@ -85,9 +85,9 @@ def __init__(self, [description], by default None build_all : bool, optional [description], by default True - pref_entities_title : str, optional + pref_title : str, optional How to display entities by default. Two options accepted: "qname" (default) or "label" for rdfs:label. - pref_language : str, optional + pref_lang : str, optional Default: 'en' """ @@ -98,8 +98,8 @@ def __init__(self, self.credentials = None # tuple: auth credentials for endpoint if needed self.sources = None self.sparqlHelper = None - self.pref_title = pref_entities_title - self.pref_language = pref_language + self.pref_title = pref_title + self.pref_lang = pref_lang self.namespaces = [] # entities buckets start with 'all_' self.all_ontologies = [] @@ -120,7 +120,7 @@ def __init__(self, self.namespaces, False, self.pref_title, - self.pref_language) + self.pref_lang) # finally: if uri_or_path or data or file_obj: @@ -296,21 +296,21 @@ def build_ontologies(self, exclude_BNodes=False, return_string=False): namespaces=self.namespaces, pref_prefix=checkDC_prefix[0], pref_title=self.pref_title, - pref_language=self.pref_language, + pref_lang=self.pref_lang, ) ] else: out += [Ontology(checkDC_ID[0], namespaces=self.namespaces, pref_title=self.pref_title, - pref_language=self.pref_language, + pref_lang=self.pref_lang, )] else: out += [Ontology(candidate[0], namespaces=self.namespaces, pref_title=self.pref_title, - pref_language=self.pref_language, + pref_lang=self.pref_lang, )] else: @@ -360,7 +360,7 @@ def build_classes(self, hide_base_schemas=True, hide_implicit_types=True): self.namespaces, False, self.pref_title, - self.pref_language) + self.pref_lang) self.all_classes += [ontoclass] else: # if OWL.Class over RDFS.Class - update it @@ -435,7 +435,7 @@ def build_properties(self, hide_implicit_preds=True): self.namespaces, False, self.pref_title, - self.pref_language, + self.pref_lang, )] else: # update it @@ -509,7 +509,7 @@ def build_skos_concepts(self): self.namespaces, None, self.pref_title, - self.pref_language,) + self.pref_lang,) ] else: pass @@ -576,7 +576,7 @@ def build_shapes(self): self.namespaces, None, self.pref_title, - self.pref_language,) + self.pref_lang,) ] else: pass @@ -638,7 +638,7 @@ def build_entity_from_uri(self, uri, ontospyClass=None): self.namespaces, None, self.pref_title, - self.pref_language,) + self.pref_lang,) entity.triples = qres entity._buildGraph() # force construction of mini graph # try to add class info @@ -681,7 +681,7 @@ def __buildDomainRanges(self, aProp): self.namespaces, True, # ext_model arg self.pref_title, - self.pref_language,)] + self.pref_lang,)] for x in ranges: if isBlankNode(x): @@ -699,7 +699,7 @@ def __buildDomainRanges(self, aProp): self.namespaces, True, self.pref_title, - self.pref_language,)] + self.pref_lang,)] def __computeTopLayer(self): """ diff --git a/ontospy/core/rdf_loader.py b/ontospy/core/rdf_loader.py index 1eb25544..f207b25e 100755 --- a/ontospy/core/rdf_loader.py +++ b/ontospy/core/rdf_loader.py @@ -26,7 +26,7 @@ class RDFLoader(object): Accepts: [single item or list] :: uri_or_path = a uri or local path :: data = a string containing rdf - :: file_obj = a python file objecy + :: file_obj = a python file object Returns: rdflib graph instance. @@ -258,7 +258,7 @@ def loading_failed(self, rdf_format_opts, uri=""): "----------\nFatal error parsing graph%s\n(using RDF serializations: %s)" % (uri, str(rdf_format_opts)), "red") printDebug( - "----------\nTIP: You can try one of the following RDF validation services\n<http://mowl-power.cs.man.ac.uk:8080/validator/validate>\n<http://www.ivan-herman.net/Misc/2008/owlrl/>" + "----------\nTIP: You can try one of the following RDF validation services\n<http://mowl-power.cs.man.ac.uk:8080/validator/validate>\n<http://rdfvalidator.mybluemix.net/>\n<https://json-ld.org/playground/>" ) return diff --git a/ontospy/tests/rdf/multilingual.ttl b/ontospy/tests/rdf/multilingual.ttl new file mode 100644 index 00000000..bb835aa8 --- /dev/null +++ b/ontospy/tests/rdf/multilingual.ttl @@ -0,0 +1,31 @@ +@prefix : <http://ns.nature.com/terms/> . +@prefix bibo: <http://purl.org/ontology/bibo/> . +@prefix dc: <http://purl.org/dc/elements/1.1/> . +@prefix dcterms: <http://purl.org/dc/terms/> . +@prefix foaf: <http://xmlns.com/foaf/0.1/> . +@prefix npg: <http://ns.nature.com/terms/> . +@prefix npgd: <http://ns.nature.com/datasets/> . +@prefix npgg: <http://ns.nature.com/graphs/> . +@prefix owl: <http://www.w3.org/2002/07/owl#> . +@prefix prism: <http://prismstandard.org/namespaces/basic/2.1/> . +@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +@prefix skos: <http://www.w3.org/2004/02/skos/core#> . +@prefix vann: <http://purl.org/vocab/vann/> . +@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . + +# a dummy multilingual ontology + + +:University a owl:Class ; + rdfs:label "University"@en ; + rdfs:label "Universita'"@it . + +:UniversityStaff a owl:Class ; + rdfs:label "University staff"@en ; + rdfs:label "Trabajador universitario"@es . + +:position a owl:DatatypeProperty ; + rdfs:domain :UniversityStaff ; + rdfs:label "Position"@en ; + rdfs:label "Puesto"@es . diff --git a/ontospy/tests/test_methods.py b/ontospy/tests/test_methods.py index 4269e1a4..f76786d7 100644 --- a/ontospy/tests/test_methods.py +++ b/ontospy/tests/test_methods.py @@ -23,10 +23,11 @@ + class SampleCustomEntity(ontospy.RdfEntity): - def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, pref_title="qname"): - super(SampleCustomEntity, self).__init__(uri, rdftype, namespaces, ext_model, pref_title) + def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False, pref_title="qname", pref_lang="en"): + super(SampleCustomEntity, self).__init__(uri, rdftype, namespaces, ext_model, pref_title, pref_lang) def __repr__(self): return "<SampleCustomEntity *%s*>" % ( self.uri) @@ -44,14 +45,19 @@ def disjointWith(self): class TestMethods(unittest.TestCase): - # updated 2018-05-08 + # load sample ontologies dir_path = os.path.dirname(os.path.realpath(__file__)) DATA_FOLDER = dir_path + "/rdf/" + f = DATA_FOLDER + "pizza.ttl" - o = Ontospy(f, verbose=True, pref_entities_title="label") + printDebug("\n*****\n ..loading local ontology > %s\n*****" % str(f), "important") + o = Ontospy(f, verbose=True, pref_title="label") + + f = DATA_FOLDER + "multilingual.ttl" + printDebug("\n*****\n ..loading local ontology > %s\n*****" % str(f), "important") + o2 = Ontospy(f, verbose=True, pref_title="qname", pref_lang="en") - printDebug("\n*****\nTest: loading with local file... > %s\n*****" % str(f), "important") def test0(self): """ @@ -78,7 +84,7 @@ def test1(self): for c in self.o.all_classes: # c.describe() if c.instances: - print("CLASS: " + c.uri + " " + c.display_title) + print("CLASS: " + c.uri + " " + c.title) print("INSTANCES: ") for el in c.instances: print(el.uri, el.qname) @@ -95,7 +101,7 @@ def test2(self): for c in self.o.all_classes[:3]: print("CLASS: ") - print(c.uri, c.qname, c.display_title) + print(c.uri, c.qname, c.title) print("RDF:TYPE VALUES: ") print(c.getValuesForProperty("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")) @@ -131,11 +137,50 @@ def test4(self): print("OWL DISJOINT WITH: ") print("\n".join([x for x in e.disjointWith()])) printDebug("Test completed succesfully.\n", "green") - + + + + def test5(self): + """ + Pref label and pref language parameters + """ + + printDebug("\n=================\nTEST 5-1: pref_title=qname / pref_lang=en", "green") + for c in self.o2.all_classes: + print("URI: ", c.uri) + print("RDFTYPE: ", c.rdftype) + print("BEST LABEL: ", c.bestLabel()) + print("TITLE: ", c.title) + print("===") + + printDebug("\n=================\nTEST 5-2: pref_title=label / pref_lang=it", "green") + for c in self.o2.all_classes: + print("URI: ", c.uri) + print("RDFTYPE: ", c.rdftype) + print("BEST LABEL: ", c.bestLabel()) + print("TITLE: ", c.title) + print("===") + + printDebug("\n=================\nTEST 5-3: pref_title=label / pref_lang=es", "green") + for c in self.o2.all_classes: + print("URI: ", c.uri) + print("RDFTYPE: ", c.rdftype) + print("BEST LABEL: ", c.bestLabel()) + print("TITLE: ", c.title) + print("===") + + printDebug("Test completed succesfully.\n", "green") + print("Success.\n") + + + + + + if __name__ == "__main__": unittest.main() diff --git a/ontospy/tests/test_quick.py b/ontospy/tests/test_quick.py index dc8a34e8..efa7574c 100644 --- a/ontospy/tests/test_quick.py +++ b/ontospy/tests/test_quick.py @@ -36,7 +36,7 @@ class MyRDFEntity(ontospy.RdfEntity): def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False): - super(MyRDFEntity, self).__init__(uri, rdftype, namespaces, ext_model) + super().__init__(uri, rdftype, namespaces, ext_model) def __repr__(self): return "<MyRDFEntity *%s*>" % (self.uri) @@ -60,8 +60,8 @@ def test_quick1(self): dir_path = os.path.dirname(os.path.realpath(__file__)) DATA_FOLDER = dir_path + "/rdf/" - f = DATA_FOLDER + "pizza.ttl" - o = Ontospy(f, verbose=True, pref_entities_title="qname", pref_language="de") + f = DATA_FOLDER + "multilingual.ttl" + o = Ontospy(f, verbose=True, pref_title="label", pref_lang="it") for c in o.all_classes: print("URI: ", c.uri) From 9328a8e3fd578e616809dc3e17eaf59755f886d7 Mon Sep 17 00:00:00 2001 From: lambdamusic <michele.pasin@gmail.com> Date: Fri, 24 Sep 2021 17:11:33 +0100 Subject: [PATCH 07/16] update --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements.txt b/requirements.txt index 2e612844..fee53789 100755 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,5 @@ colorama>=0.3.7 # note: on windows click requires colorama too http://click.poco pyparsing>=2.1.10 keepalive>=0.5 # readline==6.2.4.1 # optional, for shell autocomplete +# django>=1.10.3 # optional: for gendocs +# pygments==2.1.3 # optional: for gendocs \ No newline at end of file From 6b233e1110bf08d5acba5b3488d272f35f2def28 Mon Sep 17 00:00:00 2001 From: lambdamusic <michele.pasin@gmail.com> Date: Fri, 24 Sep 2021 17:11:49 +0100 Subject: [PATCH 08/16] v 1.9.9 --- ontospy/VERSION.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ontospy/VERSION.py b/ontospy/VERSION.py index 2eebbab4..8e3f9d9d 100755 --- a/ontospy/VERSION.py +++ b/ontospy/VERSION.py @@ -8,7 +8,7 @@ # note: 1.8 major update with ontodocs split ################## -__version__ = "1.9.8.3" # Pypi latest: https://pypi.org/project/ontospy/ +__version__ = "1.9.9" # Pypi latest: https://pypi.org/project/ontospy/ __copyright__ = "CopyRight (C) 2015-2018 by Michele Pasin" __license__ = "GNU" From b7338c8f74610dffebac370c585b07b57d81cf13 Mon Sep 17 00:00:00 2001 From: lambdamusic <michele.pasin@gmail.com> Date: Fri, 24 Sep 2021 17:12:06 +0100 Subject: [PATCH 09/16] preflabel in simple html viz --- =1.10.3 | 10 +++ ontospy/cli.py | 18 ++++ ontospy/core/actions.py | 6 +- .../templates/html-single/html-single.html | 86 +++++++++---------- 4 files changed, 75 insertions(+), 45 deletions(-) create mode 100644 =1.10.3 diff --git a/=1.10.3 b/=1.10.3 new file mode 100644 index 00000000..085667ed --- /dev/null +++ b/=1.10.3 @@ -0,0 +1,10 @@ +Collecting django + Downloading Django-3.2.7-py3-none-any.whl (7.9 MB) +Collecting sqlparse>=0.2.2 + Downloading sqlparse-0.4.2-py3-none-any.whl (42 kB) +Collecting pytz + Using cached pytz-2021.1-py2.py3-none-any.whl (510 kB) +Collecting asgiref<4,>=3.3.2 + Downloading asgiref-3.4.1-py3-none-any.whl (25 kB) +Installing collected packages: sqlparse, pytz, asgiref, django +Successfully installed asgiref-3.4.1 django-3.2.7 pytz-2021.1 sqlparse-0.4.2 diff --git a/ontospy/cli.py b/ontospy/cli.py index b7758f3f..4e581cd6 100755 --- a/ontospy/cli.py +++ b/ontospy/cli.py @@ -197,6 +197,14 @@ def scan(ctx, sources=None, endpoint=False, raw=False, extra=False): help= 'THEME: select bootstrap style (only for the html-multi-page visualization). Default: simplex (random=use a random theme).' ) +@click.option( + '--preflabel', + help='PREF-LABEL: default value to use for entity titles (qname|label - default=qname).') +@click.option( + '--preflang', + help= + 'PREF-LANGUAGE: default language for multilingual strings (default=en).' +) @click.option( '--nobrowser', is_flag=True, @@ -218,6 +226,8 @@ def gendocs(ctx, type="", title="", theme="", + preflabel="", + preflang="", nobrowser=False, showthemes=False, showtypes=False): @@ -256,6 +266,12 @@ def gendocs(ctx, if theme and theme == "random": theme = random_theme() + if preflabel and preflabel not in ["label", "qname"]: + click.secho( + "WARNING: the valid preflabel options are either 'qname' or 'label' (= rdfs:label) only. Using defaults.", + fg="red") + preflabel = "qname" + if outputpath: if not (os.path.exists(outputpath)) or not (os.path.isdir(outputpath)): click.secho( @@ -283,6 +299,8 @@ def gendocs(ctx, title=title, viztype=type, theme=theme, + preflabel=preflabel, + preflang=preflang, verbose=verbose) if url and (not nobrowser): # open browser diff --git a/ontospy/core/actions.py b/ontospy/core/actions.py index 682f6787..81aa8ee3 100755 --- a/ontospy/core/actions.py +++ b/ontospy/core/actions.py @@ -636,6 +636,8 @@ def action_visualize(args, title="", viztype="", theme="", + preflabel="", + preflang="", verbose=False): """ export model into another format eg html, d3 etc... @@ -663,9 +665,9 @@ def action_visualize(args, # 2017-01-23: bypass pickled stuff as it has wrong counts etc.. # get ontospy graph printDebug("Loading graph...", dim=True) - g = Ontospy(ontouri, verbose=verbose) + g = Ontospy(ontouri, verbose=verbose, pref_title=preflabel, pref_lang=preflang) - # put in home folder by default: <ontouri>/<viztype>/files.. + # put viz in home folder by default: <ontouri>/<viztype>/files.. if not path: from os.path import expanduser home = expanduser("~") diff --git a/ontospy/ontodocs/media/templates/html-single/html-single.html b/ontospy/ontodocs/media/templates/html-single/html-single.html index d7d578c1..cc1c90c2 100755 --- a/ontospy/ontodocs/media/templates/html-single/html-single.html +++ b/ontospy/ontodocs/media/templates/html-single/html-single.html @@ -296,7 +296,7 @@ <h1><a name="a-z"> </a>A-Z of terms</h1> {% if classes %} <fieldset> <legend>Classes ({{classes|length}})</legend> - {% for each in classes %}<span><a href="#{{each.qname}}">{{each.qname}}</a></span> + {% for each in classes %}<span><a href="#{{each.qname}}">{{each.title}}</a></span> {% if not forloop.last %}|{% endif %} {% endfor %} </fieldset> @@ -305,7 +305,7 @@ <h1><a name="a-z"> </a>A-Z of terms</h1> {% if objproperties %} <fieldset> <legend>Object Properties ({{objproperties|length}})</legend> -  {% for each in objproperties %}<a href="#{{each.qname}}">{{each.qname}}</a> +  {% for each in objproperties %}<a href="#{{each.qname}}">{{each.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} </fieldset> @@ -313,7 +313,7 @@ <h1><a name="a-z"> </a>A-Z of terms</h1> {% if dataproperties %} <fieldset> <legend>Datatype Properties ({{dataproperties|length}})</legend> -  {% for each in dataproperties %}<a href="#{{each.qname}}">{{each.qname}}</a> +  {% for each in dataproperties %}<a href="#{{each.qname}}">{{each.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} </fieldset> {% endif %} @@ -321,7 +321,7 @@ <h1><a name="a-z"> </a>A-Z of terms</h1> {% if annotationproperties %} <fieldset> <legend>Annotation Properties ({{annotationproperties|length}})</legend> -  {% for each in annotationproperties %}<a href="#{{each.qname}}">{{each.qname}}</a> +  {% for each in annotationproperties %}<a href="#{{each.qname}}">{{each.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} </fieldset> @@ -330,7 +330,7 @@ <h1><a name="a-z"> </a>A-Z of terms</h1> {% if skosConcepts %} <fieldset> <legend>SKOS Concepts ({{skosConcepts|length}})</legend> -  {% for each in skosConcepts %}<a href="#{{each.qname}}">{{each.qname}}</a> +  {% for each in skosConcepts %}<a href="#{{each.qname}}">{{each.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} </fieldset> @@ -355,7 +355,7 @@ <h1 class="margintop" ><a name="classes"> </a>Classes</h1> - <h3 class="entity-section">Class: <a name="{{each.qname}}" href="#{{each.qname}}">{{each.qname}}</a> + <h3 class="entity-section">Class: <a name="{{each.qname}}" href="#{{each.qname}}">{{each.title}}</a> <small>  <a href="#a-z" class="backlink">back to top</a></small> </h3> <hr> @@ -365,15 +365,15 @@ <h3 class="entity-section">Class: <a name="{{each.qname}}" href="#{{each.qname}} <div class="tree"> <ul> {% if each.parents %} - {% for s in each.parents %}<li> <a href="#{{s.qname}}">{{s.qname}}</a> + {% for s in each.parents %}<li> <a href="#{{s.qname}}">{{s.title}}</a> <ul> - <li><a style="font-weight: bold;">{{each.qname}}</a> + <li><a style="font-weight: bold;">{{each.title}}</a> {% if each.children %} <ul> - {% for s in each.children %}<li><a href="#{{s.qname}}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.children %}<li><a href="#{{s.qname}}">{{s.title}}</a></li>{% endfor %} </ul> {% endif %} </li> @@ -388,11 +388,11 @@ <h3 class="entity-section">Class: <a name="{{each.qname}}" href="#{{each.qname}} <li href="#"><a>owl:Thing</a> <ul> - <li><a style="font-weight: bold;">{{each.qname}}</a> + <li><a style="font-weight: bold;">{{each.title}}</a> {% if each.children %} <ul> - {% for s in each.children %}<li><a href="#{{s.qname}}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.children %}<li><a href="#{{s.qname}}">{{s.title}}</a></li>{% endfor %} </ul> {% endif %} </li> @@ -409,7 +409,7 @@ <h3 class="entity-section">Class: <a name="{{each.qname}}" href="#{{each.qname}} {% if not each.children %} <p class="section-desc"> - <small>NOTE</small> {{each.qname}} is a leaf node.</p> + <small>NOTE</small> {{each.title}} is a leaf node.</p> {% endif %} <p class="section-desc"><b>Description</b> @@ -420,7 +420,7 @@ <h3 class="entity-section">Class: <a name="{{each.qname}}" href="#{{each.qname}} {% if each.ancestors %} <p class="section-desc"><b>Inherits from <small>({{ each.ancestors|length }})</small>:</b> <br /> - {% for s in each.ancestors %}<a href="#{{s.qname}}">{{s.qname}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} + {% for s in each.ancestors %}<a href="#{{s.qname}}">{{s.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} </p> {% else %} <p class="section-desc"><b>Inherits from:</b> <br />owl:Thing</p> @@ -431,14 +431,14 @@ <h3 class="entity-section">Class: <a name="{{each.qname}}" href="#{{each.qname}} {% if each.domain_of %} <p class="section-desc"><b>Property Domain of:</b> <br> - {% for s in each.domain_of %}<a href="#{{s.qname}}">{{s.qname}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} + {% for s in each.domain_of %}<a href="#{{s.qname}}">{{s.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} </p> {% endif %} {% if each.range_of %} <p class="section-desc"><b>Property Range of:</b> <br> - {% for s in each.range_of %}<a href="#{{s.qname}}">{{s.qname}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} + {% for s in each.range_of %}<a href="#{{s.qname}}">{{s.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} </p> {% endif %} @@ -468,7 +468,7 @@ <h1 class="margintop"><a name="objproperties"> </a>Object Properties</h1> <div class="entity-div"> - <h3 class="entity-section">Object Property: <a name="{{each.qname}}" href="#{{each.qname}}">{{each.qname}}</a> + <h3 class="entity-section">Object Property: <a name="{{each.qname}}" href="#{{each.qname}}">{{each.title}}</a> <small>  <a href="#a-z" class="backlink">back to top</a></small> </h3> <hr> @@ -486,7 +486,7 @@ <h3 class="entity-section">Object Property: <a name="{{each.qname}}" href="#{{ea {% if each.ancestors %} <p class="section-desc"><b>Inherits from <small>({{ each.ancestors|length }})</small>:</b> <br /> - {% for s in each.ancestors %}<a href="#{{s.qname}}">{{s.qname}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} + {% for s in each.ancestors %}<a href="#{{s.qname}}">{{s.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} </p> {% else %} @@ -497,24 +497,24 @@ <h3 class="entity-section">Object Property: <a name="{{each.qname}}" href="#{{ea {% if each.children %} <p class="section-desc"><b>Has sub-property <small>(direct)</small>:</b> <br /> - {% for s in each.children %}<a href="#{{s.qname}}">{{s.qname}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} + {% for s in each.children %}<a href="#{{s.qname}}">{{s.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} </p> {% endif %} {% if 0 and each.descendants and each.descendants|length > each.children|length %} - <p class="section-desc"><b>Has Sub Property <small>(all) </small>:</b> {% for s in each.descendants %}<a href="#{{s.qname}}">{{s.qname}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> + <p class="section-desc"><b>Has Sub Property <small>(all) </small>:</b> {% for s in each.descendants %}<a href="#{{s.qname}}">{{s.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> {% endif %} {% if each.domains %} <p class="section-desc"><b>Class Domain for:</b> <br> - {% for s in each.domains %}<a href="#{{s.qname|default:each.qname}}">{{s.qname|default:s}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> + {% for s in each.domains %}<a href="#{{s.qname|default:each.qname}}">{{s.title|default:s}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> {% endif %} {% if each.ranges %} <p class="section-desc"><b>Class Range for:</b> <br> - {% for s in each.ranges %}<a href="#{{s.qname|default:each.qname}}">{{s.qname|default:s}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> + {% for s in each.ranges %}<a href="#{{s.qname|default:each.qname}}">{{s.title|default:s}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> {% endif %} @@ -546,14 +546,14 @@ <h1 class="margintop"><a name="dataproperties"> </a>Datatype Properties</h1 <div class="entity-div"> - <h3 class="entity-section">Datatype Property: <a name="{{each.qname}}" href="#{{each.qname}}">{{each.qname}}</a> + <h3 class="entity-section">Datatype Property: <a name="{{each.qname}}" href="#{{each.qname}}">{{each.title}}</a> <small>  <a href="#a-z" class="backlink">back to top</a></small> </h3> <hr> {% if not each.children %} <p class="section-desc"> - <small>NOTE</small> {{each.qname}} is a leaf node.</p> + <small>NOTE</small> {{each.title}} is a leaf node.</p> {% endif %} <p class="section-desc"><b>Description</b> @@ -564,7 +564,7 @@ <h3 class="entity-section">Datatype Property: <a name="{{each.qname}}" href="#{{ {% if each.ancestors %} <p class="section-desc"><b>Inherits from <small>({{ each.ancestors|length }})</small>:</b> <br /> - {% for s in each.ancestors %}<a href="#{{s.qname}}">{{s.qname}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} + {% for s in each.ancestors %}<a href="#{{s.qname}}">{{s.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} </p> {% else %} @@ -575,24 +575,24 @@ <h3 class="entity-section">Datatype Property: <a name="{{each.qname}}" href="#{{ {% if each.children %} <p class="section-desc"><b>Has sub-property <small>(direct)</small>:</b> <br /> - {% for s in each.children %}<a href="#{{s.qname}}">{{s.qname}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} + {% for s in each.children %}<a href="#{{s.qname}}">{{s.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} </p> {% endif %} {% if 0 and each.descendants and each.descendants|length > each.children|length %} - <p class="section-desc"><b>Has Sub Property <small>(all) </small>:</b> {% for s in each.descendants %}<a href="#{{s.qname}}">{{s.qname}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> + <p class="section-desc"><b>Has Sub Property <small>(all) </small>:</b> {% for s in each.descendants %}<a href="#{{s.qname}}">{{s.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> {% endif %} {% if each.domains %} <p class="section-desc"><b>Class Domain for:</b> <br> - {% for s in each.domains %}<a href="#{{s.qname|default:each.qname}}">{{s.qname|default:s}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> + {% for s in each.domains %}<a href="#{{s.qname|default:each.qname}}">{{s.title|default:s}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> {% endif %} {% if each.ranges %} <p class="section-desc"><b>Class Range for:</b> <br> - {% for s in each.ranges %}<a href="#{{s.qname|default:each.qname}}">{{s.qname|default:s}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> + {% for s in each.ranges %}<a href="#{{s.qname|default:each.qname}}">{{s.title|default:s}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> {% endif %} @@ -624,14 +624,14 @@ <h1 class="margintop"><a name="annotationproperties"> </a>Annotation Proper <div class="entity-div"> - <h3 class="entity-section">Annotation Property: <a name="{{each.qname}}" href="#{{each.qname}}">{{each.qname}}</a> + <h3 class="entity-section">Annotation Property: <a name="{{each.qname}}" href="#{{each.qname}}">{{each.title}}</a> <small>  <a href="#a-z" class="backlink">back to top</a></small> </h3> <hr> {% if not each.children %} <p class="section-desc"> - <small>NOTE</small> {{each.qname}} is a leaf node.</p> + <small>NOTE</small> {{each.title}} is a leaf node.</p> {% endif %} <p class="section-desc"><b>Description</b> @@ -642,7 +642,7 @@ <h3 class="entity-section">Annotation Property: <a name="{{each.qname}}" href="# {% if each.ancestors %} <p class="section-desc"><b>Inherits from <small>({{ each.ancestors|length }})</small>:</b> <br /> - {% for s in each.ancestors %}<a href="#{{s.qname}}">{{s.qname}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} + {% for s in each.ancestors %}<a href="#{{s.qname}}">{{s.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} </p> {% else %} @@ -653,24 +653,24 @@ <h3 class="entity-section">Annotation Property: <a name="{{each.qname}}" href="# {% if each.children %} <p class="section-desc"><b>Has sub-property <small>(direct)</small>:</b> <br /> - {% for s in each.children %}<a href="#{{s.qname}}">{{s.qname}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} + {% for s in each.children %}<a href="#{{s.qname}}">{{s.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} </p> {% endif %} {% if 0 and each.descendants and each.descendants|length > each.children|length %} - <p class="section-desc"><b>Has Sub Property <small>(all) </small>:</b> {% for s in each.descendants %}<a href="#{{s.qname}}">{{s.qname}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> + <p class="section-desc"><b>Has Sub Property <small>(all) </small>:</b> {% for s in each.descendants %}<a href="#{{s.qname}}">{{s.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> {% endif %} {% if each.domains %} <p class="section-desc"><b>Class Domain for:</b> <br> - {% for s in each.domains %}<a href="#{{s.qname|default:each.qname}}">{{s.qname|default:s}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> + {% for s in each.domains %}<a href="#{{s.qname|default:each.qname}}">{{s.title|default:s}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> {% endif %} {% if each.ranges %} <p class="section-desc"><b>Class Range for:</b> <br> - {% for s in each.ranges %}<a href="#{{s.qname|default:each.qname}}">{{s.qname|default:s}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> + {% for s in each.ranges %}<a href="#{{s.qname|default:each.qname}}">{{s.title|default:s}}</a> {% if not forloop.last %}|{% endif %} {% endfor %}</p> {% endif %} @@ -701,7 +701,7 @@ <h1 class="margintop"><a name="skosconcepts"> </a>SKOS Concepts</h1> <div class="entity-div"> - <h3 class="entity-section">Concept: <a name="{{each.qname}}" href="#{{each.qname}}">{{each.qname}}</a> + <h3 class="entity-section">Concept: <a name="{{each.qname}}" href="#{{each.qname}}">{{each.title}}</a> <small>  <a href="#a-z" class="backlink">back to top</a></small> </h3> <hr> @@ -709,15 +709,15 @@ <h3 class="entity-section">Concept: <a name="{{each.qname}}" href="#{{each.qname <div class="tree"> <ul> {% if each.parents %} - {% for s in each.parents %}<li> <a href="#{{s.qname}}">{{s.qname}}</a> + {% for s in each.parents %}<li> <a href="#{{s.qname}}">{{s.title}}</a> <ul> - <li><a style="font-weight: bold;">{{each.qname}}</a> + <li><a style="font-weight: bold;">{{each.title}}</a> {% if each.children %} <ul> - {% for s in each.children %}<li><a href="#{{s.qname}}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.children %}<li><a href="#{{s.qname}}">{{s.title}}</a></li>{% endfor %} </ul> {% endif %} </li> @@ -732,11 +732,11 @@ <h3 class="entity-section">Concept: <a name="{{each.qname}}" href="#{{each.qname <li href="#"><a>skos:Concept</a> <ul> - <li><a style="font-weight: bold;">{{each.qname}}</a> + <li><a style="font-weight: bold;">{{each.title}}</a> {% if each.children %} <ul> - {% for s in each.children %}<li><a href="#{{s.qname}}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.children %}<li><a href="#{{s.qname}}">{{s.title}}</a></li>{% endfor %} </ul> {% endif %} </li> @@ -752,7 +752,7 @@ <h3 class="entity-section">Concept: <a name="{{each.qname}}" href="#{{each.qname {% if not each.children %} <p class="section-desc"> - <small>NOTE</small> {{each.qname}} is a leaf node.</p> + <small>NOTE</small> {{each.title}} is a leaf node.</p> {% endif %} <p class="section-desc"><b>Description</b> @@ -763,7 +763,7 @@ <h3 class="entity-section">Concept: <a name="{{each.qname}}" href="#{{each.qname {% if each.ancestors %} <p class="section-desc"><b>Has Broader concept <small>({{ each.ancestors|length }})</small>:</b> <br /> - {% for s in each.ancestors %}<a href="#{{s.qname}}">{{s.qname}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} + {% for s in each.ancestors %}<a href="#{{s.qname}}">{{s.title}}</a> {% if not forloop.last %}|{% endif %} {% endfor %} </p> {% endif %} From 7cd536c1a904eeb68c52a28c978a7a0c6cafe9a5 Mon Sep 17 00:00:00 2001 From: lambdamusic <michele.pasin@gmail.com> Date: Sun, 26 Sep 2021 18:24:08 +0100 Subject: [PATCH 10/16] cleanup --- =1.10.3 | 10 - .../media/templates/html-multi/viz_list.html | 286 ------------------ ontospy/ontodocs/viz/viz_html_multi.py | 7 - 3 files changed, 303 deletions(-) delete mode 100644 =1.10.3 delete mode 100755 ontospy/ontodocs/media/templates/html-multi/viz_list.html diff --git a/=1.10.3 b/=1.10.3 deleted file mode 100644 index 085667ed..00000000 --- a/=1.10.3 +++ /dev/null @@ -1,10 +0,0 @@ -Collecting django - Downloading Django-3.2.7-py3-none-any.whl (7.9 MB) -Collecting sqlparse>=0.2.2 - Downloading sqlparse-0.4.2-py3-none-any.whl (42 kB) -Collecting pytz - Using cached pytz-2021.1-py2.py3-none-any.whl (510 kB) -Collecting asgiref<4,>=3.3.2 - Downloading asgiref-3.4.1-py3-none-any.whl (25 kB) -Installing collected packages: sqlparse, pytz, asgiref, django -Successfully installed asgiref-3.4.1 django-3.2.7 pytz-2021.1 sqlparse-0.4.2 diff --git a/ontospy/ontodocs/media/templates/html-multi/viz_list.html b/ontospy/ontodocs/media/templates/html-multi/viz_list.html deleted file mode 100755 index c50e2df7..00000000 --- a/ontospy/ontodocs/media/templates/html-multi/viz_list.html +++ /dev/null @@ -1,286 +0,0 @@ -{% extends "base.html" %} - - -{% block navbar %} - - {% with thispage="visualizations" %} - {% include "navbar.html" %} - {% endwith %} - -{% endblock navbar %} - - - -{% block sidebar %} - - {% with thispage="visualizations" %} - {% include "sidebar.html" %} - {% endwith %} - -{% endblock sidebar %} - - - - {% block bodycontent %} - - - - - - - <div class="row"> - <a name="1"></a> - <h3 class="text-muted" style="margin-top: 50px;">Subject ontology - <span class="glyphicon glyphicon-info-sign jstooltip icon-xxs" title="Visualizations of the taxonomy of subject areas used to index content on nature.com"></span> - </h3> - <hr> - - - - <div class="col-md-4 img-container"> - - <div class=""> - - - <h5 class="text-warning">Main view</h5> - - - <a href="#" title="Main view: A visualization of the subject ontology that combines HTML trees with some interactive visualizations."> - - <img class="img-responsive" src="{{STATIC_URL}}img/app_manager/app_tree.png" alt="Icon" /> - - </a> - - - </div> - - </div> - - - - - - - - - <div class="col-md-4 img-container"> - - <div class=""> - - - <h5 class="text-warning">Collapsible tree</h5> - - - <a href="#" title="Collapsible tree: Classic tree visualization, obtained using D3 collapsible tree plugin: http://bl.ocks.org/mbostock/4339083"> - - <img class="img-responsive" src="{{STATIC_URL}}img/app_manager/app_d3tree.png" alt="Icon" /> - - </a> - - - </div> - - </div> - - - - - - - - - <div class="col-md-4 img-container"> - - <div class=""> - - - <h5 class="text-warning">Bar hierarchy</h5> - - - <a href="#" title="Bar hierarchy: One level at-a-time visualization, obtained using D3's plugin http://bl.ocks.org/mbostock/1283663. "> - - <img class="img-responsive" src="{{STATIC_URL}}img/app_manager/app_d3barHierarchy.png" alt="Icon" /> - - </a> - - - </div> - - </div> - - - - - - - - - <div class="col-md-4 img-container"> - - <div class=""> - - - <h5 class="text-warning">Icicle</h5> - - - <a href="#" title="Icicle: Tree map visualization, obrained via Jit plugin: https://philogb.github.io/jit/static/v20/Jit/Examples/Icicle/example1.html"> - - <img class="img-responsive" src="{{STATIC_URL}}img/app_manager/app_jitIcicle.png" alt="Icon" /> - - </a> - - - </div> - - </div> - - - - - - - - - <div class="col-md-4 img-container"> - - <div class=""> - - - <h5 class="text-warning">Partition table</h5> - - - <a href="#" title="Partition table: Another tree map visualization, with D3's plugin: http://mbostock.github.io/d3/talk/20111018/partition.html"> - - <img class="img-responsive" src="{{STATIC_URL}}img/app_manager/app_d3partitionTable.png" alt="Icon" /> - - </a> - - - </div> - - </div> - - - - - - - - - <div class="col-md-4 img-container"> - - <div class=""> - - - <h5 class="text-warning">Rotating Cluster</h5> - - - <a href="#" title="Rotating Cluster: Tree plotted on a circle, obtained with D3 plugin: http://mbostock.github.io/d3/talk/20111018/cluster.html"> - - <img class="img-responsive" src="{{STATIC_URL}}img/app_manager/app_d3cluster.png" alt="Icon" /> - - </a> - - - </div> - - </div> - - - - - - - - - <div class="col-md-4 img-container"> - - <div class=""> - - - <h5 class="text-warning">Sunburst Tree</h5> - - - <a href="#" title="Sunburst Tree: Tree map plotted on a wheel: http://bl.ocks.org/mbostock/4348373"> - - <img class="img-responsive" src="{{STATIC_URL}}img/app_manager/app_sunburstWheel.png" alt="Icon" /> - - </a> - - - </div> - - </div> - - - - - - - - - <div class="col-md-4 img-container"> - - <div class=""> - - - <h5 class="text-warning">Hierarchical pie chart </h5> - - - <a href="#" title="Hierarchical pie chart : Tree plotted on an interactive pie chart: http://bl.ocks.org/mbostock/4348373"> - - <img class="img-responsive" src="{{STATIC_URL}}img/app_manager/app_hiearchicalPieChart.png" alt="Icon" /> - - </a> - - - </div> - - </div> - - - - - - - - - <div class="col-md-4 img-container"> - - <div class=""> - - - <h5 class="text-warning">Bubble chart</h5> - - - <a href="#" title="Bubble chart: A bubble chart, obtained via D3's plugin http://bl.ocks.org/mbostock/4063269"> - - <img class="img-responsive" src="{{STATIC_URL}}img/app_manager/app_bubblechartsubjects.png" alt="Icon" /> - - </a> - - - </div> - - </div> - - - - - </div> - - - - - - - - - - <div class="container margin50"> - - - </div> <!-- /container --> - - - {% endblock bodycontent %} diff --git a/ontospy/ontodocs/viz/viz_html_multi.py b/ontospy/ontodocs/viz/viz_html_multi.py index c499f02d..c7b22f20 100755 --- a/ontospy/ontodocs/viz/viz_html_multi.py +++ b/ontospy/ontodocs/viz/viz_html_multi.py @@ -51,13 +51,6 @@ def _buildTemplates(self): FILE_NAME = "statistics.html" self._save2File(contents, FILE_NAME, self.output_path) - # VIZ LIST - if False: - contents = self._renderTemplate("html-multi/viz_list.html", extraContext={"theme": self.theme}) - FILE_NAME = "visualizations.html" - self._save2File(contents, FILE_NAME, self.output_path) - - browser_output_path = self.output_path # ENTITIES A-Z From 799771462dcc200704b02f96cbb20eccccbea917 Mon Sep 17 00:00:00 2001 From: lambdamusic <michele.pasin@gmail.com> Date: Sun, 26 Sep 2021 18:24:25 +0100 Subject: [PATCH 11/16] minor --- ontospy/VERSION.py | 2 +- ontospy/ontodocs/media/templates/html-single/html-single.html | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ontospy/VERSION.py b/ontospy/VERSION.py index 8e3f9d9d..705e23fc 100755 --- a/ontospy/VERSION.py +++ b/ontospy/VERSION.py @@ -10,7 +10,7 @@ __version__ = "1.9.9" # Pypi latest: https://pypi.org/project/ontospy/ -__copyright__ = "CopyRight (C) 2015-2018 by Michele Pasin" +__copyright__ = "CopyRight (C) 2015-2021 by Michele Pasin" __license__ = "GNU" __author__ = "Michele Pasin" __author_email__ = "michele dot pasin at gmail dot com" diff --git a/ontospy/ontodocs/media/templates/html-single/html-single.html b/ontospy/ontodocs/media/templates/html-single/html-single.html index cc1c90c2..6749f3c4 100755 --- a/ontospy/ontodocs/media/templates/html-single/html-single.html +++ b/ontospy/ontodocs/media/templates/html-single/html-single.html @@ -229,8 +229,7 @@ <body> - {# <h1>{{ontology.bestLabel}}</h1> #} - <h1 class="title">Graph: <a href="{{main_uri}}" target="_blank">{{docs_title}}</a></h1> + <h1 class="title">Ontology: <a href="{{main_uri}}" target="_blank">{{docs_title}}</a></h1> <h3>{{ontologies.0.bestDescription}}</h3> <p><small>Ontology documentation automatically generated by <a class="greylink" href="http://lambdamusic.github.io/Ontospy/">Ontospy</a> on {% now "jS F Y H:i" %}</small></p> From 3f1730b1fb1c21d9c0625587a3bb06aac514355c Mon Sep 17 00:00:00 2001 From: lambdamusic <michele.pasin@gmail.com> Date: Sun, 26 Sep 2021 19:49:29 +0100 Subject: [PATCH 12/16] linebreaks and title --- .../templates/html-multi/breadcrumbs.html | 8 +++--- .../html-multi/browser/browser_classinfo.html | 28 +++++++++---------- .../browser/browser_conceptinfo.html | 16 +++++------ .../browser/browser_entities_az.html | 8 +++--- .../html-multi/browser/browser_propinfo.html | 28 +++++++++---------- .../html-multi/browser/browser_shapeinfo.html | 18 ++++++------ .../media/templates/html-multi/navbar.html | 4 --- .../media/templates/html-multi/sidebar.html | 6 ++-- .../templates/html-multi/statistics.html | 4 +-- .../templates/html-single/html-single.html | 14 +++++----- ontospy/ontodocs/utils.py | 2 +- 11 files changed, 66 insertions(+), 70 deletions(-) diff --git a/ontospy/ontodocs/media/templates/html-multi/breadcrumbs.html b/ontospy/ontodocs/media/templates/html-multi/breadcrumbs.html index bfaa2cb8..43a4f0f1 100755 --- a/ontospy/ontodocs/media/templates/html-multi/breadcrumbs.html +++ b/ontospy/ontodocs/media/templates/html-multi/breadcrumbs.html @@ -124,7 +124,7 @@ <a href="entities-tree-classes.html">Classes</a> </li> <li class="active"> - {{each.uri}} + {{each.title}} </li> </ol> @@ -147,7 +147,7 @@ <a href="entities-tree-properties.html">Properties</a> </li> <li class="active"> - {{each.uri}} + {{each.title}} </li> </ol> @@ -170,7 +170,7 @@ <a href="entities-tree-concepts.html">Concepts</a> </li> <li class="active"> - {{each.uri}} + {{each.title}} </li> </ol> @@ -192,7 +192,7 @@ <a href="entities-tree-shapes.html">Shapes</a> </li> <li class="active"> - {{each.uri}} + {{each.title}} </li> </ol> diff --git a/ontospy/ontodocs/media/templates/html-multi/browser/browser_classinfo.html b/ontospy/ontodocs/media/templates/html-multi/browser/browser_classinfo.html index dcbb6f25..1371f3bd 100755 --- a/ontospy/ontodocs/media/templates/html-multi/browser/browser_classinfo.html +++ b/ontospy/ontodocs/media/templates/html-multi/browser/browser_classinfo.html @@ -42,7 +42,7 @@ <h1> {# Class: #} - {{each.qname}} + {{each.title}} {% if not each.children %} <small class="label label-info label-xs">leaf node</small> {% endif %} @@ -61,14 +61,14 @@ <h1> <li> - <a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.qname}}</a> + <a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.title}}</a> <ul> - <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.qname}}</a> + <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.title}}</a> {% if each.children %} <ul> - {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.title}}</a></li>{% endfor %} </ul> {% endif %} </li> @@ -83,11 +83,11 @@ <h1> <li><a href="entities-tree-classes.html">owl:Thing</a> <ul> - <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.qname}}</a> + <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.title}}</a> {% if each.children %} <ul> - {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.title}}</a></li>{% endfor %} </ul> {% endif %} </li> @@ -140,7 +140,7 @@ <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> - {{each.bestDescription|default:"--"}} + {{each.bestDescription|linebreaks|default:"--"}} </div> </div> </div></div> @@ -158,7 +158,7 @@ <h3 class="panel-title">Superclasses ({{each.ancestors|length}})</h3> <div class="panel-body"> {% if each.ancestors %} - {% for s in each.ancestors %}<li><a href="{{s.slug}}.html" title="{{s.uri}}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.ancestors %}<li><a href="{{s.slug}}.html" title="{{s.uri}}">{{s.title}}</a></li>{% endfor %} {% else %} <li>owl:Thing</li> {% endif %} @@ -179,7 +179,7 @@ <h3 class="panel-title">Shapes ({{each.all_shapes|length}})</h3> <div class="panel-body"> - {% for s in each.all_shapes%}<li><a href="{{s.slug}}.html" title="{{s.uri}}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.all_shapes%}<li><a href="{{s.slug}}.html" title="{{s.uri}}">{{s.title}}</a></li>{% endfor %} </div> @@ -197,7 +197,7 @@ <h3 class="panel-title">Usage</h3> </div> <div class="panel-body" style="overflow: auto;"> - <p>Instances of {{each.qname}} can have the following properties:</p> + <p>Instances of {{each.title}} can have the following properties:</p> </div> <table class="table table-bordered" style="overflow: auto;"> @@ -212,14 +212,14 @@ <h3 class="panel-title">Usage</h3> {% if v %} <tr class="table-inheritanceinfo"> - <th colspan="4" class="treeinfo"><span class="label label-default">From class <a title="{{k.qname}}" href="{{k.slug}}.html" class="fromclass_link">{{k.qname}}</a></span> + <th colspan="4" class="treeinfo"><span class="label label-default">From class <a title="{{k.qname}}" href="{{k.slug}}.html" class="fromclass_link">{{k.title}}</a></span> </th> </tr> {% for prop in v %} <tr> <td class="firsttd"> - <a class="propcolor" title="{{prop.qname}}" href="{{prop.slug}}.html">{{prop.qname}}</a> + <a class="propcolor" title="{{prop.qname}}" href="{{prop.slug}}.html">{{prop.title}}</a> </td> <td class="secondtd"> <i>{{prop.rdftype_qname}}<i> @@ -232,9 +232,9 @@ <h3 class="panel-title">Usage</h3> {% for range in prop.ranges %} {% if not range.ext_model %} - <a title="{{range.qname}}" href="{{range.slug}}.html" class="rdfclass">{{range.qname}}</a> + <a title="{{range.qname}}" href="{{range.slug}}.html" class="rdfclass">{{range.title}}</a> {% else %} - <i>{{range.qname}}</i> + <i>{{range.title}}</i> {% endif %} diff --git a/ontospy/ontodocs/media/templates/html-multi/browser/browser_conceptinfo.html b/ontospy/ontodocs/media/templates/html-multi/browser/browser_conceptinfo.html index 1c20834e..3ed34e13 100755 --- a/ontospy/ontodocs/media/templates/html-multi/browser/browser_conceptinfo.html +++ b/ontospy/ontodocs/media/templates/html-multi/browser/browser_conceptinfo.html @@ -40,7 +40,7 @@ <h1> {# Concept: #} - {{each.qname}} + {{each.title}} {% if not each.children %} <small class="label label-info label-xs ">leaf node</small> {% endif %} @@ -61,14 +61,14 @@ <h1> <li> - <a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.qname}}</a> + <a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.title}}</a> <ul> - <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.qname}}</a> + <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.title}}</a> {% if each.children %} <ul> - {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.title}}</a></li>{% endfor %} </ul> {% endif %} </li> @@ -83,11 +83,11 @@ <h1> <li><a href="entities-tree-properties.html">skos:Concept</a> <ul> - <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.qname}}</a> + <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.title}}</a> {% if each.children %} <ul> - {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.title}}</a></li>{% endfor %} </ul> {% endif %} </li> @@ -143,7 +143,7 @@ <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> - {{each.bestDescription|default:"--"}} + {{each.bestDescription|linebreaks|default:"--"}} </div> </div> </div></div> @@ -161,7 +161,7 @@ <h3 class="panel-title">Inherits from</h3> <div class="panel-body"> {% if each.ancestors %} - {% for s in each.ancestors %}<li><a href="{{s.slug}}.html">{{s.qname}}</a></li>{% endfor %} + {% for s in each.ancestors %}<li><a href="{{s.slug}}.html">{{s.title}}</a></li>{% endfor %} {% else %} <li>owl:Thing</li> {% endif %} diff --git a/ontospy/ontodocs/media/templates/html-multi/browser/browser_entities_az.html b/ontospy/ontodocs/media/templates/html-multi/browser/browser_entities_az.html index eb090df3..06fff1a0 100755 --- a/ontospy/ontodocs/media/templates/html-multi/browser/browser_entities_az.html +++ b/ontospy/ontodocs/media/templates/html-multi/browser/browser_entities_az.html @@ -57,7 +57,7 @@ <h3 class="panel-title">Classes ({{ ontospy_graph.all_classes|length }})</h3> <dl> {% for each in ontospy_graph.all_classes %} - <dt><a href="{{each.slug}}.html">{{each.qname}}</a></dt> + <dt><a href="{{each.slug}}.html">{{each.title}}</a></dt> <dd> {# {{ each.bestDescription|default:"[no definition]" }}#} </dd> @@ -84,7 +84,7 @@ <h3 class="panel-title">Concepts ({{ ontospy_graph.all_skos_concepts|length }})< <dl> {% for each in ontospy_graph.all_skos_concepts %} - <dt><a href="{{each.slug}}.html">{{each.qname}}</a></dt> + <dt><a href="{{each.slug}}.html">{{each.title}}</a></dt> <dd> {# {{ each.bestDescription|default:"[no definition]" }}#} </dd> @@ -120,7 +120,7 @@ <h3 class="panel-title">Properties ({{ ontospy_graph.all_properties|length }})</ <dl> {% for each in ontospy_graph.all_properties %} - <dt><a href="{{each.slug}}.html">{{each.qname}}</a></dt> + <dt><a href="{{each.slug}}.html">{{each.title}}</a></dt> <dd> {# {{ each.bestDescription|default:"[no definition]" }}#} </dd> @@ -149,7 +149,7 @@ <h3 class="panel-title">Shapes ({{ ontospy_graph.all_shapes|length }})</h3> <dl> {% for each in ontospy_graph.all_shapes %} - <dt><a href="{{each.slug}}.html">{{each.qname}}</a></dt> + <dt><a href="{{each.slug}}.html">{{each.title}}</a></dt> <dd> {# {{ each.bestDescription|default:"[no definition]" }}#} </dd> diff --git a/ontospy/ontodocs/media/templates/html-multi/browser/browser_propinfo.html b/ontospy/ontodocs/media/templates/html-multi/browser/browser_propinfo.html index 55db5c6d..c0e3ef16 100755 --- a/ontospy/ontodocs/media/templates/html-multi/browser/browser_propinfo.html +++ b/ontospy/ontodocs/media/templates/html-multi/browser/browser_propinfo.html @@ -36,7 +36,7 @@ <h1> {# Property: #} - {{each.qname}} + {{each.title}} {% if not each.children %} <small class="label label-info label-xs ">leaf node</small> {% endif %} @@ -56,14 +56,14 @@ <h1> <li> - <a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.qname}}</a> + <a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.title}}</a> <ul> - <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.qname}}</a> + <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.title}}</a> {% if each.children %} <ul> - {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.title}}</a></li>{% endfor %} </ul> {% endif %} </li> @@ -78,11 +78,11 @@ <h1> <li><a href="entities-tree-properties.html">rdf:Property</a> <ul> - <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.qname}}</a> + <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.title}}</a> {% if each.children %} <ul> - {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.title}}</a></li>{% endfor %} </ul> {% endif %} </li> @@ -136,7 +136,7 @@ <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> - {{each.bestDescription|default:"--"}} + {{each.bestDescription|linebreaks|default:"--"}} </div> </div> </div></div> @@ -154,7 +154,7 @@ <h3 class="panel-title">Inherits from</h3> <div class="panel-body"> {% if each.ancestors %} - {% for s in each.ancestors %}<li><a href="{{s.slug}}.html" title="{{s.uri}}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.ancestors %}<li><a href="{{s.slug}}.html" title="{{s.uri}}">{{s.title}}</a></li>{% endfor %} {% else %} <li>owl:Thing</li> {% endif %} @@ -176,7 +176,7 @@ <h3 class="panel-title">Sub Property</h3> </div> <div class="panel-body"> - {% for s in each.children %}<li><a href="{{s.slug}}.html" title="{{s.uri}}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.children %}<li><a href="{{s.slug}}.html" title="{{s.uri}}">{{s.title}}</a></li>{% endfor %} </div> @@ -202,11 +202,11 @@ <h3 class="panel-title">Usage</h3> {% if each.domains %} {% for s in each.domains %} {% if s.ext_model %} - <a href="{{s.uri}}" target="_blank" title="{{s.uri}}">{{s.qname|default:s}}</a> + <a href="{{s.uri}}" target="_blank" title="{{s.uri}}">{{s.title|default:s}}</a> {% elif s.is_Bnode %} <a>Blank node</a> (see implementation) {% else %} - <a href="{{s.slug}}.html" title="{{s.uri}}">{{s.qname|default:s}}</a> + <a href="{{s.slug}}.html" title="{{s.uri}}">{{s.title|default:s}}</a> {% endif %} {% if not forloop.last %}, {% endif %} {% endfor %} @@ -216,18 +216,18 @@ <h3 class="panel-title">Usage</h3> </td> <td> - {{each.qname}} + {{each.title}} </td> <td> {% if each.ranges %} {% for s in each.ranges %} {% if s.ext_model %} - <a href="{{s.uri}}" target="_blank" title="{{s.uri}}">{{s.qname|default:s}}</a> + <a href="{{s.uri}}" target="_blank" title="{{s.uri}}">{{s.title|default:s}}</a> {% elif s.is_Bnode %} <a>Blank node</a> (see implementation) {% else %} - <a href="{{s.slug}}.html" title="{{s.uri}}">{{s.qname|default:s}}</a> + <a href="{{s.slug}}.html" title="{{s.uri}}">{{s.title|default:s}}</a> {% endif %} {% if not forloop.last %}, {% endif %} {% endfor %} diff --git a/ontospy/ontodocs/media/templates/html-multi/browser/browser_shapeinfo.html b/ontospy/ontodocs/media/templates/html-multi/browser/browser_shapeinfo.html index 44d161a8..e800dc76 100644 --- a/ontospy/ontodocs/media/templates/html-multi/browser/browser_shapeinfo.html +++ b/ontospy/ontodocs/media/templates/html-multi/browser/browser_shapeinfo.html @@ -42,7 +42,7 @@ <h1> {# Class: #} - {{each.qname}} + {{each.title}} {% if not each.children %} <small class="label label-info label-xs">leaf node</small> {% endif %} @@ -61,14 +61,14 @@ <h1> <li> - <a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.qname}}</a> + <a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.title}}</a> <ul> - <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.qname}}</a> + <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.title}}</a> {% if each.children %} <ul> - {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.title}}</a></li>{% endfor %} </ul> {% endif %} </li> @@ -83,11 +83,11 @@ <h1> <li><a href="entities-tree-classes.html">sh:Shape</a> <ul> - <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.qname}}</a> + <li><a style="font-weight: bold;" title="'{{each.bestLabel}}'{% if each.bestDescription %} - {{each.bestDescription|truncatewords:20}}{% endif %}">{{each.title}}</a> {% if each.children %} <ul> - {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.qname}}</a></li>{% endfor %} + {% for s in each.children %}<li><a href="{{s.slug}}.html" title="'{{s.bestLabel}}'{% if s.bestDescription %} - {{s.bestDescription|truncatewords:20}}{% endif %}">{{s.title}}</a></li>{% endfor %} </ul> {% endif %} </li> @@ -140,7 +140,7 @@ <h3 class="panel-title">Description</h3> </div> <div class="panel-body"> - {{each.bestDescription|default:"--"}} + {{each.bestDescription|linebreaks|default:"--"}} </div> </div> </div></div> @@ -158,7 +158,7 @@ <h3 class="panel-title">Superclasses ({{each.ancestors|length}})</h3> <div class="panel-body"> {% if each.ancestors %} - {% for s in each.ancestors %}<li><a href="{{s.slug}}.html">{{s.qname}}</a></li>{% endfor %} + {% for s in each.ancestors %}<li><a href="{{s.slug}}.html">{{s.title}}</a></li>{% endfor %} {% else %} <li>owl:Thing</li> {% endif %} @@ -177,7 +177,7 @@ <h3 class="panel-title">Target Classes ({{each.targetClasses|length}})</h3> </div> <div class="panel-body"> - {% for s in each.targetClasses %}<li><a href="{{s.slug}}.html">{{s.qname}}</a></li>{% endfor %} + {% for s in each.targetClasses %}<li><a href="{{s.slug}}.html">{{s.title}}</a></li>{% endfor %} </div> diff --git a/ontospy/ontodocs/media/templates/html-multi/navbar.html b/ontospy/ontodocs/media/templates/html-multi/navbar.html index 350ea86a..8fab3fe4 100755 --- a/ontospy/ontodocs/media/templates/html-multi/navbar.html +++ b/ontospy/ontodocs/media/templates/html-multi/navbar.html @@ -18,10 +18,6 @@ <div id="navbar" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li {% ifequal thispage "home" %}class="active"{% endifequal %}><a href="index.html"><code style="font-size: 115%;">{{docs_title}}</code></a></li> - {# <li {% ifequal thispage "about" %}class="active"{% endifequal %} ><a href="#">About</a></li>#} - - {# <li><a href="#menu-toggle" id="menu-toggle">Toggle Menu</a></li>#} - <li {% ifequal thispage "entities-az" %}class="active"{% endifequal %} ><a href="entities-az.html">Entities A-Z</a></li> {% if ontospy_graph.all_classes%} diff --git a/ontospy/ontodocs/media/templates/html-multi/sidebar.html b/ontospy/ontodocs/media/templates/html-multi/sidebar.html index 75f1f479..c12611a9 100755 --- a/ontospy/ontodocs/media/templates/html-multi/sidebar.html +++ b/ontospy/ontodocs/media/templates/html-multi/sidebar.html @@ -14,7 +14,7 @@ {# simulated second level #} {% for each in ontospy_graph.all_classes%} - <li class="second-level" style="line-height: 20px;" id="sd_{{each.id}}"><a {% ifequal thispage each.qname %}class="active"{% endifequal %} href="{{each.slug}}.html">{{each.qname}}</a></li> + <li class="second-level" style="line-height: 20px;" id="sd_{{each.id}}"><a {% ifequal thispage each.qname %}class="active"{% endifequal %} href="{{each.slug}}.html">{{each.title}}</a></li> {% endfor %} {% endif %} @@ -24,7 +24,7 @@ {# simulated second level #} {% for each in ontospy_graph.all_properties %} - <li class="second-level" style="line-height: 20px;" id="sd_{{each.id}}"><a {% ifequal thispage each.qname %}class="active"{% endifequal %} href="{{each.slug}}.html">{{each.qname}}</a></li> + <li class="second-level" style="line-height: 20px;" id="sd_{{each.id}}"><a {% ifequal thispage each.qname %}class="active"{% endifequal %} href="{{each.slug}}.html">{{each.title}}</a></li> {% endfor %} {% endif %} @@ -35,7 +35,7 @@ {# simulated second level #} {% for each in ontospy_graph.all_skos_concepts %} - <li class="second-level" style="line-height: 20px;" id="sd_{{each.id}}"><a {% ifequal thispage each.qname %}class="active"{% endifequal %} href="{{each.slug}}.html">{{each.qname}}</a></li> + <li class="second-level" style="line-height: 20px;" id="sd_{{each.id}}"><a {% ifequal thispage each.qname %}class="active"{% endifequal %} href="{{each.slug}}.html">{{each.title}}</a></li> {% endfor %} {% endif %} diff --git a/ontospy/ontodocs/media/templates/html-multi/statistics.html b/ontospy/ontodocs/media/templates/html-multi/statistics.html index c37beb10..4db639d7 100755 --- a/ontospy/ontodocs/media/templates/html-multi/statistics.html +++ b/ontospy/ontodocs/media/templates/html-multi/statistics.html @@ -334,7 +334,7 @@ <h3 class="panel-title">Top Layer: SKOS</h3> label: 'Top Layer' // for legend }], labels: [ - {% for class in topclasses %}"{{class.bestLabel|safe}}"{% if not forloop.last %}, {% endif %} + {% for class in topclasses %}"{{class.title|safe}}"{% if not forloop.last %}, {% endif %} {% endfor %} ] }; @@ -375,7 +375,7 @@ <h3 class="panel-title">Top Layer: SKOS</h3> label: 'Top Layer' // for legend }], labels: [ - {% for concept in ontospy_graph.toplayer_skos %}"{{concept.bestLabel|safe}}"{% if not forloop.last %}, {% endif %} + {% for concept in ontospy_graph.toplayer_skos %}"{{concept.title|safe}}"{% if not forloop.last %}, {% endif %} {% endfor %} ] }; diff --git a/ontospy/ontodocs/media/templates/html-single/html-single.html b/ontospy/ontodocs/media/templates/html-single/html-single.html index 6749f3c4..3d3e00d2 100755 --- a/ontospy/ontodocs/media/templates/html-single/html-single.html +++ b/ontospy/ontodocs/media/templates/html-single/html-single.html @@ -229,8 +229,8 @@ <body> - <h1 class="title">Ontology: <a href="{{main_uri}}" target="_blank">{{docs_title}}</a></h1> - <h3>{{ontologies.0.bestDescription}}</h3> + <h1 class="title"> <a href="{{main_uri}}" target="_blank">{{docs_title}}</a></h1> + <h3>{{ontologies.0.bestDescription|linebreaks}}</h3> <p><small>Ontology documentation automatically generated by <a class="greylink" href="http://lambdamusic.github.io/Ontospy/">Ontospy</a> on {% now "jS F Y H:i" %}</small></p> @@ -413,7 +413,7 @@ <h3 class="entity-section">Class: <a name="{{each.qname}}" href="#{{each.qname}} <p class="section-desc"><b>Description</b> <br> - {{each.bestDescription}} + {{each.bestDescription|linebreaks}} </p> {% if each.ancestors %} @@ -479,7 +479,7 @@ <h3 class="entity-section">Object Property: <a name="{{each.qname}}" href="#{{ea <p class="section-desc"><b>Description</b> <br> - {{each.bestDescription}} + {{each.bestDescription|linebreaks}} </p> {% if each.ancestors %} @@ -557,7 +557,7 @@ <h3 class="entity-section">Datatype Property: <a name="{{each.qname}}" href="#{{ <p class="section-desc"><b>Description</b> <br> - {{each.bestDescription}} + {{each.bestDescription|linebreaks}} </p> {% if each.ancestors %} @@ -635,7 +635,7 @@ <h3 class="entity-section">Annotation Property: <a name="{{each.qname}}" href="# <p class="section-desc"><b>Description</b> <br> - {{each.bestDescription}} + {{each.bestDescription|linebreaks}} </p> {% if each.ancestors %} @@ -756,7 +756,7 @@ <h3 class="entity-section">Concept: <a name="{{each.qname}}" href="#{{each.qname <p class="section-desc"><b>Description</b> <br> - {{each.bestDescription}} + {{each.bestDescription|linebreaks}} </p> {% if each.ancestors %} diff --git a/ontospy/ontodocs/utils.py b/ontospy/ontodocs/utils.py index 49597d3f..88450f4c 100755 --- a/ontospy/ontodocs/utils.py +++ b/ontospy/ontodocs/utils.py @@ -206,7 +206,7 @@ def formatHTML_EntityTreeTable(treedict, element=0): else: stringa += """<tr> <td class="tc" colspan=4><a title=\"%s\" class=\"treelinks\" href=\"%s.html\">%s</a></td> - </tr>""" % (x.uri, x.slug, truncchar_inverse(x.qname, 50)) + </tr>""" % (x.uri, x.slug, truncchar_inverse(x.title, 50)) if treedict.get(x, None): stringa += """ <tr> From 843d121e40c192b984ffe89d074a6bc862ee983e Mon Sep 17 00:00:00 2001 From: lambdamusic <michele.pasin@gmail.com> Date: Sun, 26 Sep 2021 19:56:10 +0100 Subject: [PATCH 13/16] md updates --- .../templates/markdown/markdown_classinfo.md | 16 ++++++++-------- .../templates/markdown/markdown_conceptinfo.md | 10 +++++----- .../templates/markdown/markdown_ontoinfo.md | 12 ++++++------ .../templates/markdown/markdown_propinfo.md | 14 +++++++------- ontospy/ontodocs/viz/viz_markdown.py | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/ontospy/ontodocs/media/templates/markdown/markdown_classinfo.md b/ontospy/ontodocs/media/templates/markdown/markdown_classinfo.md index 2694dd6a..19f3b852 100755 --- a/ontospy/ontodocs/media/templates/markdown/markdown_classinfo.md +++ b/ontospy/ontodocs/media/templates/markdown/markdown_classinfo.md @@ -12,12 +12,12 @@ #### Tree {% if each.parents %} {% for s in each.parents %} -* [{{s.qname}}]({{s.slug}}.md) +* [{{s.title}}]({{s.slug}}.md) {% endfor %} * {{each.qname}} {% if each.children %} {% for s in each.children %} - * [{{s.qname}}]({{s.slug}}.md) + * [{{s.title}}]({{s.slug}}.md) {% endfor %} {% endif %} @@ -26,7 +26,7 @@ * {{each.qname}} {% if each.children %} {% for s in each.children %} - * [{{s.qname}}]({{s.slug}}.md) + * [{{s.title}}]({{s.slug}}.md) {% endfor %} {% endif %} @@ -40,13 +40,13 @@ {{each.uri}} #### Description -{{each.bestDescription|default:"--"}} +{{each.bestDescription|linebreaks|default:"--"}} {% if each.ancestors %} #### Inherits from ({{ each.ancestors|length }}) {% for s in each.ancestors %} -- [{{s.qname}}]({{s.slug}}.md) +- [{{s.title}}]({{s.slug}}.md) {% endfor %} {% else %} #### Inherits from: @@ -78,14 +78,14 @@ owl:Thing <tr style="background: lightcyan;text-align: left;"> <th colspan="3" height="10" class="treeinfo"><span style="font-size: 80%;"> - From <a title="{{k.qname}}" href="{{k.slug}}.md" class="rdfclass">{{k.qname}}</a></span> + From <a title="{{k.qname}}" href="{{k.slug}}.md" class="rdfclass">{{k.title}}</a></span> </th> </tr> {% for prop in v %} <tr> <td class="firsttd"> - <a class="propcolor" title="{{prop.qname}}" href="{{prop.slug}}.md">{{prop.qname}}</a> + <a class="propcolor" title="{{prop.qname}}" href="{{prop.slug}}.md">{{prop.title}}</a> </td> <td class="thirdtd"> <span>{{prop.bestDescription}}</span> @@ -94,7 +94,7 @@ owl:Thing {% if prop.ranges %} {% for range in prop.ranges %} - <a title="{{range.qname}}" href="{{range.slug}}.md" class="rdfclass">{{range.qname}}</a> + <a title="{{range.qname}}" href="{{range.slug}}.md" class="rdfclass">{{range.title}}</a> {% endfor %} {% else %} diff --git a/ontospy/ontodocs/media/templates/markdown/markdown_conceptinfo.md b/ontospy/ontodocs/media/templates/markdown/markdown_conceptinfo.md index 32296e85..67b7fb46 100755 --- a/ontospy/ontodocs/media/templates/markdown/markdown_conceptinfo.md +++ b/ontospy/ontodocs/media/templates/markdown/markdown_conceptinfo.md @@ -12,12 +12,12 @@ #### Tree {% if each.parents %} {% for s in each.parents %} -* [{{s.qname}}]({{s.slug}}.md) +* [{{s.title}}]({{s.slug}}.md) {% endfor %} * {{each.qname}} {% if each.children %} {% for s in each.children %} - * [{{s.qname}}]({{s.slug}}.md) + * [{{s.title}}]({{s.slug}}.md) {% endfor %} {% endif %} @@ -26,7 +26,7 @@ * {{each.qname}} {% if each.children %} {% for s in each.children %} - * [{{s.qname}}]({{s.slug}}.md) + * [{{s.title}}]({{s.slug}}.md) {% endfor %} {% endif %} @@ -40,13 +40,13 @@ {{each.uri}} #### Description -{{each.bestDescription|default:"--"}} +{{each.bestDescription|linebreaks|default:"--"}} {% if each.ancestors %} #### Inherits from ({{ each.ancestors|length }}) {% for s in each.ancestors %} -- [{{s.qname}}]({{s.slug}}.md) +- [{{s.title}}]({{s.slug}}.md) {% endfor %} {% else %} #### Inherits from: diff --git a/ontospy/ontodocs/media/templates/markdown/markdown_ontoinfo.md b/ontospy/ontodocs/media/templates/markdown/markdown_ontoinfo.md index db2bf125..744d9b6a 100755 --- a/ontospy/ontodocs/media/templates/markdown/markdown_ontoinfo.md +++ b/ontospy/ontodocs/media/templates/markdown/markdown_ontoinfo.md @@ -51,7 +51,7 @@ Prefix | URI | #### Classes ({{ontospy_graph.all_classes|length}}) {% for each in ontospy_graph.all_classes %} -- [{{each.qname}}]({{each.slug}}.md "Open") +- [{{each.title}}]({{each.slug}}.md "Open") {% endfor %} {% endif %} @@ -61,7 +61,7 @@ Prefix | URI | #### SKOS Concepts ({{ontospy_graph.all_skos_concepts|length}}) {% for each in ontograph.all_skos_concepts %} -- [{{each.qname}}]({{each.slug}}.md "Open") +- [{{each.title}}]({{each.slug}}.md "Open") {% endfor %} {% endif %} @@ -71,7 +71,7 @@ Prefix | URI | #### Object Properties ({{ontospy_graph.all_properties_object|length}}) {% for each in ontospy_graph.all_properties_object %} -- [{{each.qname}}]({{each.slug}}.md "Open") +- [{{each.title}}]({{each.slug}}.md "Open") {% endfor %} {% endif %} @@ -81,7 +81,7 @@ Prefix | URI | #### Datatype Properties ({{ontospy_graph.all_properties_datatype|length}}) {% for each in ontospy_graph.all_properties_datatype %} -- [{{each.qname}}]({{each.slug}}.md "Open") +- [{{each.title}}]({{each.slug}}.md "Open") {% endfor %} {% endif %} @@ -91,7 +91,7 @@ Prefix | URI | #### Annotation Properties ({{ontograph.all_properties_annotation|length}}) {% for each in ontospy_graph.all_properties_annotation %} -- [{{each.qname}}]({{each.slug}}.md "Open") +- [{{each.title}}]({{each.slug}}.md "Open") {% endfor %} {% endif %} @@ -102,7 +102,7 @@ Prefix | URI | #### Properties ({{ontospy_graph.all_properties|length}}) {% for each in ontospy_graph.all_properties %} -- [{{each.qname}}]({{each.slug}}.md "Open") +- [{{each.title}}]({{each.slug}}.md "Open") {% endfor %} {% endif %} diff --git a/ontospy/ontodocs/media/templates/markdown/markdown_propinfo.md b/ontospy/ontodocs/media/templates/markdown/markdown_propinfo.md index 5509575e..dd7f6f3b 100755 --- a/ontospy/ontodocs/media/templates/markdown/markdown_propinfo.md +++ b/ontospy/ontodocs/media/templates/markdown/markdown_propinfo.md @@ -12,12 +12,12 @@ #### Tree {% if each.parents %} {% for s in each.parents %} -* [{{s.qname}}]({{s.slug}}.md) +* [{{s.title}}]({{s.slug}}.md) {% endfor %} * {{each.qname}} {% if each.children %} {% for s in each.children %} - * [{{s.qname}}]({{s.slug}}.md) + * [{{s.title}}]({{s.slug}}.md) {% endfor %} {% endif %} @@ -26,7 +26,7 @@ * {{each.qname}} {% if each.children %} {% for s in each.children %} - * [{{s.qname}}]({{s.slug}}.md) + * [{{s.title}}]({{s.slug}}.md) {% endfor %} {% endif %} @@ -40,12 +40,12 @@ {{each.uri}} #### Description -{{each.bestDescription|default:"--"}} +{{each.bestDescription|linebreaks|default:"--"}} {% if each.ancestors %} #### Inherits from ({{ each.ancestors|length }}) {% for s in each.ancestors %} -- [{{s.qname}}]({{s.slug}}.md) +- [{{s.title}}]({{s.slug}}.md) {% endfor %} {% else %} #### Inherits from: @@ -56,8 +56,8 @@ owl:Thing #### Usage {% if each.domains %} {% for s in each.domains %} -[{{s.qname}}]({{s.slug}}.md){% if not forloop.last %} && {% endif %} -{% endfor %}{% else %}owl:Thing{% endif %}=> _{{each.qname}}_ => {% if each.ranges %}{% for s in each.ranges %}[{{s.qname}}]({{s.slug}}.md){% if not forloop.last %} && {% endif %}{% endfor %}{% else %}owl:Thing{% endif %} +[{{s.title}}]({{s.slug}}.md){% if not forloop.last %} && {% endif %} +{% endfor %}{% else %}owl:Thing{% endif %}=> _{{each.title}}_ => {% if each.ranges %}{% for s in each.ranges %}[{{s.title}}]({{s.slug}}.md){% if not forloop.last %} && {% endif %}{% endfor %}{% else %}owl:Thing{% endif %} #### Implementation ``` diff --git a/ontospy/ontodocs/viz/viz_markdown.py b/ontospy/ontodocs/viz/viz_markdown.py index f9575c18..2fecd9ed 100755 --- a/ontospy/ontodocs/viz/viz_markdown.py +++ b/ontospy/ontodocs/viz/viz_markdown.py @@ -16,7 +16,7 @@ class MarkdownViz(VizFactory): """ - A simple markdown rendering in multi pages + A simple markdown rendering, using multiple pages """ From aefdd6429a48a71de46a9cd54265be62908755ab Mon Sep 17 00:00:00 2001 From: lambdamusic <michele.pasin@gmail.com> Date: Sun, 26 Sep 2021 20:09:39 +0100 Subject: [PATCH 14/16] fixes --- .../media/templates/markdown/markdown_classinfo.md | 8 ++++---- .../media/templates/markdown/markdown_conceptinfo.md | 6 +++--- .../media/templates/markdown/markdown_propinfo.md | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ontospy/ontodocs/media/templates/markdown/markdown_classinfo.md b/ontospy/ontodocs/media/templates/markdown/markdown_classinfo.md index 19f3b852..3eebe264 100755 --- a/ontospy/ontodocs/media/templates/markdown/markdown_classinfo.md +++ b/ontospy/ontodocs/media/templates/markdown/markdown_classinfo.md @@ -6,7 +6,7 @@ {% with main_entity as each %} -## Class {{each.qname}} +## Class {{each.title}} #### Tree @@ -14,7 +14,7 @@ {% for s in each.parents %} * [{{s.title}}]({{s.slug}}.md) {% endfor %} - * {{each.qname}} + * {{each.title}} {% if each.children %} {% for s in each.children %} * [{{s.title}}]({{s.slug}}.md) @@ -23,7 +23,7 @@ {% else %} * owl:Thing - * {{each.qname}} + * {{each.title}} {% if each.children %} {% for s in each.children %} * [{{s.title}}]({{s.slug}}.md) @@ -63,7 +63,7 @@ owl:Thing {% if each.domain_of_inferred %} -#### Instances of {{each.qname}} can have the following properties: +#### Instances of {{each.title}} can have the following properties: <table border="1" cellspacing="3" cellpadding="5" class="classproperties table-hover "> diff --git a/ontospy/ontodocs/media/templates/markdown/markdown_conceptinfo.md b/ontospy/ontodocs/media/templates/markdown/markdown_conceptinfo.md index 67b7fb46..de589326 100755 --- a/ontospy/ontodocs/media/templates/markdown/markdown_conceptinfo.md +++ b/ontospy/ontodocs/media/templates/markdown/markdown_conceptinfo.md @@ -6,7 +6,7 @@ {% with main_entity as each %} -# SKOS Concept {{each.qname}} +# SKOS Concept {{each.title}} #### Tree @@ -14,7 +14,7 @@ {% for s in each.parents %} * [{{s.title}}]({{s.slug}}.md) {% endfor %} - * {{each.qname}} + * {{each.title}} {% if each.children %} {% for s in each.children %} * [{{s.title}}]({{s.slug}}.md) @@ -23,7 +23,7 @@ {% else %} * skos:Concept - * {{each.qname}} + * {{each.title}} {% if each.children %} {% for s in each.children %} * [{{s.title}}]({{s.slug}}.md) diff --git a/ontospy/ontodocs/media/templates/markdown/markdown_propinfo.md b/ontospy/ontodocs/media/templates/markdown/markdown_propinfo.md index dd7f6f3b..7167d70c 100755 --- a/ontospy/ontodocs/media/templates/markdown/markdown_propinfo.md +++ b/ontospy/ontodocs/media/templates/markdown/markdown_propinfo.md @@ -6,7 +6,7 @@ {% with main_entity as each %} -## Property {{each.qname}} +## Property {{each.title}} #### Tree @@ -14,7 +14,7 @@ {% for s in each.parents %} * [{{s.title}}]({{s.slug}}.md) {% endfor %} - * {{each.qname}} + * {{each.title}} {% if each.children %} {% for s in each.children %} * [{{s.title}}]({{s.slug}}.md) @@ -23,7 +23,7 @@ {% else %} * rdf:Property - * {{each.qname}} + * {{each.title}} {% if each.children %} {% for s in each.children %} * [{{s.title}}]({{s.slug}}.md) From 0ba75a12cf2d4e225c3ee36f30a853462f34e014 Mon Sep 17 00:00:00 2001 From: lambdamusic <michele.pasin@gmail.com> Date: Sun, 26 Sep 2021 23:26:33 +0100 Subject: [PATCH 15/16] title and inheritance --- ontospy/ontodocs/CONFIG.py | 2 +- ontospy/ontodocs/builder.py | 14 +- ...arHierarchy.html => d3_bar_hierarchy.html} | 49 +- ..._bubblechart.html => d3_bubble_chart.html} | 119 ++-- .../{d3tree.html => d3_dendogram copy.html} | 15 +- .../media/templates/d3/d3_dendogram.html | 554 ++++++++++++++++++ ...khierarchy.html => d3_pack_hierarchy.html} | 147 ++--- ...tionTable.html => d3_partition_table.html} | 56 +- ...gCluster.html => d3_rotating_cluster.html} | 41 +- .../media/templates/d3/d3_treePie.html | 56 +- .../ontodocs/media/templates/d3/d3base.html | 148 +++++ .../media/templates/d3/d3tree_hiddendivs.html | 92 ++- .../media/templates/d3/js_slidereveal.html | 27 + ontospy/ontodocs/utils.py | 6 +- ...barHierarchy.py => viz_d3bar_hierarchy.py} | 2 +- ...d3bubbleChart.py => viz_d3bubble_chart.py} | 2 +- .../viz/{viz_d3tree.py => viz_d3dendogram.py} | 2 +- ...ckHierarchy.py => viz_d3pack_hierarchy.py} | 2 +- ...itionTable.py => viz_d3partition_table.py} | 2 +- ontospy/ontodocs/viz/viz_d3rotatingCluster.py | 126 ---- .../ontodocs/viz/viz_d3rotating_cluster.py | 77 +++ ontospy/ontodocs/viz/viz_d3treePie.py | 162 ----- ontospy/ontodocs/viz/viz_d3tree_pie.py | 84 +++ 23 files changed, 1214 insertions(+), 571 deletions(-) rename ontospy/ontodocs/media/templates/d3/{d3_barHierarchy.html => d3_bar_hierarchy.html} (91%) rename ontospy/ontodocs/media/templates/d3/{d3_bubblechart.html => d3_bubble_chart.html} (68%) rename ontospy/ontodocs/media/templates/d3/{d3tree.html => d3_dendogram copy.html} (95%) create mode 100755 ontospy/ontodocs/media/templates/d3/d3_dendogram.html rename ontospy/ontodocs/media/templates/d3/{d3_packhierarchy.html => d3_pack_hierarchy.html} (70%) rename ontospy/ontodocs/media/templates/d3/{d3_partitionTable.html => d3_partition_table.html} (85%) rename ontospy/ontodocs/media/templates/d3/{d3_rotatingCluster.html => d3_rotating_cluster.html} (86%) create mode 100644 ontospy/ontodocs/media/templates/d3/d3base.html create mode 100644 ontospy/ontodocs/media/templates/d3/js_slidereveal.html rename ontospy/ontodocs/viz/{viz_d3barHierarchy.py => viz_d3bar_hierarchy.py} (95%) rename ontospy/ontodocs/viz/{viz_d3bubbleChart.py => viz_d3bubble_chart.py} (95%) rename ontospy/ontodocs/viz/{viz_d3tree.py => viz_d3dendogram.py} (98%) rename ontospy/ontodocs/viz/{viz_d3packHierarchy.py => viz_d3pack_hierarchy.py} (96%) rename ontospy/ontodocs/viz/{viz_d3partitionTable.py => viz_d3partition_table.py} (95%) delete mode 100755 ontospy/ontodocs/viz/viz_d3rotatingCluster.py create mode 100755 ontospy/ontodocs/viz/viz_d3rotating_cluster.py delete mode 100755 ontospy/ontodocs/viz/viz_d3treePie.py create mode 100755 ontospy/ontodocs/viz/viz_d3tree_pie.py diff --git a/ontospy/ontodocs/CONFIG.py b/ontospy/ontodocs/CONFIG.py index 6ad20af6..3c426522 100755 --- a/ontospy/ontodocs/CONFIG.py +++ b/ontospy/ontodocs/CONFIG.py @@ -18,7 +18,7 @@ "Description": "@todo", }, { - "ID": "d3-tree", + "ID": "d3-dendogram", "Title": "D3 Dendogram", "Description": "@todo", }, diff --git a/ontospy/ontodocs/builder.py b/ontospy/ontodocs/builder.py index ac6a0fe0..84744f6d 100755 --- a/ontospy/ontodocs/builder.py +++ b/ontospy/ontodocs/builder.py @@ -177,28 +177,28 @@ def build_visualization(ontouri, g, viz_index, path=None, title="", theme=""): from .viz.viz_markdown import MarkdownViz v = MarkdownViz(g, title) - elif this_viz['ID'] == "d3-tree": - from .viz.viz_d3tree import Dataviz + elif this_viz['ID'] == "d3-dendogram": + from .viz.viz_d3dendogram import Dataviz v = Dataviz(g, title) elif this_viz['ID'] == "d3-bubble-chart": - from .viz.viz_d3bubbleChart import Dataviz + from .viz.viz_d3bubble_chart import Dataviz v = Dataviz(g, title) elif this_viz['ID'] == "d3-pack-hierarchy": - from .viz.viz_d3packHierarchy import Dataviz + from .viz.viz_d3pack_hierarchy import Dataviz v = Dataviz(g, title) elif this_viz['ID'] == "d3-bar-hierarchy": - from .viz.viz_d3barHierarchy import Dataviz + from .viz.viz_d3bar_hierarchy import Dataviz v = Dataviz(g, title) elif this_viz['ID'] == "d3-partition-table": - from .viz.viz_d3partitionTable import Dataviz + from .viz.viz_d3partition_table import Dataviz v = Dataviz(g, title) elif this_viz['ID'] == "d3-rotating-cluster": - from .viz.viz_d3rotatingCluster import Dataviz + from .viz.viz_d3rotating_cluster import Dataviz v = Dataviz(g, title) elif this_viz['ID'] == "sigma-force-directed": diff --git a/ontospy/ontodocs/media/templates/d3/d3_barHierarchy.html b/ontospy/ontodocs/media/templates/d3/d3_bar_hierarchy.html similarity index 91% rename from ontospy/ontodocs/media/templates/d3/d3_barHierarchy.html rename to ontospy/ontodocs/media/templates/d3/d3_bar_hierarchy.html index afb5aaaa..796f2f8d 100755 --- a/ontospy/ontodocs/media/templates/d3/d3_barHierarchy.html +++ b/ontospy/ontodocs/media/templates/d3/d3_bar_hierarchy.html @@ -1,12 +1,9 @@ -<!DOCTYPE html> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> +{% extends "d3base.html" %} -<title>{{ontology.uri}} - +{% block custom_css %} +{% endblock custom_css %} - - - {# VISIBLE PAGE HTML #} - {# note: showpanel arg is the ID of the div that is showing.. #} +{% block main_content %} -

Ontology: {{main_uri}}

-

{{ontology.bestDescription}}

-

Ontology documentation automatically generated by Ontospy on {% now "jS F Y H:i" %}

- -
{% if TOTAL_CLASSES %} @@ -93,13 +83,20 @@

Classes ({{TOTAL_CLASSES}})

-
- Documentation automatically generated by Ontospy on {% now "jS F Y H:i" %} +{% endblock main_content %} + + + + + +{% block the_javascript %} + + {# JAVASCRIPT #} @@ -109,6 +106,17 @@

Classes ({{TOTAL_CLASSES}})

+ + + + + +{% include 'js_slidereveal.html' %} + + + + + + + + + +{% include 'js_slidereveal.html' %} + + + + + #} - - {# JAVASCRIPT #} @@ -353,7 +347,6 @@

Concepts ({{TOTAL_CONCEPTS}})

.append("svg:g") .attr("transform", "translate(" + m[3] + "," + m[0] + ")"); - // d3.json(JSON_FILE, function(json) { root_classes = json1; root_classes.x0 = h / 2; root_classes.y0 = 0; @@ -363,6 +356,7 @@

Concepts ({{TOTAL_CONCEPTS}})

// Initialize the display to show no nodes: root_classes.children.forEach(toggleAll); + {% endif %} @@ -408,7 +402,6 @@

Concepts ({{TOTAL_CONCEPTS}})

.append("svg:g") .attr("transform", "translate(" + m[3] + "," + m[0] + ")"); - // d3.json(JSON_FILE, function(json) { root_properties = json2; root_properties.x0 = h / 2; root_properties.y0 = 0; diff --git a/ontospy/ontodocs/media/templates/d3/d3_dendogram.html b/ontospy/ontodocs/media/templates/d3/d3_dendogram.html new file mode 100755 index 00000000..19f0c109 --- /dev/null +++ b/ontospy/ontodocs/media/templates/d3/d3_dendogram.html @@ -0,0 +1,554 @@ +{% extends "d3base.html" %} + + + + +{% block custom_css %} + + + + + +{% endblock custom_css %} + + + + + + + +{% block main_content %} + + + + {% if TOTAL_CLASSES %} +
+

Classes ({{TOTAL_CLASSES}})

+
+ + +
+ + +
+ {% endif %} + + {% if TOTAL_PROPERTIES %} +
+

Properties ({{TOTAL_PROPERTIES}})

+
+ + +
+ + +
+ {% endif %} + + + {% if TOTAL_CONCEPTS %} + +
+

Concepts ({{TOTAL_CONCEPTS}})

+
+ + +
+ + +
+ + {% endif %} + + + + +{% endblock main_content %} + + + + + + + + + + +{% block the_javascript %} + + + + + + {# JAVASCRIPT #} + + {% if save_on_github %} + + + + + + + + {% else %} + + + + + + + + + {% endif %} + + + + + {% include 'js_slidereveal.html' %} + + + + + +{# JAVASCRIPT FOR D3 TREE #} + + + + + + + + +{% endblock the_javascript %} + + + + diff --git a/ontospy/ontodocs/media/templates/d3/d3_packhierarchy.html b/ontospy/ontodocs/media/templates/d3/d3_pack_hierarchy.html similarity index 70% rename from ontospy/ontodocs/media/templates/d3/d3_packhierarchy.html rename to ontospy/ontodocs/media/templates/d3/d3_pack_hierarchy.html index f032f5a7..9c02e959 100755 --- a/ontospy/ontodocs/media/templates/d3/d3_packhierarchy.html +++ b/ontospy/ontodocs/media/templates/d3/d3_pack_hierarchy.html @@ -1,15 +1,9 @@ +{% extends "d3base.html" %} - - - - -{{ontology.uri}} - - - +{% block custom_css %} - .text-muted { - color: grey; - } - hr { - margin-top: 20px; - margin-bottom: 20px; - } +{% endblock custom_css %} - - - - {# VISIBLE PAGE HTML #} - {# note: showpanel arg is the ID of the div that is showing.. #} -

Ontology: {{main_uri}}

-

{{ontology.bestDescription}}

+{% block main_content %} -

Ontology documentation automatically generated by Ontospy on {% now "jS F Y H:i" %}

-
{% if TOTAL_CLASSES %} @@ -181,13 +117,16 @@

Classes ({{TOTAL_CLASSES}})

-
- Documentation automatically generated by Ontospy on {% now "jS F Y H:i" %} +{% endblock main_content %} +{% block the_javascript %} + + + @@ -196,6 +135,12 @@

Classes ({{TOTAL_CLASSES}})

+ + {% include 'js_slidereveal.html' %} + + + + - - + +{% endblock the_javascript %} + + diff --git a/ontospy/ontodocs/media/templates/d3/d3_partitionTable.html b/ontospy/ontodocs/media/templates/d3/d3_partition_table.html similarity index 85% rename from ontospy/ontodocs/media/templates/d3/d3_partitionTable.html rename to ontospy/ontodocs/media/templates/d3/d3_partition_table.html index db74f139..0f76b449 100755 --- a/ontospy/ontodocs/media/templates/d3/d3_partitionTable.html +++ b/ontospy/ontodocs/media/templates/d3/d3_partition_table.html @@ -1,12 +1,10 @@ - - - +{% extends "d3base.html" %} -{{ontology.uri}} - +{% block custom_css %} + - +{% endblock custom_css %} + + - - {# VISIBLE PAGE HTML #} - {# note: showpanel arg is the ID of the div that is showing.. #} -

Ontology: {{main_uri}}

-

{{ontology.bestDescription}}

-

Ontology documentation automatically generated by Ontospy on {% now "jS F Y H:i" %}

-
+{% block main_content %} + {% if TOTAL_CLASSES %} @@ -159,8 +153,10 @@

Classes ({{TOTAL_CLASSES}})

-
- Documentation automatically generated by Ontospy on {% now "jS F Y H:i" %} + + {% endblock main_content %} + + @@ -168,6 +164,12 @@

Classes ({{TOTAL_CLASSES}})

+{% block the_javascript %} + + + + + {# JAVASCRIPT #} @@ -175,6 +177,17 @@

Classes ({{TOTAL_CLASSES}})

+ + + + + +{% include 'js_slidereveal.html' %} + + + + + + + + + +{% include 'js_slidereveal.html' %} + + + + + + + + +{% include 'js_slidereveal.html' %} + + + + + + + + diff --git a/ontospy/ontodocs/utils.py b/ontospy/ontodocs/utils.py index 88450f4c..17f0e718 100755 --- a/ontospy/ontodocs/utils.py +++ b/ontospy/ontodocs/utils.py @@ -36,7 +36,8 @@ def build_D3treeStandard(old, MAX_DEPTH, level=1, toplayer=None): d = {} # print "*" * level, x.label d['qname'] = x.qname - d['name'] = x.bestLabel(quotes=False).replace("_", " ") + # d['name'] = x.bestLabel(quotes=False).replace("_", " ") + d['name'] = x.title d['objid'] = x.id if x.children() and level < MAX_DEPTH: d['size'] = len(x.children()) + 5 # fake size @@ -93,7 +94,8 @@ def build_D3bubbleChart(old, MAX_DEPTH, level=1, toplayer=None): d = {} # print "*" * level, x.label d['qname'] = x.qname - d['name'] = x.bestLabel(quotes=False).replace("_", " ") + # d['name'] = x.bestLabel(quotes=False).replace("_", " ") + d['name'] = x.title d['objid'] = x.id if x.children() and level < MAX_DEPTH: duplicate_row = {} diff --git a/ontospy/ontodocs/viz/viz_d3barHierarchy.py b/ontospy/ontodocs/viz/viz_d3bar_hierarchy.py similarity index 95% rename from ontospy/ontodocs/viz/viz_d3barHierarchy.py rename to ontospy/ontodocs/viz/viz_d3bar_hierarchy.py index dd2210c2..2e9ad955 100755 --- a/ontospy/ontodocs/viz/viz_d3barHierarchy.py +++ b/ontospy/ontodocs/viz/viz_d3bar_hierarchy.py @@ -48,7 +48,7 @@ def _buildTemplates(self): # Ontology - MAIN PAGE contents = self._renderTemplate( - "d3/d3_barHierarchy.html", extraContext=extra_context) + "d3/d3_bar_hierarchy.html", extraContext=extra_context) FILE_NAME = "index.html" main_url = self._save2File(contents, FILE_NAME, self.output_path) diff --git a/ontospy/ontodocs/viz/viz_d3bubbleChart.py b/ontospy/ontodocs/viz/viz_d3bubble_chart.py similarity index 95% rename from ontospy/ontodocs/viz/viz_d3bubbleChart.py rename to ontospy/ontodocs/viz/viz_d3bubble_chart.py index 4283ba22..80eb1ef2 100755 --- a/ontospy/ontodocs/viz/viz_d3bubbleChart.py +++ b/ontospy/ontodocs/viz/viz_d3bubble_chart.py @@ -48,7 +48,7 @@ def _buildTemplates(self): # Ontology - MAIN PAGE contents = self._renderTemplate( - "d3/d3_bubblechart.html", extraContext=extra_context) + "d3/d3_bubble_chart.html", extraContext=extra_context) FILE_NAME = "index.html" main_url = self._save2File(contents, FILE_NAME, self.output_path) diff --git a/ontospy/ontodocs/viz/viz_d3tree.py b/ontospy/ontodocs/viz/viz_d3dendogram.py similarity index 98% rename from ontospy/ontodocs/viz/viz_d3tree.py rename to ontospy/ontodocs/viz/viz_d3dendogram.py index 25021bbf..d92b7b6a 100755 --- a/ontospy/ontodocs/viz/viz_d3tree.py +++ b/ontospy/ontodocs/viz/viz_d3dendogram.py @@ -96,7 +96,7 @@ def _buildTemplates(self): # Ontology - MAIN PAGE contents = self._renderTemplate( - "d3/d3tree.html", extraContext=extra_context) + "d3/d3_dendogram.html", extraContext=extra_context) FILE_NAME = "index.html" main_url = self._save2File(contents, FILE_NAME, self.output_path) diff --git a/ontospy/ontodocs/viz/viz_d3packHierarchy.py b/ontospy/ontodocs/viz/viz_d3pack_hierarchy.py similarity index 96% rename from ontospy/ontodocs/viz/viz_d3packHierarchy.py rename to ontospy/ontodocs/viz/viz_d3pack_hierarchy.py index 59dca2aa..7190757a 100644 --- a/ontospy/ontodocs/viz/viz_d3packHierarchy.py +++ b/ontospy/ontodocs/viz/viz_d3pack_hierarchy.py @@ -54,7 +54,7 @@ def _buildTemplates(self): # Ontology - MAIN PAGE contents = self._renderTemplate( - "d3/d3_packHierarchy.html", extraContext=extra_context) + "d3/d3_pack_hierarchy.html", extraContext=extra_context) FILE_NAME = "index.html" main_url = self._save2File(contents, FILE_NAME, self.output_path) diff --git a/ontospy/ontodocs/viz/viz_d3partitionTable.py b/ontospy/ontodocs/viz/viz_d3partition_table.py similarity index 95% rename from ontospy/ontodocs/viz/viz_d3partitionTable.py rename to ontospy/ontodocs/viz/viz_d3partition_table.py index 51b216b4..5fce0fe4 100755 --- a/ontospy/ontodocs/viz/viz_d3partitionTable.py +++ b/ontospy/ontodocs/viz/viz_d3partition_table.py @@ -48,7 +48,7 @@ def _buildTemplates(self): # Ontology - MAIN PAGE contents = self._renderTemplate( - "d3/d3_partitionTable.html", extraContext=extra_context) + "d3/d3_partition_table.html", extraContext=extra_context) FILE_NAME = "index.html" main_url = self._save2File(contents, FILE_NAME, self.output_path) diff --git a/ontospy/ontodocs/viz/viz_d3rotatingCluster.py b/ontospy/ontodocs/viz/viz_d3rotatingCluster.py deleted file mode 100755 index 3692e4e3..00000000 --- a/ontospy/ontodocs/viz/viz_d3rotatingCluster.py +++ /dev/null @@ -1,126 +0,0 @@ -# !/usr/bin/env python -# -*- coding: UTF-8 -*- - -import os, sys -import json - -from ..utils import * -from ..builder import * # loads and sets up Django -from ..viz_factory import VizFactory - -# =========== -# D3 ROTATING CLUSTER -# =========== - - -class Dataviz(VizFactory): - """ - D3 rotating cluster - - """ - - def __init__(self, ontospy_graph, title=""): - """ - Init - """ - super(Dataviz, self).__init__(ontospy_graph, title) - self.static_files = ["libs/d3-v3", "libs/jquery"] - - def _buildTemplates(self): - """ - OVERRIDING THIS METHOD from Factory - """ - - jsontree_classes = build_D3treeStandard( - 0, 99, 1, self.ontospy_graph.toplayer_classes) - c_total = len(self.ontospy_graph.all_classes) - - JSON_DATA_CLASSES = json.dumps({ - 'children': jsontree_classes, - 'name': 'owl:Thing', - }) - - extra_context = { - "ontograph": self.ontospy_graph, - "TOTAL_CLASSES": c_total, - 'JSON_DATA_CLASSES': JSON_DATA_CLASSES, - } - - # Ontology - MAIN PAGE - contents = self._renderTemplate( - "d3/d3_rotatingCluster.html", extraContext=extra_context) - FILE_NAME = "index.html" - main_url = self._save2File(contents, FILE_NAME, self.output_path) - - return main_url - - -# if called directly, for testing purposes pick a random ontology - -if __name__ == '__main__': - - TEST_ONLINE = False - try: - - g = get_onto_for_testing(TEST_ONLINE) - - v = Dataviz(g, title="") - v.build() - v.preview() - - sys.exit(0) - - except KeyboardInterrupt as e: # Ctrl-C - raise e - - -def run(graph, save_on_github=False, main_entity=None): - """ - """ - try: - ontology = graph.all_ontologies[0] - uri = ontology.uri - except: - ontology = None - uri = ";".join([s for s in graph.sources]) - - # ontotemplate = open("template.html", "r") - ontotemplate = open(ONTODOCS_VIZ_TEMPLATES + "d3_cluster.html", "r") - t = Template(ontotemplate.read()) - - c_total = len(graph.classes) - - mylist = build_D3treeStandard(0, 99, 1, graph.toplayer_classes) - - JSON_DATA_CLASSES = json.dumps({ - 'children': mylist, - 'name': 'owl:Thing', - }) - - c = Context({ - "ontology": ontology, - "main_uri": uri, - "STATIC_PATH": ONTODOCS_VIZ_STATIC, - "save_on_github": save_on_github, - 'JSON_DATA_CLASSES': JSON_DATA_CLASSES, - "TOTAL_CLASSES": c_total, - }) - - rnd = t.render(c) - - return safe_str(rnd) - - -if __name__ == '__main__': - import sys - try: - # script for testing - must launch this module - # >python -m viz.viz_packh - - func = locals()["run"] # main func dynamically - run_test_viz(func) - - sys.exit(0) - - except KeyboardInterrupt as e: # Ctrl-C - raise e diff --git a/ontospy/ontodocs/viz/viz_d3rotating_cluster.py b/ontospy/ontodocs/viz/viz_d3rotating_cluster.py new file mode 100755 index 00000000..15a328d3 --- /dev/null +++ b/ontospy/ontodocs/viz/viz_d3rotating_cluster.py @@ -0,0 +1,77 @@ +# !/usr/bin/env python +# -*- coding: UTF-8 -*- + +import os, sys +import json + +from ..utils import * +from ..builder import * # loads and sets up Django +from ..viz_factory import VizFactory + +# =========== +# D3 ROTATING CLUSTER +# +# NOTE results are not that good +# =========== + + +class Dataviz(VizFactory): + """ + D3 rotating cluster + + """ + + def __init__(self, ontospy_graph, title=""): + """ + Init + """ + super(Dataviz, self).__init__(ontospy_graph, title) + self.static_files = ["libs/d3-v3", "libs/jquery"] + + def _buildTemplates(self): + """ + OVERRIDING THIS METHOD from Factory + """ + + jsontree_classes = build_D3treeStandard( + 0, 99, 1, self.ontospy_graph.toplayer_classes) + c_total = len(self.ontospy_graph.all_classes) + + JSON_DATA_CLASSES = json.dumps({ + 'children': jsontree_classes, + 'name': 'owl:Thing', + }) + + extra_context = { + "ontograph": self.ontospy_graph, + "TOTAL_CLASSES": c_total, + 'JSON_DATA_CLASSES': JSON_DATA_CLASSES, + } + + # Ontology - MAIN PAGE + contents = self._renderTemplate( + "d3/d3_rotating_cluster.html", extraContext=extra_context) + FILE_NAME = "index.html" + main_url = self._save2File(contents, FILE_NAME, self.output_path) + + return main_url + + +# if called directly, for testing purposes pick a random ontology + +if __name__ == '__main__': + + TEST_ONLINE = False + try: + + g = get_onto_for_testing(TEST_ONLINE) + + v = Dataviz(g, title="") + v.build() + v.preview() + + sys.exit(0) + + except KeyboardInterrupt as e: # Ctrl-C + raise e + diff --git a/ontospy/ontodocs/viz/viz_d3treePie.py b/ontospy/ontodocs/viz/viz_d3treePie.py deleted file mode 100755 index eb563ccb..00000000 --- a/ontospy/ontodocs/viz/viz_d3treePie.py +++ /dev/null @@ -1,162 +0,0 @@ -# !/usr/bin/env python -# -*- coding: UTF-8 -*- - -import os, sys -import json - -from ..utils import * -from ..builder import * # loads and sets up Django -from ..viz_factory import VizFactory - -# =========== -# D3 TREE PIE -# =========== - - -class Dataviz(VizFactory): - """ - D3 TREE PIE - - """ - - def __init__(self, ontospy_graph, title=""): - """ - Init - """ - super(Dataviz, self).__init__(ontospy_graph, title) - self.static_files = ["libs/d3-v3", "libs/jquery"] - - def _buildTemplates(self): - """ - OVERRIDING THIS METHOD from Factory - """ - - jsontree_classes = build_D3treepie(0, 99, 1, - self.ontospy_graph.toplayer_classes) - c_total = len(self.ontospy_graph.all_classes) - c_toplayer = len(self.ontospy_graph.toplayer_classes) - - # weird - DBCheck! - JSON_DATA_CLASSES = json.dumps( - ["owl:Thing", [c_toplayer, c_toplayer], jsontree_classes]) - - extra_context = { - "ontograph": self.ontospy_graph, - "TOTAL_CLASSES": c_total, - 'JSON_DATA_CLASSES': JSON_DATA_CLASSES, - } - - # Ontology - MAIN PAGE - contents = self._renderTemplate( - "d3/d3_treePie.html", extraContext=extra_context) - FILE_NAME = "index.html" - main_url = self._save2File(contents, FILE_NAME, self.output_path) - - return main_url - - -# if called directly, for testing purposes pick a random ontology - -if __name__ == '__main__': - - TEST_ONLINE = False - try: - - g = get_onto_for_testing(TEST_ONLINE) - - v = Dataviz(g, title="") - v.build() - v.preview() - - sys.exit(0) - - except KeyboardInterrupt as e: # Ctrl-C - raise e - -# -# -# -# def run(graph, save_on_github=False, main_entity=None): -# """ -# """ -# try: -# ontology = graph.all_ontologies[0] -# uri = ontology.uri -# except: -# ontology = None -# uri = ";".join([s for s in graph.sources]) -# -# # ontotemplate = open("template.html", "r") -# ontotemplate = open(ONTODOCS_VIZ_TEMPLATES + "d3_treePie.html", "r") -# t = Template(ontotemplate.read()) -# -# c_total = len(graph.classes) -# c_toplayer = len(graph.toplayer_classes) -# -# mydict = build_D3treepie(0, 99, 1, graph.toplayer_classes) -# -# # JSON_DATA_CLASSES = json.dumps({'children': mylist, 'name': 'owl:Thing',}) -# JSON_DATA_CLASSES = json.dumps(["owl:Thing", [c_toplayer, c_toplayer], mydict]) -# -# c = Context({ -# "ontology": ontology, -# "main_uri" : uri, -# "STATIC_PATH": ONTODOCS_VIZ_STATIC, -# "save_on_github" : save_on_github, -# 'JSON_DATA_CLASSES' : JSON_DATA_CLASSES, -# "TOTAL_CLASSES": c_total, -# }) -# -# rnd = t.render(c) -# -# return safe_str(rnd) -# -# -# -# -# def build_D3treepie(old, MAX_DEPTH, level=1, toplayer=None): -# """ -# Create the JSON needed by the treePie viz -# http://bl.ocks.org/adewes/4710330/94a7c0aeb6f09d681dbfdd0e5150578e4935c6ae -# -# Eg -# -# ['origin' , [n1, n2], -# { 'name1' : -# ['name1', [n1, n2], -# {'name1-1' : ...} -# ] , -# } , -# ] -# -# """ -# d = {} -# if not old: -# old = toplayer -# for x in old: -# label = x.bestLabel(quotes=False).replace("_", " ") -# if x.children() and level < MAX_DEPTH: -# size = len(x.children()) -# d[x.qname] = [label, [size, size], -# build_D3treepie(x.children(), MAX_DEPTH, level + 1)] -# else: -# size = 1 -# d[x.qname] = [label, [size, size], {}] -# -# return d -# -# -# -# if __name__ == '__main__': -# import sys -# try: -# # script for testing - must launch this module -# # >python -m viz.viz_packh -# -# func = locals()["run"] # main func dynamically -# run_test_viz(func) -# -# sys.exit(0) -# -# except KeyboardInterrupt as e: # Ctrl-C -# raise e diff --git a/ontospy/ontodocs/viz/viz_d3tree_pie.py b/ontospy/ontodocs/viz/viz_d3tree_pie.py new file mode 100755 index 00000000..05f06520 --- /dev/null +++ b/ontospy/ontodocs/viz/viz_d3tree_pie.py @@ -0,0 +1,84 @@ +# !/usr/bin/env python +# -*- coding: UTF-8 -*- + + +# =========== +# D3 TREE PIE +# +# NOT IN USE / NEEDS MORE TESTING +# =========== + + + + + + + +import os, sys +import json + +from ..utils import * +from ..builder import * # loads and sets up Django +from ..viz_factory import VizFactory + + + +class Dataviz(VizFactory): + """ + D3 TREE PIE + + """ + + def __init__(self, ontospy_graph, title=""): + """ + Init + """ + super(Dataviz, self).__init__(ontospy_graph, title) + self.static_files = ["libs/d3-v3", "libs/jquery"] + + def _buildTemplates(self): + """ + OVERRIDING THIS METHOD from Factory + """ + + jsontree_classes = build_D3treepie(0, 99, 1, + self.ontospy_graph.toplayer_classes) + c_total = len(self.ontospy_graph.all_classes) + c_toplayer = len(self.ontospy_graph.toplayer_classes) + + # weird - DBCheck! + JSON_DATA_CLASSES = json.dumps( + ["owl:Thing", [c_toplayer, c_toplayer], jsontree_classes]) + + extra_context = { + "ontograph": self.ontospy_graph, + "TOTAL_CLASSES": c_total, + 'JSON_DATA_CLASSES': JSON_DATA_CLASSES, + } + + # Ontology - MAIN PAGE + contents = self._renderTemplate( + "d3/d3_treepie.html", extraContext=extra_context) + FILE_NAME = "index.html" + main_url = self._save2File(contents, FILE_NAME, self.output_path) + + return main_url + + +# if called directly, for testing purposes pick a random ontology + +if __name__ == '__main__': + + TEST_ONLINE = False + try: + + g = get_onto_for_testing(TEST_ONLINE) + + v = Dataviz(g, title="") + v.build() + v.preview() + + sys.exit(0) + + except KeyboardInterrupt as e: # Ctrl-C + raise e From 4f4b0cd7c42f4ae246b35e62d5b81cec05f12034 Mon Sep 17 00:00:00 2001 From: lambdamusic Date: Mon, 27 Sep 2021 22:26:47 +0100 Subject: [PATCH 16/16] improve tests --- ontospy/core/rdf_loader.py | 8 +- ontospy/core/utils.py | 4 +- ontospy/tests/context.py | 11 ++ ontospy/tests/{test_quick.py => quick.py} | 33 +--- .../{periodical.jsonld => .periodical.jsonld} | 4 +- ontospy/tests/rdf/.recipe.jsonld | 46 +++++ ontospy/tests/rdf/paper.jsonld | 171 ++++++++++++++++++ ontospy/tests/test_load_local.py | 11 +- ontospy/tests/test_methods.py | 12 +- ontospy/tests/test_shaped_properties.py | 18 +- ontospy/tests/test_shapes.py | 10 +- ontospy/tests/test_sparql.py | 1 - tools/run-quick-test.sh | 4 +- 13 files changed, 271 insertions(+), 62 deletions(-) create mode 100644 ontospy/tests/context.py rename ontospy/tests/{test_quick.py => quick.py} (57%) rename ontospy/tests/rdf/{periodical.jsonld => .periodical.jsonld} (99%) create mode 100644 ontospy/tests/rdf/.recipe.jsonld create mode 100644 ontospy/tests/rdf/paper.jsonld diff --git a/ontospy/core/rdf_loader.py b/ontospy/core/rdf_loader.py index f207b25e..db0bbfe6 100755 --- a/ontospy/core/rdf_loader.py +++ b/ontospy/core/rdf_loader.py @@ -20,8 +20,7 @@ class RDFLoader(object): - """ - Utility to Load any RDF source into an RDFLIB graph instance. + """Utility to Load any RDF source into an RDFLIB graph instance. Accepts: [single item or list] :: uri_or_path = a uri or local path @@ -112,12 +111,11 @@ def load(self, uri_or_path=None, data=None, file_obj=None, rdf_format=""): return self.rdflib_graph def load_uri(self, uri): - """ - Load a single resource into the graph for this object. + """Load a single resource into the graph for this object. Approach: try loading into a temporary graph first, if that succeeds merge it into the main graph. This allows to deal with the JSONLD loading issues which can solved only by using a ConjunctiveGraph (https://github.com/RDFLib/rdflib/issues/436). Also it deals with the RDFA error message which seems to stick into a graph even if the parse operation fails. - NOTE the final merge operation can be improved as graph-set operations involving blank nodes could case collisions (https://rdflib.readthedocs.io/en/stable/merging.html) + TODO the final merge operation can be improved as graph-set operations involving blank nodes could case collisions (https://rdflib.readthedocs.io/en/stable/merging.html) :param uri: single RDF source location :return: None (sets self.rdflib_graph and self.sources_valid) diff --git a/ontospy/core/utils.py b/ontospy/core/utils.py index 2dd41202..a3490ed3 100755 --- a/ontospy/core/utils.py +++ b/ontospy/core/utils.py @@ -877,13 +877,13 @@ def slugify(value): def get_files_with_extensions(folder, extensions): - """walk dir and return .* files as a list + """walk dir and return .* files as a list. Hidden files are ignored. Note: directories are walked recursively""" out = [] for root, dirs, files in os.walk(folder): for file in files: filename, file_extension = os.path.splitext(file) - if file_extension.replace(".", "") in extensions: + if not filename.startswith('.') and file_extension.replace(".", "") in extensions: out += [os.path.join(root, file)] # break diff --git a/ontospy/tests/context.py b/ontospy/tests/context.py new file mode 100644 index 00000000..118c3d68 --- /dev/null +++ b/ontospy/tests/context.py @@ -0,0 +1,11 @@ +# !/usr/bin/env python +# -*- coding: UTF-8 -*- +""" +Unit tests shared constants +""" + +import os + +dir_path = os.path.dirname(os.path.realpath(__file__)) +TEST_RDF_FOLDER = dir_path + "/rdf/" +TEST_SHAPES_FOLDER = dir_path + "/shapes/" \ No newline at end of file diff --git a/ontospy/tests/test_quick.py b/ontospy/tests/quick.py similarity index 57% rename from ontospy/tests/test_quick.py rename to ontospy/tests/quick.py index efa7574c..61bad125 100644 --- a/ontospy/tests/test_quick.py +++ b/ontospy/tests/quick.py @@ -7,7 +7,7 @@ Running it: -./run-quick-test.sh +.tools/run-quick-test.sh TIP @@ -30,23 +30,14 @@ from ..core import * from ..core.utils import * -# sanity check -print("-------------------\nOntospy ", VERSION, "\n-------------------") +from .context import TEST_RDF_FOLDER, TEST_SHAPES_FOLDER -class MyRDFEntity(ontospy.RdfEntity): - def __init__(self, uri, rdftype=None, namespaces=None, ext_model=False): - super().__init__(uri, rdftype, namespaces, ext_model) - def __repr__(self): - return "" % (self.uri) +# sanity check +print("-------------------\nOntospy ", VERSION, "\n-------------------") + - def disjointWith(self): - """ - Example: pull out disjoint with statements - """ - pred = "http://www.w3.org/2002/07/owl#disjointWith" - return self.getValuesForProperty(pred) class TestQuick(unittest.TestCase): @@ -58,17 +49,9 @@ def test_quick1(self): """ print("=================\n*** QUICK TEST 1 ***\n=================\n") - dir_path = os.path.dirname(os.path.realpath(__file__)) - DATA_FOLDER = dir_path + "/rdf/" - f = DATA_FOLDER + "multilingual.ttl" - o = Ontospy(f, verbose=True, pref_title="label", pref_lang="it") - - for c in o.all_classes: - print("URI: ", c.uri) - print("RDFTYPE: ", c.rdftype) - print("BEST LABEL: ", c.bestLabel()) - print("TITLE: ", c.title) - print("===") + f = TEST_RDF_FOLDER + "periodical.jsonld" + + o = Ontospy(f, verbose=True, rdf_format="json-ld") diff --git a/ontospy/tests/rdf/periodical.jsonld b/ontospy/tests/rdf/.periodical.jsonld similarity index 99% rename from ontospy/tests/rdf/periodical.jsonld rename to ontospy/tests/rdf/.periodical.jsonld index 545d8a3a..e6699e32 100644 --- a/ontospy/tests/rdf/periodical.jsonld +++ b/ontospy/tests/rdf/.periodical.jsonld @@ -1,4 +1,4 @@ -{ +[{ "@context": "http://schema.org/", "@graph": [ { @@ -36,4 +36,4 @@ "author": "Smiraglia, Richard P." } ] -} \ No newline at end of file +}] \ No newline at end of file diff --git a/ontospy/tests/rdf/.recipe.jsonld b/ontospy/tests/rdf/.recipe.jsonld new file mode 100644 index 00000000..90b43448 --- /dev/null +++ b/ontospy/tests/rdf/.recipe.jsonld @@ -0,0 +1,46 @@ +{ + "@context": { + "name": "http://rdf.data-vocabulary.org/#name", + "ingredient": "http://rdf.data-vocabulary.org/#ingredients", + "yield": "http://rdf.data-vocabulary.org/#yield", + "instructions": "http://rdf.data-vocabulary.org/#instructions", + "step": { + "@id": "http://rdf.data-vocabulary.org/#step", + "@type": "xsd:integer" + }, + "description": "http://rdf.data-vocabulary.org/#description", + "xsd": "http://www.w3.org/2001/XMLSchema#" + }, + "name": "Mojito", + "ingredient": [ + "12 fresh mint leaves", + "1/2 lime, juiced with pulp", + "1 tablespoons white sugar", + "1 cup ice cubes", + "2 fluid ounces white rum", + "1/2 cup club soda" + ], + "yield": "1 cocktail", + "instructions": [ + { + "step": 1, + "description": "Crush lime juice, mint and sugar together in glass." + }, + { + "step": 2, + "description": "Fill glass to top with ice cubes." + }, + { + "step": 3, + "description": "Pour white rum over ice." + }, + { + "step": 4, + "description": "Fill the rest of glass with club soda, stir." + }, + { + "step": 5, + "description": "Garnish with a lime wedge." + } + ] + } \ No newline at end of file diff --git a/ontospy/tests/rdf/paper.jsonld b/ontospy/tests/rdf/paper.jsonld new file mode 100644 index 00000000..d3346e5c --- /dev/null +++ b/ontospy/tests/rdf/paper.jsonld @@ -0,0 +1,171 @@ +[ + { + "@context": "https://springernature.github.io/scigraph/jsonld/sgcontext.json", + "about": [ + { + "id": "http://purl.org/au-research/vocabulary/anzsrc-for/2008/1199", + "inDefinedTermSet": "http://purl.org/au-research/vocabulary/anzsrc-for/2008/", + "name": "Other Medical and Health Sciences", + "type": "DefinedTerm" + }, + { + "id": "http://purl.org/au-research/vocabulary/anzsrc-for/2008/11", + "inDefinedTermSet": "http://purl.org/au-research/vocabulary/anzsrc-for/2008/", + "name": "Medical and Health Sciences", + "type": "DefinedTerm" + } + ], + "author": [ + { + "affiliation": { + "name": [ + "MBA Datamonitor plc, Charles House, 108\u2013110 Finchley Road, NW3 5JJ, London, UK" + ], + "type": "Organization" + }, + "familyName": "Belsey", + "givenName": "Mark", + "id": "sg:person.07674367221.06", + "sameAs": [ + "https://app.dimensions.ai/discover/publication?and_facet_researcher=ur.07674367221.06" + ], + "type": "Person" + }, + { + "affiliation": { + "name": [ + "MBA Datamonitor plc, Charles House, 108\u2013110 Finchley Road, NW3 5JJ, London, UK" + ], + "type": "Organization" + }, + "familyName": "Evans", + "givenName": "David", + "id": "sg:person.012622670623.47", + "sameAs": [ + "https://app.dimensions.ai/discover/publication?and_facet_researcher=ur.012622670623.47" + ], + "type": "Person" + }, + { + "affiliation": { + "name": [ + "MBA Datamonitor plc, Charles House, 108\u2013110 Finchley Road, NW3 5JJ, London, UK" + ], + "type": "Organization" + }, + "familyName": "Pavlou", + "givenName": "Alex", + "id": "sg:person.010471747621.06", + "sameAs": [ + "https://app.dimensions.ai/discover/publication?and_facet_researcher=ur.010471747621.06" + ], + "type": "Person" + }, + { + "affiliation": { + "name": [ + "MBA Datamonitor plc, Charles House, 108\u2013110 Finchley Road, NW3 5JJ, London, UK" + ], + "type": "Organization" + }, + "familyName": "Savopoulos", + "givenName": "John", + "id": "sg:person.01175104551.77", + "sameAs": [ + "https://app.dimensions.ai/discover/publication?and_facet_researcher=ur.01175104551.77" + ], + "type": "Person" + } + ], + "citation": [ + { + "id": "https://doi.org/10.1016/s0140-6736(04)16934-1", + "sameAs": [ + "https://app.dimensions.ai/details/publication/pub.1011166483" + ], + "type": "CreativeWork" + }, + { + "id": "https://doi.org/10.1016/j.virusres.2004.02.006", + "sameAs": [ + "https://app.dimensions.ai/details/publication/pub.1015699065" + ], + "type": "CreativeWork" + }, + { + "id": "https://doi.org/10.1016/j.jviromet.2004.03.011", + "sameAs": [ + "https://app.dimensions.ai/details/publication/pub.1017215790" + ], + "type": "CreativeWork" + } + ], + "datePublished": "2006-01", + "datePublishedReg": "2006-01-01", + "description": "Following flu vaccine manufacturing and supply issues in the USA and the global threat of an avian flu pandemic, the flu market is attracting considerable interest. This market was worth approximately US$1.1bn in 2004, and it is expected to grow to US$3.1bn by 2010: a compound annual growth rate of 17.1 per cent. To capitalise on this explosive growth rate, flu vaccine manufacturers should position their products towards combating the avian flu pandemic threat. However, there are a number of challenges associated with producing avian flu vaccines using egg-based manufacture systems: currently the dominant vaccine production technique. In the current paper, Datamonitor's infectious disease analysis team argues the case for the potential transformation of the flu market by governmental initiatives, and specifically on the role of these initiatives in driving cell culture flu manufacture as part of pandemic preparedness plans.", + "genre": "research_article", + "id": "sg:pub.10.1057/palgrave.jcb.3040160", + "inLanguage": [ + "en" + ], + "isAccessibleForFree": false, + "isPartOf": [ + { + "id": "sg:journal.1020999", + "issn": [ + "1462-8732", + "1478-565X" + ], + "name": "Journal of Commercial Biotechnology", + "type": "Periodical" + }, + { + "issueNumber": "2", + "type": "PublicationIssue" + }, + { + "type": "PublicationVolume", + "volumeNumber": "12" + } + ], + "name": "Growth drivers and resistors of the influenza market: The importance of cell culture flu", + "pagination": "150-155", + "productId": [ + { + "name": "readcube_id", + "type": "PropertyValue", + "value": [ + "a005dd24aba8e6af14ce8998a6c8c57b1c155ebbdae3208e274ee78870fa4ccc" + ] + }, + { + "name": "doi", + "type": "PropertyValue", + "value": [ + "10.1057/palgrave.jcb.3040160" + ] + }, + { + "name": "dimensions_id", + "type": "PropertyValue", + "value": [ + "pub.1033592356" + ] + } + ], + "sameAs": [ + "https://doi.org/10.1057/palgrave.jcb.3040160", + "https://app.dimensions.ai/details/publication/pub.1033592356" + ], + "sdDataset": "articles", + "sdDatePublished": "2019-04-11T00:13", + "sdLicense": "https://scigraph.springernature.com/explorer/license/", + "sdPublisher": { + "name": "Springer Nature - SN SciGraph project", + "type": "Organization" + }, + "sdSource": "s3://com-uberresearch-data-dimensions-target-20181106-alternative/cleanup/v134/2549eaecd7973599484d7c17b260dba0a4ecb94b/merge/v9/a6c9fde33151104705d4d7ff012ea9563521a3ce/jats-lookup/v90/0000000001_0000000264/records_8695_00000500.jsonl", + "type": "ScholarlyArticle", + "url": "http://link.springer.com/10.1057/palgrave.jcb.3040160" + } + ] \ No newline at end of file diff --git a/ontospy/tests/test_load_local.py b/ontospy/tests/test_load_local.py index 4e1dae57..b38771dd 100644 --- a/ontospy/tests/test_load_local.py +++ b/ontospy/tests/test_load_local.py @@ -5,7 +5,7 @@ Run like this: -:path/to/ontospyProject>python -m ontospy.tests.test_load_local +$ python -m ontospy.tests.test_load_local """ @@ -16,6 +16,7 @@ from .. core import * from .. core.utils import * +from .context import TEST_RDF_FOLDER, TEST_SHAPES_FOLDER # sanity check @@ -24,20 +25,18 @@ class TestLoadOntologies(unittest.TestCase): - dir_path = os.path.dirname(os.path.realpath(__file__)) - DATA_FOLDER = dir_path + "/rdf/" def test1_load_locally(self): """ Check if the ontologies in /RDF folder load ok """ - print("=================\nTEST 1: Loading ontologies from <%s> folder and printing detailed entities descriptions.\n=================" % self.DATA_FOLDER) + print("=================\nTEST 1: Loading ontologies from <%s> folder and printing detailed entities descriptions.\n=================" % TEST_RDF_FOLDER) - for f in os.listdir(self.DATA_FOLDER): + for f in os.listdir(TEST_RDF_FOLDER): if not f.startswith('.'): printDebug("\n*****\nTest: loading local file... > %s\n*****" % str(f), "important") - o = Ontospy(self.DATA_FOLDER + f, verbose=True) + o = Ontospy(TEST_RDF_FOLDER + f, verbose=True) print("CLASS TREE") o.printClassTree() diff --git a/ontospy/tests/test_methods.py b/ontospy/tests/test_methods.py index f76786d7..f27b8407 100644 --- a/ontospy/tests/test_methods.py +++ b/ontospy/tests/test_methods.py @@ -18,6 +18,11 @@ from ..core.utils import * + +from .context import TEST_RDF_FOLDER, TEST_SHAPES_FOLDER + + + # sanity check print("-------------------\nOntospy ", VERSION, "\n-------------------") @@ -47,14 +52,11 @@ class TestMethods(unittest.TestCase): # load sample ontologies - dir_path = os.path.dirname(os.path.realpath(__file__)) - DATA_FOLDER = dir_path + "/rdf/" - - f = DATA_FOLDER + "pizza.ttl" + f = TEST_RDF_FOLDER + "pizza.ttl" printDebug("\n*****\n ..loading local ontology > %s\n*****" % str(f), "important") o = Ontospy(f, verbose=True, pref_title="label") - f = DATA_FOLDER + "multilingual.ttl" + f = TEST_RDF_FOLDER + "multilingual.ttl" printDebug("\n*****\n ..loading local ontology > %s\n*****" % str(f), "important") o2 = Ontospy(f, verbose=True, pref_title="qname", pref_lang="en") diff --git a/ontospy/tests/test_shaped_properties.py b/ontospy/tests/test_shaped_properties.py index a43f7696..bcc37f30 100644 --- a/ontospy/tests/test_shaped_properties.py +++ b/ontospy/tests/test_shaped_properties.py @@ -5,7 +5,7 @@ Run like this: -:path/to/ontospyProject>python -m ontospy.tests.test_shaped_properties +$ python -m ontospy.tests.test_shaped_properties """ @@ -17,6 +17,9 @@ from ..core.utils import * +from .context import TEST_RDF_FOLDER, TEST_SHAPES_FOLDER + + # sanity check print("-------------------\nOntospy ", VERSION, "\n-------------------") @@ -24,30 +27,27 @@ class TestShapedProperties(unittest.TestCase): - dir_path = os.path.dirname(os.path.realpath(__file__)) - DATA_FOLDER = dir_path + "/rdf/schema/webapi.ttl" - - def test_shaped_properties(self): """ Check if the shapes and their properties on a class are loaded properly. """ - printDebug("=================\nTEST: Loading ontology & shapes from <%s> folder and printing summary.\n=================" % self.DATA_FOLDER, "important") + printDebug("=================\nTEST: Loading/merging ALL ontology & shapes from local folder and printing summary.\n .. => %s\n=================" % TEST_RDF_FOLDER, "important") - o = Ontospy(self.DATA_FOLDER, verbose=False) + o = Ontospy(TEST_RDF_FOLDER, verbose=False) for el in o.stats(): print("%s : %d" % (el[0], el[1])) for c in o.all_classes: - printDebug("\Class: %s" % str(c), "green") if c.shapedProperties: + printDebug("Class: %s" % str(c), "green") for x in c.shapedProperties: print(".....hasProperty: " + str(x["property"])) print(" the property has %s associated shapes." % x["shape"]) else: - print("..... has no target class!") + pass + # print("..... has no target class!") if __name__ == "__main__": diff --git a/ontospy/tests/test_shapes.py b/ontospy/tests/test_shapes.py index d77164ff..c83321f6 100644 --- a/ontospy/tests/test_shapes.py +++ b/ontospy/tests/test_shapes.py @@ -17,6 +17,9 @@ from ..core.utils import * +from .context import TEST_RDF_FOLDER, TEST_SHAPES_FOLDER + + # sanity check print("-------------------\nOntospy ", VERSION, "\n-------------------") @@ -24,18 +27,15 @@ class TestShapes(unittest.TestCase): - dir_path = os.path.dirname(os.path.realpath(__file__)) - DATA_FOLDER = dir_path + "/shapes/" - def test1_local_shapes(self): """ Check if the shapes in the SciGraph onto are loaded properly """ - printDebug("=================\nTEST: Loading ontology & shapes from <%s> folder and printing summary.\n=================" % self.DATA_FOLDER, "important") + printDebug("=================\nTEST: Loading ontology & shapes from <%s> folder and printing summary.\n=================" % TEST_RDF_FOLDER, "important") - o = Ontospy(self.DATA_FOLDER, verbose=False) + o = Ontospy(TEST_RDF_FOLDER, verbose=False) for el in o.stats(): print("%s : %d" % (el[0], el[1])) diff --git a/ontospy/tests/test_sparql.py b/ontospy/tests/test_sparql.py index d79630de..322c8dec 100644 --- a/ontospy/tests/test_sparql.py +++ b/ontospy/tests/test_sparql.py @@ -17,7 +17,6 @@ from ..core.utils import * - # sanity check print("-------------------\nOntospy ", VERSION, "\n-------------------") diff --git a/tools/run-quick-test.sh b/tools/run-quick-test.sh index 6db183c6..090779cc 100755 --- a/tools/run-quick-test.sh +++ b/tools/run-quick-test.sh @@ -7,10 +7,10 @@ clear echo "==================" -echo "CALLING [test_quick] in 1 second..." +echo "CALLING [tests/quick] in 1 second..." echo "==================" sleep 1 -python -m ontospy.tests.test_quick +python -m ontospy.tests.quick echo ""