Skip to content

Commit 28f6dba

Browse files
authored
Merge pull request #76 from Eddy1919/feat/pelagios-registration-prep
docs(pelagios): registration runbook + emit DB pleiades_id
2 parents 1ef18d9 + a431f7c commit 28f6dba

4 files changed

Lines changed: 105 additions & 0 deletions

File tree

docs/PELAGIOS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ dataset record. The LOD emission lives in
1010
This page documents the workflows that *grow* that linked data. The triad
1111
Pelagios cares about is **place + time + people**; we already emit people
1212
(SNAP prosopography, [`snap_exporter.py`](../src/openetruscan/api/snap_exporter.py)).
13+
To actually join the Pelagios graph, see the prerequisites and submission steps
14+
in [`PELAGIOS_REGISTRATION.md`](PELAGIOS_REGISTRATION.md).
1315

1416
## Raising Pleiades coverage (place axis)
1517

docs/PELAGIOS_REGISTRATION.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Registering OpenEtruscan with Pelagios / Peripleo
2+
3+
Getting into the Pelagios graph is a **community / hosting action**, not a code
4+
change — and it has hard prerequisites that are **not yet met**. This page is the
5+
honest runbook: what's missing, in what order to fix it, and how to submit.
6+
7+
> **Status (2026-06): NOT yet registerable.** The Pelagios artifacts are
8+
> generated correctly by this repo but are **not served on the live site**, so
9+
> there is nothing for Peripleo to crawl. Fix the prerequisites below first.
10+
11+
## What works today
12+
13+
`openetruscan.api.lod` renders the corpus as valid **W3C Web Annotation**
14+
JSON-LD. Regenerate and inspect the full dump from the live corpus with:
15+
16+
```bash
17+
python - <<'PY' # (see git history of this doc for the full snippet)
18+
# pages /api/search and runs lod.inscription_to_jsonld over every row
19+
PY
20+
```
21+
22+
A run on 2026-06-20 produced 5,932 annotations (~2.9 MB); every item had
23+
`type` + `target` + `body`; 301 carried a PeriodO `dcterms:temporal`, 307 a
24+
GeoJSON point. The pipeline is sound.
25+
26+
## Prerequisites (blockers, in order)
27+
28+
1. **Serve the discovery artifacts on the live origin.** Today these all 404:
29+
- `https://openetruscan.com/void.ttl` (the dataset description)
30+
- `https://openetruscan.com/pelagios.jsonld` (the annotation dump named by
31+
`void:dataDump` in [`void.ttl`](../void.ttl))
32+
- a SPARQL endpoint (optional)
33+
34+
The live API is the **Vercel/TypeScript** app in the `openEtruscan-frontend`
35+
repo; the `/pelagios.jsonld` route in *this* repo's FastAPI is not deployed.
36+
Port the feed to a Vercel function (or publish the dump as a static file).
37+
38+
2. **Make item URIs dereference to JSON-LD.** `…/api/inscription/100` with
39+
`Accept: application/ld+json` currently returns plain JSON. Peripleo and LOD
40+
consumers expect content negotiation to JSON-LD on each `id`.
41+
42+
3. **Populate the place links the feed under-reports.** The generated dump had
43+
**0 Pleiades bodies** even though the DB reports 408 linked, because
44+
`inscription_to_jsonld` resolves Pleiades only from `data/pleiades_mapping.yaml`
45+
and **ignores the `inscriptions.pleiades_id` column**. Two fixes:
46+
- have `lod.get_pleiades_uri` fall back to the row's `pleiades_id`;
47+
- run the (now tuned) Pleiades review pipeline to grow the mapping — see
48+
[`PELAGIOS.md`](PELAGIOS.md).
49+
50+
4. **Reconcile `void.ttl` with reality.** It currently advertises 11,361
51+
entities / 34,477 triples; the live corpus is 5,932 inscriptions. Regenerate
52+
it (`api/void_gen.py`) so the counts, `void:dataDump`, and licence are
53+
accurate before anyone crawls it.
54+
55+
## Submitting (once the prerequisites are met)
56+
57+
The Pelagios discovery mechanism has changed across Peripleo versions, so
58+
**confirm the current path with the community** rather than assuming — start at
59+
<https://pelagios.org> and the Pelagios Network GitHub org. As of writing the
60+
route is roughly:
61+
62+
1. **Join the Pelagios Network** (it's an association of projects) via the
63+
"Get involved" / membership path on pelagios.org.
64+
2. **Announce the dataset** on the community channels (the mailing list / Slack)
65+
and at a **Linked Pasts** event — this is how new gazetteer-linked corpora
66+
are surfaced.
67+
3. **Make it Peripleo-ingestable.** Current Peripleo builds ingest a dataset by
68+
pointing a config at a stable dump URL (the `void:dataDump`). Provide the
69+
served `pelagios.jsonld` + `void.ttl` URLs.
70+
4. **Contribute place records upstream** where Etruscan findspots are thin in
71+
Pleiades — the highest-value, most-welcomed contribution.
72+
73+
## What I could not do
74+
75+
The submission itself is an external, authenticated community process and
76+
depends on the live feed existing first — it is **not** something this repo can
77+
complete on its own. Everything code-side that *can* be prepared is prepared;
78+
the remaining steps are deploy-and-submit, listed above.

src/openetruscan/api/lod.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,13 @@ def inscription_to_jsonld(inscription, language: str = "ett") -> dict:
130130
pleiades_uri = None
131131
if inscription.findspot:
132132
pleiades_uri = get_pleiades_uri(inscription.findspot)
133+
# Fall back to the row's own pleiades_id column: the findspot→id YAML mapping
134+
# doesn't cover every already-linked row, and without this the feed silently
135+
# drops Pleiades links the DB already holds.
136+
if not pleiades_uri:
137+
pid = getattr(inscription, "pleiades_id", None)
138+
if pid:
139+
pleiades_uri = f"{PLEIADES_BASE}{pid}"
133140

134141
tm_uri = get_trismegistos_uri(inscription.id)
135142
eagle_uri = get_eagle_uri(inscription.id)

tests/test_lod.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,24 @@ def test_jsonld_includes_tm_uri(self, mock_map):
8282
]
8383
assert any(urlparse(s).hostname == "www.trismegistos.org" for s in sources)
8484

85+
def test_jsonld_uses_row_pleiades_id_when_mapping_misses(self):
86+
# The findspot→id YAML doesn't cover this row, but its pleiades_id column
87+
# does — the feed must still emit the Pleiades link.
88+
insc = Inscription(
89+
id="ET_Vc_1.1",
90+
raw_text="mi velthur",
91+
canonical="mi velthur",
92+
findspot="an unmapped findspot string",
93+
pleiades_id="413291",
94+
)
95+
jsonld = inscription_to_jsonld(insc)
96+
sources = [
97+
b.get("source", "")
98+
for b in jsonld.get("body", [])
99+
if isinstance(b, dict) and b.get("purpose") == "identifying"
100+
]
101+
assert "https://pleiades.stoa.org/places/413291" in sources
102+
85103
@patch("openetruscan.api.lod._load_eagle_mapping", return_value={"ET_Cr_1.1": "EDR000001"})
86104
def test_jsonld_includes_eagle_uri(self, mock_map):
87105
insc = Inscription(

0 commit comments

Comments
 (0)