iolanta 2.0.2__tar.gz → 2.0.6__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.
Files changed (137) hide show
  1. {iolanta-2.0.2 → iolanta-2.0.6}/PKG-INFO +2 -2
  2. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/cli/main.py +2 -2
  3. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/data/context.yaml +15 -0
  4. iolanta-2.0.6/iolanta/data/graph-triples.yamlld +6 -0
  5. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/data/textual-browser.yaml +67 -52
  6. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/locator.py +34 -8
  7. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_class/facets.py +35 -46
  8. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_class/sparql/instances.sparql +1 -1
  9. iolanta-2.0.6/iolanta/facets/textual_no_facet_found.py +68 -0
  10. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/iolanta.py +3 -3
  11. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/parse_quads.py +0 -7
  12. iolanta-2.0.6/iolanta/sparqlspace/cli.py +64 -0
  13. {iolanta-2.0.2/iolanta/cyberspace → iolanta-2.0.6/iolanta/sparqlspace}/processor.py +105 -69
  14. iolanta-2.0.6/iolanta/sparqlspace/sparqlspace.py +32 -0
  15. iolanta-2.0.6/iolanta/widgets/description.py +12 -0
  16. {iolanta-2.0.2 → iolanta-2.0.6}/pyproject.toml +4 -4
  17. {iolanta-2.0.2 → iolanta-2.0.6}/README.md +0 -0
  18. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/__init__.py +0 -0
  19. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/base_plugin.py +0 -0
  20. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/cli/__init__.py +0 -0
  21. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/cli/formatters/__init__.py +0 -0
  22. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/cli/formatters/choose.py +0 -0
  23. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/cli/formatters/csv.py +0 -0
  24. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/cli/formatters/json.py +0 -0
  25. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/cli/formatters/pretty.py +0 -0
  26. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/cli/models.py +0 -0
  27. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/cli/pretty_print.py +0 -0
  28. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/context.py +0 -0
  29. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/conversions.py +0 -0
  30. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/data/cli.yaml +0 -0
  31. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/data/html.yaml +0 -0
  32. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/data/iolanta.yaml +0 -0
  33. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/ensure_is_context.py +0 -0
  34. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/entry_points.py +0 -0
  35. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/errors.py +0 -0
  36. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/__init__.py +0 -0
  37. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/cli/__init__.py +0 -0
  38. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/cli/base.py +0 -0
  39. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/cli/default.py +0 -0
  40. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/cli/record.py +0 -0
  41. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/cli/sparql/link.sparql +0 -0
  42. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/cli/sparql/record.sparql +0 -0
  43. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/errors.py +0 -0
  44. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/facet.py +0 -0
  45. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/foaf_person_title/__init__.py +0 -0
  46. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/foaf_person_title/facet.py +0 -0
  47. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/foaf_person_title/sparql/names.sparql +0 -0
  48. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/generic/__init__.py +0 -0
  49. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/generic/bool_literal.py +0 -0
  50. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/generic/date_literal.py +0 -0
  51. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/generic/default.py +0 -0
  52. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/generic/sparql/default.sparql +0 -0
  53. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/html/__init__.py +0 -0
  54. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/html/base.py +0 -0
  55. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/html/code_literal.py +0 -0
  56. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/html/default.py +0 -0
  57. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/icon.py +0 -0
  58. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/page_title.py +0 -0
  59. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/qname.py +0 -0
  60. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_browser/__init__.py +0 -0
  61. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_browser/app.py +0 -0
  62. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_browser/facet.py +0 -0
  63. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_browser/history.py +0 -0
  64. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_browser/home.py +0 -0
  65. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_browser/location.py +0 -0
  66. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_browser/models.py +0 -0
  67. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_browser/page.py +0 -0
  68. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_browser/page_switcher.py +0 -0
  69. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_class/__init__.py +0 -0
  70. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_default/__init__.py +0 -0
  71. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_default/facets.py +0 -0
  72. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_default/sparql/inverse-properties.sparql +0 -0
  73. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_default/sparql/label.sparql +0 -0
  74. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_default/sparql/nodes-for-property.sparql +0 -0
  75. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_default/sparql/properties.sparql +0 -0
  76. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_default/tcss/default.tcss +0 -0
  77. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_default/templates/default.md +0 -0
  78. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_default/triple_uri_ref.py +0 -0
  79. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_default/widgets.py +0 -0
  80. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_graph/__init__.py +0 -0
  81. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_graph/facets.py +0 -0
  82. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_graph/sparql/triples.sparql +0 -0
  83. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_graph_triples.py +0 -0
  84. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_link/__init__.py +0 -0
  85. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_link/facet.py +0 -0
  86. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_nanopublication/__init__.py +0 -0
  87. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_nanopublication/facet.py +0 -0
  88. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_nanopublication/models.py +0 -0
  89. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_nanopublication/nanopublication_widget.py +0 -0
  90. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_nanopublication/term_list_widget.py +0 -0
  91. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_nanopublication/term_widget.py +0 -0
  92. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_ontology/__init__.py +0 -0
  93. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_ontology/facets.py +0 -0
  94. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_ontology/sparql/terms.sparql +0 -0
  95. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_ontology/sparql/visualization-vocab.sparql +0 -0
  96. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_property_pairs_table.py +0 -0
  97. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_provenance/__init__.py +0 -0
  98. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_provenance/facets.py +0 -0
  99. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_provenance/sparql/graphs.sparql +0 -0
  100. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/textual_provenance/sparql/triples.sparql +0 -0
  101. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/title/__init__.py +0 -0
  102. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/title/facets.py +0 -0
  103. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/title/sparql/title.sparql +0 -0
  104. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/wikibase_statement_title/__init__.py +0 -0
  105. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/wikibase_statement_title/facets.py +0 -0
  106. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/facets/wikibase_statement_title/sparql/statement-title.sparql +0 -0
  107. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/loaders/__init__.py +0 -0
  108. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/loaders/base.py +0 -0
  109. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/loaders/data_type_choice.py +0 -0
  110. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/loaders/dict_loader.py +0 -0
  111. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/loaders/errors.py +0 -0
  112. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/loaders/http.py +0 -0
  113. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/loaders/local_directory.py +0 -0
  114. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/loaders/local_file.py +0 -0
  115. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/loaders/scheme_choice.py +0 -0
  116. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/models.py +0 -0
  117. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/namespaces.py +0 -0
  118. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/node_to_qname.py +0 -0
  119. {iolanta-2.0.2/iolanta/cyberspace → iolanta-2.0.6/iolanta/parsers}/__init__.py +0 -0
  120. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/parsers/base.py +0 -0
  121. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/parsers/dict_parser.py +0 -0
  122. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/parsers/errors.py +0 -0
  123. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/parsers/json.py +0 -0
  124. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/parsers/markdown.py +0 -0
  125. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/parsers/yaml.py +0 -0
  126. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/plugin.py +0 -0
  127. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/query_result.py +0 -0
  128. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/reformat_blank_nodes.py +0 -0
  129. {iolanta-2.0.2/iolanta/parsers → iolanta-2.0.6/iolanta/resolvers}/__init__.py +0 -0
  130. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/resolvers/base.py +0 -0
  131. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/resolvers/python_import.py +0 -0
  132. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/shortcuts.py +0 -0
  133. {iolanta-2.0.2/iolanta/resolvers → iolanta-2.0.6/iolanta/sparqlspace}/__init__.py +0 -0
  134. {iolanta-2.0.2/iolanta/cyberspace → iolanta-2.0.6/iolanta/sparqlspace}/inference/wikibase-claim.sparql +0 -0
  135. {iolanta-2.0.2/iolanta/cyberspace → iolanta-2.0.6/iolanta/sparqlspace}/inference/wikibase-statement-property.sparql +0 -0
  136. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/widgets/__init__.py +0 -0
  137. {iolanta-2.0.2 → iolanta-2.0.6}/iolanta/widgets/mixin.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: iolanta
3
- Version: 2.0.2
3
+ Version: 2.0.6
4
4
  Summary: Semantic Web browser
5
5
  License: MIT
6
6
  Author: Anatoly Scherbakov
@@ -32,7 +32,7 @@ Requires-Dist: rich (>=13.3.1)
32
32
  Requires-Dist: textual (>=0.83.0)
33
33
  Requires-Dist: typer (>=0.9.0)
34
34
  Requires-Dist: watchfiles (>=1.0.4,<2.0.0)
35
- Requires-Dist: yaml-ld (>=1.1.7)
35
+ Requires-Dist: yaml-ld (>=1.1.9)
36
36
  Requires-Dist: yarl (>=1.9.4)
37
37
  Description-Content-Type: text/markdown
38
38
 
@@ -94,7 +94,7 @@ def render_command( # noqa: WPS231, WPS238, WPS210, C901
94
94
  )
95
95
 
96
96
  node_url = URL(url)
97
- if node_url.scheme:
97
+ if node_url.scheme and node_url.scheme != 'file':
98
98
  node = URIRef(url)
99
99
 
100
100
  iolanta: Iolanta = Iolanta(
@@ -102,7 +102,7 @@ def render_command( # noqa: WPS231, WPS238, WPS210, C901
102
102
  logger=logger,
103
103
  )
104
104
  else:
105
- path = Path(url).absolute()
105
+ path = Path(node_url.path).absolute()
106
106
  node = URIRef(f'file://{path}')
107
107
  iolanta: Iolanta = Iolanta(
108
108
  language=Literal(language),
@@ -59,3 +59,18 @@
59
59
 
60
60
  rdf:type:
61
61
  "@type": "@id"
62
+
63
+ $: rdfs:label
64
+ →:
65
+ "@type": "@id"
66
+ "@id": iolanta:outputs
67
+
68
+ ⊆:
69
+ "@type": "@id"
70
+ "@id": rdfs:subClassOf
71
+
72
+ ⪯:
73
+ "@type": "@id"
74
+ "@id": iolanta:is-preferred-over
75
+
76
+ ↦: iolanta:matches
@@ -0,0 +1,6 @@
1
+ "@context": context.yaml
2
+ $id: python://iolanta.facets.textual_graph.GraphFacet
3
+ $: Graph Triples
4
+ →: https://iolanta.tech/cli/textual
5
+ ⪯: python://iolanta.facets.textual_default.InverseProperties
6
+ ↦: ASK WHERE { GRAPH $this { ?s ?p ?o } }
@@ -13,57 +13,75 @@
13
13
  iolanta:outputs:
14
14
  "@type": "@id"
15
15
 
16
+ iolanta:when-no-facet-found:
17
+ "@type": "@id"
18
+
16
19
  $: rdfs:label
20
+ →:
21
+ "@type": "@id"
22
+ "@id": iolanta:outputs
23
+
24
+ ⊆:
25
+ "@type": "@id"
26
+ "@id": rdfs:subClassOf
27
+
28
+ ⪯:
29
+ "@type": "@id"
30
+ "@id": iolanta:is-preferred-over
31
+
32
+ ↦: iolanta:matches
17
33
 
18
34
  "@included":
19
35
  - $id: iolanta:icon
20
- rdfs:label: Icon
21
- rdfs:subClassOf:
22
- $id: xsd:string
36
+ $: Icon
37
+ ⊆: xsd:string
23
38
 
24
39
  - $id: dcterms:creator
25
40
  iolanta:icon: ©️
26
41
 
27
42
  - $id: https://iolanta.tech/datatypes/icon
28
- rdfs:label: Icon
43
+ $: Icon
29
44
  iolanta:hasDefaultFacet:
30
45
  $id: python://iolanta.facets.icon.IconFacet
31
- iolanta:outputs:
32
- $id: https://iolanta.tech/datatypes/icon
46
+ →: https://iolanta.tech/datatypes/icon
33
47
 
34
48
  - $id: np:Nanopublication
35
- rdfs:label: Nanopublication
49
+ $: Nanopublication
36
50
  iolanta:hasInstanceFacet:
37
51
  $id: python://iolanta.facets.textual_nanopublication.NanopublicationFacet
38
- rdfs:label: Nanopublication
39
- iolanta:outputs:
40
- $id: https://iolanta.tech/cli/textual
41
- iolanta:is-preferred-over:
42
- $id: python://iolanta.facets.textual_default.TextualDefaultFacet
52
+ $: Nanopublication
53
+ →: https://iolanta.tech/cli/textual
54
+ ⪯:
55
+ - python://iolanta.facets.textual_default.TextualDefaultFacet
56
+ - python://iolanta.facets.textual_graph.GraphFacet
43
57
 
44
58
  - $id: https://iolanta.tech/cli/interactive
45
59
  iolanta:hasDefaultFacet:
46
60
  $id: python://iolanta.facets.textual_browser.TextualBrowserFacet
47
61
 
48
- - $id: https://iolanta.tech/cli/textual
49
- iolanta:hasDefaultFacet:
50
- $id: python://iolanta.facets.textual_default.TextualDefaultFacet
51
- rdfs:label: Properties
52
- iolanta:is-preferred-over:
53
- $id: python://iolanta.facets.textual_default.InverseProperties
54
-
55
- - $id: https://iolanta.tech/cli/textual
56
- iolanta:hasDefaultFacet:
57
- $id: python://iolanta.facets.textual_default.InverseProperties
58
- rdfs:label: Inverse Properties
59
- iolanta:is-preferred-over:
60
- $id: python://iolanta.facets.textual_graph.GraphFacet
62
+ - $id: python://iolanta.facets.textual_default.TextualDefaultFacet
63
+ $: Properties
64
+ ⪯: python://iolanta.facets.textual_default.InverseProperties
65
+ →: https://iolanta.tech/cli/textual
66
+ ↦: |
67
+ ASK WHERE {
68
+ GRAPH ?graph { $this ?property ?value }
69
+ FILTER (?graph != <iolanta://_meta>)
70
+ }
71
+
72
+ - $id: python://iolanta.facets.textual_default.InverseProperties
73
+ $: Inverse Properties
74
+ →: https://iolanta.tech/cli/textual
75
+ ↦: |
76
+ ASK WHERE {
77
+ GRAPH ?graph { ?something ?property $this }
78
+ FILTER (?graph != <iolanta://_meta>)
79
+ }
61
80
 
62
81
  - $id: "urn:"
63
82
  iolanta:hasFacetByPrefix:
64
83
  $id: python://iolanta.facets.textual_provenance.TextualProvenanceFacet
65
- iolanta:outputs:
66
- $id: https://iolanta.tech/cli/textual
84
+ →: https://iolanta.tech/cli/textual
67
85
 
68
86
  - $id: https://iolanta.tech/cli/link
69
87
  iolanta:hasDefaultFacet:
@@ -72,47 +90,44 @@
72
90
  - $id: https://wikiba.se/ontology#Statement
73
91
  iolanta:hasInstanceFacet:
74
92
  $id: python://iolanta.facets.wikibase_statement_title.WikibaseStatementTitle
75
- rdfs:label: Title
76
- iolanta:outputs:
77
- $id: https://iolanta.tech/datatypes/title
93
+ $: Title
94
+ →: https://iolanta.tech/datatypes/title
78
95
 
79
96
  - $id: rdfs:Class
80
97
  iolanta:hasInstanceFacet:
81
98
  $id: python://iolanta.facets.textual_class.Class
82
- rdfs:label: Instances
83
- iolanta:outputs:
84
- $id: https://iolanta.tech/cli/textual
85
- iolanta:is-preferred-over:
86
- - $id: python://iolanta.facets.textual_browser.TextualBrowserFacet
87
- - $id: python://iolanta.facets.textual_default.InverseProperties
99
+ $: Instances
100
+ →: https://iolanta.tech/cli/textual
101
+ ⪯:
102
+ - python://iolanta.facets.textual_browser.TextualBrowserFacet
103
+ - python://iolanta.facets.textual_default.InverseProperties
88
104
 
89
105
  - $id: owl:Ontology
90
106
  iolanta:hasInstanceFacet:
91
107
  $id: python://iolanta.facets.textual_ontology.OntologyFacet
92
- rdfs:label: Ontology
93
- iolanta:outputs:
94
- $id: https://iolanta.tech/cli/textual
95
- iolanta:is-preferred-over:
96
- - $id: python://iolanta.facets.textual_default.TextualDefaultFacet
97
-
98
- - $id: iolanta:Graph
99
- iolanta:hasInstanceFacet:
100
- $id: python://iolanta.facets.textual_graph.GraphFacet
101
- rdfs:label: Graph Triples
102
- iolanta:outputs:
103
- $id: https://iolanta.tech/cli/textual
108
+ $: Ontology
109
+ →: https://iolanta.tech/cli/textual
110
+ ⪯: python://iolanta.facets.textual_default.TextualDefaultFacet
104
111
 
105
112
  - $id: https://iolanta.tech/datatypes/textual-graph-triples
106
- rdfs:label: Graph Triples
113
+ $: Graph Triples
107
114
  iolanta:hasDefaultFacet:
108
115
  $id: python://iolanta.facets.textual_graph_triples.GraphTriplesFacet
109
- iolanta:outputs:
110
- $id: https://iolanta.tech/datatypes/textual-graph-triples
116
+ →: https://iolanta.tech/datatypes/textual-graph-triples
111
117
 
112
118
  - $id: https://iolanta.tech/qname
113
119
  iolanta:hasDefaultFacet:
114
120
  $id: python://iolanta.facets.qname.QNameFacet
115
121
 
116
122
  - $id: python://iolanta.facets.textual_property_pairs_table.TextualPropertyPairsTableFacet
117
- iolanta:outputs: https://iolanta.tech/cli/textual
118
123
  $: Subjects → Objects
124
+ →: https://iolanta.tech/cli/textual
125
+ ↦: ASK WHERE { ?subject $this ?object }
126
+
127
+ - $id: python://iolanta.facets.textual_class.Class
128
+ ↦:
129
+ - ASK WHERE { ?instance a $this }
130
+ - ASK WHERE { $this rdfs:subClassOf ?superclass }
131
+
132
+ - $id: https://iolanta.tech/cli/textual
133
+ iolanta:when-no-facet-found: python://iolanta.facets.textual_no_facet_found.TextualNoFacetFound
@@ -18,6 +18,15 @@ class FoundRow(TypedDict):
18
18
  output_datatype: NotLiteralNode
19
19
 
20
20
 
21
+ GET_QUERY_TO_FACET = """
22
+ SELECT ?facet ?match WHERE {
23
+ ?facet
24
+ iolanta:matches ?match ;
25
+ iolanta:outputs $as_datatype .
26
+ }
27
+ """
28
+
29
+
21
30
  def reorder_rows_by_facet_preferences( # noqa: WPS214, WPS210
22
31
  rows: list[FoundRow],
23
32
  ordering: set[tuple[URIRef, URIRef]],
@@ -108,16 +117,14 @@ class FacetFinder: # noqa: WPS214
108
117
  if not isinstance(self.node, URIRef):
109
118
  return
110
119
 
111
- if self.as_datatype != URIRef('https://iolanta.tech/cli/textual'):
112
- return
120
+ rows = self.iolanta.query(
121
+ GET_QUERY_TO_FACET,
122
+ as_datatype=self.as_datatype,
123
+ )
113
124
 
114
- # TODO: Retrieve queries from the graph
115
- # TODO: Verify datatype for which we are visualizing $this
116
125
  query_to_facet = {
117
- 'ASK WHERE { ?subject $this ?object }': URIRef(
118
- 'python://iolanta.facets.textual_property_pairs_table'
119
- '.TextualPropertyPairsTableFacet',
120
- ),
126
+ row['match']: row['facet']
127
+ for row in rows
121
128
  }
122
129
 
123
130
  for query, facet in query_to_facet.items():
@@ -233,6 +240,22 @@ class FacetFinder: # noqa: WPS214
233
240
  for row in rows
234
241
  ]
235
242
 
243
+ def by_facet_not_found(self) -> Iterable[FoundRow]:
244
+ """What facet to show if no facets are found?"""
245
+ rows = self.iolanta.query( # noqa: WPS462
246
+ """
247
+ SELECT ?facet ?output_datatype WHERE {
248
+ $output_datatype iolanta:when-no-facet-found ?facet .
249
+ }
250
+ """,
251
+ output_datatype=self.as_datatype,
252
+ )
253
+
254
+ return [
255
+ FoundRow(facet=row['facet'], output_datatype=row['output_datatype'])
256
+ for row in rows
257
+ ]
258
+
236
259
  def retrieve_facets_preference_ordering(self) -> set[tuple[URIRef, URIRef]]:
237
260
  """
238
261
  Construct partial ordering on the set of facets.
@@ -256,6 +279,9 @@ class FacetFinder: # noqa: WPS214
256
279
  """Return all suitable facets."""
257
280
  rows = list(self._found_facets())
258
281
 
282
+ if not rows:
283
+ rows = self.by_facet_not_found()
284
+
259
285
  if len(rows) == 1:
260
286
  # Nothing to order.
261
287
  return rows
@@ -6,7 +6,7 @@ import funcy
6
6
  from rich.console import RenderResult
7
7
  from rich.text import Text
8
8
  from textual.binding import Binding, BindingType
9
- from textual.containers import Vertical
9
+ from textual.containers import Vertical # removed unused VerticalScroll (F401)
10
10
  from textual.reactive import Reactive
11
11
  from textual.widget import Widget
12
12
  from textual.widgets import Label, ListItem, ListView
@@ -70,10 +70,8 @@ class InstancesList(ListView): # noqa: WPS214
70
70
 
71
71
  DEFAULT_CSS = """
72
72
  InstancesList {
73
- height: auto;
74
-
73
+ height: 1fr;
75
74
  layout: vertical;
76
- overflow-x: hidden;
77
75
  overflow-y: auto;
78
76
  }
79
77
  """
@@ -121,31 +119,6 @@ class InstancesList(ListView): # noqa: WPS214
121
119
  parent_class=self.parent_class,
122
120
  )
123
121
 
124
- def on_list_view_highlighted(self):
125
- """
126
- Find out whether the last item of the list is highlighted.
127
-
128
- If yes then add more elements.
129
- """
130
- if not self._nodes or (self.index >= len(self._nodes) - 1):
131
- new_instance_items = list(self.stream_instance_items_chunk())
132
- self.run_worker(
133
- functools.partial(
134
- self.render_newly_added_instances,
135
- new_instance_items,
136
- ),
137
- thread=True,
138
- )
139
-
140
- # #126 `extend()` here will lead to freeze in some situations
141
- for new_item in new_instance_items:
142
- self.append(new_item)
143
-
144
- def on_list_item__child_clicked(self) -> None: # noqa: WPS116
145
- """Navigate on click."""
146
- # FIXME if we call `action_goto()` here we'll navigate to the item that
147
- # was selected _prior_ to this click.
148
-
149
122
  def action_goto(self):
150
123
  """Navigate."""
151
124
  self.app.action_goto(self.highlighted_child.node)
@@ -160,6 +133,32 @@ class InstancesList(ListView): # noqa: WPS214
160
133
  ),
161
134
  )
162
135
 
136
+ def compose(self):
137
+ """Fill in the instances."""
138
+ for instance in self.instances: # noqa: WPS526
139
+ yield InstanceItem(
140
+ node=instance,
141
+ parent_class=self.parent_class,
142
+ )
143
+
144
+ def render_instances(self):
145
+ """Render all instances."""
146
+ for instance_item in self.children:
147
+ self.app.call_from_thread(
148
+ instance_item.update,
149
+ self.app.iolanta.render(
150
+ instance_item.node,
151
+ as_datatype=DATATYPES.title,
152
+ ),
153
+ )
154
+
155
+ def on_mount(self):
156
+ """Render the first chunk of instances."""
157
+ self.run_worker(
158
+ self.render_instances,
159
+ thread=True,
160
+ )
161
+
163
162
 
164
163
  class Bottom(Label):
165
164
  """Label below the instances list."""
@@ -198,29 +197,19 @@ class Class(Facet[Widget]):
198
197
  We have to stop if a subsequent attempt returns no results. That's why
199
198
  we can't use `funcy.distinct()` or something similar.
200
199
  """
201
- known_instances: set[NotLiteralNode] = set()
202
- while True:
203
- instances = set(
204
- funcy.pluck(
205
- 'instance',
206
- self.stored_query('instances.sparql', iri=self.iri),
207
- ),
208
- ).difference(known_instances)
209
-
210
- if not instances:
211
- return
212
-
213
- yield from instances
214
-
215
- known_instances.update(instances)
200
+ return set(
201
+ funcy.pluck(
202
+ 'instance',
203
+ self.stored_query('instances.sparql', iri=self.iri),
204
+ ),
205
+ )
216
206
 
217
207
  def show(self) -> Widget:
218
208
  """Render the instances list."""
219
209
  return InstancesBody(
220
210
  PageTitle(self.iri),
221
211
  InstancesList(
222
- instances=self.stream_instances(),
212
+ instances=list(self.stream_instances()),
223
213
  parent_class=self.iri,
224
214
  ),
225
- Bottom('Select the last element to try loading more instances.'),
226
215
  )
@@ -1,5 +1,5 @@
1
1
  SELECT ?instance WHERE {
2
- ?instance rdf:type $iri .
2
+ ?instance a $iri .
3
3
 
4
4
  FILTER(!isLiteral(?instance)) .
5
5
  } ORDER BY ?instance
@@ -0,0 +1,68 @@
1
+ from pathlib import Path
2
+
3
+ from rich.markdown import Markdown
4
+ from textual.containers import Vertical
5
+ from yarl import URL
6
+
7
+ from iolanta import Facet
8
+ from iolanta.facets.page_title import PageTitle
9
+ from iolanta.widgets.description import Description
10
+
11
+ TEXT = """
12
+ **😕 Iolanta is unable to visualize this resource**
13
+
14
+ * The URI might be incorrect;
15
+ * Or, no edges might exist which involve it;
16
+ * Or maybe Iolanta does not know of such edges.
17
+ {content}
18
+ **What can you do?**
19
+
20
+ * If you feel this might indicate a bug 🐛, please do let us know at GitHub
21
+ issues: https://github.com/iolanta.tech/iolanta/issues
22
+ """
23
+
24
+ CONTENT_TEMPLATE = """
25
+ **File content**
26
+
27
+ ```{type}
28
+ {content}
29
+ ```
30
+ """
31
+
32
+
33
+ class TextualNoFacetFound(Facet):
34
+ """Facet to handle the case when no facet is found."""
35
+
36
+ @property
37
+ def raw_content(self):
38
+ """Content of the file, if applicable."""
39
+ url = URL(self.uriref)
40
+ if url.scheme != 'file':
41
+ return None
42
+
43
+ path = Path(url.path)
44
+ if not path.is_relative_to(self.iolanta.project_root):
45
+ return None
46
+
47
+ if not path.exists():
48
+ return None
49
+
50
+ if path.is_dir():
51
+ return None
52
+
53
+ file_content = path.read_text()
54
+ return CONTENT_TEMPLATE.format(
55
+ content=file_content,
56
+ type={
57
+ '.yamlld': 'yaml',
58
+ }.get(path.suffix, ''),
59
+ )
60
+
61
+ def show(self):
62
+ """Compose the page."""
63
+ return Vertical(
64
+ PageTitle(self.this),
65
+ Description(
66
+ Markdown(TEXT.format(content=self.raw_content or '')),
67
+ ),
68
+ )
@@ -28,7 +28,6 @@ from yaml_ld.errors import YAMLLDError
28
28
 
29
29
  from iolanta import entry_points, namespaces
30
30
  from iolanta.conversions import path_to_iri
31
- from iolanta.cyberspace.processor import normalize_term
32
31
  from iolanta.errors import UnresolvedIRI
33
32
  from iolanta.facets.errors import FacetError
34
33
  from iolanta.facets.facet import Facet
@@ -53,6 +52,7 @@ from iolanta.query_result import (
53
52
  format_query_bindings,
54
53
  )
55
54
  from iolanta.resolvers.python_import import PythonImportResolver
55
+ from iolanta.sparqlspace.processor import normalize_term
56
56
 
57
57
 
58
58
  class LoggerProtocol(Protocol):
@@ -161,7 +161,7 @@ class Iolanta: # noqa: WPS214
161
161
  try:
162
162
  sparql_result: SPARQLResult = self.graph.query(
163
163
  query_text,
164
- processor='cyberspace',
164
+ processor='sparqlspace',
165
165
  initBindings=kwargs,
166
166
  )
167
167
  except ParseException as err:
@@ -259,7 +259,7 @@ class Iolanta: # noqa: WPS214
259
259
  )
260
260
 
261
261
  if not quads:
262
- self.logger.warning(f'{source_file} | No data found')
262
+ self.logger.info(f'{source_file} | No data found')
263
263
  continue
264
264
 
265
265
  quad_tuples = [
@@ -73,13 +73,6 @@ def parse_quads(
73
73
  graph,
74
74
  )
75
75
 
76
- yield Quad(
77
- graph_name,
78
- RDF.type,
79
- IOLANTA.Graph,
80
- IOLANTA.meta,
81
- )
82
-
83
76
  for quad in quads:
84
77
  try:
85
78
  yield Quad(
@@ -0,0 +1,64 @@
1
+ from enum import StrEnum
2
+ from typing import Annotated
3
+
4
+ import rich
5
+ from rdflib import Node
6
+ from rdflib.query import Result
7
+ from rich.table import Table
8
+ from typer import Option, Typer
9
+
10
+ from iolanta.sparqlspace.sparqlspace import SPARQLSpace
11
+
12
+ app = Typer()
13
+
14
+
15
+ class OutputFormat(StrEnum):
16
+ """Output formats for the query command."""
17
+
18
+ CSV = 'csv' # noqa: WPS115
19
+ JSON = 'json' # noqa: WPS115
20
+ TABLE = 'table' # noqa: WPS115
21
+
22
+
23
+ def _format_node(node: Node):
24
+ return node
25
+
26
+
27
+ def _format_result(query_result: Result, output_format: OutputFormat):
28
+ match output_format:
29
+ case OutputFormat.CSV:
30
+ return query_result.serialize(format='csv').decode()
31
+
32
+ case OutputFormat.JSON:
33
+ return query_result.serialize(format='json').decode()
34
+
35
+ case OutputFormat.TABLE:
36
+ table = Table(*query_result.vars)
37
+ for row in query_result:
38
+ table.add_row(
39
+ *[
40
+ _format_node(node)
41
+ for node in row
42
+ ],
43
+ )
44
+ return table
45
+
46
+ raise NotImplementedError(f'Output format {output_format} not implemented.')
47
+
48
+
49
+ @app.command(name='query')
50
+ def query_command(
51
+ query: str,
52
+ output_format: Annotated[
53
+ OutputFormat,
54
+ Option(help='Output format.'),
55
+ ] = OutputFormat.TABLE,
56
+ ):
57
+ """Execute a SPARQL query."""
58
+ query_result = SPARQLSpace().query(query)
59
+ rich.print(
60
+ _format_result(
61
+ query_result=query_result,
62
+ output_format=output_format,
63
+ ),
64
+ )