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.
Files changed (135) hide show
  1. {iolanta-2.1.1 → iolanta-2.1.4}/PKG-INFO +5 -7
  2. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/main.py +45 -25
  3. iolanta-2.1.4/iolanta/declension/data/declension.yamlld +39 -0
  4. iolanta-2.1.4/iolanta/declension/facet.py +44 -0
  5. iolanta-2.1.4/iolanta/declension/sparql/declension.sparql +8 -0
  6. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/cli/record.py +2 -2
  7. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/facet.py +1 -22
  8. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/foaf_person_title/facet.py +2 -2
  9. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/generic/bool_literal.py +3 -3
  10. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/generic/date_literal.py +1 -1
  11. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/generic/default.py +2 -2
  12. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/html/code_literal.py +3 -3
  13. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/icon.py +1 -1
  14. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/locator.py +1 -4
  15. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/qname.py +2 -2
  16. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/app.py +7 -3
  17. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/facet.py +1 -1
  18. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/page_switcher.py +12 -17
  19. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_class/facets.py +3 -3
  20. iolanta-2.1.4/iolanta/facets/textual_class/sparql/instances.sparql +8 -0
  21. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/facets.py +5 -5
  22. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/widgets.py +1 -1
  23. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_graph/facets.py +3 -3
  24. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_graph_triples.py +1 -1
  25. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_link/facet.py +4 -4
  26. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_nanopublication/facet.py +1 -1
  27. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_no_facet_found.py +3 -1
  28. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_ontology/facets.py +3 -3
  29. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_provenance/facets.py +1 -1
  30. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/title/facets.py +1 -4
  31. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/wikibase_statement_title/facets.py +2 -2
  32. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/iolanta.py +2 -2
  33. iolanta-2.1.4/iolanta/labeled_triple_set/data/labeled_triple_set.yamlld +42 -0
  34. iolanta-2.1.4/iolanta/labeled_triple_set/labeled_triple_set.py +137 -0
  35. iolanta-2.1.4/iolanta/labeled_triple_set/sparql/triples.sparql +5 -0
  36. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/mermaid/models.py +34 -7
  37. iolanta-2.1.4/iolanta/sparqlspace/__init__.py +0 -0
  38. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/sparqlspace/processor.py +4 -1
  39. iolanta-2.1.4/iolanta/widgets/__init__.py +0 -0
  40. {iolanta-2.1.1 → iolanta-2.1.4}/pyproject.toml +5 -4
  41. iolanta-2.1.1/iolanta/facets/textual_class/sparql/instances.sparql +0 -5
  42. {iolanta-2.1.1 → iolanta-2.1.4}/README.md +0 -0
  43. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/__init__.py +0 -0
  44. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/base_plugin.py +0 -0
  45. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/__init__.py +0 -0
  46. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/formatters/__init__.py +0 -0
  47. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/formatters/choose.py +0 -0
  48. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/formatters/csv.py +0 -0
  49. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/formatters/json.py +0 -0
  50. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/formatters/pretty.py +0 -0
  51. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/models.py +0 -0
  52. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/cli/pretty_print.py +0 -0
  53. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/context.py +0 -0
  54. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/conversions.py +0 -0
  55. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/data/context.yaml +0 -0
  56. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/data/graph-triples.yamlld +0 -0
  57. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/data/iolanta.yaml +0 -0
  58. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/data/textual-browser.yaml +0 -0
  59. {iolanta-2.1.1/iolanta/mermaid → iolanta-2.1.4/iolanta/declension}/__init__.py +0 -0
  60. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/ensure_is_context.py +0 -0
  61. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/entry_points.py +0 -0
  62. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/errors.py +0 -0
  63. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/__init__.py +0 -0
  64. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/cli/__init__.py +0 -0
  65. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/cli/base.py +0 -0
  66. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/cli/default.py +0 -0
  67. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/cli/sparql/link.sparql +0 -0
  68. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/cli/sparql/record.sparql +0 -0
  69. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/errors.py +0 -0
  70. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/foaf_person_title/__init__.py +0 -0
  71. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/foaf_person_title/sparql/names.sparql +0 -0
  72. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/generic/__init__.py +0 -0
  73. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/generic/sparql/default.sparql +0 -0
  74. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/html/__init__.py +0 -0
  75. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/html/base.py +0 -0
  76. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/html/default.py +0 -0
  77. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/page_title.py +0 -0
  78. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/__init__.py +0 -0
  79. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/history.py +0 -0
  80. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/home.py +0 -0
  81. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/location.py +0 -0
  82. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/models.py +0 -0
  83. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_browser/page.py +0 -0
  84. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_class/__init__.py +0 -0
  85. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/__init__.py +0 -0
  86. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/sparql/inverse-properties.sparql +0 -0
  87. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/sparql/label.sparql +0 -0
  88. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/sparql/nodes-for-property.sparql +0 -0
  89. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/sparql/properties.sparql +0 -0
  90. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/tcss/default.tcss +0 -0
  91. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/templates/default.md +0 -0
  92. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_default/triple_uri_ref.py +0 -0
  93. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_graph/__init__.py +0 -0
  94. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_graph/sparql/triples.sparql +0 -0
  95. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_link/__init__.py +0 -0
  96. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_nanopublication/__init__.py +0 -0
  97. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_nanopublication/models.py +0 -0
  98. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_nanopublication/nanopublication_widget.py +0 -0
  99. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_nanopublication/term_list_widget.py +0 -0
  100. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_nanopublication/term_widget.py +0 -0
  101. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_ontology/__init__.py +0 -0
  102. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_ontology/sparql/terms.sparql +0 -0
  103. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_ontology/sparql/visualization-vocab.sparql +0 -0
  104. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_property_pairs_table.py +0 -0
  105. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_provenance/__init__.py +0 -0
  106. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_provenance/sparql/graphs.sparql +0 -0
  107. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/textual_provenance/sparql/triples.sparql +0 -0
  108. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/title/__init__.py +0 -0
  109. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/title/sparql/title.sparql +0 -0
  110. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/wikibase_statement_title/__init__.py +0 -0
  111. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/facets/wikibase_statement_title/sparql/statement-title.sparql +0 -0
  112. {iolanta-2.1.1/iolanta/resolvers → iolanta-2.1.4/iolanta/labeled_triple_set}/__init__.py +0 -0
  113. {iolanta-2.1.1/iolanta/sparqlspace → iolanta-2.1.4/iolanta/mermaid}/__init__.py +0 -0
  114. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/mermaid/facet.py +0 -0
  115. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/mermaid/mermaid.yamlld +0 -0
  116. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/mermaid/sparql/graph.sparql +0 -0
  117. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/mermaid/sparql/subgraphs.sparql +0 -0
  118. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/models.py +0 -0
  119. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/namespaces.py +0 -0
  120. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/node_to_qname.py +0 -0
  121. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/parse_quads.py +0 -0
  122. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/plugin.py +0 -0
  123. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/query_result.py +0 -0
  124. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/reformat_blank_nodes.py +0 -0
  125. {iolanta-2.1.1/iolanta/widgets → iolanta-2.1.4/iolanta/resolvers}/__init__.py +0 -0
  126. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/resolvers/base.py +0 -0
  127. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/resolvers/dispatch.py +0 -0
  128. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/resolvers/pypi.py +0 -0
  129. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/resolvers/python_import.py +0 -0
  130. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/sparqlspace/cli.py +0 -0
  131. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/sparqlspace/inference/wikibase-claim.sparql +0 -0
  132. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/sparqlspace/inference/wikibase-statement-property.sparql +0 -0
  133. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/sparqlspace/sparqlspace.py +0 -0
  134. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/widgets/description.py +0 -0
  135. {iolanta-2.1.1 → iolanta-2.1.4}/iolanta/widgets/mixin.py +0 -0
@@ -1,16 +1,15 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: iolanta
3
- Version: 2.1.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.10,<4.0
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.10)
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
- def construct_app() -> Typer:
26
- """
27
- Construct Typer app.
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
- logger = loguru.logger
89
- logger.add(
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=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=URIRef(as_datatype),
130
+ as_datatype=decode_datatype(as_datatype),
117
131
  )
118
132
 
119
133
  except DocumentedError as documented_error:
120
- if iolanta.logger.level in {logging.DEBUG, logging.INFO}:
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
- print(renderable)
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
@@ -0,0 +1,8 @@
1
+ PREFIX lexinfo: <https://www.lexinfo.net/ontology/2.0/lexinfo#>
2
+
3
+ SELECT * WHERE {
4
+ ?declension
5
+ rdf:type $this ;
6
+ lexinfo:person ?person ;
7
+ lexinfo:number ?number .
8
+ }
@@ -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.iri)
20
+ rows = self.stored_query('record.sparql', node=self.this)
21
21
 
22
- caption = self.render(self.iri, as_datatype=IOLANTA['cli/title'])
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
- iri: NotLiteralNode
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.iri))
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.iri,
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.iri, Literal):
12
+ if not isinstance(self.this, Literal):
13
13
  raise NotALiteral(
14
- node=self.iri,
14
+ node=self.this,
15
15
  )
16
16
 
17
- return '✔️' if self.iri.value else '❌'
17
+ return '✔️' if self.this.value else '❌'
@@ -11,7 +11,7 @@ class DateLiteral(Facet):
11
11
 
12
12
  def show(self):
13
13
  """Render date or datetime as a date."""
14
- literal = cast(Literal, self.iri)
14
+ literal = cast(Literal, self.this)
15
15
 
16
16
  date_value = literal.value
17
17
 
@@ -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.iri),
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.iri)
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.iri, Literal):
12
+ if not isinstance(self.this, Literal):
13
13
  raise NotALiteral(
14
- node=self.iri,
14
+ node=self.this,
15
15
  )
16
16
 
17
- return f'<code>{self.iri.value}</code>'
17
+ return f'<code>{self.this.value}</code>'
@@ -15,7 +15,7 @@ class IconFacet(Facet[str]):
15
15
  $iri iolanta:icon ?icon .
16
16
  }
17
17
  """,
18
- iri=self.iri,
18
+ iri=self.this,
19
19
  ),
20
20
  )
21
21
 
@@ -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.iri,
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.iri)
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, iri: Node):
48
+ def __init__(self, iolanta: Iolanta, this: Node):
49
49
  """Set up parameters for the browser."""
50
50
  self.iolanta = iolanta
51
- self.iri = iri
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
- self.iolanta.logger.remove(0)
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(
@@ -20,7 +20,7 @@ class TextualBrowserFacet(Facet[ReturnType | None]):
20
20
 
21
21
  app = IolantaBrowser(
22
22
  iolanta=self.iolanta,
23
- iri=self.iri,
23
+ this=self.this,
24
24
  )
25
25
  try:
26
26
  app.run()
@@ -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
  )
@@ -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
- 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
  )
@@ -0,0 +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
+
4
+ SELECT ?instance WHERE {
5
+ ?instance rdf:type $this .
6
+
7
+ FILTER(!isLiteral(?instance)) .
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