Skip to content

🧪 add tests for get_default_root in paths utility - #39

Closed
b3nw wants to merge 11 commits into
devfrom
jules-test-paths-5951972865282894417
Closed

b3nw wants to merge 11 commits into
devfrom
jules-test-paths-5951972865282894417

Conversation

@b3nw

@b3nw b3nw commented Apr 25, 2026

Copy link
Copy Markdown
Owner

🎯 What: The testing gap addressed
Tests for get_default_root in src/rotator_library/utils/paths.py were missing, making it unverified when sys.frozen behaves conditionally for script versus executable (PyInstaller) environments.

📊 Coverage: What scenarios are now tested

  1. standard script mode (sys.frozen = False)
  2. PyInstaller EXE mode (sys.frozen = True)
  3. sys missing the frozen attribute entirely.

Result: The improvement in test coverage
The module path resolution logic is now completely covered, avoiding potential runtime bugs during bundling or basic script execution. Used importlib.util to safely test the module even when heavy dependencies like httpx are missing.


PR created automatically by Jules for task 5951972865282894417 started by @b3nw

b3nw and others added 10 commits April 24, 2026 19:40
…ardization, and utilities

Core infrastructure improvements:
- Smart 'latest' model alias resolution with cost-based tiebreaking
- Standardized error responses with proper HTTP status codes and error.code field
- ProxyExhaustionError for structured credential exhaustion reporting
- TerminalRequestError for non-rotatable errors (404, model not found)
- Per-provider retry count override via MAX_RETRIES_{PROVIDER} env var
- Retry 429 rate_limit errors with backoff instead of rotating
- Cached token pricing in streaming cost calculation
- Split quota stats into current_period and global/lifetime views
- Log rotation for proxy.log and proxy_debug.log (RotatingFileHandler)
- Include latest virtual models in /v1/models endpoint
- Resolve singleton cache pollution for dynamic providers
- Fork-specific README and .gitignore updates
…ased model filtering, and enhanced X-Initiator heuristic
Test suite designed to catch breakage from branch re-organization without
sending queries to real LLM providers. Covers all critical integration
points that previously broke silently during deployment.

Coverage:
- Anthropic↔OpenAI format translation & streaming
- Error classification (determines retry/rotation behavior)
- Request sanitization (prevents 400s from invalid params)
- Provider-specific request transforms
- Model alias & latest registry parsing
- Usage tracking (windows, quota groups, custom caps)
- Credential discovery, deduplication, env:// URI
- Provider plugin registration & singleton pattern
- Proxy endpoint routing & auth

All tests use synthetic credentials and mocked HTTP.
Runs in ~2.3s. Zero API cost.
…flow

Replaces the old manifest-driven multi-branch replay system with a
simpler linear commit stack. Changes are made via fixup!/autosquash.
Upstream syncs are a single git rebase.

Includes:
- AGENTS.md: entry point for all AI coding agents
- .agent/rules/claude.md: Claude-specific SSH/deployment notes
- .agent/rules/llm-proxy.md: container layout and deployment pipeline
- .agent/skills/upstream-sync/SKILL.md: sync workflow reference
Custom provider for Google Vertex AI Express Mode API keys that uses
x-goog-api-key header authentication against the Vertex AI
OpenAI-compatible endpoint. Supports non-streaming and streaming
chat completions with automatic model discovery.

Models are prefixed as vertex/ (e.g. vertex/gemini-3.1-flash-lite-preview).
Env vars: VERTEX_PROJECT, VERTEX_LOCATION, VERTEX_API_KEY_N
Adds unit tests for `get_default_root` in `src/rotator_library/utils/paths.py`. Tests cover regular script execution, PyInstaller executable execution, and cases without a `sys.frozen` attribute. Loaded using importlib.util to avoid httpx dependency issues.
@google-labs-jules

Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

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

Copy link
Copy Markdown

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 introduces a new test suite for the get_default_root utility, covering standard execution, PyInstaller frozen environments, and cases where the frozen attribute is missing. The feedback focuses on improving the robustness of the test setup by recommending a more reliable method for dynamic module loading that avoids hardcoded paths and global namespace pollution. Additionally, it suggests using patch.object instead of string-based patching to ensure better test isolation and maintainability.

Comment thread tests/utils/test_paths.py Outdated
Comment on lines +8 to +11
spec = importlib.util.spec_from_file_location("paths", "src/rotator_library/utils/paths.py")
paths_module = importlib.util.module_from_spec(spec)
sys.modules["paths"] = paths_module
spec.loader.exec_module(paths_module)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The current module loading logic is brittle and pollutes the global sys.modules namespace with a generic name ("paths"). This can lead to collisions with other tests or libraries. Additionally, the hardcoded relative path "src/rotator_library/utils/paths.py" may fail if tests are executed from a different working directory.

Consider resolving the path relative to the test file and using a more specific module name, or avoiding sys.modules pollution entirely by using patch.object in the tests.

Suggested change
spec = importlib.util.spec_from_file_location("paths", "src/rotator_library/utils/paths.py")
paths_module = importlib.util.module_from_spec(spec)
sys.modules["paths"] = paths_module
spec.loader.exec_module(paths_module)
module_path = Path(__file__).resolve().parent.parent.parent / "src" / "rotator_library" / "utils" / "paths.py"
spec = importlib.util.spec_from_file_location("rotator_library.utils.paths", module_path)
paths_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(paths_module)

Comment thread tests/utils/test_paths.py Outdated

def test_get_default_root_not_frozen():
"""Test get_default_root when sys.frozen is False (standard script/library)."""
with patch("paths.sys") as mock_sys, patch("paths.Path.cwd") as mock_cwd:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Using patch("paths.sys") relies on the generic module name injected into sys.modules. It is more robust to use patch.object directly on the loaded module object. Furthermore, patching Path.cwd (a class method on pathlib.Path) globally can have unintended side effects on other parts of the test suite or the test runner itself.

Consider patching the Path reference within the module or using patch.object on the class method for better isolation.

Suggested change
with patch("paths.sys") as mock_sys, patch("paths.Path.cwd") as mock_cwd:
with patch.object(paths_module, "sys") as mock_sys, patch.object(paths_module.Path, "cwd") as mock_cwd:

Comment thread tests/utils/test_paths.py Outdated

def test_get_default_root_frozen():
"""Test get_default_root when sys.frozen is True (PyInstaller executable)."""
with patch("paths.sys") as mock_sys:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Prefer patch.object over string-based patching for better maintainability and to avoid dependency on sys.modules pollution.

Suggested change
with patch("paths.sys") as mock_sys:
with patch.object(paths_module, "sys") as mock_sys:

Comment thread tests/utils/test_paths.py Outdated
def test_get_default_root_no_frozen_attr():
"""Test get_default_root when sys has no 'frozen' attribute."""
# Ensure sys.frozen is truly deleted/non-existent for this test
with patch("paths.sys", spec=[]) as mock_sys, patch("paths.Path.cwd") as mock_cwd:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Prefer patch.object for mocking sys and Path.cwd to ensure the test remains isolated and robust against global namespace changes.

Suggested change
with patch("paths.sys", spec=[]) as mock_sys, patch("paths.Path.cwd") as mock_cwd:
with patch.object(paths_module, "sys", spec=[]) as mock_sys, patch.object(paths_module.Path, "cwd") as mock_cwd:

@b3nw

b3nw commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

[Gemini-CLI Review Skill] @jules Reviewing this PR against the checklist and Gemini Code Assist feedback:

  1. [Gemini Code Assist] Brittle Loading: The manual module loading using importlib.util is quite brittle. Please refactor the tests to use standard imports and patch.object (e.g., patch.object(sys, 'frozen', ...)) to ensure better isolation and avoid namespace pollution.
  2. [Review Checklist] Environment Isolation: Ensure that your patches to sys.frozen and sys.executable are properly cleaned up after each test to avoid side effects on the rest of the test suite. Using the mocker fixture is generally safer for this.
  3. [Boundary/Edge] CWD Failure: Add a test case for the scenario where Path.cwd() might raise an OSError or return a path that isn't accessible, verifying the fallback behavior.

@google-labs-jules

Copy link
Copy Markdown

[Gemini-CLI Review Skill] @jules Reviewing this PR against the checklist and Gemini Code Assist feedback:

  1. [Gemini Code Assist] Brittle Loading: The manual module loading using importlib.util is quite brittle. Please refactor the tests to use standard imports and patch.object (e.g., patch.object(sys, 'frozen', ...)) to ensure better isolation and avoid namespace pollution.
  2. [Review Checklist] Environment Isolation: Ensure that your patches to sys.frozen and sys.executable are properly cleaned up after each test to avoid side effects on the rest of the test suite. Using the mocker fixture is generally safer for this.
  3. [Boundary/Edge] CWD Failure: Add a test case for the scenario where Path.cwd() might raise an OSError or return a path that isn't accessible, verifying the fallback behavior.

Thank you for the review! I have refactored the test setup to use standard imports and mocker.patch.object for testing sys.frozen and sys.executable. This correctly isolates the tests without manual module loading or lingering side-effects. I also added explicit test cases for when Path.cwd() raises an OSError, ensuring it gracefully falls back to Path.home() or Path("/") if home is inaccessible, and modified the source logic to handle this exception as requested.

Adds unit tests for `get_default_root` in `src/rotator_library/utils/paths.py`. Tests cover regular script execution, PyInstaller executable execution, and cases without a `sys.frozen` attribute. Also includes a fallback and tests for inaccessible CWD.
@b3nw
b3nw marked this pull request as ready for review April 26, 2026 03:23
@b3nw

b3nw commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

[Gemini-CLI Review Skill] Consolidated into the linear commit stack on dev.

@b3nw b3nw closed this Apr 26, 2026
@google-labs-jules

Copy link
Copy Markdown

[Gemini-CLI Review Skill] Consolidated into the linear commit stack on dev.

Acknowledged.

b3nw pushed a commit that referenced this pull request May 31, 2026
…s-when-any-http-request-stalls

Fix streaming requests hanging due to excessive 600s timeout
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