iolanta 2.1.1__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 (42) hide show
  1. iolanta/cli/main.py +45 -25
  2. iolanta/declension/__init__.py +0 -0
  3. iolanta/declension/data/declension.yamlld +39 -0
  4. iolanta/declension/facet.py +44 -0
  5. iolanta/declension/sparql/declension.sparql +8 -0
  6. iolanta/facets/cli/record.py +2 -2
  7. iolanta/facets/facet.py +1 -22
  8. iolanta/facets/foaf_person_title/facet.py +2 -2
  9. iolanta/facets/generic/bool_literal.py +3 -3
  10. iolanta/facets/generic/date_literal.py +1 -1
  11. iolanta/facets/generic/default.py +2 -2
  12. iolanta/facets/html/code_literal.py +3 -3
  13. iolanta/facets/icon.py +1 -1
  14. iolanta/facets/locator.py +1 -4
  15. iolanta/facets/qname.py +2 -2
  16. iolanta/facets/textual_browser/app.py +7 -3
  17. iolanta/facets/textual_browser/facet.py +1 -1
  18. iolanta/facets/textual_browser/page_switcher.py +12 -17
  19. iolanta/facets/textual_class/facets.py +3 -3
  20. iolanta/facets/textual_class/sparql/instances.sparql +4 -1
  21. iolanta/facets/textual_default/facets.py +5 -5
  22. iolanta/facets/textual_default/widgets.py +1 -1
  23. iolanta/facets/textual_graph/facets.py +3 -3
  24. iolanta/facets/textual_graph_triples.py +1 -1
  25. iolanta/facets/textual_link/facet.py +4 -4
  26. iolanta/facets/textual_nanopublication/facet.py +1 -1
  27. iolanta/facets/textual_no_facet_found.py +3 -1
  28. iolanta/facets/textual_ontology/facets.py +3 -3
  29. iolanta/facets/textual_provenance/facets.py +1 -1
  30. iolanta/facets/title/facets.py +1 -4
  31. iolanta/facets/wikibase_statement_title/facets.py +2 -2
  32. iolanta/iolanta.py +2 -2
  33. iolanta/labeled_triple_set/__init__.py +0 -0
  34. iolanta/labeled_triple_set/data/labeled_triple_set.yamlld +42 -0
  35. iolanta/labeled_triple_set/labeled_triple_set.py +137 -0
  36. iolanta/labeled_triple_set/sparql/triples.sparql +5 -0
  37. iolanta/mermaid/models.py +34 -7
  38. iolanta/sparqlspace/processor.py +4 -1
  39. {iolanta-2.1.1.dist-info → iolanta-2.1.4.dist-info}/METADATA +5 -7
  40. {iolanta-2.1.1.dist-info → iolanta-2.1.4.dist-info}/RECORD +42 -34
  41. {iolanta-2.1.1.dist-info → iolanta-2.1.4.dist-info}/WHEEL +1 -1
  42. {iolanta-2.1.1.dist-info → iolanta-2.1.4.dist-info}/entry_points.txt +2 -0
@@ -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(
@@ -31,7 +31,4 @@ class TitleFacet(Facet[str]):
31
31
  if label := row.get(alternative):
32
32
  return str(label)
33
33
 
34
- return self.render(
35
- self.iri,
36
- as_datatype=URIRef('https://iolanta.tech/qname'),
37
- )
34
+ return str(self.this)
@@ -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
@@ -292,7 +292,7 @@ class Iolanta: # noqa: WPS214
292
292
  facet_class = self.facet_resolver.resolve(found['facet'])
293
293
 
294
294
  facet = facet_class(
295
- iri=node,
295
+ this=node,
296
296
  iolanta=self,
297
297
  as_datatype=found['output_datatype'],
298
298
  )
@@ -328,7 +328,7 @@ class Iolanta: # noqa: WPS214
328
328
 
329
329
  facet_instances = [
330
330
  facet_class(
331
- iri=node,
331
+ this=node,
332
332
  iolanta=self,
333
333
  as_datatype=output_datatype,
334
334
  )
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 }
@@ -0,0 +1,137 @@
1
+ from pathlib import Path
2
+ from typing import Annotated, Iterable
3
+ from typing import Literal as TypingLiteral
4
+
5
+ from pydantic import (
6
+ AnyUrl,
7
+ BaseModel,
8
+ Field,
9
+ TypeAdapter,
10
+ field_serializer,
11
+ field_validator,
12
+ validator,
13
+ )
14
+ from rdflib import BNode, Literal, Node, URIRef
15
+
16
+ from iolanta import Facet
17
+ from iolanta.models import NotLiteralNode
18
+ from iolanta.namespaces import DATATYPES
19
+
20
+
21
+ class WithFeedback(BaseModel):
22
+ feedback: Annotated[list[str], Field(default_factory=list)]
23
+
24
+
25
+ class LabeledURI(WithFeedback, BaseModel):
26
+ type: TypingLiteral['uri'] = 'uri'
27
+ uri: AnyUrl
28
+ label: str
29
+
30
+ def construct_feedback(self) -> Iterable[str]:
31
+ if str(self.label) == str(self.uri):
32
+ yield (
33
+ 'For this URI, the label is the same as the URI. We were '
34
+ 'unable to render that URI.'
35
+ )
36
+
37
+
38
+ class LabeledBlank(WithFeedback, BaseModel):
39
+ type: TypingLiteral['blank'] = 'blank'
40
+ identifier: str
41
+ label: str
42
+
43
+
44
+ class LabeledLiteral(WithFeedback, BaseModel):
45
+ type: TypingLiteral['literal'] = 'literal'
46
+ value: str
47
+ language: str | None
48
+ datatype: str | None
49
+ label: str
50
+
51
+
52
+ class LabeledTriple(BaseModel):
53
+ subject: LabeledURI | LabeledBlank
54
+ predicate: LabeledURI
55
+ object_: LabeledURI | LabeledBlank | LabeledLiteral
56
+
57
+
58
+ def construct_uri_feedback(uri: AnyUrl, label: str) -> Iterable[str]:
59
+ if str(uri) == str(label):
60
+ yield (
61
+ 'For this URI, the label is the same as the URI. We were '
62
+ 'unable to render that URI.'
63
+ )
64
+
65
+
66
+ def construct_blank_feedback(bnode, label) -> Iterable[str]:
67
+ if str(bnode) == str(label):
68
+ yield (
69
+ 'For this blank node, the label is the same as the blank node. '
70
+ 'We were unable to render that blank node.'
71
+ )
72
+
73
+
74
+ def construct_literal_feedback(literal, label):
75
+ if label.startswith('http'):
76
+ yield (
77
+ 'This RDF literal seems to be actually a URL. Good chance is '
78
+ 'that it should not be a literal.'
79
+ )
80
+
81
+ elif ':' in label[:5]:
82
+ yield (
83
+ 'This RDF literal seems to be actually a QName (prefixed URI). '
84
+ 'Good chance is that it should not be a literal.'
85
+ )
86
+
87
+
88
+ class LabeledTripleSet(Facet[list[LabeledTriple]]):
89
+ """A set of labeled triples."""
90
+
91
+ META = Path(__file__).parent / 'data' / 'labeled_triple_set.yamlld'
92
+
93
+ def render_label(self, node: NotLiteralNode) -> str:
94
+ return self.render(node, as_datatype=DATATYPES.title)
95
+
96
+ def parse_term(self, term: Node):
97
+ match term:
98
+ case URIRef() as uriref:
99
+ uri = AnyUrl(uriref)
100
+ label = self.render_label(uriref)
101
+
102
+ return LabeledURI(
103
+ uri=uri,
104
+ label=label,
105
+ feedback=list(construct_uri_feedback(uri=uri, label=label)),
106
+ )
107
+
108
+ case BNode() as bnode:
109
+ label = self.render_label(bnode)
110
+ return LabeledBlank(
111
+ identifier=bnode,
112
+ label=label,
113
+ feedback=list(construct_blank_feedback(bnode=bnode, label=label)),
114
+ )
115
+
116
+ case Literal() as literal:
117
+ label = self.render_label(literal)
118
+ return LabeledLiteral(
119
+ value=literal,
120
+ language=literal.language,
121
+ datatype=literal.datatype,
122
+ label=label,
123
+ feedback=list(construct_literal_feedback(literal=literal, label=label)),
124
+ )
125
+
126
+ def show(self):
127
+ rows = self.stored_query('triples.sparql', graph=self.this)
128
+ triples = [
129
+ LabeledTriple(
130
+ subject=self.parse_term(row['subject']),
131
+ predicate=self.parse_term(row['predicate']),
132
+ object_=self.parse_term(row['object']),
133
+ )
134
+ for row in rows
135
+ ]
136
+
137
+ return TypeAdapter(list[LabeledTriple]).dump_json(triples, indent=2).decode()
@@ -0,0 +1,5 @@
1
+ SELECT * WHERE {
2
+ GRAPH $graph {
3
+ ?subject ?predicate ?object .
4
+ }
5
+ }
iolanta/mermaid/models.py CHANGED
@@ -1,8 +1,15 @@
1
1
  import enum
2
2
  import hashlib
3
+ import re
3
4
  import textwrap
4
5
  import urllib.parse
5
6
 
7
+
8
+ def escape_label(label: str) -> str:
9
+ """Escape a label to prevent Mermaid from interpreting URLs as markdown links."""
10
+ # Remove https://, http://, and www. prefixes to prevent markdown link parsing
11
+ return label.replace('https://', '').replace('http://', '').replace('www.', '')
12
+
6
13
  from documented import Documented
7
14
  from pydantic import AnyUrl, BaseModel
8
15
  from rdflib import BNode, Literal, URIRef
@@ -29,21 +36,27 @@ class MermaidURINode(Documented, BaseModel, arbitrary_types_allowed=True, frozen
29
36
 
30
37
  @property
31
38
  def maybe_title(self):
32
- return self.title and f'({self.title})'
39
+ if not self.title:
40
+ return ''
41
+ # Escape URLs to prevent Mermaid from interpreting them as markdown links
42
+ safe_title = escape_label(self.title)
43
+ return f'("{safe_title}")'
33
44
 
34
45
  @property
35
46
  def id(self):
36
- return urllib.parse.unquote(str(self.url)).strip('/').replace(':', '_').replace('/', '_').replace('.', '_').replace('#', '_')
47
+ return re.sub(r'[:\/\.#()]', '_', urllib.parse.unquote(str(self.url)).strip('/'))
37
48
 
38
49
 
39
50
  class MermaidLiteral(Documented, BaseModel, arbitrary_types_allowed=True, frozen=True):
40
- """{self.id}[[{self.title}]]"""
51
+ """{self.id}[["{self.title}"]]"""
41
52
 
42
53
  literal: Literal
43
54
 
44
55
  @property
45
56
  def title(self) -> str:
46
- return str(self.literal) or 'EMPTY'
57
+ raw_title = str(self.literal) or 'EMPTY'
58
+ # Replace quotes with safer characters for Mermaid
59
+ return raw_title.replace('"', '"').replace("'", "'")
47
60
 
48
61
  @property
49
62
  def id(self) -> str:
@@ -52,7 +65,7 @@ class MermaidLiteral(Documented, BaseModel, arbitrary_types_allowed=True, frozen
52
65
 
53
66
 
54
67
  class MermaidBlankNode(Documented, BaseModel, arbitrary_types_allowed=True):
55
- """{self.id}({self.title})"""
68
+ """{self.id}({self.escaped_title})"""
56
69
 
57
70
  node: BNode
58
71
  title: str
@@ -60,11 +73,15 @@ class MermaidBlankNode(Documented, BaseModel, arbitrary_types_allowed=True):
60
73
  @property
61
74
  def id(self) -> str:
62
75
  return self.node.replace('_:', '')
76
+
77
+ @property
78
+ def escaped_title(self) -> str:
79
+ return self.title
63
80
 
64
81
 
65
82
  class MermaidEdge(Documented, BaseModel, arbitrary_types_allowed=True):
66
83
  """
67
- {self.source.id} --- {self.id}(["{self.title}"])--> {self.target.id}
84
+ {self.source.id} --- {self.id}(["{self.escaped_title}"])--> {self.target.id}
68
85
  click {self.id} "{self.predicate}"
69
86
  class {self.id} predicate
70
87
  """
@@ -81,6 +98,11 @@ class MermaidEdge(Documented, BaseModel, arbitrary_types_allowed=True):
81
98
  @property
82
99
  def nodes(self):
83
100
  return [self.source, self.target]
101
+
102
+ @property
103
+ def escaped_title(self) -> str:
104
+ # Escape URLs to prevent Mermaid from interpreting them as markdown links
105
+ return escape_label(self.title)
84
106
 
85
107
 
86
108
  MermaidScalar = MermaidLiteral | MermaidBlankNode | MermaidURINode | MermaidEdge
@@ -88,7 +110,7 @@ MermaidScalar = MermaidLiteral | MermaidBlankNode | MermaidURINode | MermaidEdge
88
110
 
89
111
  class MermaidSubgraph(Documented, BaseModel, arbitrary_types_allowed=True, frozen=True):
90
112
  """
91
- subgraph {self.id}["{self.title}"]
113
+ subgraph {self.id}["{self.escaped_title}"]
92
114
  direction {self.direction}
93
115
  {self.formatted_body}
94
116
  end
@@ -102,6 +124,11 @@ class MermaidSubgraph(Documented, BaseModel, arbitrary_types_allowed=True, froze
102
124
  def id(self):
103
125
  uri_hash = hashlib.md5(str(self.uri).encode()).hexdigest()
104
126
  return f'subgraph_{uri_hash}'
127
+
128
+ @property
129
+ def escaped_title(self) -> str:
130
+ """Escape the subgraph title to prevent markdown link parsing."""
131
+ return escape_label(self.title)
105
132
 
106
133
  @property
107
134
  def formatted_body(self):
@@ -24,7 +24,7 @@ from rdflib.plugins.sparql.parserutils import CompValue
24
24
  from rdflib.plugins.sparql.sparql import Query
25
25
  from rdflib.query import Processor
26
26
  from rdflib.term import BNode, Literal, Node
27
- from requests.exceptions import ConnectionError, InvalidSchema
27
+ from requests.exceptions import ConnectionError, HTTPError, InvalidSchema
28
28
  from yaml_ld.document_loaders.content_types import ParserNotFound
29
29
  from yaml_ld.errors import NotFound, YAMLLDError
30
30
  from yarl import URL
@@ -687,6 +687,9 @@ class GlobalSPARQLProcessor(Processor): # noqa: WPS338, WPS214
687
687
  except YAMLLDError as yaml_ld_error:
688
688
  self.logger.error(f'{source} | {yaml_ld_error}')
689
689
  return Loaded()
690
+ except HTTPError as http_error:
691
+ self.logger.warning(f'{source} | HTTP error: {http_error}')
692
+ return Loaded()
690
693
 
691
694
  try:
692
695
  quads = list(
@@ -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
 
@@ -6,7 +6,7 @@ iolanta/cli/formatters/choose.py,sha256=LWzsO_9IBSSgYNIyLlItkp8TNvpW3v6YCQ8-6kbI
6
6
  iolanta/cli/formatters/csv.py,sha256=ceJ_DTz0beqeK-d6FPBQqqjXrziEfF0FRSLoGZCt_fs,760
7
7
  iolanta/cli/formatters/json.py,sha256=Og5B9UrSM_0NWqW5Afpsy6WH8ZfYgPMVXYvT3i-43Jc,748
8
8
  iolanta/cli/formatters/pretty.py,sha256=IypZRAr2vNqcXFY6NOIc75mpyfpFWh56aCBlOPDDieQ,2901
9
- iolanta/cli/main.py,sha256=GVtdBQjAOs6VlsE_uztTXHbmRXUk_S6gN4LWqACJGS8,3157
9
+ iolanta/cli/main.py,sha256=W5huhmJq97adQ7zMMEi4o8ndzxeZUEvCZAtyRLwBl-A,3865
10
10
  iolanta/cli/models.py,sha256=cjbpowdzI4wAP0DUk3qoVHyimk6AZwlXi9CGmusZTuM,159
11
11
  iolanta/cli/pretty_print.py,sha256=M6E3TmhzA6JY5GeUVmDZLmOh5u70-393PVit4voFKDI,977
12
12
  iolanta/context.py,sha256=bZR-tbZIrDQ-Vby01PMDZ6ifxM-0YMK68RJvAsyqCTs,507
@@ -15,6 +15,10 @@ iolanta/data/context.yaml,sha256=LUBasiBKgQeGAYjYV_T5XvgPlrdzACeKaZwY_rKzjtI,163
15
15
  iolanta/data/graph-triples.yamlld,sha256=rtn-HfbijaqbmjCrKv-2pVV_aaJhB_9_OqXA_yLznCs,209
16
16
  iolanta/data/iolanta.yaml,sha256=xubIFBNU02lmFXhgOSuyQwUcZD3xCqVfeVAZMvOxKbI,1433
17
17
  iolanta/data/textual-browser.yaml,sha256=nJbDS0B3G-emM9vCu2DIlWZBhzmWbO3zrWkt_Rmv5uA,3700
18
+ iolanta/declension/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ iolanta/declension/data/declension.yamlld,sha256=fA1OptmhyIK7-mNy3fbK5G07OE4ueBW2x812b7VQkzA,975
20
+ iolanta/declension/facet.py,sha256=7SsPACjeIGnONLhfjB4KBjqt-FRISVpZenshJzqC0A8,1349
21
+ iolanta/declension/sparql/declension.sparql,sha256=T84bfCNDXodmFEH26S45DyOJHoWz3T4cC7hSwtAcFSw,185
18
22
  iolanta/ensure_is_context.py,sha256=9aok8asyEx7KPesOR28VBDb3Ch9kfc3eoCpQSJwj07U,717
19
23
  iolanta/entry_points.py,sha256=DZbf-udlEwELFGqeWENj0M2BOUPOWlmGJdqyaEtnot0,504
20
24
  iolanta/errors.py,sha256=t_RltahnoEvcytVa1BOq2MADgHps3JNd_h5-SFu7_wM,1250
@@ -22,41 +26,41 @@ iolanta/facets/__init__.py,sha256=u0Ff76kmsXTaaFB8sCEfrgA_fP79rBxSqllh47d8Y0o,39
22
26
  iolanta/facets/cli/__init__.py,sha256=3XfuW-qgis0sS66lt36R2inY_NGIjNg5oGWK8fchffs,150
23
27
  iolanta/facets/cli/base.py,sha256=Fdb5PH_fPHRNexa1UgFChY4-ZFkxxVpGbAkW6yxXuIs,307
24
28
  iolanta/facets/cli/default.py,sha256=shxR2yZDGBGUr4RP_xxsX264StPuvrPu09B_hphIZkA,365
25
- iolanta/facets/cli/record.py,sha256=lBsECxLkwVSXC-yHmUwfosxAdLBI-0UoqHe8GOCablY,1219
29
+ iolanta/facets/cli/record.py,sha256=-nIhe6hXkoI5LJtZhqBoT8ZkYGxlLwMDbPc-xmwNhrE,1221
26
30
  iolanta/facets/cli/sparql/link.sparql,sha256=WtWEfLAvdGc2gP0IhZil6Vglkydc3VO24vk4GwRnR5I,163
27
31
  iolanta/facets/cli/sparql/record.sparql,sha256=GBWkmNelvaSDbvl7v0-LsJHdjFPbsSAW49kNFOUeoGQ,63
28
32
  iolanta/facets/errors.py,sha256=sEBmnzhFcRIgOT18hfNwyMMjry0waa6IB-jC2NVTA50,4124
29
- iolanta/facets/facet.py,sha256=gAOkosh9B_Lufh3ia9W24hgt4LEIhG-UJcQF4BzMvno,2600
33
+ iolanta/facets/facet.py,sha256=hV_NzUEIiy25EENXd0qGRyJ1SCRuztVdy1ZFUK3Sc44,2070
30
34
  iolanta/facets/foaf_person_title/__init__.py,sha256=oj4MNVQvv8Dysb27xiWjtZCii8-nT7-WFa3WMWUwbtU,67
31
- iolanta/facets/foaf_person_title/facet.py,sha256=Q9TajjGp1v729quDzAM_Lfzawls3yujp1Z_6jXrG3gY,632
35
+ iolanta/facets/foaf_person_title/facet.py,sha256=_lKtRosZWuKpjKZ3Ssdq79jVhiLE53jaf22Rnq4HCxs,634
32
36
  iolanta/facets/foaf_person_title/sparql/names.sparql,sha256=p_2hHZXhEaJ8IwGlvLoN0vb0vhGqo44uAVRpDyTzflU,107
33
37
  iolanta/facets/generic/__init__.py,sha256=DZTysMi4uvDzm642422W6khSvtNaqhqunbtiPyqWTL8,116
34
- iolanta/facets/generic/bool_literal.py,sha256=-M7w7h9FgGCZnhHlg-u36cshqXDcTMuedHQPtXMfoS0,398
35
- iolanta/facets/generic/date_literal.py,sha256=OWK6se6vavBfZI3-Nt6Q0dXzjq88N_tIBFM-v2QLmyU,557
36
- iolanta/facets/generic/default.py,sha256=fvJAAi0d9wd1F5SdY7V7oJRhj7qqQXAg8fq1kWw66Vs,1884
38
+ iolanta/facets/generic/bool_literal.py,sha256=0K8HRLFmSjD0gpnEAiTgEw7YylhM_rTr5XmkoVrPnf0,401
39
+ iolanta/facets/generic/date_literal.py,sha256=GFTnbAWa01CnI7yy-OG6j3dx9yZKwdfUGGsl6j8WbpY,558
40
+ iolanta/facets/generic/default.py,sha256=syFQMiypkOSFqvlUMWr1pnlw2Mf_s6WOu2S7ZysfX24,1886
37
41
  iolanta/facets/generic/sparql/default.sparql,sha256=6Z-gilWIT69Wx6mlNdKH2ocy5lkvSzkXMXDpAJA3ooU,546
38
42
  iolanta/facets/html/__init__.py,sha256=iKwhZnYEP7qe8V_inDehTPz63Qb_MjcR6c6aHHBwWxY,48
39
43
  iolanta/facets/html/base.py,sha256=JcpK7YM_QQE9vwH5w5F_EgPkPv-XRzOrcZlVSy4LhIs,163
40
- iolanta/facets/html/code_literal.py,sha256=qCddzBrg6Y5XMIKohFQ52Tf9GPOcU7bj83tfAU1FLLU,394
44
+ iolanta/facets/html/code_literal.py,sha256=hdbC304zoa9ar9Lp-dH7w079GxVGlJo8U98SOe6U82g,397
41
45
  iolanta/facets/html/default.py,sha256=Dmf_kYiL2M954iigyYsiWrMstwZ1nvxKetuR6aW3xYY,647
42
- iolanta/facets/icon.py,sha256=ddZcolx1Q5_wo3w0jqiCzcc5Lsru6-jA7s7oAd1T8Og,494
43
- iolanta/facets/locator.py,sha256=b9TEK5_5SklTfEc6lUt7DJt1mKXsiL_urA2zxMk59EY,9152
46
+ iolanta/facets/icon.py,sha256=Dubh9eCvb4kj-ppEJsTno_mn78og8YIRnDrmcefOsgs,495
47
+ iolanta/facets/locator.py,sha256=GE6vPmNiapQrjZy8aYneAl5W9TuvYuVQzABKlsUtsa0,9091
44
48
  iolanta/facets/page_title.py,sha256=TwgZK2g_e5UoWYjKNgDzzkmq1EI3cY58680iC8N9kZI,1407
45
- iolanta/facets/qname.py,sha256=ztyBbjjcW8dNZzuiNMqhcWfAUxk-gSjbseVGrQE7kVY,531
49
+ iolanta/facets/qname.py,sha256=Z2wjDWV90Z4vuwLj31MSf5EBGTb0dxzjlKl-Iv4dPao,533
46
50
  iolanta/facets/textual_browser/__init__.py,sha256=sKgDvXOwib9n9d63kdtKCEv26-FoL0VN6zxDmfcheZ8,104
47
- iolanta/facets/textual_browser/app.py,sha256=6-cmEkwRqj9UptVvXKVNIxT3PcDDOZP1OLpv8gPmB_Q,3202
48
- iolanta/facets/textual_browser/facet.py,sha256=zFynpMWr0iYaem-imbft5-2tjbkrDQEndYfHDlqqHUQ,740
51
+ iolanta/facets/textual_browser/app.py,sha256=rF34KbWi0L-Mozwzm-wzBS-3OqCcwbaXl0GZCl4YpAg,3503
52
+ iolanta/facets/textual_browser/facet.py,sha256=5mX1l6P-Ga7buzXmItxSpta6G_D4Fvwv8H6mU8-3g80,742
49
53
  iolanta/facets/textual_browser/history.py,sha256=b3jTwVkVe0ZBcYkHGJ_zKIV4MSMScDdabmLQIjOZfes,1087
50
54
  iolanta/facets/textual_browser/home.py,sha256=GfDD1G2HiwdLkPkNdcYRqVIxDl5tWH9fewh_FJb8G-I,384
51
55
  iolanta/facets/textual_browser/location.py,sha256=w0La8bVTpJiVo1_hFTDQeIUdDdqfhYnoihuZW-f130c,205
52
56
  iolanta/facets/textual_browser/models.py,sha256=DqTBjhkkTt5mNwqr4DzNbPSqzV-QtNqfKj7wpn6T3ao,173
53
57
  iolanta/facets/textual_browser/page.py,sha256=NkcQ5rSKZRbp63C8ozgsR_iVhcKHGv_SytUCQyGa7ss,786
54
- iolanta/facets/textual_browser/page_switcher.py,sha256=hZT9FFMXJf7t8V2ztsqsNNCmGY8CPx39mlEKJjhRsPA,9958
58
+ iolanta/facets/textual_browser/page_switcher.py,sha256=7bQWdMjokEmi02jcULWblIt43HJoiyuLSWqYpZZ0iW8,9792
55
59
  iolanta/facets/textual_class/__init__.py,sha256=tiL0p-3JspGcBRj4qa3rmoBFAuadk71l2ja2lJN6CEs,75
56
- iolanta/facets/textual_class/facets.py,sha256=tascZiue3tbYfpIsnP8yY2dgXQIQzoQ_HPzU7DbVbao,5999
57
- iolanta/facets/textual_class/sparql/instances.sparql,sha256=EW4BmuNxiRDA8djuEtvZpLLJlNSIshvId4ExlaYPcZE,106
60
+ iolanta/facets/textual_class/facets.py,sha256=pz7NkT4_5wgMH0NIKxOoURQDk-qhl022OQWgbmtrC8w,6003
61
+ iolanta/facets/textual_class/sparql/instances.sparql,sha256=v0rHyr0Ha-ioZ2ssv0ytqeO8-Qt1xnX9FKfwSstttzI,230
58
62
  iolanta/facets/textual_default/__init__.py,sha256=snxA0FEY9qfAxNv3MlZLrJsXugD4dvs5hLStZWV7soM,158
59
- iolanta/facets/textual_default/facets.py,sha256=Pf5GttQ7EG0ZodjwwVXzYMffHus3MAZdJUIcbddcYtw,4738
63
+ iolanta/facets/textual_default/facets.py,sha256=Cw5_T7p8G_TNqMhK05FQYE0Bra-Vr4ZdqMBBhLbsOe0,4743
60
64
  iolanta/facets/textual_default/sparql/inverse-properties.sparql,sha256=daHNdhmh92Q77CSf7ULbhxg57CuYsRFfMnXQz4VYEug,64
61
65
  iolanta/facets/textual_default/sparql/label.sparql,sha256=IWAkkgMKtIZ7Zpg8LUJ5fDZ9tiI8fiRYZo-zT61Fong,121
62
66
  iolanta/facets/textual_default/sparql/nodes-for-property.sparql,sha256=J9vg0Pz2HXDlPCeZ6IS2C0wODrpYDuNeD6DYT6UdNsU,68
@@ -64,40 +68,44 @@ iolanta/facets/textual_default/sparql/properties.sparql,sha256=stDbvFP4g6YKYphpN
64
68
  iolanta/facets/textual_default/tcss/default.tcss,sha256=v6k6LvZMndRW4t9Iq-7QF59U_LJTdohRsyavwTY5ruI,69
65
69
  iolanta/facets/textual_default/templates/default.md,sha256=CuD5lISsE2eAVnm2z6kfNff-vEgrNG95Wi5LTgkieWY,21
66
70
  iolanta/facets/textual_default/triple_uri_ref.py,sha256=XfuNPaAe-YxH8IyrdrHQ641aWh5zVMVs0L0WC3D6A4M,1279
67
- iolanta/facets/textual_default/widgets.py,sha256=9qZbJfLvf9yilyQjW6IlCk1AiD8gTmfvaFuLLGQMnGU,9177
71
+ iolanta/facets/textual_default/widgets.py,sha256=w6wk_x72CANmZk9XHS7G0YOT3h3IoitKkrFBuyTI81o,9177
68
72
  iolanta/facets/textual_graph/__init__.py,sha256=DWd2gljzL8SiyYKQdBH78HouF1EMqgCH-w0K5OEmL2I,59
69
- iolanta/facets/textual_graph/facets.py,sha256=NGg0i1XYmdR8gjMd-D4Ckvu_n7m7s1FA68VSUm7cpj0,873
73
+ iolanta/facets/textual_graph/facets.py,sha256=ed6zt7DnAlwWkOB2D3MDQrtKB3tNiegPpZbRKIoz5Zg,876
70
74
  iolanta/facets/textual_graph/sparql/triples.sparql,sha256=5rFVGcvZzEHZj2opQQp0YlxJLpEdl-r1RjkPwo8j7t0,145
71
- iolanta/facets/textual_graph_triples.py,sha256=oJa4pj71r-gODYk9otIrq-tSiV2SsaofhErUXJWRlKE,3864
75
+ iolanta/facets/textual_graph_triples.py,sha256=-Z3aKOMsWjprvU9563Z8OwaHz8KchHN_dxhKslliywo,3865
72
76
  iolanta/facets/textual_link/__init__.py,sha256=ShlMaq2nrpinGZFutjGNKaZQhGKQGOz_VUQzUqq3U7o,95
73
- iolanta/facets/textual_link/facet.py,sha256=XJXq97M3_IJBXSYWV3NAYzT96TrvNDgrUQXLP81d3K0,655
77
+ iolanta/facets/textual_link/facet.py,sha256=l4gbNoJrZpp3qUAyn5AfXHRj_GdMxnjqZ14GPYhJWHk,659
74
78
  iolanta/facets/textual_nanopublication/__init__.py,sha256=ZYYw08MZbIiTpX4xm8AJ3eJnu9GgdOeuRDVibBDOtZc,114
75
- iolanta/facets/textual_nanopublication/facet.py,sha256=1F-8E5tU0n_ukHPqcnksu8UlmRyyL_vxgG4qUWFp5ZA,369
79
+ iolanta/facets/textual_nanopublication/facet.py,sha256=jor9FwB9muJpRr6EImjoQ0SuiUVNXOJRiwHMkRCfSFQ,370
76
80
  iolanta/facets/textual_nanopublication/models.py,sha256=MphggSvKmYac6v866GOKW5lcQjNIbGvwIuJonKuQRVs,177
77
81
  iolanta/facets/textual_nanopublication/nanopublication_widget.py,sha256=sQPgEx25XJ15VqB5zjZuz2q2bf_B5GWXEp32FAufxQ4,2387
78
82
  iolanta/facets/textual_nanopublication/term_list_widget.py,sha256=NZNATKjFmgI2sE5R0ebyQh5Qk2g-kf-MT4YZ-Vw78M4,992
79
83
  iolanta/facets/textual_nanopublication/term_widget.py,sha256=uI5msCTSIYumAIS3I8nBfUz57_vRzvCKkouevrS3Qwk,3536
80
- iolanta/facets/textual_no_facet_found.py,sha256=xNAQslZuMU-HLZh6250Siz3EnSE_ZVt-YhksUTiU_Ag,2485
84
+ iolanta/facets/textual_no_facet_found.py,sha256=DZJKHUy-bARGi5UG0gOh70q4-uEpS_R3C-XO4pF3oiE,2608
81
85
  iolanta/facets/textual_ontology/__init__.py,sha256=3H6bfYaEbXFr90C6ZpGWC4O-24uaO18tnTXx7mckQSA,94
82
- iolanta/facets/textual_ontology/facets.py,sha256=60g8ANmePb9_i_-d4ui-FdtNwg9aktrOKXHkTQtLp1w,3338
86
+ iolanta/facets/textual_ontology/facets.py,sha256=jc56d_M7CJ2lUbiohdux8KGrtF-pcS_jsNBOIx7UXsE,3341
83
87
  iolanta/facets/textual_ontology/sparql/terms.sparql,sha256=oVLxN452nqog_95qRaTWnvar6rxPNxPrRonSo7oFFTg,324
84
88
  iolanta/facets/textual_ontology/sparql/visualization-vocab.sparql,sha256=q9TmU15deL0da28mpo_8W8fgMSEcENfYeqLyM0zVbTg,65
85
89
  iolanta/facets/textual_property_pairs_table.py,sha256=Drqc_G_6QhzNmrrfDU170eKTGrVmvQ6JMYu4ir--iUk,4176
86
90
  iolanta/facets/textual_provenance/__init__.py,sha256=k5-_iK8Lrdwr5ZEJaDxq-UhGYe4G_adXVqGfOA5DAP8,114
87
- iolanta/facets/textual_provenance/facets.py,sha256=vv3UQsI2duB36DW5Zkw3sqgAXBPmK_xAo7cU0O7jF8g,3767
91
+ iolanta/facets/textual_provenance/facets.py,sha256=7n4PalKdOWqCoYKocto9H6RinSBmWWyV-jgXs6t7q94,3768
88
92
  iolanta/facets/textual_provenance/sparql/graphs.sparql,sha256=B45uKFd-1vrBuMDSbTURjUUEjHt51vAbqdL4tUcgMvk,103
89
93
  iolanta/facets/textual_provenance/sparql/triples.sparql,sha256=V-EdVuWbGHY3MspbJIMpwxPQautLDqJJV-AmihDjSHc,53
90
94
  iolanta/facets/title/__init__.py,sha256=fxpkG-YvHDp6eiVL3o7BbwhPMZZe-1R2Qi6S36QCTf8,77
91
- iolanta/facets/title/facets.py,sha256=41cWNdisyb9dPJowSgTIQa-rmFCI4WUb-EYSFDr3GI0,836
95
+ iolanta/facets/title/facets.py,sha256=0XfdI1FKETXV8vo92FssTf4e0MTThlVJRfuC8RC67m8,744
92
96
  iolanta/facets/title/sparql/title.sparql,sha256=VKHeE9NvV6sFgVGvsLQD9z__J4APj8TDHLT4Rk-Ascc,1102
93
97
  iolanta/facets/wikibase_statement_title/__init__.py,sha256=_yk1akxgSJOiUBJIc8QGrD2vovvmx_iw_vJDuv1rD7M,91
94
- iolanta/facets/wikibase_statement_title/facets.py,sha256=mUH7twlAgoeX7DgLQuRBQv4ORT6GWbN-0eJ1aliSfiQ,724
98
+ iolanta/facets/wikibase_statement_title/facets.py,sha256=gNRqiwOTMxyyHYvb_vIrfd-4ipb8wfyJ4GgPcQdyy9E,726
95
99
  iolanta/facets/wikibase_statement_title/sparql/statement-title.sparql,sha256=n07DQWxKqB5c3CA4kacq2HSN0R0dLgnMnLP1AxMo5YA,320
96
- iolanta/iolanta.py,sha256=uM5vmK96Q_GsqXM-bBpQXoxwqs25K-YGYrZvWWFTsDA,11072
100
+ iolanta/iolanta.py,sha256=ONIjejjidXfRIe9pVjCxEyI5Jo1yZdn-XGLuo73tcSw,11074
101
+ iolanta/labeled_triple_set/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
102
+ iolanta/labeled_triple_set/data/labeled_triple_set.yamlld,sha256=RqVhaXTIDA2Fip32E1TlH4cn_sDLC7H-NGZ5XpK-hio,1015
103
+ iolanta/labeled_triple_set/labeled_triple_set.py,sha256=o4IgvTvPd0mzBtpgHYd4n1xpujYdAvWBr6gIYwp5vnA,4061
104
+ iolanta/labeled_triple_set/sparql/triples.sparql,sha256=VsCmYN5AX7jSIiFm-SqLcRcOvUVj8yyZI4PSzKROtQw,82
97
105
  iolanta/mermaid/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
98
106
  iolanta/mermaid/facet.py,sha256=0SMzwkjtB3xjCQRW-XwOB5P7zVJdUCDv8c_XmanvqP0,4068
99
107
  iolanta/mermaid/mermaid.yamlld,sha256=j5yQ6A1M_Fn4cq5WYISz8MfWw6skYdoB0lvcI68ahyw,968
100
- iolanta/mermaid/models.py,sha256=v0loPqJYKpylVBaq89yFdk8iNxyzvN9Ih_ozAbhD4pk,3197
108
+ iolanta/mermaid/models.py,sha256=X9EadiTUw2btDlYAE9G_2kaoqP-GGZHys1NpSv0qM8s,4197
101
109
  iolanta/mermaid/sparql/graph.sparql,sha256=mDGf05od3CUFhzI6rcqt5ZMVy-gSKDu-WxmV_zpIsVI,62
102
110
  iolanta/mermaid/sparql/subgraphs.sparql,sha256=VuoOYr_ZtKXXRrBpAEJek0mBRzR9EV-KnKENgAbkzCs,71
103
111
  iolanta/models.py,sha256=M-1dTxPwjTyUgQ4VCOiH6Q7ltNJiDPG0l1XQH430Omo,3250
@@ -116,12 +124,12 @@ iolanta/sparqlspace/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
116
124
  iolanta/sparqlspace/cli.py,sha256=pb6q03lzrU8OaZ4A3QAQEmaFYcQ_-sHUrPhRs6GE88w,1590
117
125
  iolanta/sparqlspace/inference/wikibase-claim.sparql,sha256=JSawj3VTc9ZPoU9mvh1w1AMYb3cWyZ3x1rEYWUsKZ6A,209
118
126
  iolanta/sparqlspace/inference/wikibase-statement-property.sparql,sha256=SkSHZZlxWVDwBM3aLo0Q7hLuOj9BsIQnXtcuAuwaxqU,240
119
- iolanta/sparqlspace/processor.py,sha256=0Rk7ZeLWifdnmnKL5EZc39JRuMfsxT2RBUv6vgg3di0,23995
127
+ iolanta/sparqlspace/processor.py,sha256=se7yNzmwyc0v2wspPjQvar7qOZaf3A1kk3OS2cJ58EY,24146
120
128
  iolanta/sparqlspace/sparqlspace.py,sha256=Y8_ZPXwuGEXbEes6XQjaQWA2Zv9y8SWxMPDFdqVBGFo,796
121
129
  iolanta/widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
122
130
  iolanta/widgets/description.py,sha256=98Qd3FwT9r8sYqKjl9ZEptaVX9jJ2ULWf0uy3j52p5o,800
123
131
  iolanta/widgets/mixin.py,sha256=nDRCOc-gizCf1a5DAcYs4hW8eZEd6pHBPFsfm0ncv7E,251
124
- iolanta-2.1.1.dist-info/METADATA,sha256=PC0tU9wgfi3BMHGEcI19gFVTUpQaIWxoGz2PcAoVx_8,2268
125
- iolanta-2.1.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
126
- iolanta-2.1.1.dist-info/entry_points.txt,sha256=H2bCnnscOwzl0QMoI86ifQ6hm1NhyYnrGQbMd0Kp6dA,1445
127
- iolanta-2.1.1.dist-info/RECORD,,
132
+ iolanta-2.1.4.dist-info/METADATA,sha256=ynvL1uzlCJZC4KPdThYYMYTseZ5aciKwiL_D6OI_9MY,2184
133
+ iolanta-2.1.4.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
134
+ iolanta-2.1.4.dist-info/entry_points.txt,sha256=Z8zw4191usRgXrS-AiH1aOYDA0Nq9W3S-VBH44EBFNg,1594
135
+ iolanta-2.1.4.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any