iolanta 2.1.1__tar.gz → 2.1.4__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.1 → iolanta-2.1.4}/PKG-INFO +5 -7
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/main.py +45 -25
- iolanta-2.1.4/iolanta/declension/data/declension.yamlld +39 -0
- iolanta-2.1.4/iolanta/declension/facet.py +44 -0
- iolanta-2.1.4/iolanta/declension/sparql/declension.sparql +8 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/cli/record.py +2 -2
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/facet.py +1 -22
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/foaf_person_title/facet.py +2 -2
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/generic/bool_literal.py +3 -3
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/generic/date_literal.py +1 -1
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/generic/default.py +2 -2
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/html/code_literal.py +3 -3
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/icon.py +1 -1
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/locator.py +1 -4
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/qname.py +2 -2
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/app.py +7 -3
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/facet.py +1 -1
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/page_switcher.py +12 -17
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_class/facets.py +3 -3
- iolanta-2.1.4/iolanta/facets/textual_class/sparql/instances.sparql +8 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/facets.py +5 -5
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/widgets.py +1 -1
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_graph/facets.py +3 -3
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_graph_triples.py +1 -1
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_link/facet.py +4 -4
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_nanopublication/facet.py +1 -1
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_no_facet_found.py +3 -1
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_ontology/facets.py +3 -3
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_provenance/facets.py +1 -1
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/title/facets.py +1 -4
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/wikibase_statement_title/facets.py +2 -2
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/iolanta.py +2 -2
- iolanta-2.1.4/iolanta/labeled_triple_set/data/labeled_triple_set.yamlld +42 -0
- iolanta-2.1.4/iolanta/labeled_triple_set/labeled_triple_set.py +137 -0
- iolanta-2.1.4/iolanta/labeled_triple_set/sparql/triples.sparql +5 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/mermaid/models.py +34 -7
- iolanta-2.1.4/iolanta/sparqlspace/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/sparqlspace/processor.py +4 -1
- iolanta-2.1.4/iolanta/widgets/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/pyproject.toml +5 -4
- iolanta-2.1.1/iolanta/facets/textual_class/sparql/instances.sparql +0 -5
- {iolanta-2.1.1 → iolanta-2.1.4}/README.md +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/base_plugin.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/formatters/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/formatters/choose.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/formatters/csv.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/formatters/json.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/formatters/pretty.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/models.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/pretty_print.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/context.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/conversions.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/data/context.yaml +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/data/graph-triples.yamlld +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/data/iolanta.yaml +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/data/textual-browser.yaml +0 -0
- {iolanta-2.1.1/iolanta/mermaid → iolanta-2.1.4/iolanta/declension}/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/ensure_is_context.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/entry_points.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/errors.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/cli/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/cli/base.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/cli/default.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/cli/sparql/link.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/cli/sparql/record.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/errors.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/foaf_person_title/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/foaf_person_title/sparql/names.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/generic/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/generic/sparql/default.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/html/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/html/base.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/html/default.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/page_title.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/history.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/home.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/location.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/models.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/page.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_class/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/sparql/inverse-properties.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/sparql/label.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/sparql/nodes-for-property.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/sparql/properties.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/tcss/default.tcss +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/templates/default.md +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/triple_uri_ref.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_graph/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_graph/sparql/triples.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_link/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_nanopublication/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_nanopublication/models.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_nanopublication/nanopublication_widget.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_nanopublication/term_list_widget.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_nanopublication/term_widget.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_ontology/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_ontology/sparql/terms.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_ontology/sparql/visualization-vocab.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_property_pairs_table.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_provenance/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_provenance/sparql/graphs.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_provenance/sparql/triples.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/title/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/title/sparql/title.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/wikibase_statement_title/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/wikibase_statement_title/sparql/statement-title.sparql +0 -0
- {iolanta-2.1.1/iolanta/resolvers → iolanta-2.1.4/iolanta/labeled_triple_set}/__init__.py +0 -0
- {iolanta-2.1.1/iolanta/sparqlspace → iolanta-2.1.4/iolanta/mermaid}/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/mermaid/facet.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/mermaid/mermaid.yamlld +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/mermaid/sparql/graph.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/mermaid/sparql/subgraphs.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/models.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/namespaces.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/node_to_qname.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/parse_quads.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/plugin.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/query_result.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/reformat_blank_nodes.py +0 -0
- {iolanta-2.1.1/iolanta/widgets → iolanta-2.1.4/iolanta/resolvers}/__init__.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/resolvers/base.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/resolvers/dispatch.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/resolvers/pypi.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/resolvers/python_import.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/sparqlspace/cli.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/sparqlspace/inference/wikibase-claim.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/sparqlspace/inference/wikibase-statement-property.sparql +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/sparqlspace/sparqlspace.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/widgets/description.py +0 -0
- {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/widgets/mixin.py +0 -0
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: iolanta
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.4
|
|
4
4
|
Summary: Semantic Web browser
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Anatoly Scherbakov
|
|
7
7
|
Author-email: altaisoft@gmail.com
|
|
8
|
-
Requires-Python: >=3.
|
|
8
|
+
Requires-Python: >=3.12,<4.0
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
13
11
|
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
13
|
Provides-Extra: all
|
|
15
14
|
Requires-Dist: boltons (>=24.0.0)
|
|
16
15
|
Requires-Dist: classes (>=0.4.0)
|
|
@@ -21,7 +20,6 @@ Requires-Dist: dominate (>=2.6.0)
|
|
|
21
20
|
Requires-Dist: funcy (>=2.0)
|
|
22
21
|
Requires-Dist: loguru (>=0.7.3)
|
|
23
22
|
Requires-Dist: more-itertools (>=9.0.0)
|
|
24
|
-
Requires-Dist: nanopub (>=2.0.1)
|
|
25
23
|
Requires-Dist: owlrl (>=6.0.2)
|
|
26
24
|
Requires-Dist: oxrdflib (>=0.4.0)
|
|
27
25
|
Requires-Dist: packageurl-python (>=0.17.5)
|
|
@@ -33,7 +31,7 @@ Requires-Dist: rich (>=13.3.1)
|
|
|
33
31
|
Requires-Dist: textual (>=0.83.0)
|
|
34
32
|
Requires-Dist: typer (>=0.9.0)
|
|
35
33
|
Requires-Dist: watchfiles (>=1.0.4)
|
|
36
|
-
Requires-Dist: yaml-ld (>=1.1.
|
|
34
|
+
Requires-Dist: yaml-ld (>=1.1.12)
|
|
37
35
|
Requires-Dist: yarl (>=1.9.4)
|
|
38
36
|
Description-Content-Type: text/markdown
|
|
39
37
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import locale
|
|
2
2
|
import logging
|
|
3
|
+
import sys
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from typing import Annotated
|
|
5
6
|
|
|
@@ -9,6 +10,7 @@ from documented import DocumentedError
|
|
|
9
10
|
from rdflib import Literal, URIRef
|
|
10
11
|
from rich.console import Console
|
|
11
12
|
from rich.markdown import Markdown
|
|
13
|
+
from rich.table import Table
|
|
12
14
|
from typer import Argument, Exit, Option, Typer
|
|
13
15
|
from yarl import URL
|
|
14
16
|
|
|
@@ -22,23 +24,9 @@ DEFAULT_LANGUAGE = locale.getlocale()[0].split('_')[0]
|
|
|
22
24
|
console = Console()
|
|
23
25
|
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
FIXME: Remove this function, just create the app on module level.
|
|
30
|
-
"""
|
|
31
|
-
iolanta = Iolanta()
|
|
32
|
-
|
|
33
|
-
return Typer(
|
|
34
|
-
no_args_is_help=True,
|
|
35
|
-
context_settings={
|
|
36
|
-
'obj': iolanta,
|
|
37
|
-
},
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
app = construct_app()
|
|
27
|
+
app = Typer(
|
|
28
|
+
no_args_is_help=True,
|
|
29
|
+
)
|
|
42
30
|
|
|
43
31
|
|
|
44
32
|
def string_to_node(name: str) -> NotLiteralNode:
|
|
@@ -57,6 +45,13 @@ def string_to_node(name: str) -> NotLiteralNode:
|
|
|
57
45
|
return URIRef(f'file://{path}')
|
|
58
46
|
|
|
59
47
|
|
|
48
|
+
def decode_datatype(datatype: str) -> URIRef:
|
|
49
|
+
if datatype.startswith('http'):
|
|
50
|
+
return URIRef(datatype)
|
|
51
|
+
|
|
52
|
+
return URIRef(f'https://iolanta.tech/datatypes/{datatype}')
|
|
53
|
+
|
|
54
|
+
|
|
60
55
|
@app.command(name='browse')
|
|
61
56
|
def render_command( # noqa: WPS231, WPS238, WPS210, C901
|
|
62
57
|
url: Annotated[str, Argument()],
|
|
@@ -85,14 +80,32 @@ def render_command( # noqa: WPS231, WPS238, WPS210, C901
|
|
|
85
80
|
ensure_exists=True,
|
|
86
81
|
) / 'iolanta.log'
|
|
87
82
|
|
|
88
|
-
|
|
89
|
-
|
|
83
|
+
# Get the level name first
|
|
84
|
+
level_name = {
|
|
85
|
+
logging.DEBUG: 'DEBUG',
|
|
86
|
+
logging.INFO: 'INFO',
|
|
87
|
+
logging.WARNING: 'WARNING',
|
|
88
|
+
logging.ERROR: 'ERROR',
|
|
89
|
+
}[level]
|
|
90
|
+
|
|
91
|
+
# Configure global loguru logger BEFORE creating Iolanta instance
|
|
92
|
+
loguru.logger.remove()
|
|
93
|
+
loguru.logger.add(
|
|
90
94
|
log_file_path,
|
|
91
|
-
level=
|
|
95
|
+
level=level_name,
|
|
92
96
|
format='{time} {level} {message}',
|
|
93
97
|
enqueue=True,
|
|
94
98
|
)
|
|
95
|
-
|
|
99
|
+
loguru.logger.add(
|
|
100
|
+
sys.stderr,
|
|
101
|
+
level=level_name,
|
|
102
|
+
format='{time} | {level:<8} | {name}:{function}:{line} - {message}',
|
|
103
|
+
)
|
|
104
|
+
loguru.logger.level(level_name)
|
|
105
|
+
|
|
106
|
+
# Use the global logger
|
|
107
|
+
logger = loguru.logger
|
|
108
|
+
|
|
96
109
|
node_url = URL(url)
|
|
97
110
|
if node_url.scheme and node_url.scheme != 'file':
|
|
98
111
|
node = URIRef(url)
|
|
@@ -101,6 +114,7 @@ def render_command( # noqa: WPS231, WPS238, WPS210, C901
|
|
|
101
114
|
language=Literal(language),
|
|
102
115
|
logger=logger,
|
|
103
116
|
)
|
|
117
|
+
|
|
104
118
|
else:
|
|
105
119
|
path = Path(node_url.path).absolute()
|
|
106
120
|
node = URIRef(f'file://{path}')
|
|
@@ -113,11 +127,11 @@ def render_command( # noqa: WPS231, WPS238, WPS210, C901
|
|
|
113
127
|
try:
|
|
114
128
|
renderable = iolanta.render(
|
|
115
129
|
node=URIRef(node),
|
|
116
|
-
as_datatype=
|
|
130
|
+
as_datatype=decode_datatype(as_datatype),
|
|
117
131
|
)
|
|
118
132
|
|
|
119
133
|
except DocumentedError as documented_error:
|
|
120
|
-
if
|
|
134
|
+
if level in {logging.DEBUG, logging.INFO}:
|
|
121
135
|
raise
|
|
122
136
|
|
|
123
137
|
console.print(
|
|
@@ -129,11 +143,17 @@ def render_command( # noqa: WPS231, WPS238, WPS210, C901
|
|
|
129
143
|
raise Exit(1)
|
|
130
144
|
|
|
131
145
|
except Exception as err:
|
|
132
|
-
if level in {logging.DEBUG, logging.INFO}:
|
|
146
|
+
if iolanta.logger.level in {logging.DEBUG, logging.INFO}:
|
|
133
147
|
raise
|
|
134
148
|
|
|
135
149
|
console.print(str(err))
|
|
136
150
|
raise Exit(1)
|
|
137
151
|
|
|
138
152
|
else:
|
|
139
|
-
|
|
153
|
+
# FIXME: An intermediary Literal can be used to dispatch rendering.
|
|
154
|
+
match renderable:
|
|
155
|
+
case Table() as table:
|
|
156
|
+
console.print(table)
|
|
157
|
+
|
|
158
|
+
case unknown:
|
|
159
|
+
print(unknown)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"@context":
|
|
2
|
+
"@import": https://json-ld.org/contexts/dollar-convenience.jsonld
|
|
3
|
+
vann: https://purl.org/vocab/vann/
|
|
4
|
+
foaf: https://xmlns.com/foaf/0.1/
|
|
5
|
+
owl: https://www.w3.org/2002/07/owl#
|
|
6
|
+
iolanta: https://iolanta.tech/
|
|
7
|
+
rdfs: "https://www.w3.org/2000/01/rdf-schema#"
|
|
8
|
+
rdf: https://www.w3.org/1999/02/22-rdf-syntax-ns#
|
|
9
|
+
dcterms: https://purl.org/dc/terms/
|
|
10
|
+
dcam: https://purl.org/dc/dcam/
|
|
11
|
+
|
|
12
|
+
iolanta:outputs:
|
|
13
|
+
"@type": "@id"
|
|
14
|
+
|
|
15
|
+
iolanta:when-no-facet-found:
|
|
16
|
+
"@type": "@id"
|
|
17
|
+
|
|
18
|
+
$: rdfs:label
|
|
19
|
+
→:
|
|
20
|
+
"@type": "@id"
|
|
21
|
+
"@id": iolanta:outputs
|
|
22
|
+
|
|
23
|
+
⊆:
|
|
24
|
+
"@type": "@id"
|
|
25
|
+
"@id": rdfs:subClassOf
|
|
26
|
+
|
|
27
|
+
⪯:
|
|
28
|
+
"@type": "@id"
|
|
29
|
+
"@id": iolanta:is-preferred-over
|
|
30
|
+
|
|
31
|
+
↦: iolanta:matches
|
|
32
|
+
iolanta:hasDefaultFacet:
|
|
33
|
+
"@type": "@id"
|
|
34
|
+
|
|
35
|
+
$id: https://w3id.org/np/RASSJ01s2tPPJfFVx__m9gHtY4ct1YSd1ntL3R1OaQfLI/EasternArmenianPersonalPronoun
|
|
36
|
+
iolanta:facet:
|
|
37
|
+
$id: pkg:pypi/iolanta#rich-declension-table
|
|
38
|
+
$: Declension Table
|
|
39
|
+
→: https://iolanta.tech/datatypes/rich
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import funcy
|
|
4
|
+
from docutils.nodes import row
|
|
5
|
+
from rdflib import Literal, Namespace
|
|
6
|
+
from rich.table import Table
|
|
7
|
+
|
|
8
|
+
from iolanta import Facet
|
|
9
|
+
from iolanta.namespaces import DATATYPES, LOCAL
|
|
10
|
+
|
|
11
|
+
LEXINFO = Namespace('https://www.lexinfo.net/ontology/2.0/lexinfo#')
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class RichDeclensionTable(Facet[Table]):
|
|
15
|
+
"""Declension forms of something."""
|
|
16
|
+
|
|
17
|
+
META = Path(__file__).parent / 'data' / 'declension.yamlld'
|
|
18
|
+
|
|
19
|
+
def show(self) -> Table:
|
|
20
|
+
"""Render declension forms of something."""
|
|
21
|
+
rows = self.stored_query('declension.sparql', this=self.this)
|
|
22
|
+
form_by_number_and_person = [
|
|
23
|
+
((row['number'], row['person']), self.render(row['declension'], as_datatype=DATATYPES.title))
|
|
24
|
+
for row in rows
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
declensions = funcy.group_values(form_by_number_and_person)
|
|
28
|
+
|
|
29
|
+
table = Table('', 'Singular', 'Plural', title='Declension')
|
|
30
|
+
|
|
31
|
+
table_rows = [
|
|
32
|
+
[
|
|
33
|
+
', '.join(declensions[number, person])
|
|
34
|
+
for number in [LEXINFO.singular, LEXINFO.plural]
|
|
35
|
+
]
|
|
36
|
+
for person in [LEXINFO.firstPerson, LEXINFO.secondPerson, LEXINFO.thirdPerson]
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
row_titles = ['1st', '2nd', '3rd']
|
|
40
|
+
|
|
41
|
+
for title, table_row in zip(row_titles, table_rows):
|
|
42
|
+
table.add_row(title, *table_row)
|
|
43
|
+
|
|
44
|
+
return table
|
|
@@ -17,9 +17,9 @@ class Record(RichFacet):
|
|
|
17
17
|
|
|
18
18
|
def show(self) -> Renderable:
|
|
19
19
|
return "RECORD"
|
|
20
|
-
rows = self.stored_query('record.sparql', node=self.
|
|
20
|
+
rows = self.stored_query('record.sparql', node=self.this)
|
|
21
21
|
|
|
22
|
-
caption = self.render(self.
|
|
22
|
+
caption = self.render(self.this, as_datatype=IOLANTA['cli/title'])
|
|
23
23
|
|
|
24
24
|
table = Table(
|
|
25
25
|
show_header=False,
|
|
@@ -16,28 +16,15 @@ FacetOutput = TypeVar('FacetOutput')
|
|
|
16
16
|
class Facet(Generic[FacetOutput]):
|
|
17
17
|
"""Base facet class."""
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
this: Node
|
|
20
20
|
iolanta: 'iolanta.Iolanta' = field(repr=False)
|
|
21
21
|
as_datatype: Optional[NotLiteralNode] = None
|
|
22
22
|
|
|
23
|
-
@property
|
|
24
|
-
def this(self) -> NotLiteralNode:
|
|
25
|
-
"""This node."""
|
|
26
|
-
return self.iri
|
|
27
|
-
|
|
28
23
|
@property
|
|
29
24
|
def stored_queries_path(self) -> Path:
|
|
30
25
|
"""Construct directory for stored queries for this facet."""
|
|
31
26
|
return Path(inspect.getfile(self.__class__)).parent / 'sparql'
|
|
32
27
|
|
|
33
|
-
@cached_property
|
|
34
|
-
def uriref(self) -> NotLiteralNode:
|
|
35
|
-
"""Format as URIRef."""
|
|
36
|
-
if isinstance(self.iri, BNode):
|
|
37
|
-
return self.iri
|
|
38
|
-
|
|
39
|
-
return URIRef(self.iri)
|
|
40
|
-
|
|
41
28
|
def query(
|
|
42
29
|
self,
|
|
43
30
|
query_text: str,
|
|
@@ -60,14 +47,6 @@ class Facet(Generic[FacetOutput]):
|
|
|
60
47
|
as_datatype=as_datatype,
|
|
61
48
|
)
|
|
62
49
|
|
|
63
|
-
def render_all(
|
|
64
|
-
self,
|
|
65
|
-
node: Node,
|
|
66
|
-
as_datatype: NotLiteralNode,
|
|
67
|
-
) -> Iterable[Any]:
|
|
68
|
-
"""Render all we can."""
|
|
69
|
-
return self.iolanta.render_all(node=node, as_datatype=as_datatype)
|
|
70
|
-
|
|
71
50
|
def stored_query(self, file_name: str, **kwargs: SPARQLQueryArgument):
|
|
72
51
|
"""Execute a stored SPARQL query."""
|
|
73
52
|
query_text = (self.stored_queries_path / file_name).read_text()
|
|
@@ -9,12 +9,12 @@ class FOAFPersonTitle(Facet[str]):
|
|
|
9
9
|
|
|
10
10
|
def show(self) -> str:
|
|
11
11
|
"""Render full name of a person."""
|
|
12
|
-
row = funcy.first(self.stored_query('names.sparql', person=self.
|
|
12
|
+
row = funcy.first(self.stored_query('names.sparql', person=self.this))
|
|
13
13
|
|
|
14
14
|
if row is None:
|
|
15
15
|
# Render default title.
|
|
16
16
|
return self.render(
|
|
17
|
-
self.
|
|
17
|
+
self.this,
|
|
18
18
|
as_datatype=DATATYPES['fallback-title'],
|
|
19
19
|
)
|
|
20
20
|
|
|
@@ -9,9 +9,9 @@ class BoolLiteral(Facet):
|
|
|
9
9
|
|
|
10
10
|
def show(self):
|
|
11
11
|
"""Render as icon."""
|
|
12
|
-
if not isinstance(self.
|
|
12
|
+
if not isinstance(self.this, Literal):
|
|
13
13
|
raise NotALiteral(
|
|
14
|
-
node=self.
|
|
14
|
+
node=self.this,
|
|
15
15
|
)
|
|
16
16
|
|
|
17
|
-
return '✔️' if self.
|
|
17
|
+
return '✔️' if self.this.value else '❌'
|
|
@@ -27,7 +27,7 @@ class DefaultMixin(Facet[FacetOutput]):
|
|
|
27
27
|
def description(self) -> Description:
|
|
28
28
|
return Description(
|
|
29
29
|
**funcy.first(
|
|
30
|
-
self.stored_query('default.sparql', iri=self.
|
|
30
|
+
self.stored_query('default.sparql', iri=self.this),
|
|
31
31
|
),
|
|
32
32
|
)
|
|
33
33
|
|
|
@@ -59,7 +59,7 @@ class DefaultMixin(Facet[FacetOutput]):
|
|
|
59
59
|
return label
|
|
60
60
|
|
|
61
61
|
def render_fallback(self) -> str:
|
|
62
|
-
string_iri = str(self.
|
|
62
|
+
string_iri = str(self.this)
|
|
63
63
|
|
|
64
64
|
if string_iri.startswith('local:'):
|
|
65
65
|
string_iri = string_iri.removeprefix(
|
|
@@ -9,9 +9,9 @@ class CodeLiteral(Facet):
|
|
|
9
9
|
|
|
10
10
|
def show(self):
|
|
11
11
|
"""Render as icon."""
|
|
12
|
-
if not isinstance(self.
|
|
12
|
+
if not isinstance(self.this, Literal):
|
|
13
13
|
raise NotALiteral(
|
|
14
|
-
node=self.
|
|
14
|
+
node=self.this,
|
|
15
15
|
)
|
|
16
16
|
|
|
17
|
-
return f'<code>{self.
|
|
17
|
+
return f'<code>{self.this.value}</code>'
|
|
@@ -114,9 +114,6 @@ class FacetFinder: # noqa: WPS214
|
|
|
114
114
|
|
|
115
115
|
def by_sparql(self) -> Iterable[FoundRow]:
|
|
116
116
|
"""Determine facet by SHACL shape of the data."""
|
|
117
|
-
if not isinstance(self.node, URIRef):
|
|
118
|
-
return
|
|
119
|
-
|
|
120
117
|
rows = self.iolanta.query(
|
|
121
118
|
GET_QUERY_TO_FACET,
|
|
122
119
|
as_datatype=self.as_datatype,
|
|
@@ -138,7 +135,7 @@ class FacetFinder: # noqa: WPS214
|
|
|
138
135
|
|
|
139
136
|
TODO fix this to allow arbitrary prefixes.
|
|
140
137
|
"""
|
|
141
|
-
scheme = URL(self.node).scheme
|
|
138
|
+
scheme = URL(str(self.node)).scheme
|
|
142
139
|
if scheme != 'urn':
|
|
143
140
|
return []
|
|
144
141
|
|
|
@@ -9,11 +9,11 @@ class QNameFacet(Facet[str]):
|
|
|
9
9
|
def show(self) -> str:
|
|
10
10
|
"""Return a qname."""
|
|
11
11
|
qname: ComputedQName | NotLiteralNode = node_to_qname(
|
|
12
|
-
self.
|
|
12
|
+
self.this,
|
|
13
13
|
self.iolanta.graph,
|
|
14
14
|
)
|
|
15
15
|
|
|
16
16
|
if isinstance(qname, ComputedQName):
|
|
17
17
|
return f'{qname.namespace_name}:{qname.term}'
|
|
18
18
|
|
|
19
|
-
return str(self.
|
|
19
|
+
return str(self.this)
|
|
@@ -45,10 +45,10 @@ def _log_message_to_dev_console(app: App):
|
|
|
45
45
|
class IolantaBrowser(App): # noqa: WPS214, WPS230
|
|
46
46
|
"""Browse Linked Data."""
|
|
47
47
|
|
|
48
|
-
def __init__(self, iolanta: Iolanta,
|
|
48
|
+
def __init__(self, iolanta: Iolanta, this: Node):
|
|
49
49
|
"""Set up parameters for the browser."""
|
|
50
50
|
self.iolanta = iolanta
|
|
51
|
-
self.
|
|
51
|
+
self.this = this
|
|
52
52
|
self.renderers = ThreadPoolExecutor()
|
|
53
53
|
super().__init__()
|
|
54
54
|
|
|
@@ -79,7 +79,11 @@ class IolantaBrowser(App): # noqa: WPS214, WPS230
|
|
|
79
79
|
)
|
|
80
80
|
|
|
81
81
|
# Disable stderr logging, to not break the TUI.
|
|
82
|
-
|
|
82
|
+
# Remove only the stderr handler, keep file handler
|
|
83
|
+
for handler_id in list(self.iolanta.logger._core.handlers.keys()):
|
|
84
|
+
handler = self.iolanta.logger._core.handlers[handler_id]
|
|
85
|
+
if hasattr(handler, 'sink') and str(handler.sink) == '<stderr>':
|
|
86
|
+
self.iolanta.logger.remove(handler_id)
|
|
83
87
|
|
|
84
88
|
# Log to the dev console.
|
|
85
89
|
self.iolanta.logger.add(
|
|
@@ -5,7 +5,7 @@ from dataclasses import dataclass
|
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
7
|
import watchfiles
|
|
8
|
-
from rdflib import BNode, URIRef
|
|
8
|
+
from rdflib import BNode, Node, URIRef
|
|
9
9
|
from textual.widgets import ContentSwitcher, RichLog
|
|
10
10
|
from textual.worker import Worker, WorkerState
|
|
11
11
|
|
|
@@ -74,7 +74,7 @@ class PageSwitcher(IolantaWidgetMixin, ContentSwitcher): # noqa: WPS214
|
|
|
74
74
|
|
|
75
75
|
def on_mount(self):
|
|
76
76
|
"""Navigate to the initial page."""
|
|
77
|
-
self.action_goto(self.app.
|
|
77
|
+
self.action_goto(self.app.this)
|
|
78
78
|
if self.iolanta.project_root:
|
|
79
79
|
self.run_worker(
|
|
80
80
|
self._watch_files,
|
|
@@ -94,24 +94,24 @@ class PageSwitcher(IolantaWidgetMixin, ContentSwitcher): # noqa: WPS214
|
|
|
94
94
|
|
|
95
95
|
def render_iri( # noqa: WPS210
|
|
96
96
|
self,
|
|
97
|
-
|
|
97
|
+
this: NotLiteralNode,
|
|
98
98
|
facet_iri: URIRef | None,
|
|
99
99
|
is_reload: bool,
|
|
100
100
|
) -> RenderResult:
|
|
101
101
|
"""Render an IRI in a thread."""
|
|
102
|
-
self.
|
|
102
|
+
self.this = this
|
|
103
103
|
iolanta: Iolanta = self.iolanta
|
|
104
104
|
|
|
105
105
|
as_datatype = URIRef('https://iolanta.tech/cli/textual')
|
|
106
106
|
choices = FacetFinder(
|
|
107
107
|
iolanta=self.iolanta,
|
|
108
|
-
node=
|
|
108
|
+
node=this,
|
|
109
109
|
as_datatype=as_datatype,
|
|
110
110
|
).choices()
|
|
111
111
|
|
|
112
112
|
if not choices:
|
|
113
113
|
raise FacetNotFound(
|
|
114
|
-
node=self.
|
|
114
|
+
node=self.this,
|
|
115
115
|
as_datatype=as_datatype,
|
|
116
116
|
node_types=[],
|
|
117
117
|
)
|
|
@@ -139,7 +139,7 @@ class PageSwitcher(IolantaWidgetMixin, ContentSwitcher): # noqa: WPS214
|
|
|
139
139
|
facet_class = iolanta.facet_resolver.resolve(facet_iri)
|
|
140
140
|
|
|
141
141
|
facet = facet_class(
|
|
142
|
-
|
|
142
|
+
this=self.this,
|
|
143
143
|
iolanta=iolanta,
|
|
144
144
|
as_datatype=URIRef('https://iolanta.tech/cli/textual'),
|
|
145
145
|
)
|
|
@@ -149,13 +149,13 @@ class PageSwitcher(IolantaWidgetMixin, ContentSwitcher): # noqa: WPS214
|
|
|
149
149
|
|
|
150
150
|
except Exception as err:
|
|
151
151
|
raise FacetError(
|
|
152
|
-
node=self.
|
|
152
|
+
node=self.this,
|
|
153
153
|
facet_iri=facet_iri,
|
|
154
154
|
error=err,
|
|
155
155
|
) from err
|
|
156
156
|
|
|
157
157
|
return RenderResult(
|
|
158
|
-
iri=
|
|
158
|
+
iri=this,
|
|
159
159
|
renderable=renderable,
|
|
160
160
|
flip_options=flip_options,
|
|
161
161
|
facet_iri=facet_iri,
|
|
@@ -222,7 +222,7 @@ class PageSwitcher(IolantaWidgetMixin, ContentSwitcher): # noqa: WPS214
|
|
|
222
222
|
self.run_worker(
|
|
223
223
|
functools.partial(
|
|
224
224
|
self.render_iri,
|
|
225
|
-
|
|
225
|
+
this=self.history.current.url,
|
|
226
226
|
facet_iri=self.history.current.facet_iri,
|
|
227
227
|
is_reload=True,
|
|
228
228
|
),
|
|
@@ -267,19 +267,14 @@ class PageSwitcher(IolantaWidgetMixin, ContentSwitcher): # noqa: WPS214
|
|
|
267
267
|
|
|
268
268
|
def action_goto(
|
|
269
269
|
self,
|
|
270
|
-
|
|
270
|
+
this: Node,
|
|
271
271
|
facet_iri: str | None = None,
|
|
272
272
|
):
|
|
273
273
|
"""Go to an IRI."""
|
|
274
|
-
if destination.startswith('_:'):
|
|
275
|
-
iri = BNode(destination)
|
|
276
|
-
else:
|
|
277
|
-
iri = URIRef(destination)
|
|
278
|
-
|
|
279
274
|
self.run_worker(
|
|
280
275
|
functools.partial(
|
|
281
276
|
self.render_iri,
|
|
282
|
-
|
|
277
|
+
this=this,
|
|
283
278
|
facet_iri=facet_iri and URIRef(facet_iri),
|
|
284
279
|
is_reload=False,
|
|
285
280
|
),
|
|
@@ -200,16 +200,16 @@ class Class(Facet[Widget]):
|
|
|
200
200
|
return set(
|
|
201
201
|
funcy.pluck(
|
|
202
202
|
'instance',
|
|
203
|
-
self.stored_query('instances.sparql',
|
|
203
|
+
self.stored_query('instances.sparql', this=self.this),
|
|
204
204
|
),
|
|
205
205
|
)
|
|
206
206
|
|
|
207
207
|
def show(self) -> Widget:
|
|
208
208
|
"""Render the instances list."""
|
|
209
209
|
return InstancesBody(
|
|
210
|
-
PageTitle(self.
|
|
210
|
+
PageTitle(self.this),
|
|
211
211
|
InstancesList(
|
|
212
212
|
instances=list(self.stream_instances()),
|
|
213
|
-
parent_class=self.
|
|
213
|
+
parent_class=self.this,
|
|
214
214
|
),
|
|
215
215
|
)
|
|
@@ -32,7 +32,7 @@ class TextualDefaultFacet(Facet[Widget]): # noqa: WPS214
|
|
|
32
32
|
"""Properties of current node & their values."""
|
|
33
33
|
property_rows = self.stored_query(
|
|
34
34
|
self.query_file_name,
|
|
35
|
-
iri=self.
|
|
35
|
+
iri=self.this,
|
|
36
36
|
)
|
|
37
37
|
|
|
38
38
|
property_pairs = [
|
|
@@ -64,11 +64,11 @@ class TextualDefaultFacet(Facet[Widget]): # noqa: WPS214
|
|
|
64
64
|
property_values = [
|
|
65
65
|
LiteralPropertyValue(
|
|
66
66
|
property_value=property_value,
|
|
67
|
-
subject=self.
|
|
67
|
+
subject=self.this,
|
|
68
68
|
property_iri=property_iri,
|
|
69
69
|
) if isinstance(property_value, Literal) else PropertyValue(
|
|
70
70
|
property_value=property_value,
|
|
71
|
-
subject=self.
|
|
71
|
+
subject=self.this,
|
|
72
72
|
property_iri=property_iri,
|
|
73
73
|
property_qname=self.iolanta.node_as_qname(property_iri),
|
|
74
74
|
)
|
|
@@ -135,7 +135,7 @@ class TextualDefaultFacet(Facet[Widget]): # noqa: WPS214
|
|
|
135
135
|
def show(self) -> Widget:
|
|
136
136
|
"""Render the content."""
|
|
137
137
|
return VerticalScroll(
|
|
138
|
-
PageTitle(self.
|
|
138
|
+
PageTitle(self.this),
|
|
139
139
|
Static(self.description or ''),
|
|
140
140
|
self.properties,
|
|
141
141
|
)
|
|
@@ -149,7 +149,7 @@ class InverseProperties(TextualDefaultFacet):
|
|
|
149
149
|
def show(self) -> Widget:
|
|
150
150
|
"""Render the content."""
|
|
151
151
|
return VerticalScroll(
|
|
152
|
-
PageTitle(self.
|
|
152
|
+
PageTitle(self.this, extra='[i]& its inverse RDF properties[/i]'),
|
|
153
153
|
Static(self.description or ''),
|
|
154
154
|
self.properties,
|
|
155
155
|
)
|
|
@@ -138,7 +138,7 @@ class PropertyValue(Widget, can_focus=True, inherit_bindings=False):
|
|
|
138
138
|
self.property_iri = property_iri
|
|
139
139
|
super().__init__()
|
|
140
140
|
self.renderable = Text( # noqa: WPS601
|
|
141
|
-
f'⏳ {
|
|
141
|
+
f'⏳ {property_value}',
|
|
142
142
|
style='#696969',
|
|
143
143
|
)
|
|
144
144
|
|