From 7e67a091a1155829253d455749c3f476bef4047b Mon Sep 17 00:00:00 2001 From: Charles Tapley Hoyt Date: Mon, 27 Feb 2023 15:33:08 +0100 Subject: [PATCH 1/7] Implement bind_namespaces strategy for Prefix.cc --- rdflib/namespace/__init__.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/rdflib/namespace/__init__.py b/rdflib/namespace/__init__.py index 585ecf303..441cc8c9c 100644 --- a/rdflib/namespace/__init__.py +++ b/rdflib/namespace/__init__.py @@ -6,6 +6,7 @@ from pathlib import Path from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Set, Tuple, Union from unicodedata import category +from urllib.request import urlopen from urllib.parse import urldefrag, urljoin from rdflib.term import URIRef, Variable, _is_valid_uri @@ -418,11 +419,16 @@ def __init__(self, graph: "Graph", bind_namespaces: "_NamespaceSetString" = "cor for prefix, ns in _NAMESPACE_PREFIXES_CORE.items(): self.bind(prefix, ns) elif bind_namespaces == "cc": + for prefix, ns in _NAMESPACE_PREFIXES_RDFLIB.items(): + self.bind(prefix, ns) + for prefix, ns in _NAMESPACE_PREFIXES_CORE.items(): + self.bind(prefix, ns) # bind any prefix that can be found with lookups to prefix.cc - # first bind core and rdflib ones - # work out remainder - namespaces without prefixes - # only look those ones up - raise NotImplementedError("Haven't got to this option yet") + response = urlopen("https://prefix.cc/context.jsonld") + context = json.loads(response.read()) + for prefix, ns in context["@context"].items(): + # note that prefixes are lowercase-only in prefix.cc + self.bind(prefix, ns) elif bind_namespaces == "core": # bind a few core RDF namespaces - default for prefix, ns in _NAMESPACE_PREFIXES_CORE.items(): From f3a1ece2769b926f7cfa424c2437ad2555e8c9c7 Mon Sep 17 00:00:00 2001 From: Charles Tapley Hoyt Date: Mon, 27 Feb 2023 19:14:34 +0100 Subject: [PATCH 2/7] Add prefix.cc tests --- rdflib/namespace/__init__.py | 11 ++++++++--- test/test_namespacemanager.py | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/rdflib/namespace/__init__.py b/rdflib/namespace/__init__.py index 441cc8c9c..ff9420ae9 100644 --- a/rdflib/namespace/__init__.py +++ b/rdflib/namespace/__init__.py @@ -424,9 +424,7 @@ def __init__(self, graph: "Graph", bind_namespaces: "_NamespaceSetString" = "cor for prefix, ns in _NAMESPACE_PREFIXES_CORE.items(): self.bind(prefix, ns) # bind any prefix that can be found with lookups to prefix.cc - response = urlopen("https://prefix.cc/context.jsonld") - context = json.loads(response.read()) - for prefix, ns in context["@context"].items(): + for prefix, ns in _get_prefix_cc().items(): # note that prefixes are lowercase-only in prefix.cc self.bind(prefix, ns) elif bind_namespaces == "core": @@ -728,6 +726,13 @@ def absolutize(self, uri: str, defrag: int = 1) -> URIRef: return URIRef(result) +def _get_prefix_cc(): + """Get the context from Prefix.cc.""" + response = urlopen("https://prefix.cc/context.jsonld") + context = json.loads(response.read()) + return context["@context"] + + # From: http://www.w3.org/TR/REC-xml#NT-CombiningChar # # * Name start characters must have one of the categories Ll, Lu, Lo, diff --git a/test/test_namespacemanager.py b/test/test_namespacemanager.py index 4d073b13d..75bb506a9 100644 --- a/test/test_namespacemanager.py +++ b/test/test_namespacemanager.py @@ -149,6 +149,25 @@ def test_graph_bind_namespaces( assert namespaces is None +def test_graph_bind_cc(): + """Test binding Prefix.cc. + + Note that since prefix.cc is an inherently dynamic resource, + that checking an exact equivalence is not applicable. + """ + graph = Graph(bind_namespaces="cc") + namespaces = {*graph.namespaces()} + for namespaces in [ + _NAMESPACE_PREFIXES_CORE, + _NAMESPACE_PREFIXES_RDFLIB, + {"go", "atcc"}, # represent some prefixes in Prefix.cc + ]: + assert all( + ns in namespaces + for ns in _NAMESPACE_PREFIXES_CORE + ) + + @pytest.mark.parametrize( ["selector", "expected_result"], [ From a66538b1da85ba26c0fb1bf51b47bbb946982f80 Mon Sep 17 00:00:00 2001 From: Charles Tapley Hoyt Date: Mon, 27 Feb 2023 19:15:15 +0100 Subject: [PATCH 3/7] Update __init__.py --- rdflib/namespace/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rdflib/namespace/__init__.py b/rdflib/namespace/__init__.py index ff9420ae9..ef1a76e28 100644 --- a/rdflib/namespace/__init__.py +++ b/rdflib/namespace/__init__.py @@ -6,8 +6,8 @@ from pathlib import Path from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Set, Tuple, Union from unicodedata import category -from urllib.request import urlopen from urllib.parse import urldefrag, urljoin +from urllib.request import urlopen from rdflib.term import URIRef, Variable, _is_valid_uri From 699b98089658e6ce7659960704a555aeddb345f8 Mon Sep 17 00:00:00 2001 From: Charles Tapley Hoyt Date: Mon, 27 Feb 2023 19:20:21 +0100 Subject: [PATCH 4/7] Pass black and add example --- examples/bind_prefix_cc.py | 10 ++++++++++ test/test_namespacemanager.py | 7 ++----- 2 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 examples/bind_prefix_cc.py diff --git a/examples/bind_prefix_cc.py b/examples/bind_prefix_cc.py new file mode 100644 index 000000000..19eedbf52 --- /dev/null +++ b/examples/bind_prefix_cc.py @@ -0,0 +1,10 @@ +""" +Prefix.cc is a community curated prefix map. By using `bind_namespace="cc"`, +you can set a namespace manager or graph to dynamically load prefixes from +this resource. +""" + +import rdflib + +graph = rdflib.Graph(bind_namespaces="cc") +assert graph.qname("http://purl.obolibrary.org/obo/GO_0032571") == "go:0032571" diff --git a/test/test_namespacemanager.py b/test/test_namespacemanager.py index 75bb506a9..1ed4a41fb 100644 --- a/test/test_namespacemanager.py +++ b/test/test_namespacemanager.py @@ -160,12 +160,9 @@ def test_graph_bind_cc(): for namespaces in [ _NAMESPACE_PREFIXES_CORE, _NAMESPACE_PREFIXES_RDFLIB, - {"go", "atcc"}, # represent some prefixes in Prefix.cc + {"go", "atcc"}, # represent some prefixes in Prefix.cc ]: - assert all( - ns in namespaces - for ns in _NAMESPACE_PREFIXES_CORE - ) + assert all(ns in namespaces for ns in _NAMESPACE_PREFIXES_CORE) @pytest.mark.parametrize( From f87272047ecbebf7f9b76ab9dd118afd20da4502 Mon Sep 17 00:00:00 2001 From: Charles Tapley Hoyt Date: Mon, 27 Feb 2023 19:24:00 +0100 Subject: [PATCH 5/7] Update bind_prefix_cc.py --- examples/bind_prefix_cc.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/bind_prefix_cc.py b/examples/bind_prefix_cc.py index 19eedbf52..f0dc92c05 100644 --- a/examples/bind_prefix_cc.py +++ b/examples/bind_prefix_cc.py @@ -7,4 +7,12 @@ import rdflib graph = rdflib.Graph(bind_namespaces="cc") + +# The Gene Ontology is a biomedical ontology describing +# biological processes, cellular locations, and cellular components. +# It is typically abbreviated with the prefix "go" and uses PURLs +# issued by the Open Biological and Biomedical Ontologies Foundry. +prefix_map = {prefix: str(ns) for prefix, ns in graph.namespaces()} +assert "go" in prefix_map +assert prefix_map["go"] == "http://purl.obolibrary.org/obo/GO_" assert graph.qname("http://purl.obolibrary.org/obo/GO_0032571") == "go:0032571" From 9c3a5eca0a151f72da2dcdc07ab0a8e59677db37 Mon Sep 17 00:00:00 2001 From: Charles Tapley Hoyt Date: Sun, 5 Mar 2023 22:43:42 +0100 Subject: [PATCH 6/7] Update _type_checking.py --- rdflib/_type_checking.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rdflib/_type_checking.py b/rdflib/_type_checking.py index 4f32cdc3b..869a35cff 100644 --- a/rdflib/_type_checking.py +++ b/rdflib/_type_checking.py @@ -26,4 +26,4 @@ else: from typing_extensions import Literal as PyLiteral -_NamespaceSetString = PyLiteral["core", "rdflib", "none"] +_NamespaceSetString = PyLiteral["core", "rdflib", "none", "cc"] From 693f78685f95beec1ce2eb4593f6e7f79836073c Mon Sep 17 00:00:00 2001 From: Charles Tapley Hoyt Date: Sun, 5 Mar 2023 22:46:41 +0100 Subject: [PATCH 7/7] Update __init__.py --- rdflib/namespace/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/rdflib/namespace/__init__.py b/rdflib/namespace/__init__.py index ef1a76e28..1304ed77e 100644 --- a/rdflib/namespace/__init__.py +++ b/rdflib/namespace/__init__.py @@ -373,7 +373,6 @@ class NamespaceManager(object): * note this is NOT default behaviour * cc: * using prefix bindings from prefix.cc which is a online prefixes database - * not implemented yet - this is aspirational See the Sample usage