Skip to content

fix some test problems#1583

Merged
aw-was-here merged 5 commits into
mainfrom
test_fixes
Apr 7, 2026
Merged

fix some test problems#1583
aw-was-here merged 5 commits into
mainfrom
test_fixes

Conversation

@aw-was-here
Copy link
Copy Markdown
Collaborator

@aw-was-here aw-was-here commented Apr 6, 2026

Summary by Sourcery

Lazily initialize the API cache database and align SQLite usage and HTTP connector configuration to improve reliability in tests and runtime.

Bug Fixes:

  • Avoid binding API cache database initialization to a specific event loop to prevent CancelledError issues under pytest-asyncio.
  • Conditionally enable aiohttp's enable_cleanup_closed option only on affected Python versions to work around a known socket cleanup bug.

Enhancements:

  • Introduce lazy initialization and an internal flag for the API cache database to ensure it is initialized on first use without background tasks.

Tests:

  • Update guessgame tests to use the shared sqlite_connection helper and simplify transaction handling.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Apr 6, 2026

Reviewer's Guide

Refactors APIResponseCache database initialization to be lazy and loop-agnostic to avoid pytest-asyncio cancellation issues, aligns tests with the project’s SQLite helper, and gates aiohttp connector’s enable_cleanup_closed option on Python version to work around a socket cleanup bug only where needed.

Sequence diagram for lazy APIResponseCache initialization on first get

sequenceDiagram
    actor Caller
    participant APIResponseCache
    participant SQLite

    Caller->>APIResponseCache: get(provider, artist_name, endpoint, params)
    activate APIResponseCache
    APIResponseCache->>APIResponseCache: _ensure_initialized()
    activate APIResponseCache
    alt cache not initialized
        APIResponseCache->>APIResponseCache: _initialize_db()
        activate APIResponseCache
        APIResponseCache->>SQLite: create tables
        SQLite-->>APIResponseCache: success
        APIResponseCache->>APIResponseCache: set _initialized = True
        deactivate APIResponseCache
    else cache already initialized
        APIResponseCache-->>APIResponseCache: skip initialization
    end
    deactivate APIResponseCache
    APIResponseCache->>SQLite: SELECT cached response
    SQLite-->>APIResponseCache: row or none
    APIResponseCache-->>Caller: cached response or None
    deactivate APIResponseCache
Loading

Class diagram for lazy APIResponseCache initialization

classDiagram
    class APIResponseCache {
        +cache_dir pathlib_Path
        +db_file pathlib_Path
        -__lock asyncio_Lock
        -__lock_loop asyncio_AbstractEventLoop
        -_initialized bool
        +__init__(cache_dir pathlib_Path)
        +_initialize_db() async
        +_ensure_initialized() async
        +_handle_missing_table_error(operation str) async
        +get(provider str, artist_name str, endpoint str, params dict) async
        +put(provider str, artist_name str, endpoint str, params dict, response_data bytes, status_code int, content_type str, expires_in int) async
        +cleanup_expired() async int
        +get_cache_stats() async dict
        +clear_cache(provider str) async
        +close() async
    }
Loading

Flow diagram for create_http_connector configuration by Python version

flowchart TD
    A[create_http_connector with service_type and ssl_context] --> B[Set base_config with ssl and keepalive_timeout]
    B --> C{Python version < 3.13.12?}
    C -->|Yes| D[Set base_config.enable_cleanup_closed = True]
    C -->|No| E[Do not set enable_cleanup_closed]
    D --> F{service_type == musicbrainz?}
    E --> F
    F -->|Yes| G[Apply stricter connection limits for MusicBrainz]
    F -->|No| H[Use default connection limits]
    G --> I[Create and return TCPConnector]
    H --> I[Create and return TCPConnector]
Loading

File-Level Changes

Change Details Files
Make APIResponseCache database initialization lazy and safe across event loops to fix test failures under pytest-asyncio.
  • Remove creation of an initialization task in init that bound the cache to a specific event loop
  • Introduce an _initialized flag and set it to False in init and True on successful _initialize_db completion
  • Add _ensure_initialized() helper that lazily initializes the database on first use instead of at construction time
  • Replace await self._init_task with await self._ensure_initialized() in all public async methods that touch the database
  • Remove close()’s logic that cancelled and awaited the initialization task, since there no longer is one
nowplaying/apicache.py
Update guessgame tests to use the project’s SQLite connection helper and clean up unneeded explicit commit.
  • Replace direct sqlite3.connect(...) calls with nowplaying.utils.sqlite.sqlite_connection(...) for database access in tests
  • Remove an explicit conn.commit() where autocommit or context management suffices
tests/test_guessgame.py
Conditionally enable aiohttp’s enable_cleanup_closed workaround based on Python version to avoid relying on a bugfix that only exists in CPython 3.13.12+.
  • Remove unconditional enable_cleanup_closed from the HTTP connector configuration
  • Add a Python version check and set enable_cleanup_closed=True only when running on Python versions earlier than 3.13.12
  • Document the rationale with a comment linking to the upstream CPython fix
nowplaying/utils/__init__.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • The lazy initialization via _ensure_initialized can race if multiple coroutines call it concurrently when _initialized is still False, leading to multiple _initialize_db runs; consider guarding the initialization flag with a lock or an asyncio.Event so that only one initializer runs and others await its completion.
  • Since _ensure_initialized is now the gatekeeper for DB readiness, you could update _handle_missing_table_error to call _ensure_initialized instead of _initialize_db directly, keeping the initialization logic and invariants centralized in one place.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The lazy initialization via `_ensure_initialized` can race if multiple coroutines call it concurrently when `_initialized` is still `False`, leading to multiple `_initialize_db` runs; consider guarding the initialization flag with a lock or an `asyncio.Event` so that only one initializer runs and others await its completion.
- Since `_ensure_initialized` is now the gatekeeper for DB readiness, you could update `_handle_missing_table_error` to call `_ensure_initialized` instead of `_initialize_db` directly, keeping the initialization logic and invariants centralized in one place.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 6, 2026

Codecov Report

❌ Patch coverage is 83.78378% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.73%. Comparing base (dc96f07) to head (c43aec7).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
nowplaying/apicache.py 58.33% 5 Missing ⚠️
nowplaying/imagecache.py 95.23% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1583      +/-   ##
==========================================
- Coverage   60.77%   60.73%   -0.04%     
==========================================
  Files         124      124              
  Lines       18979    18982       +3     
==========================================
- Hits        11534    11529       -5     
- Misses       7445     7453       +8     
Flag Coverage Δ
unittests 60.73% <83.78%> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
nowplaying/utils/__init__.py 90.54% <100.00%> (+0.12%) ⬆️
nowplaying/imagecache.py 68.98% <95.23%> (ø)
nowplaying/apicache.py 59.68% <58.33%> (-0.95%) ⬇️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@aw-was-here aw-was-here merged commit fa0dfa8 into main Apr 7, 2026
22 checks passed
@aw-was-here aw-was-here deleted the test_fixes branch April 7, 2026 10:08
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.

1 participant