Skip to content

Trim any-llm development dependencies - #122

Merged
IceCodeNew merged 2 commits into
masterfrom
streamline-dev
Jul 26, 2026
Merged

Trim any-llm development dependencies#122
IceCodeNew merged 2 commits into
masterfrom
streamline-dev

Conversation

@IceCodeNew

@IceCodeNew IceCodeNew commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Summary

  • replace the any-llm-sdk[all] development extra with the providers and exception adapter used by this project
  • keep compatibility tests meaningful when optional provider modules cannot be loaded
  • regenerate uv.lock, removing unused provider SDK dependency trees

Why

The development environment installed every optional AnyLLM provider even though weather-briefing only supports DeepSeek, OpenAI, and OpenRouter at runtime. Slimming that dependency group made provider-wide unit tests fail while importing optional SDKs, so the tests now classify every loadable provider and retain the fixed default-header compatibility guard.

Impact

The dev and unittest environments resolve substantially fewer packages without changing production behavior or the Docker dependency group.

Validation

  • prek run --all-files
  • uv run --with pytest --with pytest-cov -- pytest --cov --cov-branch --cov-report=xml (1254 passed, line coverage 99.90%, branch coverage 99.66%)
  • CodeRabbit CLI review (0 issues)

Summary by CodeRabbit

  • Bug Fixes

    • Improved validation of provider compatibility and JSON response support.
    • Ensured compatibility checks accurately reflect providers available in the current environment.
  • Tests

    • Expanded coverage for dynamically available providers.
    • Added verification for key provider integrations and factory classification.
    • Improved test support documentation and shared testing utilities.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c3ae1f00-87e1-4e7f-a1bc-02703fae0f3b

📥 Commits

Reviewing files that changed from the base of the PR and between c87b94c and ed89369.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • pyproject.toml
  • tests/__init__.py
  • tests/any_llm_helpers.py
  • tests/test_any_llm_compatibility.py
  • tests/test_any_llm_provider.py

📝 Walkthrough

Walkthrough

Development dependencies now select specific AnyLLM provider extras. Shared test discovery filters providers by successful SDK imports, and compatibility and factory tests use that runtime-loadable provider set.

Changes

Runtime-loadable AnyLLM provider testing

Layer / File(s) Summary
Runtime provider setup
pyproject.toml, tests/__init__.py, tests/any_llm_helpers.py
The development dependency selects DeepSeek, OpenAI, OpenRouter, and Otari extras, while shared test support discovers importable providers.
Runtime compatibility assertions
tests/test_any_llm_compatibility.py, tests/test_any_llm_provider.py
Compatibility checks and factory parametrization use loadable providers, with assertions for blacklist intersections and required development providers.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: reducing any-llm development dependencies.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch streamline-dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@IceCodeNew

Copy link
Copy Markdown
Owner Author

/agentic_review

@codecov

codecov Bot commented Jul 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.86%. Comparing base (c87b94c) to head (ed89369).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #122   +/-   ##
=======================================
  Coverage   99.86%   99.86%           
=======================================
  Files         115      116    +1     
  Lines       12327    12345   +18     
  Branches      736      737    +1     
=======================================
+ Hits        12310    12328   +18     
  Misses         12       12           
  Partials        5        5           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@qodo-code-review

qodo-code-review Bot commented Jul 26, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 46 rules

Grey Divider


Remediation recommended

1. Vacuous provider test ✓ Resolved 🐞 Bug ☼ Reliability
Description
test_factory_classifies_every_loadable_provider is parametrized from _loadable_providers(); when
every AnyLLM.get_provider_class(...) raises ImportError, the list is empty and pytest collects 0
cases, so provider classification is never exercised. This can yield a false-green test run in
environments where provider SDKs are absent/misinstalled.
Code

tests/test_any_llm_provider.py[R414-429]

+def _loadable_providers() -> list[str]:
+    result: list[str] = []
+    for provider in AnyLLM.get_supported_providers():
+        try:
+            AnyLLM.get_provider_class(provider)
+            result.append(provider)
+        except ImportError:
+            pass
+    return result
+
+
@pytest.mark.parametrize(
    "provider",
-    tuple(AnyLLM.get_supported_providers()),
+    _loadable_providers(),
)
-def test_factory_classifies_every_any_llm_provider(monkeypatch, provider: str) -> None:
+def test_factory_classifies_every_loadable_provider(monkeypatch, provider: str) -> None:
Relevance

⭐⭐⭐ High

Repo often strengthens tests to avoid false-green/flaky runs; empty-parametrize guard is a
deterministic reliability fix.

PR-#114
PR-#11
PR-#108

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
_loadable_providers() catches and ignores ImportError, so it can produce an empty provider list;
pytest will then collect no cases for the parametrized test, leaving the classification behavior
untested.

tests/test_any_llm_provider.py[414-429]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`test_factory_classifies_every_loadable_provider` is currently generated from `_loadable_providers()`. Because `_loadable_providers()` swallows `ImportError`, it can legitimately return an empty list, which causes pytest to collect **zero** cases for the parametrized test. That makes the suite pass without validating provider classification at all.

### Issue Context
This PR intentionally makes optional providers potentially unloadable (missing SDKs). The test should still fail loudly if **nothing** is loadable, otherwise it becomes a vacuous check.

### Fix Focus Areas
- tests/test_any_llm_provider.py[414-429]

### Suggested fix
Add an explicit guard so the suite fails when no providers are loadable. Options:
- Add a separate test like `test_any_llm_has_at_least_one_loadable_provider()` asserting `_loadable_providers()` is non-empty.
- Or, in `_loadable_providers()`, if the result is empty, `pytest.fail("No any-llm providers are loadable in this environment")`.
- If there are specific providers this project requires for tests (e.g., deepseek/openai/openrouter), assert that those are present in the loadable list.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

2. Duplicated provider helper ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
The provider-loadability filtering logic is duplicated in two test modules as separate
_loadable_providers() functions (with different return types), increasing the chance of future drift
in which providers each suite considers testable. A change to one helper could silently change test
coverage without updating the other.
Code

tests/test_any_llm_compatibility.py[R10-18]

+def _loadable_providers() -> set[str]:
+    result: set[str] = set()
+    for provider in AnyLLM.get_supported_providers():
+        try:
+            AnyLLM.get_provider_class(provider)
+            result.add(provider)
+        except ImportError:
+            pass
+    return result
Relevance

⭐⭐ Medium

Deduplicating test helpers is reasonable, but no close repo precedent; could be seen as optional
refactor.

PR-#114
PR-#108

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Both modules define their own _loadable_providers() with the same filtering algorithm, which is a
duplication introduced by this PR.

tests/test_any_llm_compatibility.py[10-18]
tests/test_any_llm_provider.py[414-422]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Two independent `_loadable_providers()` implementations exist in separate test modules. This is duplicated logic and increases divergence risk.

### Issue Context
Both helpers iterate `AnyLLM.get_supported_providers()`, attempt `AnyLLM.get_provider_class(provider)`, and ignore `ImportError`, differing mainly in return type (`set[str]` vs `list[str]`).

### Fix Focus Areas
- tests/test_any_llm_compatibility.py[10-18]
- tests/test_any_llm_provider.py[414-422]

### Suggested fix
Create a shared helper (e.g., `tests/any_llm_test_utils.py` or `tests/conftest.py`) that returns a canonical type like `tuple[str, ...]` or `list[str]`. In call sites:
- Convert to `set(...)` where set operations are needed.
- Use the sequence directly for parametrization.
This keeps provider-filtering behavior consistent across the test suite.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread tests/test_any_llm_provider.py Outdated
Comment thread tests/test_any_llm_compatibility.py Outdated
@IceCodeNew

Copy link
Copy Markdown
Owner Author

/agentic_review

@IceCodeNew
IceCodeNew marked this pull request as ready for review July 26, 2026 10:54
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Trim AnyLLM dev extras and make provider tests import-safe

⚙️ Configuration changes 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Slim dev AnyLLM extras to only required provider SDKs and adapter.
• Update provider-wide tests to only assert against importable (loadable) providers.
• Add a guard test ensuring dev deps still include runtime providers (DeepSeek/OpenAI/OpenRouter).
Diagram

graph TD
  A["pyproject.toml (dev extras)"] --> B["AnyLLM SDK (selected providers)"] --> C["tests/any_llm_helpers.py"] --> D["test_any_llm_compatibility.py"]
  C --> E["test_any_llm_provider.py"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use pytest.importorskip per provider module
  • ➕ More explicit skip reasons per missing provider SDK
  • ➕ Keeps individual tests readable when tied to a single provider
  • ➖ Harder to keep global invariants (e.g., blacklist equality) meaningful
  • ➖ More scattered conditional logic across test files
2. Introduce a dedicated 'test' extra separate from 'dev'
  • ➕ Clarifies the minimal dependency set required to run the full test suite
  • ➕ Allows an even slimmer 'dev' set if desired
  • ➖ Extra packaging surface area to maintain (docs/CI wiring)
  • ➖ Can confuse contributors about which extra to install locally

Recommendation: The current approach (central helper that filters to loadable providers and intersects blacklists accordingly) is the best fit for keeping provider-wide invariants non-vacuous while allowing a trimmed dev dependency set. Consider a separate 'test' extra only if you foresee multiple distinct local workflows (e.g., docs/dev vs. CI tests) needing different footprints.

Files changed (5) +35 / -14

Tests (4) +34 / -13
__init__.pyMake tests a package for shared imports +1/-0

Make tests a package for shared imports

• Adds an '__init__.py' so test helpers can be imported via 'tests.*' consistently across the suite.

tests/init.py

any_llm_helpers.pyAdd helper to list loadable AnyLLM providers +15/-0

Add helper to list loadable AnyLLM providers

• Introduces 'loadable_any_llm_providers()' which filters 'AnyLLM.get_supported_providers()' down to providers whose classes can be imported. Missing optional SDKs are handled by catching 'ImportError'.

tests/any_llm_helpers.py

test_any_llm_compatibility.pyMake compatibility assertions non-vacuous under trimmed deps +11/-11

Make compatibility assertions non-vacuous under trimmed deps

• Updates provider-compatibility tests to compute completion providers from the loadable provider set. Provider blacklists are intersected with loadable providers so equality/coverage assertions remain meaningful when optional SDKs are not installed.

tests/test_any_llm_compatibility.py

test_any_llm_provider.pyParametrize factory tests only over loadable providers +7/-2

Parametrize factory tests only over loadable providers

• Adds a guard test asserting the dev environment can load the runtime providers (deepseek/openai/openrouter). Changes parametrization to use only loadable providers and renames the test to reflect the new intent.

tests/test_any_llm_provider.py

Other (1) +1 / -1
pyproject.tomlTrim AnyLLM dev extras to used providers +1/-1

Trim AnyLLM dev extras to used providers

• Replaces the broad 'any-llm-sdk[all]' dev extra with a narrower set of provider extras used by this project (plus the adapter dependency). This reduces transitive SDK installs in development without affecting the docker/runtime dependency group.

pyproject.toml

@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit ed89369

@IceCodeNew
IceCodeNew merged commit b5e72f6 into master Jul 26, 2026
18 checks passed
@IceCodeNew
IceCodeNew deleted the streamline-dev branch July 26, 2026 12:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant