Linked-data-python

Latest version: v0.6.4

Safety actively analyzes 1006753 Python packages for vulnerabilities to keep your Python projects secure.

Scan your dependencies

Page 1 of 3

0.6.4

- **`as` works on a dynamic prefix too**: `prefix p: f<http://{host}/ns#> as
P .` binds the `Namespace` built from the IRI resolved at that point — the
same object the prefix itself uses, so the two can never disagree. This
belongs with 0.6.3 and missed its tag by a few minutes; it is not an
afterthought but the form the corpus needed first, since every IRI of the
region that motivated `as` is computed at run time.

0.6.3

Two answers to the limit the corpus study attested most: `prefix` is
lexical, so it produces no Python value, and code that needs the `Namespace`
as an **object** had no translation at all (record ldpy/027).

- **A designated graph now inherits the block's prefixes.** A graph created
by `graph as g` already serialised with them; one merely designated by
`graph mine` carried none, so the same block filling two graphs the same
way serialised them differently. That was an inconsistency rather than a
decision. The prefixes are *added* to the graph's own bindings — it belongs
to its caller, and nothing it had is discarded. This removes the reason for
most hand-written `g.bind()` calls; one function in the corpus had
nineteen.
- **`prefix ex: <IRI> as EX .`** binds the `Namespace` object to a Python
name, for the code that must keep it: to `bind()` it on a graph it manages,
to export it, to put it in a registry. A bare `ex:` is still never a value.
The name follows Python's scope, and `global` / `nonlocal` widen it like
any other declaration.

You rarely need `as`. A `Namespace` that merely *produces* IRIs needs
nothing — the `URIRef`s it produces are ordinary values, and two regions in
three of the corpus stratum that looked blocked were expressible for exactly
that reason.

0.6.2

Bug fixes only, all found by the corpus study and all reproduced by hand
before being fixed.

- **A `` inside a full IRI is no longer read as a comment in `s{ }`.** The
SPARQL island scanner knew strings and comments but not IRIs, so the
fragment of `<http://example.org/ns#X>` — the most ordinary shape an IRI
takes in RDF — swallowed the rest of the line, closing brace included, and
the island failed to transpile with "'}' expected". `m{ }` and `g{ }` parse
IRIs as terms and never had the defect. A `<` that does not open an IRI is
still SPARQL's less-than.
- **An island inside an f-string interpolation hole is now refused by name.**
The scanner does not descend into those holes, so the island used to be
copied verbatim into the generated Python, which CPython then rejected with
a message from its f-string parser that named nothing. It now says which
island, where, and what to do instead. Supporting islands there remains
open; refusing them clearly does not foreclose it.
- **Two documentation corrections in the hover table**, which also feeds the
corpus study's translator instructions: `f<...>` does **not** percent-encode
(only `e<...>` does — `firi()` concatenates and resolves, nothing more), and
`.execute()` is not just for updates but for any query whose rdflib
`Result` you then call a method on.
- **Two silent traps documented** in `how-to/migrate-from-rdflib.md`, both
with runnable proof: interpolating a bare `str` into `s{ }` coerces it to a
literal, so the query matches nothing without raising; and `"{x}"` inside a
literal does not interpolate — `f"{x}"` does.

0.6.1

- **A tutorial that is a program**: `docs/tutorials/tour.ldpy`, one file you
run, whose comments introduce the notation section by section — declarations,
terms, `f<…>`, `g{ }`, the current graph with `+{ }` and `-{ }`, `m{ }`,
`e{ }`, `bindings` over a CSV, `s{ }`, and back to rdflib. Each section
builds, prints and asserts what it claims, so running it to the end is the
proof. The page that shows it *includes* the file rather than copying it, and
the test suite runs it.

0.6.0

- **Documentation for the device.** A tutorial (run a programme on
MicroPython, on the Unix port, no hardware needed), a how-to guide (build
for MicroPython: the target, the bundle, `mpy-cross`, the seam between
programme and device), and an explanation (running on a device: the
façade, the backend, why SPARQL is two capabilities); the command-line and
API references, the rationale's R6 and the limitations list say the same.

- **The façade has a backend, and the backend can be urdflib.** The
generated code always went through `ldpy.runtime`; that module now takes
its terms and graphs from `ldpy.backend`, which is rdflib when rdflib
imports and [urdflib](https://github.com/linked-data-python/urdflib) on a
MicroPython device. `Namespace`, `RDF` and `XSD` are provided in Python
where the C module has none; the emitted graph is lazy over rdflib and
eager over urdflib, whose graphs add in place at C speed; the `Row` of an
`m{ }` no longer needs `tuple.__new__`, which MicroPython lacks.
- **`--target micropython`** (`ldpy`, `ldpy.build`, `transpile(...,
target=)`): `s{ }` is refused at build time, on the host, where the message
can be read — a SPARQL query needs rdflib's engine, and the device has
none; `e{ }` and `m{ }` are pure Python over the terms and stay. The build
copies the device runtime (`runtime.py`, `backend.py`, `sparql.py`, a
minimal `__init__.py`) next to the emitted files, so that what is shipped
and what it imports travel together (record ldpy/026).
- **The same programme runs on MicroPython.** `tests/test_target_micropython.py`
transpiles a programme with `+{ }`, `m{ }`, `e{ }` and `serialize()`,
runs it on a MicroPython built with urdflib (`LDPY_MICROPYTHON`) and gets
the host's answer.

0.5.2

- **The interactive console keeps the current graph between entries.** A
top-level `graph` is a lexical declaration like `prefix`, and it now
survives the entry that declares it, together with the current bindings and
the fresh-variable counter — so `graph as g` on one line and `+{ ... }` on
the next write to the same graph, as they do in a file. The documentation's
snippets are now replayed a second time, typed line by line into the
console, by the same test that runs them as files.
- **`graph as g` no longer hangs the console.** Skipping inline whitespace
tested `self._peek() in " \t"`, and `"" in " \t"` is true in Python: at the
end of a buffer with no trailing newline the loop consumed nothing, for
ever. Two other sites had the same defect, one of which turned `BOUND(` at
end of buffer into an `AttributeError` instead of a syntax error.
- **A semantic error is no longer mistaken for an unfinished entry.** The
console distinguishes the two by `at_eof`, which was set from the cursor
position alone; an error such as `'+{ ... }' without a current graph`, which
more input cannot repair, is now reported at once.
- **`+{ }` and `-{ }` are statements, and print nothing.** `add_to` and
`remove_from` no longer return the graph, which the console echoed after
every addition.
- **`ldpy.debug --root DIR`**: the shadow mirrors the tree under DIR, so one
build directory can hold a whole workspace without `a/m.ldpy` and
`b/m.ldpy` claiming the same `m.py`.

Page 1 of 3

© 2026 Safety CLI Cybersecurity Inc. All Rights Reserved.