← back to Paul Conrad Archive
tests/test_loc_deep.py
81 lines
"""LOC deep enumeration (TK-12199): group handling, notes-only Conrad attribution, bounded neighbour probing."""
import json
from conrad.crawlers import loc
from conrad.crawlers.base import Blocked
from conftest import FakeHttp
GROUP = {"item": {"title": "[Proofs of political cartoons for the Los Angeles Times]",
"call_number": "Unprocessed in PR 13 CN 1983:004 [P&P]", "creators": [], "contributor_names": [],
"created_published": "[between 1971 and 1980]", "related_items": [],
"notes": [{"note": "Creators include: Paul Conrad."}, {"note": "Gift; Paul Conrad; (PR 13 CN 1983:004)"}]},
"resources": [], "related": {"neighbors": "https://www.loc.gov/pictures/related/?&pk=2010632868"}}
def _item(title, pk_creator=True):
return {"item": {"title": title, "creators": [{"title": "Conrad, Paul, 1924-2010"}] if pk_creator else [],
"created_published": "1975", "call_number": "CD 1 - Conrad, no. 1 (A size)", "notes": []},
"resources": [{"image": "https://tile.loc.gov/x.jpg"}]}
def test_group_record_is_folder_and_components_not_addressable():
rec = loc.item_record("2010632868", GROUP, "t")
assert rec is not None and rec.granularity == "folder"
g = loc.group_components("2010632868", GROUP)
assert g["components_addressable"] is False and "robots.txt disallows" in g["why"]
assert g["neighbors_link_disallowed"] is True and g["digitized_resources"] == 0
def test_notes_only_attribution_and_media_count():
d = json.loads(json.dumps(GROUP))
d["item"]["title"] = "[Original editorial cartoon drawings]"
d["item"]["notes"].append({"note": "Media includes: 21 Drawings : Ink and pencil."})
rec = loc.item_record("2010634752", d, "t")
assert rec and rec.granularity == "folder" and "21 drawings" in rec.notes
d["item"]["notes"] = [{"note": "Creators include: Pat Oliphant."}]
assert loc.item_record("2010634752", d, "t") is None # other cartoonists' lots are not Conrad
def test_neighbour_probe_bounded_and_extends(tmpdb, monkeypatch):
monkeypatch.setattr(loc, "PROBE_WINDOW", 1)
monkeypatch.setattr(loc, "PROBE_MAX", 5)
routes = {
"/pictures/item/2016685101/": (200, json.dumps(_item("Known cartoon"))),
"/pictures/item/2016685102/": (200, json.dumps(_item("Neighbour hit"))),
"/pictures/item/2016685103/": (200, json.dumps(_item("Other man's photo", pk_creator=False))),
"/pictures/item/2016685100/": (404, "not found"),
"/pictures/item/": (404, "not found"),
"robots": (200, ""),
"/photos/": (200, json.dumps({"results": [{"id": "http://www.loc.gov/item/2016685101/",
"contributor": ["conrad, paul"]}], "pagination": {}})),
"loc.gov/": (200, json.dumps({"results": [], "pagination": {}})),
}
class H(FakeHttp):
def allowed(self, url):
return "/pictures/search" not in url and "/pictures/related" not in url and "/search/" not in url
monkeypatch.setattr(loc, "KNOWN_GROUPS", {})
monkeypatch.setattr(loc, "EXTRA_CANDIDATES", {})
monkeypatch.setattr(loc.Checkpoint, "__init__", lambda self, n: setattr(self, "data", {}) or setattr(self, "path", None))
monkeypatch.setattr(loc.Checkpoint, "set", lambda self, k, v: self.data.__setitem__(k, v))
c = loc.LOCCrawler(conn=tmpdb, http=H(routes))
res = c.run()
assert res["status"] == "worked"
ids = {r[0] for r in tmpdb.execute("SELECT identifier FROM cartoon_sources WHERE source_id='loc'")}
assert ids == {"2016685101", "2016685102"} # hit extended the window; non-Conrad neighbour skipped
assert c.probe_stats["requests"] <= 5
assert any("/pictures/related/=DISALLOW" in n for n in c.notes)
assert not any("/pictures/search" in call or "/pictures/related" in call for call in c.http.calls)
def test_unprocessed_single_print_stays_item():
d = {"item": {"title": "If you liked Vietnam, you'll love this one! Angola", "creators": [{"title": "Conrad, Paul"}],
"call_number": "Unprocessed in PR 13 CN 2023:102 (AA size part) [P&P]", "medium_brief": "1 print ;",
"notes": [{"note": "Title transcribed from item."}]}, "resources": []}
assert loc.item_record("2023631806", d, "t").granularity == "item"
d["item"].update(title="[Cartoons]", medium_brief="7 drawings.")
rec = loc.item_record("2010634813", d, "t")
assert rec.granularity == "folder" and "7 drawings" in rec.notes