Skip to content

LCORE-1607: specific rules to ignore types#1465

Merged
tisnik merged 3 commits into
lightspeed-core:mainfrom
tisnik:lcore-1607-specific-rules-to-ignore-types
Apr 7, 2026
Merged

LCORE-1607: specific rules to ignore types#1465
tisnik merged 3 commits into
lightspeed-core:mainfrom
tisnik:lcore-1607-specific-rules-to-ignore-types

Conversation

@tisnik
Copy link
Copy Markdown
Contributor

@tisnik tisnik commented Apr 7, 2026

Description

LCORE-1607: specific rules to ignore types

Type of change

  • Refactor
  • New feature
  • Bug fix
  • CVE fix
  • Optimization
  • Documentation Update
  • Configuration Update
  • Bump-up service version
  • Bump-up dependent library
  • Bump-up library or tool used for development (does not change the final image)
  • CI configuration change
  • Konflux configuration change
  • Unit tests improvement
  • Integration tests improvement
  • End to end tests improvement
  • Benchmarks improvement

Tools used to create PR

  • Assisted-by: N/A
  • Generated by: N/A

Related Tickets & Documents

  • Related Issue #LCORE-1607

Summary by CodeRabbit

Release Notes

  • Tests

    • Refactored test assertions for improved readability and enhanced type-checking coverage with more specific error suppression annotations.
  • Chores

    • Updated type-suppression comments across multiple modules to use targeted suppression categories, replacing generic directives with specific error codes for better static analysis precision.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 7, 2026

Walkthrough

This pull request refactors type-checking suppressions across multiple files from generic # type: ignore comments to more specific error codes (e.g., reportCallIssue, reportArgumentType, arg-type). Additionally, three test files extract expected assertion values into local variables for improved clarity.

Changes

Cohort / File(s) Summary
Main source type suppression
src/client.py
Narrowed type-ignore suppression from generic # type: ignore to specific # type: ignore[arg-type] on a method call within update_provider_data.
E2E step definitions type suppression
tests/e2e/features/steps/auth.py, tests/e2e/features/steps/common.py, tests/e2e/features/steps/conversation.py, tests/e2e/features/steps/feedback.py
Narrowed type-ignore suppressions from generic # type: ignore to specific # type: ignore[reportCallIssue] on Behave step decorators, improving static-analysis targeting without runtime behavior changes.
Integration test assertion refactoring
tests/integration/endpoints/test_info_integration.py, tests/integration/endpoints/test_model_list.py, tests/integration/endpoints/test_query_integration.py
Extracted expected error message strings into local variables and narrowed type-ignore comments to # type: ignore[reportArgumentType] for improved assertion clarity and more targeted type suppression.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: replacing generic type-ignore comments with specific rule names across the codebase.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
✨ Simplify code
  • Create PR with simplified code

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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
tests/e2e/features/steps/feedback.py (5)

57-57: ⚠️ Potential issue | 🟡 Minor

Incomplete refactoring: Update to specific type-ignore code.

This decorator still uses a generic # type: ignore comment, while other decorators in this file (lines 21, 29, 37, 95, 101, 143) were updated to use # type: ignore[reportCallIssue]. For consistency with the PR objectives and the rest of this file, this should also be updated.

♻️ Proposed fix for consistency
-@when("I submit the following feedback for the conversation created before")  # type: ignore
+@when("I submit the following feedback for the conversation created before")  # type: ignore[reportCallIssue]
 def submit_feedback_valid_conversation(context: Context) -> None:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/features/steps/feedback.py` at line 57, The decorator `@when`("I
submit the following feedback for the conversation created before") uses a
generic "# type: ignore" that was not updated; replace it with the specific "#
type: ignore[reportCallIssue]" to match the rest of the file (see other
decorators updated at lines near the top) so the type-ignore is explicit and
consistent with functions handling step definitions in this module.

74-74: ⚠️ Potential issue | 🟡 Minor

Incomplete refactoring: Update to specific type-ignore code.

This decorator still uses a generic # type: ignore comment. For consistency with the updated decorators in this file (lines 21, 29, 37, 95, 101, 143), this should be updated to # type: ignore[reportCallIssue].

♻️ Proposed fix for consistency
-@when("I submit the following feedback without specifying conversation ID")  # type: ignore
+@when("I submit the following feedback without specifying conversation ID")  # type: ignore[reportCallIssue]
 def submit_feedback_without_conversation(context: Context) -> None:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/features/steps/feedback.py` at line 74, Update the decorator on the
step definition that reads `@when`("I submit the following feedback without
specifying conversation ID")  # type: ignore to use the specific ignore code;
replace the trailing comment with # type: ignore[reportCallIssue] so it matches
the other decorators in this file (e.g., those at lines using # type:
ignore[reportCallIssue]) and keeps consistent typing annotations for this step
definition.

66-66: ⚠️ Potential issue | 🟡 Minor

Incomplete refactoring: Update to specific type-ignore code.

This decorator still uses a generic # type: ignore comment. For consistency with the updated decorators in this file (lines 21, 29, 37, 95, 101, 143), this should be updated to # type: ignore[reportCallIssue].

♻️ Proposed fix for consistency
-@when('I submit the following feedback for nonexisting conversation "{conversation_id}"')  # type: ignore
+@when('I submit the following feedback for nonexisting conversation "{conversation_id}"')  # type: ignore[reportCallIssue]
 def submit_feedback_nonexisting_conversation(
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/features/steps/feedback.py` at line 66, Update the decorator
comment on the `@when`('I submit the following feedback for nonexisting
conversation "{conversation_id}"') line to use the specific ignore code instead
of the generic one: replace the trailing "# type: ignore" with "# type:
ignore[reportCallIssue]" so it matches the other decorators in this file (e.g.,
the ones at lines with similar `@when/`@given decorators).

7-7: ⚠️ Potential issue | 🟡 Minor

Remove duplicate type-ignore comments.

The # pyright: ignore[reportAttributeAccessIssue] comment is duplicated three times on line 7. This appears to be a copy-paste error.

🧹 Proposed fix
-from behave import (  # pyright: ignore[reportAttributeAccessIssue]  # pyright: ignore[reportAttributeAccessIssue]  # pyright: ignore[reportAttributeAccessIssue]
+from behave import (  # pyright: ignore[reportAttributeAccessIssue]
     given,
     step,
     when,
 )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/features/steps/feedback.py` at line 7, The import line in
tests/e2e/features/steps/feedback.py contains three identical pyright ignore
comments; remove the duplicates so only a single "# pyright:
ignore[reportAttributeAccessIssue]" remains after the "from behave import ("
import to avoid redundant comments while preserving the intended type-ignore;
ensure spacing and punctuation around the remaining comment matches project
style.

107-107: ⚠️ Potential issue | 🟡 Minor

Incomplete refactoring: Update to specific type-ignore code.

This decorator still uses a generic # type: ignore comment. For consistency with the updated decorators in this file (lines 21, 29, 37, 95, 101, 143), this should be updated to # type: ignore[reportCallIssue].

♻️ Proposed fix for consistency
-@given('A new conversation is initialized with user_id "{user_id}"')  # type: ignore
+@given('A new conversation is initialized with user_id "{user_id}"')  # type: ignore[reportCallIssue]
 def initialize_conversation_with_user_id(context: Context, user_id: str) -> None:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/features/steps/feedback.py` at line 107, The decorator on the step
definition `@given`('A new conversation is initialized with user_id "{user_id}"')
still uses a generic "# type: ignore"; update it to the specific ignore code
used elsewhere ("# type: ignore[reportCallIssue]") for consistency with the
other decorators (see other `@given/`@when/@then decorators in this file), by
replacing the trailing comment on that decorator line with "# type:
ignore[reportCallIssue]".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/client.py`:
- Line 175: The method currently calls self._lsc.copy(...) and suppresses a type
error; instead add a runtime guard that enforces "service mode only" by checking
the runtime type of self._lsc and rejecting library mode (e.g., if
isinstance(self._lsc, AsyncLlamaStackAsLibraryClient): raise
RuntimeError("...service mode only...")), then narrow the type using typing.cast
before calling copy (remove the # type: ignore[arg-type]); reference self._lsc
and AsyncLlamaStackAsLibraryClient to locate where to add the guard and cast,
and raise a clear error when a library client is detected.

---

Outside diff comments:
In `@tests/e2e/features/steps/feedback.py`:
- Line 57: The decorator `@when`("I submit the following feedback for the
conversation created before") uses a generic "# type: ignore" that was not
updated; replace it with the specific "# type: ignore[reportCallIssue]" to match
the rest of the file (see other decorators updated at lines near the top) so the
type-ignore is explicit and consistent with functions handling step definitions
in this module.
- Line 74: Update the decorator on the step definition that reads `@when`("I
submit the following feedback without specifying conversation ID")  # type:
ignore to use the specific ignore code; replace the trailing comment with #
type: ignore[reportCallIssue] so it matches the other decorators in this file
(e.g., those at lines using # type: ignore[reportCallIssue]) and keeps
consistent typing annotations for this step definition.
- Line 66: Update the decorator comment on the `@when`('I submit the following
feedback for nonexisting conversation "{conversation_id}"') line to use the
specific ignore code instead of the generic one: replace the trailing "# type:
ignore" with "# type: ignore[reportCallIssue]" so it matches the other
decorators in this file (e.g., the ones at lines with similar `@when/`@given
decorators).
- Line 7: The import line in tests/e2e/features/steps/feedback.py contains three
identical pyright ignore comments; remove the duplicates so only a single "#
pyright: ignore[reportAttributeAccessIssue]" remains after the "from behave
import (" import to avoid redundant comments while preserving the intended
type-ignore; ensure spacing and punctuation around the remaining comment matches
project style.
- Line 107: The decorator on the step definition `@given`('A new conversation is
initialized with user_id "{user_id}"') still uses a generic "# type: ignore";
update it to the specific ignore code used elsewhere ("# type:
ignore[reportCallIssue]") for consistency with the other decorators (see other
`@given/`@when/@then decorators in this file), by replacing the trailing comment
on that decorator line with "# type: ignore[reportCallIssue]".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c376e954-426a-4b0c-a817-7734134079c7

📥 Commits

Reviewing files that changed from the base of the PR and between 4961334 and f909e22.

📒 Files selected for processing (8)
  • src/client.py
  • tests/e2e/features/steps/auth.py
  • tests/e2e/features/steps/common.py
  • tests/e2e/features/steps/conversation.py
  • tests/e2e/features/steps/feedback.py
  • tests/integration/endpoints/test_info_integration.py
  • tests/integration/endpoints/test_model_list.py
  • tests/integration/endpoints/test_query_integration.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build-pr
  • GitHub Check: Konflux kflux-prd-rh02 / lightspeed-stack-on-pull-request
  • GitHub Check: E2E Tests for Lightspeed Evaluation job
  • GitHub Check: E2E: server mode / ci
  • GitHub Check: E2E: library mode / ci
🧰 Additional context used
📓 Path-based instructions (2)
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.py: Use pytest for all unit and integration tests; do not use unittest
Use pytest.mark.asyncio marker for async unit tests

Files:

  • tests/e2e/features/steps/common.py
  • tests/integration/endpoints/test_model_list.py
  • tests/integration/endpoints/test_info_integration.py
  • tests/e2e/features/steps/auth.py
  • tests/integration/endpoints/test_query_integration.py
  • tests/e2e/features/steps/conversation.py
  • tests/e2e/features/steps/feedback.py
src/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.py: Use absolute imports for internal modules (e.g., from authentication import get_auth_dependency)
Use from llama_stack_client import AsyncLlamaStackClient for Llama Stack imports
Check constants.py for shared constants before defining new ones
All modules start with descriptive docstrings explaining purpose
Use logger = get_logger(__name__) from log.py for module logging
Type aliases defined at module level for clarity
All functions require docstrings with brief descriptions
Use complete type annotations for function parameters and return types
Use union types with modern syntax: str | int instead of Union[str, int]
Use Optional[Type] for optional types in type annotations
Use snake_case with descriptive, action-oriented names for functions (get_, validate_, check_)
Avoid in-place parameter modification anti-patterns: return new data structures instead of modifying parameters
Use async def for I/O operations and external API calls
Handle APIConnectionError from Llama Stack in error handling
Use logger.debug() for detailed diagnostic information
Use logger.info() for general information about program execution
Use logger.warning() for unexpected events or potential problems
Use logger.error() for serious problems that prevented function execution
All classes require descriptive docstrings explaining purpose
Use PascalCase for class names with descriptive names and standard suffixes: Configuration, Error/Exception, Resolver, Interface
Use complete type annotations for all class attributes; avoid using Any
Follow Google Python docstring conventions for all modules, classes, and functions
Include Parameters:, Returns:, Raises: sections in function docstrings as needed

Files:

  • src/client.py
🧠 Learnings (1)
📚 Learning: 2026-04-05T12:19:36.009Z
Learnt from: CR
Repo: lightspeed-core/lightspeed-stack PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-05T12:19:36.009Z
Learning: Applies to src/**/*.py : Handle `APIConnectionError` from Llama Stack in error handling

Applied to files:

  • tests/integration/endpoints/test_model_list.py
  • tests/integration/endpoints/test_info_integration.py
  • tests/integration/endpoints/test_query_integration.py
🔇 Additional comments (9)
tests/integration/endpoints/test_query_integration.py (1)

134-135: Scoped ignore and explicit expected value are a good refactor.

This keeps the assertion behavior intact while making the suppression more targeted and readable.

tests/integration/endpoints/test_model_list.py (1)

210-211: Looks good: assertion refactor is clear and targeted.

Using a named expected value plus a specific type-ignore rule improves maintainability without changing behavior.

tests/integration/endpoints/test_info_integration.py (1)

126-127: Approved: consistent, behavior-preserving cleanup.

The local expected message and narrowed ignore rule are both sensible here.

tests/e2e/features/steps/common.py (2)

35-35: LGTM: Type suppression specificity improved.

The change from generic # type: ignore to # type: ignore[reportCallIssue] improves type-checking precision by narrowing the suppression scope.


1-89: Verify framework choice aligns with coding guidelines.

This file uses the Behave framework for BDD-style e2e tests. As per coding guidelines, tests/**/*.py should use pytest. While these are e2e tests (which may fall outside the "unit and integration tests" scope mentioned in the guideline), the path pattern is broad enough to include this file.

Please confirm whether the guideline applies to e2e/BDD tests, or if Behave is an approved exception for behavior-driven scenarios in the tests/e2e/ directory.

tests/e2e/features/steps/conversation.py (1)

416-416: LGTM: Type suppression specificity improved.

The change from generic # type: ignore to # type: ignore[reportCallIssue] improves type-checking precision.

tests/e2e/features/steps/auth.py (1)

40-40: LGTM: Type suppression specificity improved.

The change from generic # type: ignore to # type: ignore[reportCallIssue] improves type-checking precision.

tests/e2e/features/steps/feedback.py (2)

21-21: LGTM: Type suppression specificity improved.

The changes from generic # type: ignore to # type: ignore[reportCallIssue] improve type-checking precision.

Also applies to: 29-29, 37-37


95-95: LGTM: Type suppression specificity improved.

The changes from generic # type: ignore to # type: ignore[reportCallIssue] improve type-checking precision.

Also applies to: 101-101, 143-143

Comment thread src/client.py
}

self._lsc = self._lsc.copy(set_default_headers=updated_headers) # type: ignore
self._lsc = self._lsc.copy(set_default_headers=updated_headers) # type: ignore[arg-type]
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.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

🌐 Web query:

What is the current signature of AsyncLlamaStackClient.copy(...)inllama_stack_client, and does it accept set_default_headers: dict[str, str]?

💡 Result:

In llama_stack_client, AsyncLlamaStackClient.copy(...) is currently:

def copy(
    self,
    *,
    api_key: str | None = None,
    base_url: str | httpx.URL | None = None,
    timeout: float | Timeout | None | NotGiven = not_given,
    http_client: httpx.AsyncClient | None = None,
    max_retries: int | NotGiven = not_given,
    default_headers: Mapping[str, str] | None = None,
    set_default_headers: Mapping[str, str] | None = None,
    default_query: Mapping[str, object] | None = None,
    set_default_query: Mapping[str, object] | None = None,
    _extra_kwargs: Mapping[str, Any] = {},
) -> Self
``` ([github.com](https://github.com/llamastack/llama-stack-client-python/blob/main/src/llama_stack_client/_client.py))

Yesit accepts `set_default_headers`, typed as `Mapping[str, str] | None`, so a `dict[str, str]` is valid. ([github.com](https://github.com/llamastack/llama-stack-client-python/blob/main/src/llama_stack_client/_client.py))

Citations:

- 1: https://github.com/llamastack/llama-stack-client-python/blob/main/src/llama_stack_client/_client.py
- 2: https://github.com/llamastack/llama-stack-client-python/blob/main/src/llama_stack_client/_client.py

---

🏁 Script executed:

```shell
# First, examine the context around line 175 in src/client.py
head -200 src/client.py | tail -50

Repository: lightspeed-core/lightspeed-stack

Length of output: 1819


🏁 Script executed:

# Get the full class context and _lsc declaration
rg -B 30 "self._lsc = self._lsc.copy\(set_default_headers" src/client.py -A 5

Repository: lightspeed-core/lightspeed-stack

Length of output: 1132


🏁 Script executed:

# Check for AsyncLlamaStackAsLibraryClient definition and copy method
rg "AsyncLlamaStackAsLibraryClient" src/ -A 10 -B 2

Repository: lightspeed-core/lightspeed-stack

Length of output: 4490


🏁 Script executed:

# Check if is_library_client property exists
rg "is_library_client" src/client.py -B 2 -A 2

Repository: lightspeed-core/lightspeed-stack

Length of output: 250


🏁 Script executed:

# Check _lsc declaration type annotation
rg "_lsc:" src/client.py -B 2 -A 2

Repository: lightspeed-core/lightspeed-stack

Length of output: 706


🏁 Script executed:

# Find where AsyncLlamaStackAsLibraryClient is imported from and examine its definition
rg "AsyncLlamaStackAsLibraryClient" -A 20 | grep -E "(def copy|class AsyncLlamaStackAsLibraryClient)" -A 5

Repository: lightspeed-core/lightspeed-stack

Length of output: 58


🏁 Script executed:

# Check if llama_stack.core.library_client module defines copy() for library client
fd -e py | xargs grep -l "AsyncLlamaStackAsLibraryClient" | head -5

Repository: lightspeed-core/lightspeed-stack

Length of output: 109


🏁 Script executed:

# Look at the imports more closely - where does it come from?
rg "from llama_stack" src/client.py

Repository: lightspeed-core/lightspeed-stack

Length of output: 302


🏁 Script executed:

# Check if AsyncLlamaStackAsLibraryClient is defined locally in the repo
find src -name "*.py" -type f | xargs grep -l "class AsyncLlamaStackAsLibraryClient"

Repository: lightspeed-core/lightspeed-stack

Length of output: 60


🏁 Script executed:

# Get full context of the method signature to confirm return type
rg -B 5 "def update_provider_data" src/client.py

Repository: lightspeed-core/lightspeed-stack

Length of output: 295


🏁 Script executed:

# Verify the class structure of AsyncLlamaStackClientHolder to see all method signatures
rg "class AsyncLlamaStackClientHolder" src/client.py -A 100 | head -120

Repository: lightspeed-core/lightspeed-stack

Length of output: 4153


Enforce service-mode-only contract with a runtime guard instead of type suppression.

The method's docstring promises "For use with service mode only," but there's no runtime check, allowing it to be called with a library client. The # type: ignore[arg-type] suppresses the type mismatch between _lsc's declared type and the AsyncLlamaStackAsLibraryClient it can hold at runtime. Add an explicit guard to reject library mode and narrow the type with cast().

Proposed fix
+from typing import cast
@@
     def update_provider_data(self, updates: dict[str, str]) -> AsyncLlamaStackClient:
@@
         if not self._lsc:
             raise RuntimeError(
                 "AsyncLlamaStackClient has not been initialised. Ensure 'load(..)' has been called."
             )
+        if self.is_library_client:
+            raise RuntimeError(
+                "update_provider_data is only supported for service client mode."
+            )
@@
-        self._lsc = self._lsc.copy(set_default_headers=updated_headers)  # type: ignore[arg-type]
+        service_client = cast(AsyncLlamaStackClient, self._lsc)
+        self._lsc = service_client.copy(set_default_headers=updated_headers)
         return self._lsc
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/client.py` at line 175, The method currently calls self._lsc.copy(...)
and suppresses a type error; instead add a runtime guard that enforces "service
mode only" by checking the runtime type of self._lsc and rejecting library mode
(e.g., if isinstance(self._lsc, AsyncLlamaStackAsLibraryClient): raise
RuntimeError("...service mode only...")), then narrow the type using typing.cast
before calling copy (remove the # type: ignore[arg-type]); reference self._lsc
and AsyncLlamaStackAsLibraryClient to locate where to add the guard and cast,
and raise a clear error when a library client is detected.

@tisnik tisnik merged commit 999cee6 into lightspeed-core:main Apr 7, 2026
26 checks passed
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