Skip to content

chore: bump requires-python to >=3.10 - #706

Open
vaderollama wants to merge 2 commits into
ollama:mainfrom
vaderollama:chore/bump-python-3.10
Open

chore: bump requires-python to >=3.10#706
vaderollama wants to merge 2 commits into
ollama:mainfrom
vaderollama:chore/bump-python-3.10

Conversation

@vaderollama

Copy link
Copy Markdown

What & Why

Python 3.8 reached EOL Oct 2024 and 3.9 reaches EOL Oct 2025. This bumps to and simplifies the codebase by removing version guards for older Pythons.

Changes

  • ****: from →
  • ****: Removed conditional import — / is always available on 3.10+. Removed unused .
  • ****: Simplified — dropped the branch that used ///// fallbacks, keeping only the modern PEP 604 syntax (). Removed unused typing imports and a redundant local in .
  • ** / **: Regenerated — drops the conditional pin and removes Python-version conditional markers.

Test plan

  • ============================= test session starts ==============================
    platform darwin -- Python 3.12.3, pytest-9.1.1, pluggy-1.6.0 -- /Users/parth/ollama-python/.venv/bin/python3
    cachedir: .pytest_cache
    rootdir: /Users/parth/ollama-python
    configfile: pyproject.toml
    plugins: anyio-4.14.2, pytest_httpserver-1.1.5
    collecting ... collected 20 items

tests/test_utils.py::test_function_to_tool_conversion PASSED [ 5%]
tests/test_utils.py::test_function_with_no_args PASSED [ 10%]
tests/test_utils.py::test_function_with_all_types PASSED [ 15%]
tests/test_utils.py::test_function_docstring_parsing PASSED [ 20%]
tests/test_utils.py::test_skewed_docstring_parsing PASSED [ 25%]
tests/test_utils.py::test_function_with_no_docstring PASSED [ 30%]
tests/test_utils.py::test_function_with_only_description PASSED [ 35%]
tests/test_utils.py::test_function_with_yields PASSED [ 40%]
tests/test_utils.py::test_function_with_no_types PASSED [ 45%]
tests/test_utils.py::test_function_with_parentheses PASSED [ 50%]
tests/test_type_serialization.py::test_image_serialization_bytes PASSED [ 55%]
tests/test_type_serialization.py::test_image_serialization_base64_string PASSED [ 60%]
tests/test_type_serialization.py::test_image_serialization_long_base64_string PASSED [ 65%]
tests/test_type_serialization.py::test_image_serialization_plain_string PASSED [ 70%]
tests/test_type_serialization.py::test_image_serialization_path PASSED [ 75%]
tests/test_type_serialization.py::test_image_serialization_string_path PASSED [ 80%]
tests/test_type_serialization.py::test_create_request_serialization PASSED [ 85%]
tests/test_type_serialization.py::test_create_request_serialization_exclude_none_true PASSED [ 90%]
tests/test_type_serialization.py::test_create_request_serialization_exclude_none_false PASSED [ 95%]
tests/test_type_serialization.py::test_create_request_serialization_license_list PASSED [100%]

============================== 20 passed in 0.07s ============================== — 20 passed

  • ============================= test session starts ==============================
    platform darwin -- Python 3.12.3, pytest-9.1.1, pluggy-1.6.0 -- /Users/parth/ollama-python/.venv/bin/python3
    cachedir: .pytest_cache
    rootdir: /Users/parth/ollama-python
    configfile: pyproject.toml
    plugins: anyio-4.14.2, pytest_httpserver-1.1.5
    collecting ... collected 73 items

tests/test_client.py::test_client_chat PASSED [ 1%]
tests/test_client.py::test_client_chat_with_logprobs PASSED [ 2%]
tests/test_client.py::test_client_chat_stream PASSED [ 4%]
tests/test_client.py::test_client_chat_images[path-dict] PASSED [ 5%]
tests/test_client.py::test_client_chat_images[path-pydantic_model] PASSED [ 6%]
tests/test_client.py::test_client_chat_images[bytes-dict] PASSED [ 8%]
tests/test_client.py::test_client_chat_images[bytes-pydantic_model] PASSED [ 9%]
tests/test_client.py::test_client_chat_format_json PASSED [ 10%]
tests/test_client.py::test_client_chat_format_pydantic PASSED [ 12%]
tests/test_client.py::test_async_client_chat_format_json PASSED [ 13%]
tests/test_client.py::test_async_client_chat_format_pydantic PASSED [ 15%]
tests/test_client.py::test_client_generate PASSED [ 16%]
tests/test_client.py::test_client_generate_with_logprobs PASSED [ 17%]
tests/test_client.py::test_client_generate_with_image_type PASSED [ 19%]
tests/test_client.py::test_client_generate_with_invalid_image PASSED [ 20%]
tests/test_client.py::test_client_generate_stream PASSED [ 21%]
tests/test_client.py::test_client_generate_images PASSED [ 23%]
tests/test_client.py::test_client_generate_format_json PASSED [ 24%]
tests/test_client.py::test_client_generate_format_pydantic PASSED [ 26%]
tests/test_client.py::test_async_client_generate_format_json PASSED [ 27%]
tests/test_client.py::test_async_client_generate_format_pydantic PASSED [ 28%]
tests/test_client.py::test_client_generate_image PASSED [ 30%]
tests/test_client.py::test_client_generate_image_stream PASSED [ 31%]
tests/test_client.py::test_async_client_generate_image PASSED [ 32%]
tests/test_client.py::test_client_pull PASSED [ 34%]
tests/test_client.py::test_client_pull_stream PASSED [ 35%]
tests/test_client.py::test_client_push PASSED [ 36%]
tests/test_client.py::test_client_push_stream PASSED [ 38%]
tests/test_client.py::test_client_create_with_blob PASSED [ 39%]
tests/test_client.py::test_client_create_with_parameters_roundtrip PASSED [ 41%]
tests/test_client.py::test_client_create_from_library PASSED [ 42%]
tests/test_client.py::test_client_create_blob PASSED [ 43%]
tests/test_client.py::test_client_create_blob_exists PASSED [ 45%]
tests/test_client.py::test_client_delete PASSED [ 46%]
tests/test_client.py::test_client_copy PASSED [ 47%]
tests/test_client.py::test_async_client_chat PASSED [ 49%]
tests/test_client.py::test_async_client_chat_stream PASSED [ 50%]
tests/test_client.py::test_async_client_chat_images PASSED [ 52%]
tests/test_client.py::test_async_client_generate PASSED [ 53%]
tests/test_client.py::test_async_client_generate_stream PASSED [ 54%]
tests/test_client.py::test_async_client_generate_images PASSED [ 56%]
tests/test_client.py::test_async_client_pull PASSED [ 57%]
tests/test_client.py::test_async_client_pull_stream PASSED [ 58%]
tests/test_client.py::test_async_client_push PASSED [ 60%]
tests/test_client.py::test_async_client_push_stream PASSED [ 61%]
tests/test_client.py::test_async_client_create_with_blob PASSED [ 63%]
tests/test_client.py::test_async_client_create_with_parameters_roundtrip PASSED [ 64%]
tests/test_client.py::test_async_client_create_from_library PASSED [ 65%]
tests/test_client.py::test_async_client_create_blob PASSED [ 67%]
tests/test_client.py::test_async_client_create_blob_exists PASSED [ 68%]
tests/test_client.py::test_async_client_delete PASSED [ 69%]
tests/test_client.py::test_async_client_copy PASSED [ 71%]
tests/test_client.py::test_headers PASSED [ 72%]
tests/test_client.py::test_copy_tools PASSED [ 73%]
tests/test_client.py::test_tool_validation PASSED [ 75%]
tests/test_client.py::test_client_connection_error PASSED [ 76%]
tests/test_client.py::test_async_client_connection_error PASSED [ 78%]
tests/test_client.py::test_arbitrary_roles_accepted_in_message PASSED [ 79%]
tests/test_client.py::test_arbitrary_roles_accepted_in_message_request PASSED [ 80%]
tests/test_client.py::test_arbitrary_roles_accepted_in_message_request_async PASSED [ 82%]
tests/test_client.py::test_client_web_search_requires_bearer_auth_header PASSED [ 83%]
tests/test_client.py::test_client_web_fetch_requires_bearer_auth_header PASSED [ 84%]
tests/test_client.py::test_client_web_search_with_env_api_key PASSED [ 86%]
tests/test_client.py::test_client_web_fetch_with_env_api_key PASSED [ 87%]
tests/test_client.py::test_client_web_search_with_explicit_bearer_header PASSED [ 89%]
tests/test_client.py::test_client_web_fetch_with_explicit_bearer_header PASSED [ 90%]
tests/test_client.py::test_client_bearer_header_from_env PASSED [ 91%]
tests/test_client.py::test_client_explicit_bearer_header_overrides_env PASSED [ 93%]
tests/test_client.py::test_client_close PASSED [ 94%]
tests/test_client.py::test_async_client_close PASSED [ 95%]
tests/test_client.py::test_client_context_manager PASSED [ 97%]
tests/test_client.py::test_async_client_context_manager PASSED [ 98%]
tests/test_client.py::test_generate_think_annotation_matches_chat PASSED [100%]

============================== 73 passed in 1.16s ============================== — 73 passed

  • CI (macOS, Ubuntu, Windows)

Notes

This also supersedes the 5 open Dependabot PRs (#657#661) which were stuck failing lint because they updated without touching . The regenerated lockfile in this PR already includes those dependency upgrades (certifi, pydantic-core, httpcore, anyio, typing-extensions).

@ParthSareen

Python 3.8 reached EOL Oct 2024 and 3.9 reaches EOL Oct 2025.
Bumping the minimum to 3.10 allows:

- Remove sys.version_info < (3, 9) conditional import in _client.py
  (collections.abc.AsyncIterator/Iterator available since 3.9)
- Remove unused 'import sys' from _client.py
- Simplify test_function_with_all_types: drop the < 3.10 branch
  with Sequence/Mapping/Set/Tuple/List/Union fallbacks, keep only
  the modern PEP 604 (int | str | None) syntax
- Remove unused typing imports from test_utils.py
- uv.lock / requirements.txt regenerated (drops anyio < 3.9 pin,
  removes conditional dependency markers)

@ParthSareen ParthSareen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Blocking changes requested. Python 3.10 itself validates successfully, but the generated requirements file is invalid, the PR introduces Ruff failures, documentation still claims Python 3.8+ support, and the lockfile refresh includes dependency upgrades beyond the stated migration.

Comment thread requirements.txt Outdated
@@ -1,161 +1,165 @@
Resolved 13 packages in 4ms

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

uv export > requirements.txt does not generate this status line, so the checked-in file differs from the repository's regeneration command and the CI diff check fails. It is also not parseable as a requirements file (uv pip install --dry-run -r requirements.txt fails at this line). Please regenerate this file without capturing uv's status output.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in e2921e5 — pushed.

Comment thread ollama/_client.py Outdated
from typing import AsyncIterator, Iterator
else:
from collections.abc import AsyncIterator, Iterator
from collections.abc import AsyncIterator, Iterator

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This import now sits after third-party and local imports, which triggers Ruff I001; the canonical lint check fails. Move it into the stdlib import block.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in e2921e5 — pushed.

Comment thread tests/test_utils.py Outdated
import json
import sys
from typing import Dict, List, Mapping, Sequence, Set, Tuple, Union
from typing import Any, Dict, List, Mapping, Union

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Mapping is no longer used after removing the pre-3.10 branch, so Ruff reports F401 and the canonical lint check fails. Please remove it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in e2921e5 — pushed.

Comment thread pyproject.toml
]
readme = 'README.md'
requires-python = '>=3.8'
requires-python = '>=3.10'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The package metadata now correctly requires Python 3.10, but README.md still advertises support for “Python 3.8+”. Please update the public compatibility statement in the same change.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in e2921e5 — pushed.

Comment thread uv.lock Outdated
[[package]]
name = "pydantic"
version = "2.10.6"
version = "2.13.4"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A floor-only uv lock regeneration from current main retains pydantic 2.10.6; this changes it to 2.13.4 (and also refreshes other dependencies beyond the five Dependabot PRs named in the description). Please either split these unrelated upgrades into their own reviewed change or explicitly justify and validate them.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in e2921e5 — pushed.

…s.txt

- Move collections.abc and importlib imports into stdlib block (I001)
- Remove unused Mapping import from test_utils.py (F401)
- Update README.md from Python 3.8+ to 3.10+
- Regenerate requirements.txt without status line leak
- Regenerate uv.lock without --upgrade (no version bumps, only
  removes python_full_version < 3.9 conditional markers)
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.

2 participants