Librarian: stop warning about missing netrc when mailto is set via env
Librarian.__init__ reads the Crossref contact from CONJURER_CROSSREF_MAILTO, then tries to override it from a 'crossref' netrc entry. When no netrc is mounted (the normal container setup - default /root/.netrc) the read raises FileNotFoundError and it logged 'Crossref credentials missing in netrc ...' on EVERY search, even though the env var was set and used. Pure noise. Only warn when there is genuinely no contact from either source (env unset AND netrc unreadable) - which is also the case that then raises. When the env var is set, a missing netrc is expected and logged at debug. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit was merged in pull request #14.
This commit is contained in:
@@ -212,6 +212,9 @@ class Librarian(object):
|
||||
- search_result_from_cr: A dictionary to store the search results from Crossref.
|
||||
- done: A flag indicating if the search is done.
|
||||
"""
|
||||
# Crossref only needs a contact mailto. It can come from
|
||||
# CONJURER_CROSSREF_MAILTO (the usual container setup) OR from a
|
||||
# "crossref" entry in the netrc; netrc takes precedence when present.
|
||||
mailto_contact: Optional[str] = os.getenv("CONJURER_CROSSREF_MAILTO")
|
||||
if netrc:
|
||||
try:
|
||||
@@ -219,10 +222,22 @@ class Librarian(object):
|
||||
auth_tokens = netrc_mod.authenticators("crossref")
|
||||
if auth_tokens:
|
||||
mailto_contact = auth_tokens[0]
|
||||
except (FileNotFoundError, netrc.NetrcParseError):
|
||||
logging.getLogger("conjurer_librarian").warning(
|
||||
"Crossref credentials missing in netrc %s", NETRC_FILE
|
||||
)
|
||||
except (FileNotFoundError, netrc.NetrcParseError) as exc:
|
||||
# A missing/unreadable netrc is NORMAL when the mailto is set via
|
||||
# env - don't cry wolf on every single search. Only warn when we
|
||||
# genuinely have no contact from either source.
|
||||
_log = logging.getLogger("conjurer_librarian")
|
||||
if mailto_contact:
|
||||
_log.debug(
|
||||
"netrc %s not used (%s) - using CONJURER_CROSSREF_MAILTO",
|
||||
NETRC_FILE, exc,
|
||||
)
|
||||
else:
|
||||
_log.warning(
|
||||
"Crossref contact not configured: netrc %s unreadable (%s) "
|
||||
"and CONJURER_CROSSREF_MAILTO unset",
|
||||
NETRC_FILE, exc,
|
||||
)
|
||||
if not mailto_contact:
|
||||
raise RuntimeError(
|
||||
"Crossref credentials not configured. Set CONJURER_CROSSREF_MAILTO or add to netrc."
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
"""Integration: the librarian's Crossref-contact resolution.
|
||||
|
||||
CONJURER_CROSSREF_MAILTO alone is a valid, complete configuration. A missing
|
||||
netrc must NOT produce a "credentials missing" warning in that case - the old
|
||||
code warned on every single search even though the env var was set and used.
|
||||
Only a genuine absence of any contact should warn (and then raise).
|
||||
"""
|
||||
import logging
|
||||
import sys
|
||||
import types
|
||||
|
||||
import pytest
|
||||
|
||||
if "habanero" not in sys.modules:
|
||||
_habanero = types.ModuleType("habanero")
|
||||
_habanero.Crossref = object
|
||||
sys.modules["habanero"] = _habanero
|
||||
|
||||
import conjurer_librarian as lib # noqa: E402
|
||||
|
||||
|
||||
class _DummyCrossref:
|
||||
"""Accepts the kwargs the real Crossref does, so Librarian() can construct."""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.kwargs = kwargs
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _crossref_and_missing_netrc(monkeypatch):
|
||||
# Build with a harmless Crossref, and force the netrc read to miss so the
|
||||
# env-var path is what's exercised.
|
||||
monkeypatch.setattr(lib, "Crossref", _DummyCrossref)
|
||||
monkeypatch.setattr(lib, "NETRC_FILE", "/nonexistent/conjurer/.netrc")
|
||||
|
||||
|
||||
def test_env_mailto_alone_does_not_warn(monkeypatch, caplog):
|
||||
monkeypatch.setenv("CONJURER_CROSSREF_MAILTO", "mtuszowski@example.com")
|
||||
with caplog.at_level(logging.WARNING, logger="conjurer_librarian"):
|
||||
librarian = lib.Librarian(lib.app, "kwas foliowy", "uuid-1", False)
|
||||
assert librarian.uuid == "uuid-1" # constructed fine
|
||||
assert not any(
|
||||
"credentials missing" in r.getMessage().lower()
|
||||
or "not configured" in r.getMessage().lower()
|
||||
for r in caplog.records
|
||||
), "a missing netrc must not warn when CONJURER_CROSSREF_MAILTO is set"
|
||||
|
||||
|
||||
def test_no_contact_anywhere_raises(monkeypatch):
|
||||
monkeypatch.delenv("CONJURER_CROSSREF_MAILTO", raising=False)
|
||||
with pytest.raises(RuntimeError):
|
||||
lib.Librarian(lib.app, "kwas foliowy", "uuid-2", False)
|
||||
Reference in New Issue
Block a user