fix(sources): resolve arXiv IDs via arXiv DOI (OpenAlex /works/arxiv: 404s)

OpenAlex' /works/{id}-Pfad akzeptiert die arxiv:-Namespace-Form nicht (404).
_resolve_id löst arXiv-IDs jetzt auf die arXiv-DOI 10.48550/arXiv.<id> auf —
empirisch verifiziert für modern (1005.2698) und legacy (math/0603097) IDs.
Behebt D-03 (Erstingest: alle Metadaten leer, weil fetch_paper 404 gab).

- _resolve_id: arxiv:-Präfix strippen, arXiv-DOI bauen
- Tests: arxiv (modern/legacy/prefixed) erwarten jetzt doi:10.48550/arXiv.*
- 19 Tests grün, ruff + mypy sauber

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tarik Moussa
2026-06-07 23:14:52 +02:00
parent d48db47a7d
commit c8b127bae0
2 changed files with 23 additions and 9 deletions

View File

@@ -25,17 +25,21 @@ _BASE = "https://api.openalex.org"
def _resolve_id(id: str) -> str:
"""Prefix a bare DOI or arXiv ID for the OpenAlex /works/ endpoint.
"""Resolve a bare DOI or arXiv ID for the OpenAlex /works/ endpoint.
OpenAlex accepts: doi:<doi>, arxiv:<id>, W-IDs, or full https:// URLs.
Bare DOIs (starting with "10.") and bare arXiv IDs require a prefix.
OpenAlex resolves DOIs, W-IDs and full https:// URLs in the /works/ path,
but NOT the ``arxiv:`` namespace (that path 404s). arXiv papers are looked
up via their arXiv DOI ``10.48550/arXiv.<id>`` instead — accepted by
OpenAlex for both modern (``2301.07041``) and legacy (``math/0603097``) IDs.
"""
s = id.strip()
if s.startswith(("W", "https://", "doi:", "arxiv:")):
if s.lower().startswith("arxiv:"):
s = s[len("arxiv:") :]
if s.startswith(("W", "https://", "doi:")):
return s
if s.startswith("10."):
return f"doi:{s}"
return f"arxiv:{s}"
return f"doi:10.48550/arXiv.{s}"
def _is_retryable(exc: BaseException) -> bool: