iolanta 2.1.9__tar.gz → 2.1.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {iolanta-2.1.9 → iolanta-2.1.11}/PKG-INFO +1 -1
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/data/iolanta.yaml +9 -1
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/data/textual-browser.yaml +0 -9
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_browser/page_switcher.py +9 -4
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_default/facets.py +2 -0
- iolanta-2.1.11/iolanta/facets/textual_default/textual-inverse-properties.yamlld +25 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/title/facets.py +4 -0
- iolanta-2.1.11/iolanta/facets/title/title.yamlld +33 -0
- iolanta-2.1.11/iolanta/mcp/cli.py +24 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/parse_quads.py +18 -15
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/sparqlspace/processor.py +41 -90
- iolanta-2.1.11/iolanta/sparqlspace/redirects.py +79 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/pyproject.toml +2 -64
- iolanta-2.1.9/iolanta/mcp/cli.py +0 -40
- iolanta-2.1.9/iolanta/mcp/prompts/nanopublication_assertion_authoring_rules.md +0 -63
- iolanta-2.1.9/iolanta/mcp/prompts/rules.md +0 -83
- {iolanta-2.1.9 → iolanta-2.1.11}/README.md +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/base_plugin.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/cli/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/cli/formatters/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/cli/formatters/choose.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/cli/formatters/csv.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/cli/formatters/json.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/cli/formatters/pretty.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/cli/main.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/cli/models.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/cli/pretty_print.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/context.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/conversions.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/data/context.yaml +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/data/graph-triples.yamlld +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/declension/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/declension/data/declension.yamlld +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/declension/facet.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/declension/sparql/declension.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/ensure_is_context.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/entry_points.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/errors.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/cli/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/cli/base.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/cli/default.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/cli/record.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/cli/sparql/link.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/cli/sparql/record.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/errors.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/facet.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/foaf_person_title/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/foaf_person_title/facet.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/foaf_person_title/sparql/names.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/generic/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/generic/bool_literal.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/generic/date_literal.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/generic/default.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/generic/sparql/default.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/html/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/html/base.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/html/code_literal.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/html/default.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/icon.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/locator/sparql/get-query-to-facet.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/locator.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/mkdocs_material_insiders_markdown/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/mkdocs_material_insiders_markdown/data/mkdocs_material_insiders_markdown.yamlld +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/mkdocs_material_insiders_markdown/facet.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/mkdocs_material_insiders_markdown/templates/datatype.jinja2.md +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/page_title.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/qname.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_browser/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_browser/app.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_browser/facet.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_browser/history.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_browser/home.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_browser/location.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_browser/models.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_browser/page.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_class/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_class/facets.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_class/sparql/instances.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_class/textual-class.yamlld +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_default/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_default/sparql/inverse-properties.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_default/sparql/label.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_default/sparql/nodes-for-property.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_default/sparql/properties.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_default/tcss/default.tcss +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_default/templates/default.md +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_default/triple_uri_ref.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_default/widgets.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_graph/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_graph/facets.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_graph/sparql/triples.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_graph_triples.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_graphs/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_graphs/data/textual_graphs.yamlld +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_graphs/facets.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_graphs/sparql/graphs.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_link/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_link/facet.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_nanopublication/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_nanopublication/facet.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_nanopublication/models.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_nanopublication/nanopublication_widget.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_nanopublication/term_list_widget.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_nanopublication/term_widget.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_no_facet_found.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_ontology/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_ontology/facets.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_ontology/sparql/terms.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_ontology/sparql/visualization-vocab.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_property_pairs_table.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_provenance/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_provenance/facets.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_provenance/sparql/graphs.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/textual_provenance/sparql/triples.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/title/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/title/sparql/title.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/wikibase_statement_title/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/wikibase_statement_title/facets.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/facets/wikibase_statement_title/sparql/statement-title.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/iolanta.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/labeled_triple_set/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/labeled_triple_set/data/labeled_triple_set.yamlld +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/labeled_triple_set/labeled_triple_set.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/labeled_triple_set/sparql/triples.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/mcp/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/mermaid/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/mermaid/facet.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/mermaid/mermaid.yamlld +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/mermaid/models.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/mermaid/sparql/ask-has-triples.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/mermaid/sparql/graph.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/mermaid/sparql/subgraphs.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/models.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/namespaces.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/node_to_qname.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/plugin.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/query_result.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/reformat_blank_nodes.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/resolvers/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/resolvers/base.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/resolvers/dispatch.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/resolvers/pypi.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/resolvers/python_import.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/sparqlspace/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/sparqlspace/cli.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/sparqlspace/inference/wikidata-prop-label.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/sparqlspace/inference/wikidata-statement-label.sparql +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/sparqlspace/sparqlspace.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/widgets/__init__.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/widgets/description.py +0 -0
- {iolanta-2.1.9 → iolanta-2.1.11}/iolanta/widgets/mixin.py +0 -0
|
@@ -7,9 +7,17 @@
|
|
|
7
7
|
rdfs: "http://www.w3.org/2000/01/rdf-schema#"
|
|
8
8
|
rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#
|
|
9
9
|
|
|
10
|
+
owl:onProperty:
|
|
11
|
+
"@type": "@id"
|
|
12
|
+
|
|
10
13
|
$included:
|
|
11
14
|
- $id: iolanta:Facet
|
|
12
|
-
$type:
|
|
15
|
+
$type: owl:Class
|
|
16
|
+
rdfs:subClassOf:
|
|
17
|
+
$type: owl:Restriction
|
|
18
|
+
owl:onProperty: iolanta:outputs
|
|
19
|
+
owl:minCardinality: 1
|
|
20
|
+
|
|
13
21
|
label: Application capable to represent certain nodes of a semantic graph in a form suitable for certain user to interact with.
|
|
14
22
|
|
|
15
23
|
- $id: iolanta:OutputDatatype
|
|
@@ -70,15 +70,6 @@
|
|
|
70
70
|
FILTER (?graph != <iolanta://_meta>)
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
- $id: pkg:pypi/iolanta#textual-inverse-properties
|
|
74
|
-
$: Inverse Properties
|
|
75
|
-
→: https://iolanta.tech/cli/textual
|
|
76
|
-
↦: |
|
|
77
|
-
ASK WHERE {
|
|
78
|
-
GRAPH ?graph { ?something ?property $this }
|
|
79
|
-
FILTER (?graph != <iolanta://_meta>)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
73
|
- $id: "urn:"
|
|
83
74
|
iolanta:hasFacetByPrefix:
|
|
84
75
|
$id: pkg:pypi/iolanta#textual-provenance
|
|
@@ -274,12 +274,17 @@ class PageSwitcher(IolantaWidgetMixin, ContentSwitcher): # noqa: WPS214
|
|
|
274
274
|
facet_iri: str | None = None,
|
|
275
275
|
):
|
|
276
276
|
"""Go to an IRI."""
|
|
277
|
-
# Convert string to
|
|
277
|
+
# Convert string to Node if needed.
|
|
278
278
|
# This happens when called via Textual action strings (from keyboard bindings
|
|
279
|
-
# in page.py line 24), which serialize
|
|
280
|
-
# Direct calls (like line 77) pass
|
|
279
|
+
# in page.py line 24), which serialize nodes to strings in f-strings.
|
|
280
|
+
# Direct calls (like line 77) pass Node objects directly.
|
|
281
281
|
if isinstance(this, str):
|
|
282
|
-
|
|
282
|
+
# Check if string represents a blank node (starts with "_:")
|
|
283
|
+
if this.startswith('_:'):
|
|
284
|
+
# Create a BNode with the full string (including the "_:")
|
|
285
|
+
this = BNode(this)
|
|
286
|
+
else:
|
|
287
|
+
this = URIRef(this)
|
|
283
288
|
|
|
284
289
|
self.run_worker(
|
|
285
290
|
functools.partial(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import functools
|
|
2
|
+
from pathlib import Path
|
|
2
3
|
from xml.dom import minidom # noqa: S408
|
|
3
4
|
|
|
4
5
|
import funcy
|
|
@@ -177,6 +178,7 @@ class PageFooter(PageTitle):
|
|
|
177
178
|
class InverseProperties(TextualDefaultFacet):
|
|
178
179
|
"""Inverse properties view."""
|
|
179
180
|
|
|
181
|
+
META = Path(__file__).parent / 'textual-inverse-properties.yamlld'
|
|
180
182
|
query_file_name = 'inverse-properties.sparql'
|
|
181
183
|
properties_on_the_right = True
|
|
182
184
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"@context":
|
|
2
|
+
"@import": https://json-ld.org/contexts/dollar-convenience.jsonld
|
|
3
|
+
iolanta: https://iolanta.tech/
|
|
4
|
+
rdfs: "http://www.w3.org/2000/01/rdf-schema#"
|
|
5
|
+
rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#
|
|
6
|
+
|
|
7
|
+
$: rdfs:label
|
|
8
|
+
→:
|
|
9
|
+
"@type": "@id"
|
|
10
|
+
"@id": iolanta:outputs
|
|
11
|
+
⪯:
|
|
12
|
+
"@type": "@id"
|
|
13
|
+
"@id": iolanta:is-preferred-over
|
|
14
|
+
↦: iolanta:matches
|
|
15
|
+
|
|
16
|
+
$id: pkg:pypi/iolanta#textual-inverse-properties
|
|
17
|
+
|
|
18
|
+
$: Inverse Properties
|
|
19
|
+
→: https://iolanta.tech/cli/textual
|
|
20
|
+
|
|
21
|
+
↦: |
|
|
22
|
+
ASK WHERE {
|
|
23
|
+
GRAPH ?graph { ?something ?property $this }
|
|
24
|
+
FILTER (?graph != <iolanta://_meta>)
|
|
25
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
1
3
|
import funcy
|
|
2
4
|
from rdflib import URIRef
|
|
3
5
|
|
|
@@ -17,6 +19,8 @@ PRIORITIES = [ # noqa: WPS407
|
|
|
17
19
|
class TitleFacet(Facet[str]):
|
|
18
20
|
"""Title of an object."""
|
|
19
21
|
|
|
22
|
+
META = Path(__file__).parent / 'title.yamlld'
|
|
23
|
+
|
|
20
24
|
def show(self) -> str:
|
|
21
25
|
"""Render title of a thing."""
|
|
22
26
|
choices = self.stored_query(
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"@context":
|
|
2
|
+
"@import": https://json-ld.org/contexts/dollar-convenience.jsonld
|
|
3
|
+
iolanta: https://iolanta.tech/
|
|
4
|
+
rdfs: "http://www.w3.org/2000/01/rdf-schema#"
|
|
5
|
+
rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#
|
|
6
|
+
xsd: http://www.w3.org/2001/XMLSchema#
|
|
7
|
+
|
|
8
|
+
$: rdfs:label
|
|
9
|
+
→:
|
|
10
|
+
"@type": "@id"
|
|
11
|
+
"@id": iolanta:outputs
|
|
12
|
+
⪯:
|
|
13
|
+
"@type": "@id"
|
|
14
|
+
"@id": iolanta:is-preferred-over
|
|
15
|
+
⊆:
|
|
16
|
+
"@type": "@id"
|
|
17
|
+
"@id": rdfs:subClassOf
|
|
18
|
+
iolanta:hasDefaultFacet:
|
|
19
|
+
"@type": "@id"
|
|
20
|
+
|
|
21
|
+
$id: pkg:pypi/iolanta#title
|
|
22
|
+
|
|
23
|
+
$: Title
|
|
24
|
+
→: https://iolanta.tech/datatypes/title
|
|
25
|
+
|
|
26
|
+
"@included":
|
|
27
|
+
- $id: https://iolanta.tech/datatypes/title
|
|
28
|
+
$type: iolanta:OutputDatatype
|
|
29
|
+
$: Title
|
|
30
|
+
rdfs:comment: >
|
|
31
|
+
A short string naming something. Used in links, lists, page titles, property tables, and many other cases.
|
|
32
|
+
⊆: xsd:string
|
|
33
|
+
iolanta:hasDefaultFacet: pkg:pypi/iolanta#title
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from typing import Annotated
|
|
2
|
+
|
|
3
|
+
from fastmcp import FastMCP
|
|
4
|
+
|
|
5
|
+
from iolanta.cli.main import render_and_return
|
|
6
|
+
|
|
7
|
+
mcp = FastMCP("Iolanta MCP Server")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@mcp.tool()
|
|
11
|
+
def render_uri(
|
|
12
|
+
uri: Annotated[str, 'URL, or file system path, to render'],
|
|
13
|
+
as_format: Annotated[str, 'Format to render as. Examples: `labeled-triple-set`, `mermaid`'],
|
|
14
|
+
) -> str:
|
|
15
|
+
"""Render a URI."""
|
|
16
|
+
return str(render_and_return(uri, as_format))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def app():
|
|
20
|
+
mcp.run()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
if __name__ == "__main__":
|
|
24
|
+
app()
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import dataclasses
|
|
2
2
|
import hashlib
|
|
3
|
-
from types import MappingProxyType
|
|
4
3
|
from typing import Iterable, Optional
|
|
5
4
|
from urllib.parse import unquote
|
|
6
5
|
|
|
@@ -11,11 +10,7 @@ from rdflib.term import Node
|
|
|
11
10
|
from iolanta.errors import UnresolvedIRI
|
|
12
11
|
from iolanta.models import Quad
|
|
13
12
|
from iolanta.namespaces import IOLANTA, META
|
|
14
|
-
|
|
15
|
-
NORMALIZE_TERMS_MAP = MappingProxyType({
|
|
16
|
-
URIRef(_url := 'http://www.w3.org/2002/07/owl'): URIRef(f'{_url}#'),
|
|
17
|
-
URIRef(_url := 'http://www.w3.org/2000/01/rdf-schema'): URIRef(f'{_url}#'),
|
|
18
|
-
})
|
|
13
|
+
from iolanta.sparqlspace.redirects import apply_redirect
|
|
19
14
|
|
|
20
15
|
|
|
21
16
|
def parse_term( # noqa: C901
|
|
@@ -35,8 +30,8 @@ def parse_term( # noqa: C901
|
|
|
35
30
|
if term_type == 'literal':
|
|
36
31
|
language = term.get('language')
|
|
37
32
|
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
datatype_raw = term.get('datatype')
|
|
34
|
+
datatype = URIRef(datatype_raw) if datatype_raw else None
|
|
40
35
|
|
|
41
36
|
if language and datatype:
|
|
42
37
|
datatype = None
|
|
@@ -89,7 +84,7 @@ def _parse_quads_per_subgraph(
|
|
|
89
84
|
)
|
|
90
85
|
|
|
91
86
|
|
|
92
|
-
def parse_quads(
|
|
87
|
+
def parse_quads( # noqa: WPS210
|
|
93
88
|
quads_document,
|
|
94
89
|
graph: URIRef,
|
|
95
90
|
blank_node_prefix: str = '',
|
|
@@ -132,12 +127,20 @@ def parse_quads(
|
|
|
132
127
|
)
|
|
133
128
|
|
|
134
129
|
for quad in quads: # noqa: WPS526
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
130
|
+
# Build replacement map with subgraph names and nanopub temp namespace
|
|
131
|
+
replacement_map = subgraph_names | {
|
|
132
|
+
# To enable nanopub rendering
|
|
133
|
+
URIRef('http://purl.org/nanopub/temp/np/'): graph,
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
# Apply redirects to all URIRefs in the replacement map
|
|
137
|
+
normalized_replacement_map = {
|
|
138
|
+
apply_redirect(key) if isinstance(key, URIRef) else key:
|
|
139
|
+
apply_redirect(value_node) if isinstance(value_node, URIRef) else value_node # noqa: WPS110
|
|
140
|
+
for key, value_node in replacement_map.items()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
yield quad.replace(normalized_replacement_map).normalize()
|
|
141
144
|
|
|
142
145
|
|
|
143
146
|
def raise_if_term_is_qname(term_value: str):
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
+
# noqa: WPS201, WPS202, WPS402
|
|
1
2
|
import dataclasses
|
|
2
3
|
import datetime
|
|
3
|
-
import re
|
|
4
|
-
import time
|
|
5
4
|
from pathlib import Path
|
|
6
5
|
from threading import Lock
|
|
7
|
-
from types import MappingProxyType
|
|
8
6
|
from typing import Any, Iterable, Mapping
|
|
9
7
|
|
|
10
8
|
import diskcache
|
|
11
9
|
import funcy
|
|
12
10
|
import loguru
|
|
13
11
|
import platformdirs
|
|
14
|
-
import reasonable
|
|
15
12
|
import requests
|
|
16
13
|
import yaml_ld
|
|
17
14
|
from nanopub import NanopubClient
|
|
@@ -35,55 +32,24 @@ from iolanta.namespaces import ( # noqa: WPS235
|
|
|
35
32
|
DCTERMS,
|
|
36
33
|
FOAF,
|
|
37
34
|
IOLANTA,
|
|
38
|
-
LOCAL,
|
|
39
35
|
META,
|
|
40
36
|
OWL,
|
|
41
|
-
PROV,
|
|
42
37
|
RDF,
|
|
43
38
|
RDFS,
|
|
44
39
|
VANN,
|
|
45
40
|
)
|
|
46
|
-
from iolanta.parse_quads import
|
|
41
|
+
from iolanta.parse_quads import parse_quads
|
|
42
|
+
from iolanta.sparqlspace.redirects import apply_redirect
|
|
47
43
|
|
|
48
44
|
REASONING_ENABLED = True
|
|
49
45
|
OWL_REASONING_ENABLED = False
|
|
50
46
|
|
|
51
47
|
INFERENCE_DIR = Path(__file__).parent / 'inference'
|
|
52
|
-
INDICES = [
|
|
48
|
+
INDICES = [ # noqa: WPS407
|
|
53
49
|
URIRef('https://iolanta.tech/visualizations/index.yaml'),
|
|
54
50
|
]
|
|
55
51
|
|
|
56
52
|
|
|
57
|
-
REDIRECTS = MappingProxyType({
|
|
58
|
-
# FIXME This is presently hardcoded; we need to
|
|
59
|
-
# - either find a way to resolve these URLs automatically,
|
|
60
|
-
# - or create a repository of those redirects online.
|
|
61
|
-
'http://purl.org/vocab/vann/': URIRef(
|
|
62
|
-
'https://vocab.org/vann/vann-vocab-20100607.rdf',
|
|
63
|
-
),
|
|
64
|
-
URIRef(DC): URIRef(DCTERMS),
|
|
65
|
-
URIRef(RDF): URIRef(RDF),
|
|
66
|
-
URIRef(RDFS): URIRef(RDFS),
|
|
67
|
-
URIRef(OWL): URIRef(OWL),
|
|
68
|
-
|
|
69
|
-
# Redirect FOAF namespace to GitHub mirror
|
|
70
|
-
URIRef('https?://xmlns.com/foaf/0.1/.+'): URIRef(
|
|
71
|
-
'https://raw.githubusercontent.com/foaf/foaf/refs/heads/master/xmlns.com/htdocs/foaf/0.1/index.rdf',
|
|
72
|
-
),
|
|
73
|
-
URIRef('https://www.nanopub.org/nschema'): URIRef(
|
|
74
|
-
'https://www.nanopub.net/nschema#',
|
|
75
|
-
),
|
|
76
|
-
URIRef('https://nanopub.org/nschema'): URIRef(
|
|
77
|
-
'https://nanopub.net/nschema#',
|
|
78
|
-
),
|
|
79
|
-
URIRef(PROV): URIRef('https://www.w3.org/ns/prov-o'),
|
|
80
|
-
|
|
81
|
-
# Convert lexvo.org/id URLs to lexvo.org/data URLs
|
|
82
|
-
r'https://lexvo\.org/id/(.+)': r'http://lexvo.org/data/\1',
|
|
83
|
-
r'https://www\.lexinfo\.net/(.+)': r'http://www.lexinfo.net/\1',
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
|
|
87
53
|
@diskcache.Cache(
|
|
88
54
|
directory=str(
|
|
89
55
|
platformdirs.user_cache_path(
|
|
@@ -116,20 +82,20 @@ def find_retractions_for(nanopublication: URIRef) -> set[URIRef]:
|
|
|
116
82
|
def _extract_from_mapping( # noqa: WPS213
|
|
117
83
|
algebra: Mapping[str, Any],
|
|
118
84
|
) -> Iterable[URIRef | Variable]:
|
|
119
|
-
match algebra.name:
|
|
85
|
+
match algebra.name: # noqa: WPS242
|
|
120
86
|
case 'SelectQuery' | 'AskQuery' | 'Project' | 'Distinct' | 'Slice':
|
|
121
|
-
yield from extract_mentioned_urls(algebra['p'])
|
|
87
|
+
yield from extract_mentioned_urls(algebra['p']) # noqa: WPS226
|
|
122
88
|
|
|
123
89
|
case 'BGP':
|
|
124
90
|
yield from [ # noqa: WPS353, WPS221
|
|
125
91
|
term
|
|
126
92
|
for triple in algebra['triples']
|
|
127
93
|
for term in triple
|
|
128
|
-
if
|
|
94
|
+
if isinstance(term, (URIRef, Variable))
|
|
129
95
|
]
|
|
130
96
|
|
|
131
97
|
case 'Filter' | 'UnaryNot' | 'OrderCondition':
|
|
132
|
-
yield from extract_mentioned_urls(algebra['expr'])
|
|
98
|
+
yield from extract_mentioned_urls(algebra['expr']) # noqa: WPS204, WPS226
|
|
133
99
|
|
|
134
100
|
case built_in if built_in.startswith('Builtin_'):
|
|
135
101
|
yield from extract_mentioned_urls(algebra['arg'])
|
|
@@ -208,7 +174,10 @@ def normalize_term(term: Node) -> Node:
|
|
|
208
174
|
* A dirty hack;
|
|
209
175
|
* Based on hard code.
|
|
210
176
|
"""
|
|
211
|
-
|
|
177
|
+
if isinstance(term, URIRef):
|
|
178
|
+
return apply_redirect(term)
|
|
179
|
+
|
|
180
|
+
return term
|
|
212
181
|
|
|
213
182
|
|
|
214
183
|
def resolve_variables(
|
|
@@ -258,7 +227,7 @@ class Skipped:
|
|
|
258
227
|
LoadResult = Loaded | Skipped
|
|
259
228
|
|
|
260
229
|
|
|
261
|
-
def _extract_nanopublication_uris(
|
|
230
|
+
def _extract_nanopublication_uris( # noqa: WPS231
|
|
262
231
|
algebra: CompValue,
|
|
263
232
|
) -> Iterable[URIRef]:
|
|
264
233
|
"""Extract nanopublications to get retracting information for."""
|
|
@@ -293,34 +262,6 @@ def _extract_nanopublication_uris(
|
|
|
293
262
|
)
|
|
294
263
|
|
|
295
264
|
|
|
296
|
-
def apply_redirect(source: URIRef) -> URIRef: # noqa: WPS210
|
|
297
|
-
"""
|
|
298
|
-
Rewrite the URL using regex patterns and group substitutions.
|
|
299
|
-
|
|
300
|
-
For each pattern in REDIRECTS:
|
|
301
|
-
- If the pattern matches the source URI
|
|
302
|
-
- Replace the source with the destination, substituting any regex groups
|
|
303
|
-
"""
|
|
304
|
-
source_str = str(source)
|
|
305
|
-
|
|
306
|
-
for pattern, destination in REDIRECTS.items():
|
|
307
|
-
pattern_str = str(pattern)
|
|
308
|
-
destination_str = str(destination)
|
|
309
|
-
|
|
310
|
-
match = re.match(pattern_str, source_str)
|
|
311
|
-
if match:
|
|
312
|
-
# Replace any group references in the destination
|
|
313
|
-
# (like \1, \2, etc.)
|
|
314
|
-
redirected_uri = re.sub(
|
|
315
|
-
pattern_str,
|
|
316
|
-
destination_str,
|
|
317
|
-
source_str,
|
|
318
|
-
)
|
|
319
|
-
return URIRef(redirected_uri)
|
|
320
|
-
|
|
321
|
-
return source
|
|
322
|
-
|
|
323
|
-
|
|
324
265
|
def extract_triples(algebra: CompValue) -> Iterable[tuple[Node, Node, Node]]:
|
|
325
266
|
"""Extract triples from a SPARQL query algebra instance."""
|
|
326
267
|
if isinstance(algebra, CompValue):
|
|
@@ -419,7 +360,7 @@ class GlobalSPARQLProcessor(Processor): # noqa: WPS338, WPS214
|
|
|
419
360
|
|
|
420
361
|
self.graph._indices_loaded = True
|
|
421
362
|
|
|
422
|
-
def query( # noqa: WPS211, WPS210, WPS231, C901
|
|
363
|
+
def query( # noqa: WPS211, WPS210, WPS231, WPS213, C901
|
|
423
364
|
self,
|
|
424
365
|
strOrQuery,
|
|
425
366
|
initBindings=None,
|
|
@@ -471,8 +412,9 @@ class GlobalSPARQLProcessor(Processor): # noqa: WPS338, WPS214
|
|
|
471
412
|
|
|
472
413
|
# Run inference if there's new data since last inference run
|
|
473
414
|
# (after URLs are loaded so inference can use the loaded data)
|
|
474
|
-
if self.graph.last_not_inferred_source is not None:
|
|
475
|
-
|
|
415
|
+
if self.graph.last_not_inferred_source is not None: # noqa: WPS504
|
|
416
|
+
last_source = self.graph.last_not_inferred_source
|
|
417
|
+
self.logger.debug(f'Running inference, last_not_inferred_source: {last_source}') # noqa: WPS237
|
|
476
418
|
self._run_inference()
|
|
477
419
|
else:
|
|
478
420
|
self.logger.debug('Skipping inference, last_not_inferred_source is None')
|
|
@@ -493,7 +435,7 @@ class GlobalSPARQLProcessor(Processor): # noqa: WPS338, WPS214
|
|
|
493
435
|
|
|
494
436
|
for row in bindings:
|
|
495
437
|
break
|
|
496
|
-
for _, maybe_iri in row.items():
|
|
438
|
+
for _, maybe_iri in row.items(): # noqa: WPS427
|
|
497
439
|
if (
|
|
498
440
|
isinstance(maybe_iri, URIRef)
|
|
499
441
|
and isinstance(self.load(maybe_iri), Loaded)
|
|
@@ -542,6 +484,15 @@ class GlobalSPARQLProcessor(Processor): # noqa: WPS338, WPS214
|
|
|
542
484
|
|
|
543
485
|
TODO This function is too big, we have to refactor it.
|
|
544
486
|
"""
|
|
487
|
+
# Blank nodes cannot be loaded from URLs
|
|
488
|
+
if isinstance(source, BNode):
|
|
489
|
+
return Skipped()
|
|
490
|
+
|
|
491
|
+
# Also check if URIRef represents a blank node (can happen if BNode
|
|
492
|
+
# was serialized to string and converted to URIRef)
|
|
493
|
+
if isinstance(source, URIRef) and str(source).startswith('_:'):
|
|
494
|
+
raise ValueError('This is actually a blank node but masked as a URIREF')
|
|
495
|
+
|
|
545
496
|
url = URL(source)
|
|
546
497
|
|
|
547
498
|
if url.scheme in {'file', 'python', 'local', 'urn', 'doi'}:
|
|
@@ -575,7 +526,7 @@ class GlobalSPARQLProcessor(Processor): # noqa: WPS338, WPS214
|
|
|
575
526
|
# FIXME This is definitely inefficient. However, python-yaml-ld caches
|
|
576
527
|
# the document, so the performance overhead is not super high.
|
|
577
528
|
try:
|
|
578
|
-
|
|
529
|
+
resolved_source = yaml_ld.load_document(source)['documentUrl']
|
|
579
530
|
except NotFound as not_found:
|
|
580
531
|
self.logger.info(f'{not_found.path} | 404 Not Found')
|
|
581
532
|
namespaces = [RDF, RDFS, OWL, FOAF, DC, VANN]
|
|
@@ -618,15 +569,15 @@ class GlobalSPARQLProcessor(Processor): # noqa: WPS338, WPS214
|
|
|
618
569
|
|
|
619
570
|
return Loaded()
|
|
620
571
|
|
|
621
|
-
if
|
|
622
|
-
|
|
623
|
-
if
|
|
572
|
+
if resolved_source:
|
|
573
|
+
resolved_source_uri_ref = URIRef(resolved_source)
|
|
574
|
+
if resolved_source_uri_ref != URIRef(source):
|
|
624
575
|
self.graph.add((
|
|
625
576
|
source_uri,
|
|
626
577
|
IOLANTA['redirects-to'],
|
|
627
|
-
|
|
578
|
+
resolved_source_uri_ref,
|
|
628
579
|
))
|
|
629
|
-
source =
|
|
580
|
+
source = resolved_source
|
|
630
581
|
|
|
631
582
|
self._mark_as_loaded(source_uri)
|
|
632
583
|
|
|
@@ -691,7 +642,7 @@ class GlobalSPARQLProcessor(Processor): # noqa: WPS338, WPS214
|
|
|
691
642
|
|
|
692
643
|
return term
|
|
693
644
|
|
|
694
|
-
def _run_inference(self): # noqa: WPS231
|
|
645
|
+
def _run_inference(self): # noqa: WPS231, WPS220, WPS210
|
|
695
646
|
"""
|
|
696
647
|
Run inference queries from the inference directory.
|
|
697
648
|
|
|
@@ -711,21 +662,21 @@ class GlobalSPARQLProcessor(Processor): # noqa: WPS338, WPS214
|
|
|
711
662
|
|
|
712
663
|
# Read and execute the CONSTRUCT query
|
|
713
664
|
query_text = inference_file.read_text()
|
|
714
|
-
|
|
665
|
+
query_result = self.graph.query(query_text) # noqa: WPS110
|
|
715
666
|
|
|
716
667
|
# CONSTRUCT queries return a SPARQLResult with a graph attribute
|
|
717
|
-
result_graph =
|
|
668
|
+
result_graph = query_result.get('graph') if isinstance(query_result, dict) else query_result.graph
|
|
718
669
|
self.logger.debug(f'Inference {filename}: result_graph is {result_graph}, type: {type(result_graph)}')
|
|
719
|
-
if result_graph is not None:
|
|
670
|
+
if result_graph is not None: # noqa: WPS504
|
|
720
671
|
inferred_quads = [
|
|
721
|
-
(s, p, o, inference_graph)
|
|
722
|
-
for s, p, o in result_graph
|
|
672
|
+
(s, p, o, inference_graph) # noqa: WPS111
|
|
673
|
+
for s, p, o in result_graph # noqa: WPS111
|
|
723
674
|
]
|
|
724
675
|
self.logger.debug(f'Inference {filename}: generated {len(inferred_quads)} quads')
|
|
725
676
|
|
|
726
677
|
if inferred_quads:
|
|
727
|
-
self.graph.addN(inferred_quads)
|
|
728
|
-
self.logger.info(
|
|
678
|
+
self.graph.addN(inferred_quads) # noqa: WPS220
|
|
679
|
+
self.logger.info( # noqa: WPS220
|
|
729
680
|
'Inference {filename}: added {count} triples',
|
|
730
681
|
filename=filename,
|
|
731
682
|
count=len(inferred_quads),
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from types import MappingProxyType
|
|
3
|
+
|
|
4
|
+
from rdflib import URIRef
|
|
5
|
+
|
|
6
|
+
from iolanta.namespaces import (
|
|
7
|
+
DC,
|
|
8
|
+
DCTERMS,
|
|
9
|
+
FOAF,
|
|
10
|
+
OWL,
|
|
11
|
+
PROV,
|
|
12
|
+
RDF,
|
|
13
|
+
RDFS,
|
|
14
|
+
VANN,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
REDIRECTS = MappingProxyType({
|
|
18
|
+
# FIXME This is presently hardcoded; we need to
|
|
19
|
+
# - either find a way to resolve these URLs automatically,
|
|
20
|
+
# - or create a repository of those redirects online.
|
|
21
|
+
'http://purl.org/vocab/vann/': URIRef(
|
|
22
|
+
'https://vocab.org/vann/vann-vocab-20100607.rdf',
|
|
23
|
+
),
|
|
24
|
+
URIRef(str(DC)): URIRef(str(DCTERMS)),
|
|
25
|
+
URIRef(str(RDF)): URIRef(str(RDF)),
|
|
26
|
+
URIRef(str(RDFS)): URIRef(str(RDFS)),
|
|
27
|
+
URIRef(str(OWL)): URIRef(str(OWL)),
|
|
28
|
+
|
|
29
|
+
# Add # fragment to OWL and RDFS namespace URIs
|
|
30
|
+
# (fixes bug reported at https://stackoverflow.com/q/78934864/1245471)
|
|
31
|
+
URIRef('http://www.w3.org/2002/07/owl'): URIRef('http://www.w3.org/2002/07/owl#'),
|
|
32
|
+
URIRef('http://www.w3.org/2000/01/rdf-schema'): URIRef('http://www.w3.org/2000/01/rdf-schema#'),
|
|
33
|
+
|
|
34
|
+
# Redirect FOAF namespace to GitHub mirror
|
|
35
|
+
URIRef('https?://xmlns.com/foaf/0.1/.+'): URIRef(
|
|
36
|
+
'https://raw.githubusercontent.com/foaf/foaf/refs/heads/master/xmlns.com/htdocs/foaf/0.1/index.rdf',
|
|
37
|
+
),
|
|
38
|
+
URIRef('https://www.nanopub.org/nschema'): URIRef(
|
|
39
|
+
'https://www.nanopub.net/nschema#',
|
|
40
|
+
),
|
|
41
|
+
URIRef('https://nanopub.org/nschema'): URIRef(
|
|
42
|
+
'https://nanopub.net/nschema#',
|
|
43
|
+
),
|
|
44
|
+
|
|
45
|
+
# Convert lexvo.org/id URLs to lexvo.org/data URLs
|
|
46
|
+
r'http://lexvo\.org/id/(.+)': r'http://lexvo.org/data/\1',
|
|
47
|
+
r'https://lexvo\.org/id/(.+)': r'http://lexvo.org/data/\1',
|
|
48
|
+
r'https://www\.lexinfo\.net/(.+)': r'http://www.lexinfo.net/\1',
|
|
49
|
+
# Convert Wikidata https:// to http:// (Wikidata JSON-LD uses http:// URIs)
|
|
50
|
+
r'https://www\.wikidata\.org/entity/(.+)': r'http://www.wikidata.org/entity/\1',
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def apply_redirect(source: URIRef) -> URIRef: # noqa: WPS210
|
|
55
|
+
"""
|
|
56
|
+
Rewrite the URL using regex patterns and group substitutions.
|
|
57
|
+
|
|
58
|
+
For each pattern in REDIRECTS:
|
|
59
|
+
- If the pattern matches the source URI
|
|
60
|
+
- Replace the source with the destination, substituting any regex groups
|
|
61
|
+
"""
|
|
62
|
+
source_str = str(source)
|
|
63
|
+
|
|
64
|
+
for pattern, destination in REDIRECTS.items():
|
|
65
|
+
pattern_str = str(pattern)
|
|
66
|
+
destination_str = str(destination)
|
|
67
|
+
|
|
68
|
+
match = re.match(pattern_str, source_str)
|
|
69
|
+
if match:
|
|
70
|
+
# Replace any group references in the destination
|
|
71
|
+
# (like \1, \2, etc.)
|
|
72
|
+
redirected_uri = re.sub(
|
|
73
|
+
pattern_str,
|
|
74
|
+
destination_str,
|
|
75
|
+
source_str,
|
|
76
|
+
)
|
|
77
|
+
return URIRef(redirected_uri)
|
|
78
|
+
|
|
79
|
+
return source
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "iolanta"
|
|
3
|
-
version = "2.1.
|
|
3
|
+
version = "2.1.11"
|
|
4
4
|
description = "Semantic Web browser"
|
|
5
5
|
authors = ["Anatoly Scherbakov <altaisoft@gmail.com>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -70,7 +70,7 @@ labeled-triple-set = "iolanta.labeled_triple_set.labeled_triple_set:LabeledTripl
|
|
|
70
70
|
sparqlspace = "iolanta.sparqlspace.processor:GlobalSPARQLProcessor"
|
|
71
71
|
|
|
72
72
|
[tool.poetry.group.dev.dependencies]
|
|
73
|
-
jeeves-yeti-pyproject = ">=0
|
|
73
|
+
jeeves-yeti-pyproject = ">=1.0"
|
|
74
74
|
mkdocs-awesome-pages-plugin = ">=2.9.2"
|
|
75
75
|
mkdocs-blogging-plugin = ">=2.2.11"
|
|
76
76
|
mkdocstrings-python = ">=1.8.0"
|
|
@@ -85,65 +85,3 @@ all = ["iolanta-tables"]
|
|
|
85
85
|
[build-system]
|
|
86
86
|
requires = ["poetry-core"]
|
|
87
87
|
build-backend = "poetry.core.masonry.api"
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
[tool.flakeheaven.exceptions."iolanta/facets/**.py"]
|
|
91
|
-
wemake-python-styleguide = [
|
|
92
|
-
# Upper case constants used in Textual widget classes.
|
|
93
|
-
"-WPS115",
|
|
94
|
-
|
|
95
|
-
# __all__ in __init__.py is ok
|
|
96
|
-
"-WPS410",
|
|
97
|
-
]
|
|
98
|
-
|
|
99
|
-
[tool.flakeheaven.exceptions."iolanta/cyberspace/processor.py"]
|
|
100
|
-
wemake-python-styleguide = [
|
|
101
|
-
# Underscored variables are ok
|
|
102
|
-
"-WPS121",
|
|
103
|
-
"-WPS122",
|
|
104
|
-
]
|
|
105
|
-
|
|
106
|
-
[tool.flakeheaven.exceptions."tests/**.py"]
|
|
107
|
-
wemake-python-styleguide = [
|
|
108
|
-
# Found outer scope names shadowing
|
|
109
|
-
# Used for fixtures
|
|
110
|
-
"-WPS442",
|
|
111
|
-
]
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
[tool.flakeheaven.exceptions."iolanta/facets/textual_browser/history.py"]
|
|
115
|
-
wemake-python-styleguide = [
|
|
116
|
-
# Save stuff into a dataclass attribute
|
|
117
|
-
"-WPS601",
|
|
118
|
-
]
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
[tool.flakeheaven.exceptions."**/facets.py"]
|
|
122
|
-
wemake-python-styleguide = [
|
|
123
|
-
# Found upper-case constant in a class: DEFAULT_CSS
|
|
124
|
-
"-WPS115",
|
|
125
|
-
]
|
|
126
|
-
|
|
127
|
-
pycodestyle = [
|
|
128
|
-
# blank line contains whitespace
|
|
129
|
-
# This is TCSS, WTF?
|
|
130
|
-
"-W293"
|
|
131
|
-
]
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
[tool.flakeheaven.exceptions."**/*.md"]
|
|
135
|
-
flake8-eradicate = [
|
|
136
|
-
# Found commented out code [flake8-eradicate]
|
|
137
|
-
"-E800",
|
|
138
|
-
]
|
|
139
|
-
|
|
140
|
-
[tool.flakeheaven.exceptions."iolanta/namespaces.py"]
|
|
141
|
-
wemake-python-styleguide = [
|
|
142
|
-
# Found upper-case constant in a class: _NS
|
|
143
|
-
"-WPS115",
|
|
144
|
-
]
|
|
145
|
-
|
|
146
|
-
flake8-docstrings = [
|
|
147
|
-
# Missing docstring in public class
|
|
148
|
-
"-D101",
|
|
149
|
-
]
|