iolanta 2.0.7__tar.gz → 2.1.1__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 (129) hide show
  1. {iolanta-2.0.7 → iolanta-2.1.1}/PKG-INFO +4 -3
  2. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/cli/main.py +1 -1
  3. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/data/graph-triples.yamlld +2 -2
  4. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/data/textual-browser.yaml +23 -22
  5. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_browser/page_switcher.py +1 -1
  6. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_default/widgets.py +1 -1
  7. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/title/facets.py +3 -1
  8. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/title/sparql/title.sparql +11 -1
  9. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/iolanta.py +33 -66
  10. iolanta-2.1.1/iolanta/mermaid/facet.py +127 -0
  11. iolanta-2.1.1/iolanta/mermaid/mermaid.yamlld +42 -0
  12. iolanta-2.1.1/iolanta/mermaid/models.py +129 -0
  13. iolanta-2.1.1/iolanta/mermaid/sparql/graph.sparql +5 -0
  14. iolanta-2.1.1/iolanta/mermaid/sparql/subgraphs.sparql +3 -0
  15. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/namespaces.py +1 -1
  16. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/parse_quads.py +2 -1
  17. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/resolvers/base.py +2 -1
  18. iolanta-2.1.1/iolanta/resolvers/dispatch.py +41 -0
  19. iolanta-2.1.1/iolanta/resolvers/pypi.py +106 -0
  20. iolanta-2.1.1/iolanta/resolvers/python_import.py +17 -0
  21. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/sparqlspace/processor.py +27 -4
  22. iolanta-2.1.1/iolanta/widgets/__init__.py +0 -0
  23. {iolanta-2.0.7 → iolanta-2.1.1}/pyproject.toml +26 -3
  24. iolanta-2.0.7/iolanta/data/cli.yaml +0 -30
  25. iolanta-2.0.7/iolanta/data/html.yaml +0 -15
  26. iolanta-2.0.7/iolanta/resolvers/python_import.py +0 -40
  27. {iolanta-2.0.7 → iolanta-2.1.1}/README.md +0 -0
  28. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/__init__.py +0 -0
  29. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/base_plugin.py +0 -0
  30. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/cli/__init__.py +0 -0
  31. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/cli/formatters/__init__.py +0 -0
  32. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/cli/formatters/choose.py +0 -0
  33. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/cli/formatters/csv.py +0 -0
  34. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/cli/formatters/json.py +0 -0
  35. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/cli/formatters/pretty.py +0 -0
  36. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/cli/models.py +0 -0
  37. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/cli/pretty_print.py +0 -0
  38. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/context.py +0 -0
  39. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/conversions.py +0 -0
  40. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/data/context.yaml +0 -0
  41. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/data/iolanta.yaml +0 -0
  42. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/ensure_is_context.py +0 -0
  43. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/entry_points.py +0 -0
  44. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/errors.py +0 -0
  45. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/__init__.py +0 -0
  46. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/cli/__init__.py +0 -0
  47. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/cli/base.py +0 -0
  48. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/cli/default.py +0 -0
  49. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/cli/record.py +0 -0
  50. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/cli/sparql/link.sparql +0 -0
  51. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/cli/sparql/record.sparql +0 -0
  52. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/errors.py +0 -0
  53. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/facet.py +0 -0
  54. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/foaf_person_title/__init__.py +0 -0
  55. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/foaf_person_title/facet.py +0 -0
  56. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/foaf_person_title/sparql/names.sparql +0 -0
  57. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/generic/__init__.py +0 -0
  58. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/generic/bool_literal.py +0 -0
  59. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/generic/date_literal.py +0 -0
  60. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/generic/default.py +0 -0
  61. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/generic/sparql/default.sparql +0 -0
  62. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/html/__init__.py +0 -0
  63. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/html/base.py +0 -0
  64. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/html/code_literal.py +0 -0
  65. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/html/default.py +0 -0
  66. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/icon.py +0 -0
  67. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/locator.py +0 -0
  68. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/page_title.py +0 -0
  69. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/qname.py +0 -0
  70. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_browser/__init__.py +0 -0
  71. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_browser/app.py +0 -0
  72. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_browser/facet.py +0 -0
  73. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_browser/history.py +0 -0
  74. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_browser/home.py +0 -0
  75. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_browser/location.py +0 -0
  76. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_browser/models.py +0 -0
  77. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_browser/page.py +0 -0
  78. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_class/__init__.py +0 -0
  79. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_class/facets.py +0 -0
  80. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_class/sparql/instances.sparql +0 -0
  81. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_default/__init__.py +0 -0
  82. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_default/facets.py +0 -0
  83. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_default/sparql/inverse-properties.sparql +0 -0
  84. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_default/sparql/label.sparql +0 -0
  85. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_default/sparql/nodes-for-property.sparql +0 -0
  86. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_default/sparql/properties.sparql +0 -0
  87. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_default/tcss/default.tcss +0 -0
  88. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_default/templates/default.md +0 -0
  89. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_default/triple_uri_ref.py +0 -0
  90. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_graph/__init__.py +0 -0
  91. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_graph/facets.py +0 -0
  92. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_graph/sparql/triples.sparql +0 -0
  93. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_graph_triples.py +0 -0
  94. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_link/__init__.py +0 -0
  95. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_link/facet.py +0 -0
  96. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_nanopublication/__init__.py +0 -0
  97. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_nanopublication/facet.py +0 -0
  98. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_nanopublication/models.py +0 -0
  99. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_nanopublication/nanopublication_widget.py +0 -0
  100. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_nanopublication/term_list_widget.py +0 -0
  101. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_nanopublication/term_widget.py +0 -0
  102. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_no_facet_found.py +0 -0
  103. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_ontology/__init__.py +0 -0
  104. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_ontology/facets.py +0 -0
  105. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_ontology/sparql/terms.sparql +0 -0
  106. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_ontology/sparql/visualization-vocab.sparql +0 -0
  107. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_property_pairs_table.py +0 -0
  108. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_provenance/__init__.py +0 -0
  109. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_provenance/facets.py +0 -0
  110. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_provenance/sparql/graphs.sparql +0 -0
  111. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/textual_provenance/sparql/triples.sparql +0 -0
  112. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/title/__init__.py +0 -0
  113. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/wikibase_statement_title/__init__.py +0 -0
  114. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/wikibase_statement_title/facets.py +0 -0
  115. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/facets/wikibase_statement_title/sparql/statement-title.sparql +0 -0
  116. {iolanta-2.0.7/iolanta/resolvers → iolanta-2.1.1/iolanta/mermaid}/__init__.py +0 -0
  117. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/models.py +0 -0
  118. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/node_to_qname.py +0 -0
  119. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/plugin.py +0 -0
  120. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/query_result.py +0 -0
  121. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/reformat_blank_nodes.py +0 -0
  122. {iolanta-2.0.7/iolanta/sparqlspace → iolanta-2.1.1/iolanta/resolvers}/__init__.py +0 -0
  123. {iolanta-2.0.7/iolanta/widgets → iolanta-2.1.1/iolanta/sparqlspace}/__init__.py +0 -0
  124. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/sparqlspace/cli.py +0 -0
  125. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/sparqlspace/inference/wikibase-claim.sparql +0 -0
  126. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/sparqlspace/inference/wikibase-statement-property.sparql +0 -0
  127. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/sparqlspace/sparqlspace.py +0 -0
  128. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/widgets/description.py +0 -0
  129. {iolanta-2.0.7 → iolanta-2.1.1}/iolanta/widgets/mixin.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: iolanta
3
- Version: 2.0.7
3
+ Version: 2.1.1
4
4
  Summary: Semantic Web browser
5
5
  License: MIT
6
6
  Author: Anatoly Scherbakov
@@ -24,6 +24,7 @@ Requires-Dist: more-itertools (>=9.0.0)
24
24
  Requires-Dist: nanopub (>=2.0.1)
25
25
  Requires-Dist: owlrl (>=6.0.2)
26
26
  Requires-Dist: oxrdflib (>=0.4.0)
27
+ Requires-Dist: packageurl-python (>=0.17.5)
27
28
  Requires-Dist: python-frontmatter (>=0.5.0)
28
29
  Requires-Dist: rdflib (<8.0)
29
30
  Requires-Dist: reasonable (>=0.2.6)
@@ -31,8 +32,8 @@ Requires-Dist: requests (>=2.25.1)
31
32
  Requires-Dist: rich (>=13.3.1)
32
33
  Requires-Dist: textual (>=0.83.0)
33
34
  Requires-Dist: typer (>=0.9.0)
34
- Requires-Dist: watchfiles (>=1.0.4,<2.0.0)
35
- Requires-Dist: yaml-ld (>=1.1.9)
35
+ Requires-Dist: watchfiles (>=1.0.4)
36
+ Requires-Dist: yaml-ld (>=1.1.10)
36
37
  Requires-Dist: yarl (>=1.9.4)
37
38
  Description-Content-Type: text/markdown
38
39
 
@@ -136,4 +136,4 @@ def render_command( # noqa: WPS231, WPS238, WPS210, C901
136
136
  raise Exit(1)
137
137
 
138
138
  else:
139
- Console().print(renderable)
139
+ print(renderable)
@@ -1,6 +1,6 @@
1
1
  "@context": context.yaml
2
- $id: python://iolanta.facets.textual_graph.GraphFacet
2
+ $id: pkg:pypi/iolanta#textual-graph
3
3
  $: Graph Triples
4
4
  →: https://iolanta.tech/cli/textual
5
- ⪯: python://iolanta.facets.textual_default.InverseProperties
5
+ ⪯: pkg:pypi/iolanta#textual-inverse-properties
6
6
  ↦: ASK WHERE { GRAPH $this { ?s ?p ?o } }
@@ -30,6 +30,8 @@
30
30
  "@id": iolanta:is-preferred-over
31
31
 
32
32
  ↦: iolanta:matches
33
+ iolanta:hasDefaultFacet:
34
+ "@type": "@id"
33
35
 
34
36
  "@included":
35
37
  - $id: iolanta:icon
@@ -42,26 +44,25 @@
42
44
  - $id: https://iolanta.tech/datatypes/icon
43
45
  $: Icon
44
46
  iolanta:hasDefaultFacet:
45
- $id: python://iolanta.facets.icon.IconFacet
47
+ $id: pkg:pypi/iolanta#icon
46
48
  →: https://iolanta.tech/datatypes/icon
47
49
 
48
50
  - $id: np:Nanopublication
49
51
  $: Nanopublication
50
52
  iolanta:hasInstanceFacet:
51
- $id: python://iolanta.facets.textual_nanopublication.NanopublicationFacet
53
+ $id: pkg:pypi/iolanta#textual-nanopublication
52
54
  $: Nanopublication
53
55
  →: https://iolanta.tech/cli/textual
54
56
  ⪯:
55
- - python://iolanta.facets.textual_default.TextualDefaultFacet
56
- - python://iolanta.facets.textual_graph.GraphFacet
57
+ - pkg:pypi/iolanta#textual-properties
58
+ - pkg:pypi/iolanta#textual-graph
57
59
 
58
60
  - $id: https://iolanta.tech/cli/interactive
59
- iolanta:hasDefaultFacet:
60
- $id: python://iolanta.facets.textual_browser.TextualBrowserFacet
61
+ iolanta:hasDefaultFacet: pkg:pypi/iolanta#textual-browser
61
62
 
62
- - $id: python://iolanta.facets.textual_default.TextualDefaultFacet
63
+ - $id: pkg:pypi/iolanta#textual-properties
63
64
  $: Properties
64
- ⪯: python://iolanta.facets.textual_default.InverseProperties
65
+ ⪯: pkg:pypi/iolanta#textual-inverse-properties
65
66
  →: https://iolanta.tech/cli/textual
66
67
  ↦: |
67
68
  ASK WHERE {
@@ -69,7 +70,7 @@
69
70
  FILTER (?graph != <iolanta://_meta>)
70
71
  }
71
72
 
72
- - $id: python://iolanta.facets.textual_default.InverseProperties
73
+ - $id: pkg:pypi/iolanta#textual-inverse-properties
73
74
  $: Inverse Properties
74
75
  →: https://iolanta.tech/cli/textual
75
76
  ↦: |
@@ -80,54 +81,54 @@
80
81
 
81
82
  - $id: "urn:"
82
83
  iolanta:hasFacetByPrefix:
83
- $id: python://iolanta.facets.textual_provenance.TextualProvenanceFacet
84
+ $id: pkg:pypi/iolanta#textual-provenance
84
85
  →: https://iolanta.tech/cli/textual
85
86
 
86
87
  - $id: https://iolanta.tech/cli/link
87
88
  iolanta:hasDefaultFacet:
88
- $id: python://iolanta.facets.textual_link.TextualLinkFacet
89
+ $id: pkg:pypi/iolanta#textual-link
89
90
 
90
91
  - $id: https://wikiba.se/ontology#Statement
91
92
  iolanta:hasInstanceFacet:
92
- $id: python://iolanta.facets.wikibase_statement_title.WikibaseStatementTitle
93
+ $id: pkg:pypi/iolanta#wikibase-statement-title
93
94
  $: Title
94
95
  →: https://iolanta.tech/datatypes/title
95
96
 
96
97
  - $id: rdfs:Class
97
98
  iolanta:hasInstanceFacet:
98
- $id: python://iolanta.facets.textual_class.Class
99
+ $id: pkg:pypi/iolanta#textual-class
99
100
  $: Instances
100
101
  →: https://iolanta.tech/cli/textual
101
102
  ⪯:
102
- - python://iolanta.facets.textual_browser.TextualBrowserFacet
103
- - python://iolanta.facets.textual_default.InverseProperties
103
+ - pkg:pypi/iolanta#textual-browser
104
+ - pkg:pypi/iolanta#textual-inverse-properties
104
105
 
105
106
  - $id: owl:Ontology
106
107
  iolanta:hasInstanceFacet:
107
- $id: python://iolanta.facets.textual_ontology.OntologyFacet
108
+ $id: pkg:pypi/iolanta#textual-ontology
108
109
  $: Ontology
109
110
  →: https://iolanta.tech/cli/textual
110
- ⪯: python://iolanta.facets.textual_default.TextualDefaultFacet
111
+ ⪯: pkg:pypi/iolanta#textual-properties
111
112
 
112
113
  - $id: https://iolanta.tech/datatypes/textual-graph-triples
113
114
  $: Graph Triples
114
115
  iolanta:hasDefaultFacet:
115
- $id: python://iolanta.facets.textual_graph_triples.GraphTriplesFacet
116
+ $id: pkg:pypi/iolanta#textual-graph-triples
116
117
  →: https://iolanta.tech/datatypes/textual-graph-triples
117
118
 
118
119
  - $id: https://iolanta.tech/qname
119
120
  iolanta:hasDefaultFacet:
120
- $id: python://iolanta.facets.qname.QNameFacet
121
+ $id: pkg:pypi/iolanta#qname
121
122
 
122
- - $id: python://iolanta.facets.textual_property_pairs_table.TextualPropertyPairsTableFacet
123
+ - $id: pkg:pypi/iolanta#textual-property-pairs
123
124
  $: Subjects → Objects
124
125
  →: https://iolanta.tech/cli/textual
125
126
  ↦: ASK WHERE { ?subject $this ?object }
126
127
 
127
- - $id: python://iolanta.facets.textual_class.Class
128
+ - $id: pkg:pypi/iolanta#textual-class
128
129
  ↦:
129
130
  - ASK WHERE { ?instance a $this }
130
131
  - ASK WHERE { $this rdfs:subClassOf ?superclass }
131
132
 
132
133
  - $id: https://iolanta.tech/cli/textual
133
- iolanta:when-no-facet-found: python://iolanta.facets.textual_no_facet_found.TextualNoFacetFound
134
+ iolanta:when-no-facet-found: pkg:pypi/iolanta#textual-no-facet-found
@@ -136,7 +136,7 @@ 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
142
  iri=self.iri,
@@ -291,7 +291,7 @@ class LiteralPropertyValue(Widget, can_focus=True, inherit_bindings=False):
291
291
  self.property_iri = property_iri
292
292
  super().__init__()
293
293
  self.renderable = Text( # noqa: WPS601
294
- str(property_value.value),
294
+ str(property_value),
295
295
  style='#696969',
296
296
  )
297
297
 
@@ -9,6 +9,8 @@ PRIORITIES = [ # noqa: WPS407
9
9
  'schema_name',
10
10
  'rdfs_label',
11
11
  'foaf_name',
12
+ 'literal_form',
13
+ 'preferred_label',
12
14
  ]
13
15
 
14
16
 
@@ -19,7 +21,7 @@ class TitleFacet(Facet[str]):
19
21
  """Render title of a thing."""
20
22
  choices = self.stored_query(
21
23
  'title.sparql',
22
- iri=self.iri,
24
+ iri=self.this,
23
25
  language=self.iolanta.language,
24
26
  )
25
27
 
@@ -23,4 +23,14 @@ SELECT * WHERE {
23
23
  $iri <https://xmlns.com/foaf/0.1/name> ?foaf_name .
24
24
  FILTER (!lang(?foaf_name) || lang(?foaf_name) = $language)
25
25
  }
26
- }
26
+
27
+ OPTIONAL {
28
+ $iri <https://www.w3.org/2008/05/skos-xl#literalForm> ?literal_form .
29
+ FILTER (!lang(?literal_form) || lang(?literal_form) = $language)
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
+ }
36
+ }
@@ -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,7 +289,7 @@ 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
295
  iri=node,
@@ -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,
@@ -0,0 +1,127 @@
1
+ import functools
2
+ from pathlib import Path
3
+ from typing import Iterable
4
+
5
+ import boltons
6
+ import cachetools
7
+ import funcy
8
+ from boltons.cacheutils import cached, cachedmethod
9
+ from pydantic import AnyUrl
10
+ from rdflib import BNode, Literal, Node, URIRef
11
+
12
+ from iolanta import Facet
13
+ from iolanta.mermaid.models import (
14
+ Diagram,
15
+ MermaidBlankNode,
16
+ MermaidEdge,
17
+ MermaidLiteral,
18
+ MermaidScalar,
19
+ MermaidSubgraph,
20
+ MermaidURINode,
21
+ )
22
+ from iolanta.models import NotLiteralNode
23
+ from iolanta.namespaces import DATATYPES
24
+
25
+
26
+ def filter_edges(edges: Iterable[MermaidEdge]) -> Iterable[MermaidEdge]:
27
+ for edge in edges:
28
+ if isinstance(edge.target, MermaidLiteral) and edge.source.title == edge.target.title:
29
+ continue
30
+
31
+ yield edge
32
+
33
+
34
+ def filter_nodes(edges: Iterable[MermaidEdge], except_uris: Iterable[NotLiteralNode]) -> Iterable[MermaidURINode | MermaidLiteral | MermaidBlankNode]:
35
+ nodes = [
36
+ node
37
+ for edge in edges
38
+ for node in edge.nodes
39
+ ]
40
+
41
+ literals_in_edges = {edge.target for edge in edges if isinstance(edge.target, MermaidLiteral)}
42
+ for node in nodes:
43
+ if isinstance(node, MermaidLiteral) and node not in literals_in_edges:
44
+ continue
45
+
46
+ if isinstance(node, MermaidURINode) and node.uri in except_uris:
47
+ continue
48
+
49
+ if isinstance(node, MermaidBlankNode) and node.node in except_uris:
50
+ continue
51
+
52
+ if isinstance(node, MermaidSubgraph):
53
+ continue
54
+
55
+ yield node
56
+
57
+
58
+ class Mermaid(Facet[str]):
59
+ """Mermaid diagram."""
60
+
61
+ META = Path(__file__).parent / 'mermaid.yamlld'
62
+
63
+ def as_mermaid(self, node: Node):
64
+ match node:
65
+ case URIRef() as uri:
66
+ if uri in self.subgraph_uris:
67
+ return MermaidSubgraph(children=[], uri=uri, title=self.render(uri, as_datatype=DATATYPES.title))
68
+
69
+ return MermaidURINode(uri=uri, url=AnyUrl(uri), title=self.render(uri, as_datatype=DATATYPES.title))
70
+ case Literal() as literal:
71
+ return MermaidLiteral(literal=literal)
72
+ case BNode() as bnode:
73
+ return MermaidBlankNode(node=bnode, title=self.render(bnode, as_datatype=DATATYPES.title))
74
+ case unknown:
75
+ unknown_type = type(unknown)
76
+ raise ValueError(f'Unknown something: {unknown} ({unknown_type})')
77
+
78
+ def construct_mermaid_for_graph(self, graph: URIRef) -> Iterable[MermaidScalar]:
79
+ """Render graph as mermaid."""
80
+ rows = self.stored_query('graph.sparql', this=graph)
81
+ edges = [
82
+ MermaidEdge(
83
+ source=self.as_mermaid(row['s']),
84
+ target=self.as_mermaid(row['o']),
85
+ title=self.render(row['p'], as_datatype=DATATYPES.title),
86
+ predicate=row['p'],
87
+ ) for row in rows
88
+ ]
89
+
90
+ edges = list(filter_edges(edges))
91
+ nodes = list(
92
+ filter_nodes(
93
+ edges=edges,
94
+ except_uris=self.subgraph_uris,
95
+ ),
96
+ )
97
+
98
+ return *nodes, *edges
99
+
100
+ @functools.cached_property
101
+ def subgraph_uris(self) -> set[NotLiteralNode]:
102
+ return set(
103
+ funcy.pluck(
104
+ 'subgraph',
105
+ self.stored_query('subgraphs.sparql', this=self.this),
106
+ ),
107
+ )
108
+
109
+ def construct_mermaid_subgraphs(self) -> Iterable[MermaidSubgraph]:
110
+ for subgraph_uri in self.subgraph_uris:
111
+ children = list(self.construct_mermaid_for_graph(subgraph_uri))
112
+ if children:
113
+ title = self.render(subgraph_uri, as_datatype=DATATYPES.title)
114
+ yield MermaidSubgraph(
115
+ children=children,
116
+ uri=subgraph_uri,
117
+ title=title,
118
+ )
119
+
120
+ def show(self) -> str:
121
+ """Render mermaid diagram."""
122
+ direct_children = self.construct_mermaid_for_graph(self.this)
123
+ subgraphs = self.construct_mermaid_subgraphs()
124
+ return str(Diagram(children=[*direct_children, *subgraphs]))
125
+
126
+
127
+
@@ -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#mermaid-graph
36
+ $: Mermaid Graph
37
+ →:
38
+ $id: https://iolanta.tech/datatypes/mermaid
39
+ $: Mermaid
40
+ ↦:
41
+ - ASK WHERE { GRAPH $this { ?s ?p ?o } }
42
+ - ASK WHERE { $this iolanta:has-sub-graph ?subgraph }