Skip to content

chore(tests): wrap sqlite3 connections in contextlib.closing#1430

Merged
igorls merged 1 commit into
developfrom
chore/test-sqlite-cleanup
May 9, 2026
Merged

chore(tests): wrap sqlite3 connections in contextlib.closing#1430
igorls merged 1 commit into
developfrom
chore/test-sqlite-cleanup

Conversation

@igorls

@igorls igorls commented May 9, 2026

Copy link
Copy Markdown
Member

Summary

Several tests open sqlite3 connections without try/finally or context-manager cleanup, relying on a flat conn.close() after the work. Any assertion failure or exception between connect and close leaks the connection until GC, producing ResourceWarning: unclosed database in CI logs.

On Python 3.13 / macOS the warning isn't just noise: a leaked connection can hold a SQLite advisory lock long enough for later test setup to block on it, which appears to be the cause of recent intermittent CI hangs on those two runners specifically (e.g. the 33-minute pytest hang on #1396's first attempt).

Change

Wrap each naked conn = sqlite3.connect(...) block in contextlib.closing(...) so cleanup runs on the failure path too. Mirrors the try/finally pattern already used in production code (searcher.py, repair.py, backends/chroma.py).

Files touched:

  • tests/test_backends.py — 12 sites in the _fix_blob_seq_ids test cluster
  • tests/test_sources.py — 4 sites in the KnowledgeGraph schema/migration tests; also dedups three import sqlite3 calls inside test bodies into one top-level import
  • tests/test_repair.py — 1 site in _seed_poisoned_max_seq_id

Skipped:

  • test_hnsw_capacity.py:50/365/403 and test_repair.py:1362 already use try/finally — left as-is
  • test_cli.py and test_repair.py one-liner sqlite3.connect(...).close() patterns are already safe (single expression, no operations between)

Out of scope (worth a follow-up)

  • Bare KnowledgeGraph(...) instances in test bodies (test_sources.py, test_fact_checker.py, test_knowledge_graph_extra.py) hold their own sqlite connection on self._connection. Most already use try/finally: kg.close(), but a couple don't. Separate cleanup pass.

Test plan

  • uv run pytest tests/test_backends.py tests/test_sources.py tests/test_repair.py -x --no-cov -q → 162 passed
  • ruff check (pinned ruff>=0.4.0,<0.5) → clean
  • ruff format --check (pinned ruff>=0.4.0,<0.5) → clean
  • CI green on Linux 3.9/3.11/3.13, Windows, macOS, lint

Copilot AI review requested due to automatic review settings May 9, 2026 22:38
@igorls igorls requested a review from milla-jovovich as a code owner May 9, 2026 22:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the test suite against leaked sqlite3 connections by wrapping connection lifetimes with contextlib.closing(...), ensuring connections are closed even when assertions fail—reducing ResourceWarning: unclosed database noise and potential SQLite lock-related CI hangs.

Changes:

  • Wrap multiple sqlite3.connect(...) usages in with closing(...) blocks across affected tests.
  • Deduplicate in-test import sqlite3 statements in tests/test_sources.py into a single top-level import.
  • Apply the same connection cleanup approach to a helper in tests/test_repair.py.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
tests/test_sources.py Adds top-level sqlite3/closing imports and wraps KnowledgeGraph schema/provenance sqlite reads/writes with closing(...).
tests/test_repair.py Imports closing and wraps the _seed_poisoned_max_seq_id sqlite setup in closing(...) for failure-safe cleanup.
tests/test_backends.py Imports closing and wraps sqlite setup/verification connections in blob seq_id repair tests to prevent leaks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors several test files, including tests/test_backends.py, tests/test_repair.py, and tests/test_sources.py, to improve database connection management. It replaces manual sqlite3 connection closing with the contextlib.closing context manager to ensure resources are properly released even if exceptions occur. Additionally, redundant local imports of sqlite3 were moved to the module level in tests/test_sources.py. I have no feedback to provide.

Several tests opened sqlite3 connections without try/finally or
context-manager cleanup, relying on a flat conn.close() after the
work. Any assertion failure or exception between connect and close
leaked the connection until GC, producing
``ResourceWarning: unclosed database`` in CI logs.

On Python 3.13 / macOS the ResourceWarning isn't just noise: a
leaked connection can hold a SQLite advisory lock long enough for
later test setup to block on it, which appears to be the cause of
recent intermittent CI hangs on those two runners.

Wrap each affected ``conn = sqlite3.connect(...)`` block in
``contextlib.closing(...)`` so cleanup runs on the failure path too.
Mirrors the try/finally pattern already used in production code
(searcher.py, repair.py, backends/chroma.py).

No behavior change — same operations, same assertions, just
deterministic cleanup. All 162 affected tests pass locally.
@igorls igorls force-pushed the chore/test-sqlite-cleanup branch from 3cf555a to df5ca11 Compare May 9, 2026 23:26
@igorls igorls merged commit b9cec32 into develop May 9, 2026
6 checks passed
@igorls igorls deleted the chore/test-sqlite-cleanup branch May 9, 2026 23:58
This was referenced May 10, 2026
arnoldwender pushed a commit to arnoldwender/mempalace that referenced this pull request May 10, 2026
Bumps version 3.3.4 → 3.3.5 across pyproject.toml, version.py, plugin
manifests, README badge, and uv.lock. Flips CHANGELOG.md from
``[3.3.5] — unreleased`` to ``[3.3.5] — 2026-05-09`` and adds entries
for the four PRs that landed after the bug-fix block was authored:

- Bug Fixes: MemPalace#1396 (tool_search retry on transient HNSW flush)
- Documentation: MemPalace#1385 (CONTRIBUTING git-identity guidance, closes MemPalace#1317)
- Internal: MemPalace#1431 (test multiprocessing fork → spawn)
- Internal: MemPalace#1430 (test sqlite connection lifecycle via contextlib.closing)

The four open issues remaining on the v3.3.5 milestone (MemPalace#1266, MemPalace#1253,
MemPalace#1092, MemPalace#1082) have been moved to v3.4 — they form the concurrent-writer
/ HNSW corruption cluster that needs deeper work than this cycle could
absorb.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants