linked-data-python 0.6.0__py3-none-any.whl → 0.6.2__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.
ldpy/lsp/islanddoc.py CHANGED
@@ -134,7 +134,9 @@ ISLANDS = {
134
134
  "A SPARQL query or update, parsed when the file is transpiled rather "
135
135
  "than at run time. `{expr}` in term position becomes an initial "
136
136
  "binding — never string pasting, so nothing here can be injected. "
137
- "Call it on a graph to run it; `.execute()` runs an update.",
137
+ "Calling it on a graph gives a LAZY query; `.execute()` is what "
138
+ "forces it — for an update, and for any query whose rdflib `Result` "
139
+ "you then call a method on.",
138
140
  _QUERY, "s-a-sparql-query"),
139
141
 
140
142
  # -- terms --------------------------------------------------------------
@@ -169,10 +171,10 @@ ISLANDS = {
169
171
 
170
172
  "firi": IslandDoc(
171
173
  "(term) f<...{expr}...> -> URIRef",
172
- "A formatted IRI: the braces interpolate as in an f-string, the "
173
- "result is percent-encoded and then resolved against `@base`. "
174
- "Encoding first is what keeps a space or a slash in a value from "
175
- "changing the IRI's structure.",
174
+ "A formatted IRI: the braces interpolate as in an f-string, and the "
175
+ "result is resolved against `@base` if it is relative. It does NOT "
176
+ "percent-encode — the shape of the IRI is yours. To mint one from "
177
+ "data that may hold a space or a slash, use `e<...>`, which encodes.",
176
178
  _TERMS, "formatted-iris-f"),
177
179
 
178
180
  "fnode": IslandDoc(
@@ -202,7 +204,9 @@ ISLANDS = {
202
204
  "eiri": IslandDoc(
203
205
  "(expression) e<...{?var}...> -> Expr",
204
206
  "A deferred IRI: `f<...>`'s interpolation, except that the holes are "
205
- "SPARQL expressions re-evaluated for each set of bindings.",
207
+ "SPARQL expressions re-evaluated for each set of bindings — and that "
208
+ "it percent-encodes what it interpolates. This is the form for "
209
+ "minting an IRI from a data column.",
206
210
  _SPARQL_EXPR, "deferred-iris-e"),
207
211
  }
208
212
 
ldpy/transpiler/core.py CHANGED
@@ -592,6 +592,40 @@ class Transpiler:
592
592
  # chaînes et littéraux RDF
593
593
  # ------------------------------------------------------------------
594
594
 
595
+ # Island sigils that open with a brace or a chevron. A hole beginning
596
+ # with one of these is an island the scanner will never reach.
597
+ _HOLE_ISLANDS = ("_:{", "g{", "m{", "s{", "e{", "e<", "f{", "f<", "?{")
598
+
599
+ def _island_in_fstring_hole(self, tok_start, end):
600
+ """The island opener written inside an f-string hole, or None.
601
+
602
+ The scanner does not descend into f-string interpolation holes: an
603
+ island written there would be copied verbatim into the generated
604
+ Python, which then fails with a message from CPython's f-string
605
+ parser that names nothing (record ldpy/012). Refusing it here, by
606
+ name, costs one scan of the token and turns a baffling failure into
607
+ an actionable one.
608
+ """
609
+ tok = self.text[tok_start:end]
610
+ if "f" not in tok[:3].lower() or "{" not in tok:
611
+ return None
612
+ i, n = 0, len(tok)
613
+ while i < n:
614
+ if tok[i] != "{":
615
+ i += 1
616
+ continue
617
+ if tok[i + 1:i + 2] == "{": # '{{' is an escaped brace
618
+ i += 2
619
+ continue
620
+ j = i + 1
621
+ while j < n and tok[j] in " \t":
622
+ j += 1
623
+ for opener in self._HOLE_ISLANDS:
624
+ if tok.startswith(opener, j):
625
+ return opener
626
+ i += 1
627
+ return None
628
+
595
629
  def _handle_string(self, start, prefix_start=None):
596
630
  """start : indice du guillemet. prefix_start : indice du préfixe de
597
631
  chaîne (r/b/f/u) déjà repéré, sinon None."""
@@ -607,6 +641,12 @@ class Transpiler:
607
641
  if suffix is None and t[end:end + 2] == "^^":
608
642
  suffix = ("datatype", None, end + 2)
609
643
  if suffix is None:
644
+ opener = self._island_in_fstring_hole(tok_start, end)
645
+ if opener is not None:
646
+ self._error(
647
+ "îlot '%s' dans un trou d'f-string : le scanner n'y "
648
+ "descend pas. Sortez la lecture dans une variable "
649
+ "au-dessus de l'f-string." % opener)
610
650
  self._copy(end - self.i)
611
651
  self.operand = False
612
652
  self.stmt_start = False
@@ -2124,6 +2164,14 @@ class Transpiler:
2124
2164
  elif c in "\"'":
2125
2165
  end = self._string_end(self.i)
2126
2166
  pieces.append(self._take(end - self.i))
2167
+ elif c == "<" and self._iriref_end(self.i) is not None:
2168
+ # A full IRI is a token, not punctuation: its '#' is part of
2169
+ # the IRI, not a comment. Without this the fragment of
2170
+ # <http://example.org/ns#X> — the most ordinary shape an IRI
2171
+ # takes in RDF — swallowed the rest of the line, closing
2172
+ # brace included. `<` that does NOT open an IRI is SPARQL's
2173
+ # less-than, and falls through to the single-character case.
2174
+ pieces.append(self._take(self._iriref_end(self.i) - self.i))
2127
2175
  elif c == "#":
2128
2176
  j = t.find("\n", self.i)
2129
2177
  pieces.append(self._take((j if j != -1 else self.n) - self.i))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: linked-data-python
3
- Version: 0.6.0
3
+ Version: 0.6.2
4
4
  Summary: Python extended with Semantic Web primitives: IRIs, RDF literals and Turtle-notation graphs as expressions, transpiled by island parsing.
5
5
  Author-email: Maxime Lefrançois <maxime.lefrancois@emse.fr>
6
6
  License: MIT
@@ -13,17 +13,17 @@ ldpy/lsp/__init__.py,sha256=rK5GYOITi9PN09-WVlJ2aPKodW8dWTpgI_X6dFbP1zA,542
13
13
  ldpy/lsp/__main__.py,sha256=MIp4ktqaoWZCNIMfv14bSC9pqK86JBS5XVjd1Z3c24o,72
14
14
  ldpy/lsp/backend.py,sha256=8DnSGaBk1dsIMOBo7D1WQxxF3MZjJbYd78jp4ucWORY,5375
15
15
  ldpy/lsp/hover.py,sha256=zSJ0PpU3kTJDXcwI2zSDCbsKrT-eNTt2RlvmEPRoV-M,2407
16
- ldpy/lsp/islanddoc.py,sha256=vxxRKEcywBH31c8XgykEoC8fZfvbHok1NH-rPc-0Sy0,9540
16
+ ldpy/lsp/islanddoc.py,sha256=mBiBcaaswH3cVNSeh_h9DV8c5RaWIASxOnVS13g9KiI,9843
17
17
  ldpy/lsp/rpc.py,sha256=-TF_9U8dum23Pi4O1FZLogwoZgrGrt14J5BFB1OYVZw,3554
18
18
  ldpy/lsp/server.py,sha256=PAMMookGUn00vAW_-a5BGy3qkVe9PoUdfzAzpdlvoF8,16359
19
19
  ldpy/lsp/translate.py,sha256=HU9fBP_xWyYLih6QwQfSoyfF-MH-oInFcPX3o8Vc2GI,6116
20
20
  ldpy/transpiler/__init__.py,sha256=9mQx0e47ixz0iMqSbCBbtGiwJ7PLxTcsVSIp6KNTMG4,504
21
- ldpy/transpiler/core.py,sha256=LaZT8hE4jocIcTLyb2kc_mFtwu8QTSm0FhOMNetY_2k,114831
21
+ ldpy/transpiler/core.py,sha256=BnEm2qf9u2HC998OJ9iKFksE5eoPtG96Bd3ao9Si7H4,117145
22
22
  ldpy/transpiler/errors.py,sha256=zEEwsNvC2Tawq8jIYls7hrbcWSvQtd7eo89k_SKp0k0,1142
23
23
  ldpy/transpiler/linemap.py,sha256=ecLlCUkD4-6QQtUjGfAL28ql7LPITTS4fjLcDIbAwpQ,11386
24
- linked_data_python-0.6.0.dist-info/licenses/LICENSE.md,sha256=R6KjQ098eAFd2k5mKaSRJqMH1LhY4o7xkHrKT5vjRfs,1074
25
- linked_data_python-0.6.0.dist-info/METADATA,sha256=q7sq2gWlVV18IGg6zFfFYc9EPyuTuP50JwP1quO0ZAU,7974
26
- linked_data_python-0.6.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
27
- linked_data_python-0.6.0.dist-info/entry_points.txt,sha256=n8Vs52oH81BrKOe1DNUvdFLSOlEufRMpK2waPFa6aYk,224
28
- linked_data_python-0.6.0.dist-info/top_level.txt,sha256=dkG_F4jYkh6CS6gdpQeV_gKW3yaJBvl1ukUu0zo2KA8,5
29
- linked_data_python-0.6.0.dist-info/RECORD,,
24
+ linked_data_python-0.6.2.dist-info/licenses/LICENSE.md,sha256=R6KjQ098eAFd2k5mKaSRJqMH1LhY4o7xkHrKT5vjRfs,1074
25
+ linked_data_python-0.6.2.dist-info/METADATA,sha256=RhDkJ0IJ9BHjIQsxibF0Ln547zVLYPwsV9NTKyOddTM,7974
26
+ linked_data_python-0.6.2.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
27
+ linked_data_python-0.6.2.dist-info/entry_points.txt,sha256=n8Vs52oH81BrKOe1DNUvdFLSOlEufRMpK2waPFa6aYk,224
28
+ linked_data_python-0.6.2.dist-info/top_level.txt,sha256=dkG_F4jYkh6CS6gdpQeV_gKW3yaJBvl1ukUu0zo2KA8,5
29
+ linked_data_python-0.6.2.dist-info/RECORD,,