Skip to content

Conversation

@yarikoptic
Copy link
Member

Summary

Drop Python 3.9 support and modernize the codebase to take advantage of Python 3.10+ features.

Changes

Python version updates:

  • Bump minimum Python version from 3.8 to 3.10
  • Update test matrix to cover Python 3.10, 3.11, 3.12, 3.13, and 3.14
  • Update mypy and ruff target versions to Python 3.10

Type hint modernization (14 files):

  • Replace Union[X, Y] with X | Y syntax
  • Replace Optional[X] with X | None syntax
  • Replace Dict, List, Tuple, Type from typing with lowercase builtins (dict, list, tuple, type)
  • Use collections.abc imports for Callable, Generator, Mapping, etc.
  • Remove unused typing imports

Files affected

Configuration:

  • pyproject.toml
  • .appveyor.yml

Source code:

  • datalad_next/annexremotes/archivist.py
  • datalad_next/commands/__init__.py
  • datalad_next/commands/credentials.py
  • datalad_next/config/utils.py
  • datalad_next/constraints/exceptions.py
  • datalad_next/constraints/parameter.py
  • datalad_next/iter_collections/annexworktree.py
  • datalad_next/iter_collections/utils.py
  • datalad_next/patches/customremotes_main.py
  • datalad_next/patches/push_to_export_remote.py
  • datalad_next/url_operations/any.py
  • datalad_next/url_operations/http.py
  • datalad_next/utils/multihash.py
  • datalad_next/utils/requests_auth.py

yarikoptic and others added 2 commits December 25, 2025 13:03
- Update requires-python to >= 3.10
- Update hatch test matrix to test Python 3.10-3.14
- Update mypy target version to 3.10
- Update ruff target version to py310
- Update appveyor default test Python to 3.10

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
With Python 3.10 as the new minimum, take advantage of modern type hint
syntax:

- Replace Union[X, Y] with X | Y
- Replace Optional[X] with X | None
- Replace Dict[K, V] with dict[K, V]
- Replace List[T] with list[T]
- Replace Tuple[...] with tuple[...]
- Replace Type[T] with type[T]
- Use collections.abc imports (Callable, Generator, etc.)
- Remove unused typing imports

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Fix remaining Dict -> dict and Tuple -> tuple conversions missed in
  initial refactoring (constraints/exceptions.py, constraints/parameter.py,
  url_operations/any.py, utils/requests_auth.py)
- Update readthedocs.yml: Python 3.9 -> 3.10, Ubuntu 20.04 -> 22.04

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@yarikoptic
Copy link
Member Author

type checking in CI was selective only to files touched by PR and seems to fail often thus

these current fails likely to be unrelated
Successfully installed types-requests-2.32.4.20250913
datalad_next/constraints/exceptions.py:306: error: Signature of "errors" incompatible with supertype "ConstraintErrors"  [override]
datalad_next/constraints/exceptions.py:306: note:      Superclass:
datalad_next/constraints/exceptions.py:306: note:          MappingProxyType[Any, ConstraintError]
datalad_next/constraints/exceptions.py:306: note:      Subclass:
datalad_next/constraints/exceptions.py:306: note:          ParameterContextErrors
datalad_next/constraints/parameter.py:375: error: Need type annotation for "expected_for_joint_validation" (hint: "expected_for_joint_validation: set[<type>] = ...")  [var-annotated]
datalad_next/url_operations/any.py:73: error: Need type annotation for "_url_handler_cache" (hint: "_url_handler_cache: dict[<type>, <type>] = ...")  [var-annotated]
datalad_next/annexremotes/archivist.py:377: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs  [annotation-unchecked]
datalad_next/annexremotes/archivist.py:483: error: Assignment to variable "e" outside except: block  [misc]
datalad_next/annexremotes/archivist.py:486: error: Trying to read deleted variable "e"  [misc]
datalad_next/annexremotes/archivist.py:487: error: Trying to read deleted variable "e"  [misc]
datalad_next/utils/requests_auth.py:64: error: Argument 1 to "_convert_www_authenticate_items" has incompatible type "list[Any] | None"; expected "list[Any]"  [arg-type]
datalad_next/utils/requests_auth.py:358: error: "PreparedRequest" has no attribute "_cookies"  [attr-defined]
Installing missing stub packages:
datalad_next/utils/requests_auth.py:359: error: "PreparedRequest" has no attribute "_cookies"  [attr-defined]
/home/runner/.local/share/hatch/env/virtual/datalad-next/teNkZ7hr/types/bin/python -m pip install types-requests
seems we are left only with 2 failing ria-related tests on windows on appveyor
FAILED datalad_next/patches/tests/test_patched_ria_ora.py::test_ria_postclone_noannex - datalad.support.exceptions.IncompleteResultsError: Command did not complete successfully. 1 failed:
[{'action': 'install',
  'error_message': 'CommandError: \'"git" "-c" "diff.ignoreSubmodules=none" '
                   '"-c" "core.quotepath=false" "annex" "init" "-c" '
                   '"annex.dotfiles=true"\' failed with exitcode 1 under '
                   'C:\\DLTMP\\pytest-of-appveyor\\pytest-0\\test_ria_postclone_noannex0\\cloned_ds',
  'exception': CommandError: '"git" "-c" "diff.ignoreSubmodules=none" "-c" "core.quotepath=false" "annex" "init" "-c" "annex.dotfiles=true"' failed with exitcode 1 under C:\DLTMP\pytest-of-appveyor\pytest-0\test_ria_postclone_noannex0\cloned_ds [clone.py:clone_dataset:521,clone.py:_post_gitclone_processing_:589,clone.py:_annex_init:700,annexrepo.py:_init:1535,annexrepo.py:_call_annex:992,runner.py:run:243],
  'exception_traceback': '[clone.py:clone_dataset:521,clone.py:_post_gitclone_processing_:589,clone.py:_annex_init:700,annexrepo.py:_init:1535,annexrepo.py:_call_annex:992,runner.py:run:243]',
  'message': 'CommandError: \'"git" "-c" "diff.ignoreSubmodules=none" "-c" '
             '"core.quotepath=false" "annex" "init" "-c" '
             '"annex.dotfiles=true"\' failed with exitcode 1 under '
             'C:\\DLTMP\\pytest-of-appveyor\\pytest-0\\test_ria_postclone_noannex0\\cloned_ds',
  'path': 'C:\\DLTMP\\pytest-of-appveyor\\pytest-0\\test_ria_postclone_noannex0\\cloned_ds',
  'source': {'default_destpath': 'd021f7b2-2a8d-4d93-9a08-57d2d21f5e1f',
             'giturl': 'file:///C%3A/DLTMP/pytest-of-appveyor/pytest-0/test_ria_postclone_noannex0/ria_store/d02/1f7b2-2a8d-4d93-9a08-57d2d21f5e1f',
             'source': 'ria+file:///C:/DLTMP/pytest-of-appveyor/pytest-0/test_ria_postclone_noannex0/ria_store#d021f7b2-2a8d-4d93-9a08-57d2d21f5e1f',
             'type': 'ria',
             'version': None},
  'source_url': 'ria+file:///C:/DLTMP/pytest-of-appveyor/pytest-0/test_ria_postclone_noannex0/ria_store#d021f7b2-2a8d-4d93-9a08-57d2d21f5e1f',
  'status': 'error',
  'type': 'dataset'}]
FAILED datalad_next/patches/tests/test_push.py::test_nested_pushclone_cycle_allplatforms - datalad.runner.exception.CommandError: CommandError: '"datalad" "clone" "ria+file:///C:/DLTMP/datalad_temp_rgnc2sq6#8a1f1273-0497-4249-9365-cb0039abd2c1" "super"' failed with exitcode 1
= 2 failed, 346 passed, 58 skipped, 4 deselected, 1 warning in 2628.20s (0:43:48) =
Command exited with code 1

they were failing also a month ago e.g. in https://ci.appveyor.com/project/mih/datalad-next/builds/53200193/job/mnipjv8l3b5w3hba when even more stuff was failing...

Since 3.9 is EOLed and there are ramifications of dragging it outside of the -next, unless there are objections, I will merge this tomorrow.

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