Dark Mode

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Fix mypy errors with --check-untyped-defs#2491

Open
rhatdan wants to merge 2 commits intocontainers:mainfrom
rhatdan:mypy-check-untyped-defs
Open

Fix mypy errors with --check-untyped-defs#2491
rhatdan wants to merge 2 commits intocontainers:mainfrom
rhatdan:mypy-check-untyped-defs

Conversation

Copy link
Member

rhatdan commented Mar 6, 2026 *
edited by sourcery-ai bot
Loading

Resolve all 42 mypy errors reported by:
mypy --exclude=.venv --exclude=venv --exclude=.tox --exclude=build
--exclude test /home/dwalsh/ramalama --check-untyped-defs

  • compat: add type: ignore[call-overload] for NamedTemporaryFile wrapper
  • toml_parser: type value as object and guard with isinstance(value, dict)
  • http_client: only rename when output_file_partial is not None
  • engine: narrow pull/network/oci_runtime/device with getattr and guards
  • chat: fix choice/content type (isinstance(choice, dict)); use setattr for mcp callback; type i and total_time_slept as float; use getattr for server_process and name in kills()
  • transports/base: use getattr for resolve_model, strategy, mount_cmd (OCI)
  • transports/oci: getattr for runtime._convert_to_gguf
  • rag: getattr(self.args, 'rag', None) for BaseEngineArgsType
  • hf_style_repo_base: type blob_url, model_hash, model_filename, mmproj_* as str | None; assert mmproj_* in mmproj_file()
  • transports/huggingface: annotate safetensors_files; getattr for hf_cli_available
  • cli: getattr for inspect_metadata; type: ignore[call-arg] for model.inspect
  • daemon: type idle_check_timer as Timer | None; type idle_check_interval; guard expiration_date for None in check_model_expiration

Made-with: Cursor

Summary by Sourcery

Resolve mypy --check-untyped-defs issues by tightening type usage, guarding optional attributes, and adding targeted ignores across core modules.

Bug Fixes:

  • Prevent crashes in chat streaming, RAG label/mount setup, and HTTP downloads by checking types and None values before use.
  • Avoid attribute errors when optional arguments, strategies, runtimes, or CLI capabilities are missing in engine, transports, and runtime integration.
  • Fix incorrect model expiration handling by safely handling missing expiration_date attributes.

Enhancements:

  • Add explicit type annotations and runtime assertions for configuration objects, timers, and repository metadata structures to improve static typing and safety.

rhatdan requested review from bmahabirbu, cgruver, engelmi, jhjaggars, maxamillion, mikebonnet, olliewalsh and swarajpande5 as code owners March 6, 2026 11:51
rhatdan temporarily deployed to macos-installer March 6, 2026 11:51 -- with GitHub Actions Inactive
Copy link
Contributor

sourcery-ai bot commented Mar 6, 2026 *
edited
Loading

Reviewer's Guide

This PR resolves mypy errors (with --check-untyped-defs) across multiple modules by tightening type annotations, guarding attribute access with getattr/isinstance, and adding a few targeted type: ignore directives while keeping runtime behavior effectively unchanged.

File-Level Changes

Change Details Files
Harden chat streaming logic and MCP integration with safer typing and attribute access.
  • Guard chat choice handling with isinstance(choice, dict) and use a separate content variable when printing/accumulating assistant output.
  • Use setattr to assign the MCP agent _stream_callback to avoid direct private attribute access issues with typing.
  • Annotate backoff variables i and total_time_slept as float in the request loop.
  • In kills(), cache args.server_process and args.name via getattr, operate on local variables, and guard operational_args.name via getattr to satisfy mypy.
ramalama/chat.py
Narrow engine argument types via getattr and local variables for pull, network, oci_runtime, and device handling.
  • Use getattr with local variables for args.pull, args.network, and args.oci_runtime before adding corresponding flags to exec_args.
  • Cache args.device to a local variable and iterate only if not None when adding --device options.
ramalama/engine.py
Make transport base logic more type-safe when resolving models and setting up OCI mounts.
  • Resolve model via a getattr(self, 'resolve_model', None) callable check, falling back to args.MODEL when unavailable.
  • In OCI mount setup, fetch strategy and mount_cmd via getattr, raise NotImplementedError if missing, and use a local mount_cmd_fn for both podman and docker branches.
ramalama/transports/base.py
Make RAG transport respect optional rag argument and avoid attribute errors via getattr.
  • Use getattr(self.args, 'rag', None) for label creation and only add the label when rag is not None.
  • Refactor add_rag() to early-return when rag is None and to work with a local rag/rag_path variable, updating mount strings accordingly for DB and image cases.
ramalama/rag.py
Tighten hf_style_repo_base typing for model and mmproj metadata and assert invariants before use.
  • Annotate blob_url, model_filename, model_hash, mmproj_filename, and mmproj_hash as str
None in the constructor.
  • In mmproj_file(), assert that mmproj_filename and mmproj_hash are not None before constructing the SnapshotFile.
  • Improve daemon idle timer and model expiration handling with explicit types and None checks.
    • Annotate idle_check_timer as threading.Timer
    None and guard cancellation with an explicit is not None check in exit.
  • Annotate idle_check_interval as timedelta and guard model expiration checks by reading m.expiration_date via getattr and skipping when it is None.
  • Make OCI transport runtime conversion to GGUF explicitly checked and typed.
    • Retrieve runtime via get_runtime(args.runtime), then get _convert_to_gguf via getattr and raise NotImplementedError when it is missing.
    • Call the retrieved convert_fn to obtain model_file_name before building the GGUF containerfile.
    ramalama/transports/oci/oci.py
    Harden CLI metadata inspection and inspect invocation for typing.
    • Use getattr(model, 'inspect_metadata', lambda: {})() with a typed metadata: dict in available_metadata to avoid attribute errors and please mypy.
    • Add type: ignore[call-arg] to the model.inspect(...) call where the signature does not match static expectations.
    ramalama/cli.py
    Make TOML parser value traversal type-safe.
    • Type intermediate value as object in get() and guard each step with isinstance(value, dict), returning default early when structure is not a dict.
    ramalama/toml_parser.py
    Tighten HuggingFace transport typing and attribute access.
    • Annotate safetensors_files as list[dict[str, str]] and reset other_files appropriately.
    • Use getattr(self, 'hf_cli_available', False) when checking CLI availability in push() to avoid missing attribute errors.
    ramalama/transports/huggingface.py
    Silence a NamedTemporaryFile typing overload mismatch without changing behavior.
    • Add type: ignore[call-overload] to the _NamedTemporaryFile call that forwards *args/**kwargs with a computed delete flag.
    ramalama/compat.py
    Tighten HTTP client file handling based on partial output path presence.
    • Only rename the partial output file to the final output path when output_file is truthy and output_file_partial is not None, avoiding None issues for mypy.
    ramalama/http_client.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
    Contributor

    gemini-code-assist bot commented Mar 6, 2026

    Summary of Changes

    Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

    This pull request significantly enhances the type safety and robustness of the codebase by resolving 42 mypy errors. The changes primarily involve adding explicit type hints, implementing safer attribute access patterns using getattr, and refining conditional checks to prevent runtime errors related to unexpected data types or missing attributes. This effort improves code maintainability and reliability by making the code more predictable under static analysis.

    Highlights

    • Type Hinting and Type Safety: Introduced numerous type hints across various files to improve code clarity and enable more robust static analysis, specifically addressing mypy errors when using --check-untyped-defs.
    • Safe Attribute Access: Refactored attribute access patterns to use getattr with default values or explicit None checks, preventing potential AttributeError exceptions and improving type inference for optional attributes.
    • Conditional Logic Refinements: Enhanced conditional logic with isinstance checks for dictionary types and is not None guards for optional variables, ensuring operations are performed only on valid data structures.
    • Error Handling and Ignored Types: Added type: ignore comments where necessary to suppress specific mypy errors that are intentionally handled or where more complex type definitions are not immediately feasible.

    New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

    Changelog
    • ramalama/chat.py
      • Added isinstance check for choice before accessing its content key and clarified variable naming.
      • Changed direct assignment of _stream_callback to use setattr for dynamic attribute handling.
      • Annotated i and total_time_slept variables with float type hints.
      • Refactored kills method to use getattr for server_process and name to safely handle optional attributes.
    • ramalama/cli.py
      • Modified available_metadata to use getattr for inspect_metadata to ensure safe method invocation.
      • Added type: ignore[call-arg] to the model.inspect call to suppress a mypy error.
    • ramalama/compat.py
      • Added type: ignore[call-overload] to the _NamedTemporaryFile call to resolve a mypy error.
    • ramalama/daemon/daemon.py
      • Annotated idle_check_timer as threading.Timer | None.
      • Added an explicit is not None check for idle_check_timer before calling cancel.
      • Annotated idle_check_interval as timedelta.
      • Used getattr for expiration_date and added a None guard in check_model_expiration.
    • ramalama/engine.py
      • Refactored add_pull_newer, add_network, add_oci_runtime, and add_device_options methods to use getattr for arguments like pull, network, oci_runtime, and device, along with None checks.
    • ramalama/hf_style_repo_base.py
      • Annotated blob_url, model_filename, model_hash, mmproj_filename, and mmproj_hash as str | None.
      • Added assert statements for mmproj_filename and mmproj_hash in the mmproj_file method.
    • ramalama/http_client.py
      • Added a output_file_partial is not None check before attempting to rename the file.
    • ramalama/rag.py
      • Modified add_labels and add_rag methods to use getattr for self.args.rag and include None checks.
    • ramalama/toml_parser.py
      • Annotated value as object and added an isinstance(value, dict) guard in the get method.
    • ramalama/transports/base.py
      • Used getattr and a callable check for resolve_model in the base method.
      • Refactored setup_mounts to use getattr for strategy and mount_cmd with None checks and error handling.
    • ramalama/transports/huggingface.py
      • Annotated safetensors_files as list[dict[str, str]].
      • Used getattr for hf_cli_available with a default False value in the push method.
    • ramalama/transports/oci/oci.py
      • Used getattr for _convert_to_gguf and added a None check with error handling in the build method.
    Using Gemini Code Assist

    The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

    Invoking Gemini

    You can request assistance from Gemini at any point by creating a comment using either /gemini or @gemini-code-assist . Below is a summary of the supported commands on the current page.

    Feature Command Description
    Code Review /gemini review Performs a code review for the current pull request in its current state.
    Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
    Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
    Help /gemini help Displays a list of available commands.

    Customization

    To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

    Limitations & Feedback

    Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with and on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

    You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

    Footnotes

    1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. -

    sourcery-ai bot reviewed Mar 6, 2026
    Copy link
    Contributor

    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 found 2 issues

    Prompt for AI Agents
    Please address the comments from this code review:

    ## Individual Comments

    ### Comment 1
    <location path="ramalama/transports/base.py" line_range="367-371" />

    if self.type == "Ollama":
    args.UNRESOLVED_MODEL = args.MODEL
    - args.MODEL = self.resolve_model()
    + resolve_model = getattr(self, "resolve_model", None)
    + if callable(resolve_model):
    + args.MODEL = resolve_model()
    + else:
    + args.MODEL = args.MODEL
    self.engine = self.new_engine(args)
    if args.subcommand == "run" and not getattr(args, "ARGS", None) and sys.stdin.isatty():


    **issue (bug_risk):** Silently ignoring missing `resolve_model` may obscure configuration errors.

    Previously an AttributeError would fail fast when `resolve_model` was missing; now the code quietly continues with the original `args.MODEL`. This risks hiding misconfiguration and making debugging harder. Prefer either preserving the hard failure or explicitly raising a clear error when `resolve_model` is missing or not callable, rather than silently falling back.


    ### Comment 2
    <location path="ramalama/http_client.py" line_range="52-53" />

    finally:
    del out # Ensure file is closed before rename

    - if output_file:
    + if output_file and output_file_partial is not None:
    os.rename(output_file_partial, output_file)



    **suggestion (bug_risk):** Additional `output_file_partial is not None` guard may hide earlier failures to create the temp file.

    This change avoids a crash but can mask earlier logic errors: if `output_file` is set but `output_file_partial` was never assigned, the rename is now silently skipped. Consider either guaranteeing `output_file_partial` is always set whenever `output_file` is truthy, or explicitly raising/logging when `output_file` is provided but `output_file_partial` is unexpectedly `None`.

    ```suggestion
    if output_file:
    if output_file_partial is None:
    # If we expected to write to an output file but never created
    # a corresponding temporary file, fail explicitly rather than
    # silently skipping the rename.
    raise RuntimeError(
    "output_file is set but output_file_partial is None; "
    "temporary output file was never created"
    )

    os.rename(output_file_partial, output_file)
    ```

    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.

    Copy link
    Contributor

    gemini-code-assist bot left a comment

    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 effectively addresses a number of mypy errors by improving type safety and code robustness. However, the audit identified critical security vulnerabilities: untrusted output from LLMs is printed directly to the terminal, posing a risk of Terminal Escape Sequence Injection, and user-supplied RAG paths are used in container mount arguments without sufficient sanitization, which could lead to Argument Injection. These require immediate attention through proper sanitization for terminal output and validation of container mount arguments. Additionally, a minor code quality suggestion involves removing a redundant code block for improved conciseness.

    ramalama/chat.py Outdated
    print(f"{color_yellow}{choice}{color_default}", end="", flush=True)
    assistant_response += choice
    if content:
    print(f"{color_yellow}{content}{color_default}", end="", flush=True)
    Copy link
    Contributor

    gemini-code-assist bot Mar 6, 2026

    Choose a reason for hiding this comment

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

    The code prints untrusted output from the LLM directly to the console. If the output contains ANSI escape sequences, it can be used to manipulate the user's terminal (Terminal Escape Sequence Injection). This could lead to information disclosure or other malicious actions depending on the terminal emulator. It is recommended to sanitize the output by removing or escaping non-printable characters and potentially dangerous escape sequences.

    rhatdan force-pushed the mypy-check-untyped-defs branch from 0c6f3df to 841693d Compare March 6, 2026 12:26
    rhatdan temporarily deployed to macos-installer March 6, 2026 12:26 -- with GitHub Actions Inactive
    Copy link
    Collaborator

    mikebonnet commented Mar 9, 2026

    Looks good overall. Could you fix the lint issue?

    rhatdan added 2 commits March 21, 2026 07:00
    Resolve all 42 mypy errors reported by:
    mypy --exclude=.venv --exclude=venv --exclude=.tox --exclude=build
    --exclude test /home/dwalsh/ramalama --check-untyped-defs

    - compat: add type: ignore[call-overload] for NamedTemporaryFile wrapper
    - toml_parser: type value as object and guard with isinstance(value, dict)
    - http_client: only rename when output_file_partial is not None
    - engine: narrow pull/network/oci_runtime/device with getattr and guards
    - chat: fix choice/content type (isinstance(choice, dict)); use setattr for
    mcp callback; type i and total_time_slept as float; use getattr for
    server_process and name in kills()
    - transports/base: use getattr for resolve_model, strategy, mount_cmd (OCI)
    - transports/oci: getattr for runtime._convert_to_gguf
    - rag: getattr(self.args, 'rag', None) for BaseEngineArgsType
    - hf_style_repo_base: type blob_url, model_hash, model_filename, mmproj_*
    as str | None; assert mmproj_* in mmproj_file()
    - transports/huggingface: annotate safetensors_files; getattr for hf_cli_available
    - cli: getattr for inspect_metadata; type: ignore[call-arg] for model.inspect
    - daemon: type idle_check_timer as Timer | None; type idle_check_interval;
    guard expiration_date for None in check_model_expiration

    Made-with: Cursor
    Signed-off-by: Daniel J Walsh
    rhatdan force-pushed the mypy-check-untyped-defs branch from 841693d to c9d58e1 Compare March 21, 2026 11:01
    rhatdan temporarily deployed to macos-installer March 21, 2026 11:01 -- with GitHub Actions Inactive
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Reviewers

    sourcery-ai[bot] sourcery-ai[bot] left review comments

    bmahabirbu Awaiting requested review from bmahabirbu bmahabirbu is a code owner

    maxamillion Awaiting requested review from maxamillion maxamillion is a code owner

    swarajpande5 Awaiting requested review from swarajpande5 swarajpande5 is a code owner

    jhjaggars Awaiting requested review from jhjaggars jhjaggars is a code owner

    cgruver Awaiting requested review from cgruver cgruver is a code owner

    engelmi Awaiting requested review from engelmi engelmi is a code owner

    mikebonnet Awaiting requested review from mikebonnet mikebonnet is a code owner

    olliewalsh Awaiting requested review from olliewalsh olliewalsh is a code owner

    +1 more reviewer

    gemini-code-assist[bot] gemini-code-assist[bot] left review comments

    Reviewers whose approvals may not affect merge requirements

    At least 1 approving review is required to merge this pull request.

    Assignees

    No one assigned

    Labels

    None yet

    Projects

    None yet

    Milestone

    No milestone

    Development

    Successfully merging this pull request may close these issues.

    2 participants