From 55096e65b90d233bac27b0bf202b98906ab26648 Mon Sep 17 00:00:00 2001 From: Anas Rashid Date: Fri, 9 Oct 2026 14:02:24 +0200 Subject: [PATCH] Divan-owned order (#41): the export follows divan/.order arrangements published in Divan Co-Authored-By: Claude Opus 5.5 --- divan/README.md | 3 +++ export_divan.py | 17 ++++++++++++++++- test_divan_order.py | 16 ++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 test_divan_order.py diff --git a/divan/README.md b/divan/README.md index a4a7a0edf..bef99b93f 100644 --- a/divan/README.md +++ b/divan/README.md @@ -8,5 +8,8 @@ Works edited or published in Divan, kept here so the daily Wikisource sync never published. - `.json`: generated from the `.dtx` by the app: `Title`, `Verses` (the site's verse layout) and `Edited` (who and when). `export_divan.py` uses it in place of the Wikisource text. +- `.order`: a published arrangement: the book or section's contents (sub-sections, + then works), one per line as ` `. `export_divan.py` lists them in this + order; a work added on Wikisource later comes after them until the order is redone. The work url is the site path, e.g. `p266/ghazal/sh7870` for `/p266/ghazal/sh7870`. diff --git a/export_divan.py b/export_divan.py index 1cf39ce1e..056500fe6 100644 --- a/export_divan.py +++ b/export_divan.py @@ -132,6 +132,20 @@ def owned(url): return json.load(f) +# Divan-owned order (#41): divan/<category url>.order lists a book/section's contents, one per line, +# "<last part of the URL> <title>" (written by the Divan app when an arrangement is published). Listed items +# take that order; anything not listed (e.g. a work new on Wikisource) keeps its place after them. +def owned_order(c): + path = os.path.join(DIVAN_DIR, c["FullUrl"].lstrip("/") + ".order") + if not os.path.exists(path): + return + with open(path, encoding="utf-8") as f: + rank = {line.split()[0]: i for i, line in enumerate(l for l in f if l.strip())} + key = lambda x: rank.get(x["FullUrl"].rsplit("/", 1)[-1], len(rank)) + c["ChildCats"].sort(key=key) # stable: unlisted items keep their order + c["Poems"].sort(key=key) + + def main(): for p in ("poets", "index"): shutil.rmtree(os.path.join(D, p), ignore_errors=True) @@ -209,7 +223,8 @@ def main(): r = radif_rank(first_line[p["Id"]]) p["RadifLetter"] = URDU_ALPHABET[r] if r < len(URDU_ALPHABET) else None # lists are already in published order: works are walked by ord, and categories are - # created in order of their first work + # created in order of their first work; Divan's own order, where published, comes last + owned_order(c) write(f"poets{c['FullUrl']}/_cat.json", c) cat_idx[c["Id"]] = c["FullUrl"] diff --git a/test_divan_order.py b/test_divan_order.py new file mode 100644 index 000000000..9df715edd --- /dev/null +++ b/test_divan_order.py @@ -0,0 +1,16 @@ +# python3 test_divan_order.py +import os, tempfile +import export_divan + +with tempfile.TemporaryDirectory() as d: + export_divan.DIVAN_DIR = d + os.makedirs(os.path.join(d, "p1")) + c = {"FullUrl": "/p1/ghazal", "ChildCats": [], + "Poems": [{"FullUrl": f"/p1/ghazal/sh{i}"} for i in (1, 2, 3, 4)]} + export_divan.owned_order(c) # no order file: unchanged + assert [p["FullUrl"][-3:] for p in c["Poems"]] == ["sh1", "sh2", "sh3", "sh4"] + with open(os.path.join(d, "p1", "ghazal.order"), "w", encoding="utf-8") as f: + f.write("sh3 تیسری\nsh1 پہلی\n\nsh2 دوسری\n") # sh4 (new since) is not listed + export_divan.owned_order(c) + assert [p["FullUrl"][-3:] for p in c["Poems"]] == ["sh3", "sh1", "sh2", "sh4"] +print("ok")