chore: bump requires-python to >=3.10 - #706
Conversation
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
left a comment
There was a problem hiding this comment.
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.
| @@ -1,161 +1,165 @@ | |||
| Resolved 13 packages in 4ms | |||
There was a problem hiding this comment.
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.
| from typing import AsyncIterator, Iterator | ||
| else: | ||
| from collections.abc import AsyncIterator, Iterator | ||
| from collections.abc import AsyncIterator, Iterator |
There was a problem hiding this comment.
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.
| import json | ||
| import sys | ||
| from typing import Dict, List, Mapping, Sequence, Set, Tuple, Union | ||
| from typing import Any, Dict, List, Mapping, Union |
There was a problem hiding this comment.
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.
| ] | ||
| readme = 'README.md' | ||
| requires-python = '>=3.8' | ||
| requires-python = '>=3.10' |
There was a problem hiding this comment.
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.
| [[package]] | ||
| name = "pydantic" | ||
| version = "2.10.6" | ||
| version = "2.13.4" |
There was a problem hiding this comment.
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.
…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)
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
Test plan
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
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
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