iolanta 2.0.8__py3-none-any.whl → 2.1.4__py3-none-any.whl

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.
Files changed (58) hide show
  1. iolanta/cli/main.py +45 -25
  2. iolanta/data/graph-triples.yamlld +2 -2
  3. iolanta/data/textual-browser.yaml +23 -22
  4. iolanta/declension/__init__.py +0 -0
  5. iolanta/declension/data/declension.yamlld +39 -0
  6. iolanta/declension/facet.py +44 -0
  7. iolanta/declension/sparql/declension.sparql +8 -0
  8. iolanta/facets/cli/record.py +2 -2
  9. iolanta/facets/facet.py +1 -22
  10. iolanta/facets/foaf_person_title/facet.py +2 -2
  11. iolanta/facets/generic/bool_literal.py +3 -3
  12. iolanta/facets/generic/date_literal.py +1 -1
  13. iolanta/facets/generic/default.py +2 -2
  14. iolanta/facets/html/code_literal.py +3 -3
  15. iolanta/facets/icon.py +1 -1
  16. iolanta/facets/locator.py +1 -4
  17. iolanta/facets/qname.py +2 -2
  18. iolanta/facets/textual_browser/app.py +7 -3
  19. iolanta/facets/textual_browser/facet.py +1 -1
  20. iolanta/facets/textual_browser/page_switcher.py +13 -18
  21. iolanta/facets/textual_class/facets.py +3 -3
  22. iolanta/facets/textual_class/sparql/instances.sparql +4 -1
  23. iolanta/facets/textual_default/facets.py +5 -5
  24. iolanta/facets/textual_default/widgets.py +1 -1
  25. iolanta/facets/textual_graph/facets.py +3 -3
  26. iolanta/facets/textual_graph_triples.py +1 -1
  27. iolanta/facets/textual_link/facet.py +4 -4
  28. iolanta/facets/textual_nanopublication/facet.py +1 -1
  29. iolanta/facets/textual_no_facet_found.py +3 -1
  30. iolanta/facets/textual_ontology/facets.py +3 -3
  31. iolanta/facets/textual_provenance/facets.py +1 -1
  32. iolanta/facets/title/facets.py +3 -5
  33. iolanta/facets/title/sparql/title.sparql +5 -0
  34. iolanta/facets/wikibase_statement_title/facets.py +2 -2
  35. iolanta/iolanta.py +35 -68
  36. iolanta/labeled_triple_set/__init__.py +0 -0
  37. iolanta/labeled_triple_set/data/labeled_triple_set.yamlld +42 -0
  38. iolanta/labeled_triple_set/labeled_triple_set.py +137 -0
  39. iolanta/labeled_triple_set/sparql/triples.sparql +5 -0
  40. iolanta/mermaid/__init__.py +0 -0
  41. iolanta/mermaid/facet.py +127 -0
  42. iolanta/mermaid/mermaid.yamlld +42 -0
  43. iolanta/mermaid/models.py +156 -0
  44. iolanta/mermaid/sparql/graph.sparql +5 -0
  45. iolanta/mermaid/sparql/subgraphs.sparql +3 -0
  46. iolanta/namespaces.py +1 -1
  47. iolanta/resolvers/base.py +2 -1
  48. iolanta/resolvers/dispatch.py +41 -0
  49. iolanta/resolvers/pypi.py +106 -0
  50. iolanta/resolvers/python_import.py +9 -32
  51. iolanta/sparqlspace/processor.py +4 -1
  52. {iolanta-2.0.8.dist-info → iolanta-2.1.4.dist-info}/METADATA +7 -8
  53. {iolanta-2.0.8.dist-info → iolanta-2.1.4.dist-info}/RECORD +55 -41
  54. {iolanta-2.0.8.dist-info → iolanta-2.1.4.dist-info}/WHEEL +1 -1
  55. iolanta-2.1.4.dist-info/entry_points.txt +33 -0
  56. iolanta/data/cli.yaml +0 -30
  57. iolanta/data/html.yaml +0 -15
  58. iolanta-2.0.8.dist-info/entry_points.txt +0 -10
@@ -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.iri)
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
- destination: NotLiteralNode,
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.iri = destination
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=destination,
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.iri,
114
+ node=self.this,
115
115
  as_datatype=as_datatype,
116
116
  node_types=[],
117
117
  )
@@ -136,10 +136,10 @@ class PageSwitcher(IolantaWidgetMixin, ContentSwitcher): # noqa: WPS214
136
136
  for facet in other_facets
137
137
  ]
138
138
 
139
- facet_class = iolanta.facet_resolver[facet_iri]
139
+ facet_class = iolanta.facet_resolver.resolve(facet_iri)
140
140
 
141
141
  facet = facet_class(
142
- iri=self.iri,
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.iri,
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=destination,
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
- destination=self.history.current.url,
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
- destination: str,
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
- destination=iri,
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', iri=self.iri),
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.iri),
210
+ PageTitle(self.this),
211
211
  InstancesList(
212
212
  instances=list(self.stream_instances()),
213
- parent_class=self.iri,
213
+ parent_class=self.this,
214
214
  ),
215
215
  )
@@ -1,5 +1,8 @@
1
+ # Remember we are HTTPS-izing all URIs in Iolanta graph
2
+ PREFIX rdf: <https://www.w3.org/1999/02/22-rdf-syntax-ns#>
3
+
1
4
  SELECT ?instance WHERE {
2
- ?instance a $iri .
5
+ ?instance rdf:type $this .
3
6
 
4
7
  FILTER(!isLiteral(?instance)) .
5
8
  } ORDER BY ?instance
@@ -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.iri,
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.iri,
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.iri,
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.iri),
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.iri, extra='[i]& its inverse RDF properties[/i]'),
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'⏳ {property_qname}',
141
+ f'⏳ {property_value}',
142
142
  style='#696969',
143
143
  )
144
144
 
@@ -14,17 +14,17 @@ class GraphFacet(Facet[Widget]):
14
14
  """Show the widget."""
15
15
  triples = [
16
16
  Triple(triple['subject'], triple['predicate'], triple['object'])
17
- for triple in self.stored_query('triples.sparql', graph=self.iri)
17
+ for triple in self.stored_query('triples.sparql', graph=self.this)
18
18
  ]
19
19
 
20
20
  triple_count = len(triples)
21
21
 
22
22
  triples_view = self.iolanta.render(
23
- self.iri,
23
+ self.this,
24
24
  as_datatype=DATATYPES['textual-graph-triples'],
25
25
  )
26
26
 
27
27
  return VerticalScroll(
28
- PageTitle(self.iri, extra=f'({triple_count} triples)'),
28
+ PageTitle(self.this, extra=f'({triple_count} triples)'),
29
29
  triples_view,
30
30
  )
@@ -138,7 +138,7 @@ class GraphTriplesFacet(Facet[Widget]):
138
138
  }
139
139
  ORDER BY ?subject ?predicate ?object
140
140
  """,
141
- graph=self.iri,
141
+ graph=self.this,
142
142
  )
143
143
 
144
144
  triples = [
@@ -11,13 +11,13 @@ class TextualLinkFacet(Facet[str | Text]):
11
11
 
12
12
  def show(self) -> str | Text:
13
13
  """Render the link, or literal text, whatever."""
14
- if isinstance(self.iri, Literal):
15
- return f'[b grey37]{self.iri}[/b grey37]'
14
+ if isinstance(self.this, Literal):
15
+ return f'[b grey37]{self.this}[/b grey37]'
16
16
 
17
17
  label = self.render(
18
- self.iri,
18
+ self.this,
19
19
  as_datatype=DATATYPES.title,
20
20
  )
21
21
 
22
- invocation = f"app.goto('{self.iri}')"
22
+ invocation = f"app.goto('{self.this}')"
23
23
  return f'[@click="{invocation}"]{label}[/]'
@@ -11,4 +11,4 @@ class NanopublicationFacet(Facet[Widget]):
11
11
 
12
12
  def show(self) -> Widget:
13
13
  """Render a nanopublication."""
14
- return NanopublicationScreen(uri=self.iri)
14
+ return NanopublicationScreen(uri=self.this)
@@ -12,6 +12,7 @@ from iolanta.widgets.description import Description
12
12
  TEXT = """
13
13
  **😕 Iolanta is unable to visualize this resource**
14
14
 
15
+ * The reference type ({reference_type}) might be incorrect;
15
16
  * The URI might be incorrect;
16
17
  * Or, no edges might exist which involve it;
17
18
  * Or maybe Iolanta does not know of such edges.
@@ -44,7 +45,7 @@ class TextualNoFacetFound(Facet):
44
45
  @property
45
46
  def raw_content(self):
46
47
  """Content of the file, if applicable."""
47
- url = URL(self.uriref)
48
+ url = URL(self.this)
48
49
  if url.scheme != 'file':
49
50
  return None
50
51
 
@@ -94,6 +95,7 @@ class TextualNoFacetFound(Facet):
94
95
  TEXT.format(
95
96
  content=self.raw_content or '',
96
97
  subgraphs=self.subgraphs_description or '',
98
+ reference_type=type(self.this).__name__,
97
99
  ),
98
100
  ),
99
101
  ),
@@ -48,7 +48,7 @@ class OntologyFacet(Facet[Widget]):
48
48
  @cached_property
49
49
  def grouped_terms(self) -> dict[NotLiteralNode | None, list[TermAndStatus]]:
50
50
  """Group terms by VANN categories."""
51
- rows = self.stored_query('terms.sparql', iri=self.iri)
51
+ rows = self.stored_query('terms.sparql', iri=self.this)
52
52
  grouped = [
53
53
  (
54
54
  row.get('group'),
@@ -80,7 +80,7 @@ class OntologyFacet(Facet[Widget]):
80
80
 
81
81
  vocabs = funcy.lpluck(
82
82
  'vocab',
83
- self.stored_query('visualization-vocab.sparql', iri=self.iri),
83
+ self.stored_query('visualization-vocab.sparql', iri=self.this),
84
84
  )
85
85
 
86
86
  for vocab in vocabs:
@@ -94,7 +94,7 @@ class OntologyFacet(Facet[Widget]):
94
94
  )
95
95
 
96
96
  return Vertical(
97
- PageTitle(self.iri),
97
+ PageTitle(self.this),
98
98
  TermsContent(
99
99
  Static(
100
100
  Columns(
@@ -109,7 +109,7 @@ class TextualProvenanceFacet(Facet[Widget]):
109
109
 
110
110
  def show(self) -> Widget:
111
111
  """Obtain & render provenance info."""
112
- uri = TripleURIRef(self.iri)
112
+ uri = TripleURIRef(self.this)
113
113
  triple = uri.as_triple()
114
114
 
115
115
  graphs = funcy.lpluck(
@@ -10,6 +10,7 @@ PRIORITIES = [ # noqa: WPS407
10
10
  'rdfs_label',
11
11
  'foaf_name',
12
12
  'literal_form',
13
+ 'preferred_label',
13
14
  ]
14
15
 
15
16
 
@@ -20,7 +21,7 @@ class TitleFacet(Facet[str]):
20
21
  """Render title of a thing."""
21
22
  choices = self.stored_query(
22
23
  'title.sparql',
23
- iri=self.iri,
24
+ iri=self.this,
24
25
  language=self.iolanta.language,
25
26
  )
26
27
 
@@ -30,7 +31,4 @@ class TitleFacet(Facet[str]):
30
31
  if label := row.get(alternative):
31
32
  return str(label)
32
33
 
33
- return self.render(
34
- self.iri,
35
- as_datatype=URIRef('https://iolanta.tech/qname'),
36
- )
34
+ return str(self.this)
@@ -28,4 +28,9 @@ SELECT * WHERE {
28
28
  $iri <https://www.w3.org/2008/05/skos-xl#literalForm> ?literal_form .
29
29
  FILTER (!lang(?literal_form) || lang(?literal_form) = $language)
30
30
  }
31
+
32
+ OPTIONAL {
33
+ $iri <https://www.w3.org/2004/02/skos/core#prefLabel> ?preferred_label .
34
+ FILTER (!lang(?preferred_label) || lang(?preferred_label) = $language)
35
+ }
31
36
  }
@@ -12,14 +12,14 @@ class WikibaseStatementTitle(Facet[str]):
12
12
  """Render the title."""
13
13
  rows = self.stored_query(
14
14
  'statement-title.sparql',
15
- statement=self.iri,
15
+ statement=self.this,
16
16
  language=self.language,
17
17
  )
18
18
 
19
19
  row = funcy.first(rows)
20
20
  if not row:
21
21
  return self.render(
22
- self.iri,
22
+ self.this,
23
23
  as_datatype=URIRef('https://iolanta.tech/qname'),
24
24
  )
25
25
 
iolanta/iolanta.py CHANGED
@@ -39,23 +39,17 @@ from iolanta.query_result import (
39
39
  SPARQLQueryArgument,
40
40
  format_query_bindings,
41
41
  )
42
+ from iolanta.resolvers.base import Resolver
43
+ from iolanta.resolvers.dispatch import SchemeDispatchResolver
44
+ from iolanta.resolvers.pypi import PyPIResolver
42
45
  from iolanta.resolvers.python_import import PythonImportResolver
43
46
  from iolanta.sparqlspace.processor import normalize_term
44
47
 
45
48
 
46
49
  class LoggerProtocol(Protocol):
47
- """
48
- Abstract Logger interface.
50
+ """Abstract Logger interface that unites `loguru` & standard `logging`."""
49
51
 
50
- Unites `loguru` & standard `logging`.
51
- """
52
-
53
- def info( # noqa: WPS110
54
- self,
55
- message: str,
56
- *args: Any,
57
- **kwargs: Any,
58
- ) -> None:
52
+ def info(self, message: str, *args: Any, **kwargs: Any) -> None:
59
53
  """Log an INFO message."""
60
54
 
61
55
  def error(self, message: str, *args: Any, **kwargs: Any) -> None:
@@ -85,8 +79,12 @@ class Iolanta: # noqa: WPS214
85
79
  graph: ConjunctiveGraph = field(default_factory=_create_default_graph)
86
80
  force_plugins: List[Type[Plugin]] = field(default_factory=list)
87
81
 
88
- facet_resolver: Mapping[URIRef, Type[Facet]] = field(
89
- default_factory=PythonImportResolver,
82
+ facet_resolver: Resolver = field(
83
+ default_factory=functools.partial(
84
+ SchemeDispatchResolver,
85
+ python=PythonImportResolver,
86
+ pkg=PyPIResolver,
87
+ ),
90
88
  )
91
89
 
92
90
  logger: LoggerProtocol = loguru.logger
@@ -103,11 +101,7 @@ class Iolanta: # noqa: WPS214
103
101
 
104
102
  @functools.cached_property
105
103
  def plugins(self) -> List[Plugin]:
106
- """
107
- Construct a list of installed plugin instances.
108
-
109
- # FIXME: Get rid of those.
110
- """
104
+ """Construct a list of installed plugin instances."""
111
105
  return [
112
106
  plugin_class(iolanta=self)
113
107
  for plugin_class in self.plugin_classes
@@ -118,28 +112,7 @@ class Iolanta: # noqa: WPS214
118
112
  query_text: str,
119
113
  **kwargs: SPARQLQueryArgument,
120
114
  ) -> QueryResult:
121
- """
122
- Run a SPARQL `SELECT`, `CONSTRUCT`, or `ASK` query.
123
-
124
- Args:
125
- query_text: The SPARQL text;
126
- **kwargs: bind variables in the query to values if necessary. For
127
- example:
128
-
129
- ```python
130
- iolanta.query(
131
- 'SELECT ?title WHERE { ?page rdfs:label ?title }',
132
- ?page=page_iri,
133
- )
134
- ```
135
-
136
- Returns:
137
- Results of the query:
138
-
139
- - a graph for `CONSTRUCT`,
140
- - a list of dicts for `SELECT`,
141
- - or a boolean for `ASK`.
142
- """
115
+ """Run a SPARQL `SELECT`, `CONSTRUCT`, or `ASK` query."""
143
116
  try:
144
117
  sparql_result: SPARQLResult = self.graph.query(
145
118
  query_text,
@@ -231,11 +204,7 @@ class Iolanta: # noqa: WPS214
231
204
  return self
232
205
 
233
206
  def infer(self, closure_class=None) -> 'Iolanta':
234
- """
235
- Apply inference.
236
-
237
- TODO Remove this. Or use `reasonable`. Not sure.
238
- """
207
+ """Apply inference."""
239
208
  return self
240
209
 
241
210
  def bind_namespaces(self):
@@ -258,11 +227,7 @@ class Iolanta: # noqa: WPS214
258
227
 
259
228
  @functools.cached_property
260
229
  def context_paths(self) -> Iterable[Path]:
261
- """
262
- Compile list of context files.
263
-
264
- FIXME: Get rid of those.
265
- """
230
+ """Compile list of context files."""
266
231
  directory = Path(__file__).parent / 'data'
267
232
 
268
233
  yield directory / 'context.yaml'
@@ -272,11 +237,7 @@ class Iolanta: # noqa: WPS214
272
237
  yield path
273
238
 
274
239
  def add_files_from_plugins(self):
275
- """
276
- Load files from plugins.
277
-
278
- FIXME: Get rid of plugins.
279
- """
240
+ """Load files from plugins."""
280
241
  for plugin in self.plugins:
281
242
  try:
282
243
  self.add(plugin.data_files)
@@ -285,14 +246,24 @@ class Iolanta: # noqa: WPS214
285
246
  f'Cannot load {plugin} plugin data files: {error}',
286
247
  )
287
248
 
288
- def __post_init__(self):
289
- """
290
- Load stuff from plugins.
249
+ @property
250
+ def facet_classes(self):
251
+ """Get all registered facet classes."""
252
+ return entry_points.plugins('iolanta.facets')
291
253
 
292
- FIXME: Get rid of plugins.
293
- """
254
+ def add_files_from_facets(self):
255
+ """Add files from all registered facets to the graph."""
256
+ for facet_class in self.facet_classes:
257
+ try:
258
+ self.add(facet_class.META)
259
+ except AttributeError:
260
+ pass
261
+
262
+ def __post_init__(self):
263
+ """Initialize after instance creation."""
294
264
  self.bind_namespaces()
295
265
  self.add_files_from_plugins()
266
+ self.add_files_from_facets()
296
267
  if self.project_root:
297
268
  self.add(self.project_root)
298
269
 
@@ -318,10 +289,10 @@ class Iolanta: # noqa: WPS214
318
289
  as_datatype=as_datatype,
319
290
  ).facet_and_output_datatype
320
291
 
321
- facet_class = self.facet_resolver[found['facet']]
292
+ facet_class = self.facet_resolver.resolve(found['facet'])
322
293
 
323
294
  facet = facet_class(
324
- iri=node,
295
+ this=node,
325
296
  iolanta=self,
326
297
  as_datatype=found['output_datatype'],
327
298
  )
@@ -357,7 +328,7 @@ class Iolanta: # noqa: WPS214
357
328
 
358
329
  facet_instances = [
359
330
  facet_class(
360
- iri=node,
331
+ this=node,
361
332
  iolanta=self,
362
333
  as_datatype=output_datatype,
363
334
  )
@@ -375,11 +346,7 @@ class Iolanta: # noqa: WPS214
375
346
  ) from err
376
347
 
377
348
  def node_as_qname(self, node: Node):
378
- """
379
- Render node as a QName if possible.
380
-
381
- Return the node as is, if it is not.
382
- """
349
+ """Render node as a QName if possible."""
383
350
  qname = node_to_qname(node, self.graph)
384
351
  return f'{qname.namespace_name}:{qname.term}' if isinstance(
385
352
  qname,
File without changes
@@ -0,0 +1,42 @@
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: pkg:pypi/iolanta#labeled-triple-set
36
+ $: Labeled Triple Set
37
+ →:
38
+ $id: https://iolanta.tech/datatypes/labeled-triple-set
39
+ $: Labeled Triple Set
40
+ ↦:
41
+ - ASK WHERE { GRAPH $this { ?s ?p ?o } }
42
+ - ASK WHERE { $this <https://iolanta.tech/has-sub-graph> ?subgraph }