fix(tests): close leaked sqlite connections; gate ResourceWarning as error (refs #618)
zot Db.__init__ leak on schema-parity raise; test fixtures not closing raw Db/create_db connections; cli comments _build_bib_helpers cache connection never closed. Gate: error::ResourceWarning (coverage's own sqlitedb warning ignored). Root causes tracemalloc-verified; most per-test attributions in #618 were GC-timing misattribution across xdist workers.
This commit is contained in:
@@ -207,6 +207,10 @@ testpaths = ["tests"]
|
||||
markers = [
|
||||
"stub: marks tests that report stub vs implemented status (deselect with '-m \"not stub\"')",
|
||||
]
|
||||
filterwarnings = [
|
||||
"error::ResourceWarning",
|
||||
"ignore::ResourceWarning:coverage.*",
|
||||
]
|
||||
|
||||
[tool.coverage.run]
|
||||
# Required for reliable pytest-cov + pytest-xdist combining: each worker
|
||||
|
||||
@@ -50,15 +50,17 @@ def _build_bib_helpers(use_bib: bool, attach: bool):
|
||||
|
||||
db = str(path("db.bib"))
|
||||
con = sqlite3.connect(db, check_same_thread=False)
|
||||
|
||||
cache: dict[str, tuple[str, str]] = {}
|
||||
for row in con.execute(
|
||||
"SELECT key, url, abstract FROM items "
|
||||
"WHERE url LIKE 'https://www.regulations.gov/comment/%'"
|
||||
):
|
||||
cid = (row[1] or "").rsplit("/", 1)[-1]
|
||||
if cid:
|
||||
cache[cid] = (row[0], row[2] or "")
|
||||
try:
|
||||
cache: dict[str, tuple[str, str]] = {}
|
||||
for row in con.execute(
|
||||
"SELECT key, url, abstract FROM items "
|
||||
"WHERE url LIKE 'https://www.regulations.gov/comment/%'"
|
||||
):
|
||||
cid = (row[1] or "").rsplit("/", 1)[-1]
|
||||
if cid:
|
||||
cache[cid] = (row[0], row[2] or "")
|
||||
finally:
|
||||
con.close()
|
||||
|
||||
def body_lookup(comment_id: str) -> str:
|
||||
return cache.get(comment_id, ("", ""))[1]
|
||||
|
||||
@@ -293,10 +293,14 @@ class Db:
|
||||
def __init__(self, path: str) -> None:
|
||||
self.path = path
|
||||
self.con = sqlite3.connect(path)
|
||||
self.con.row_factory = sqlite3.Row
|
||||
self.con.execute("PRAGMA journal_mode=WAL")
|
||||
self.con.execute("PRAGMA foreign_keys=ON")
|
||||
self._verify_schema_parity()
|
||||
try:
|
||||
self.con.row_factory = sqlite3.Row
|
||||
self.con.execute("PRAGMA journal_mode=WAL")
|
||||
self.con.execute("PRAGMA foreign_keys=ON")
|
||||
self._verify_schema_parity()
|
||||
except Exception:
|
||||
self.con.close()
|
||||
raise
|
||||
|
||||
def _verify_schema_parity(self) -> None:
|
||||
"""Fail fast if Zotero's live schema disagrees with our maps.
|
||||
|
||||
@@ -182,6 +182,7 @@ def extractor(zotero_db) -> Extractor:
|
||||
ex = Extractor(db)
|
||||
yield ex
|
||||
ex.close()
|
||||
db.close()
|
||||
|
||||
|
||||
class TestExtractorQuotes:
|
||||
|
||||
@@ -35,26 +35,31 @@ class TestCreateDb:
|
||||
con = create_db()
|
||||
count = con.execute("SELECT count(*) FROM itemTypes").fetchone()[0]
|
||||
assert count == 40
|
||||
con.close()
|
||||
|
||||
def test_fields_seeded(self):
|
||||
con = create_db()
|
||||
count = con.execute("SELECT count(*) FROM fields").fetchone()[0]
|
||||
assert count == 123
|
||||
con.close()
|
||||
|
||||
def test_creator_types_seeded(self):
|
||||
con = create_db()
|
||||
count = con.execute("SELECT count(*) FROM creatorTypes").fetchone()[0]
|
||||
assert count == 37
|
||||
con.close()
|
||||
|
||||
def test_item_type_fields_seeded(self):
|
||||
con = create_db()
|
||||
count = con.execute("SELECT count(*) FROM itemTypeFields").fetchone()[0]
|
||||
assert count == 770
|
||||
con.close()
|
||||
|
||||
def test_base_field_mappings_seeded(self):
|
||||
con = create_db()
|
||||
count = con.execute("SELECT count(*) FROM baseFieldMappings").fetchone()[0]
|
||||
assert count == 72
|
||||
con.close()
|
||||
|
||||
def test_library_exists(self):
|
||||
con = create_db()
|
||||
|
||||
Reference in New Issue
Block a user