← back to Paul Conrad Archive
Fix PEP701 nested-quote f-strings (broke Kamatera py3.10); add py3.10 py_compile test over all sources (proven red on the bug)
f12cde5f207781227a2a08cb8c0495b3d4340093 · 2026-09-24 18:11:45 -0700 · Steve Abrams
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Files touched
M src/conrad/crawlers/secondary_citations.pyA tests/test_py310_syntax.py
Diff
commit f12cde5f207781227a2a08cb8c0495b3d4340093
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Sep 24 18:11:45 2026 -0700
Fix PEP701 nested-quote f-strings (broke Kamatera py3.10); add py3.10 py_compile test over all sources (proven red on the bug)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---
src/conrad/crawlers/secondary_citations.py | 6 +++---
tests/test_py310_syntax.py | 21 +++++++++++++++++++++
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/src/conrad/crawlers/secondary_citations.py b/src/conrad/crawlers/secondary_citations.py
index 51facc8..c6e156d 100644
--- a/src/conrad/crawlers/secondary_citations.py
+++ b/src/conrad/crawlers/secondary_citations.py
@@ -353,8 +353,8 @@ class SecondaryCitations(Crawler):
verified.append((url, quote, date_quote))
else:
why = "page unavailable" if t is None else "quote not found on page"
- self.rejected.append(f"{c["slug"]} @ {url} ({why})")
- self.error(url, f"citation rejected for {c["slug"]}: {why}")
+ self.rejected.append(f"{c['slug']} @ {url} ({why})")
+ self.error(url, f"citation rejected for {c['slug']}: {why}")
if not verified:
return
d = _dates(c)
@@ -367,7 +367,7 @@ class SecondaryCitations(Crawler):
if c.get("note") and i == 0:
note += f" | caveat: {c['note']}"
rec = CartoonRecord(
- canonical_id=f"sec:{c["slug"]}", identifier=f"{c["slug"]}@{url}", granularity="item",
+ canonical_id=f"sec:{c['slug']}", identifier=f"{c['slug']}@{url}", granularity="item",
title=c["title"], caption=c.get("caption"), description=c.get("desc"),
publication=c.get("pub"), rights_text=rights.COPYRIGHT_NOTE, notes=note if i == 0 else None,
repository="Secondary citation", collection_name=SITE.get(url, "secondary web page"),
diff --git a/tests/test_py310_syntax.py b/tests/test_py310_syntax.py
new file mode 100644
index 0000000..3e8edfb
--- /dev/null
+++ b/tests/test_py310_syntax.py
@@ -0,0 +1,21 @@
+"""Kamatera runs Python 3.10: every source file must parse under 3.10 grammar (e.g. no PEP 701 nested-quote f-strings)."""
+import ast
+import pathlib
+import sys
+
+import pytest
+
+ROOT = pathlib.Path(__file__).resolve().parents[1]
+FILES = sorted(p for d in ("src", "scripts", "tests") for p in (ROOT / d).rglob("*.py"))
+
+
+@pytest.mark.skipif(sys.version_info < (3, 12), reason="running ON 3.10/3.11 already proves it")
+@pytest.mark.parametrize("path", FILES, ids=lambda p: str(p.relative_to(ROOT)))
+def test_parses_as_py310(path):
+ import subprocess
+ # ast feature_version does not enforce PEP 701 f-string rules, so check with a real 3.10 if present
+ py310 = next((p for p in ("/opt/homebrew/bin/python3.10", "/usr/local/bin/python3.10", str(pathlib.Path.home() / ".local/share/uv/python/cpython-3.10-macos-aarch64-none/bin/python3.10")) if pathlib.Path(p).exists()), None)
+ if py310 is None:
+ pytest.skip("no python3.10 interpreter on this host")
+ r = subprocess.run([py310, "-m", "py_compile", str(path)], capture_output=True, text=True)
+ assert r.returncode == 0, r.stderr
← e4fc551 Copyright rail layer 2: refuse image/PDF responses by Conten
·
back to Paul Conrad Archive
·
NCR citation: use live natcath.org original (200, no robots) e1a4fb4 →