Skip to content

Add mypy type checking infrastructure and core module annotations (#2362)#2402

Open
mr-raj12 wants to merge 3 commits intoborgbase:masterfrom
mr-raj12:add-type-checking-phase1
Open

Add mypy type checking infrastructure and core module annotations (#2362)#2402
mr-raj12 wants to merge 3 commits intoborgbase:masterfrom
mr-raj12:add-type-checking-phase1

Conversation

@mr-raj12
Copy link
Contributor

@mr-raj12 mr-raj12 commented Feb 9, 2026

Description

Phases 1+2 of #2362 — sets up mypy infrastructure and adds type annotations to core modules.

Phase 1 (infrastructure):

  • Bump requires-python from >=3.8 to >=3.10 (3.8/3.9 are EOL)
  • Configure mypy with permissive defaults in pyproject.toml
  • Add mypy, PyQt6-stubs, types-peewee to dev dependencies
  • Add informational mypy step to CI (continue-on-error: true)
  • Create py.typed marker file (PEP 561)
  • Remove stale py3.8 exclude from CI matrix

Phase 2 (core module annotations):

  • Add from __future__ import annotations to all core modules (PEP 563)
  • Type all functions in store/models.py, connection.py, settings.py, migrations.py
  • Type all functions in network_status/abc.py, darwin.py, network_manager.py
  • Type all methods in scheduler.py
  • Add per-module strict override (disallow_untyped_defs = true) for fully clean modules
  • Fix incorrect return type in settings.py (List[Dict[str,str]]list[dict[str,Any]])
  • Fix control-flow bug in network_manager.py: previously, if the active connection wasn't wireless, get_current_wifi() fell through the try block without returning — the return None only existed inside the except. Now all non-returning paths explicitly hit return None.

Review feedback addressed:

  • Replaced assert con is not None in init_db() with elif con is not None: guard — the assert would crash when called without arguments from profile_export.py
  • Removed unused formatted_time() stub from ArchiveModel
  • Replaced old-style typing imports (Dict, Tuple, Union, Optional) with modern syntax (dict, tuple, X | Y) in scheduler.py

Notes:

  • warn_return_any and check_untyped_defs set to false initially — enabling them surfaces 100+ errors in unannotated modules. Will be tightened in Phase 5.
  • migrations.py excluded from strict override — Peewee's _meta table name access generates ~30 false positives from incomplete type stubs.
  • scheduler.py annotated but not in strict override — ScheduleStatus construction needs refactoring before strict enforcement.
  • mypy not added to pre-commit — PyQt6-stubs is incompatible with mirrors-mypy isolated environments. Deferred to Phase 5.
  • Full error count increases from ~137 to ~179 because annotated function bodies are now checked. Strict-enforced modules have 0 errors.

Related Issue

Partial implementation of #2362 (Phases 1+2 of 5)

Motivation and Context

The codebase has inconsistent type annotations with no type checker enforcing correctness. This PR adds infrastructure and annotates the core modules as a foundation for gradually typing the rest of the codebase.

How Has This Been Tested?

  • uv run mypy src/vorta/store/ src/vorta/network_status/ — 0 errors on strict modules
  • uv run pre-commit run --all-files — all hooks pass
  • uv run mypy src/vorta — runs without crashes (179 errors, all in future-phase modules)

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • I have read the CONTRIBUTING guide.
  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

I provide my contribution under the terms of the license of this repository and I affirm the Developer Certificate of Origin.

@mr-raj12 mr-raj12 force-pushed the add-type-checking-phase1 branch from 7f62908 to 339ba02 Compare February 9, 2026 11:27
@mr-raj12 mr-raj12 changed the title Add mypy type checking infrastructure (Phase 1, #2362) Add mypy type checking infrastructure and core module annotations (#2362) Feb 9, 2026
@m3nu
Copy link
Contributor

m3nu commented Feb 9, 2026

Did you evaluate other type‑checking tools, like the upcoming ty?

@mr-raj12
Copy link
Contributor Author

mr-raj12 commented Feb 9, 2026

mypy was specifically recommended in #2362 for its mature ecosystem, PyQt6-stubs support, and stable CI
integration — so I went with that. Also, ty looks promising but is still in early alpha and not production-ready yet. Since the annotations are tool-agnostic, switching later would be straightforward if ty matures.
Open for changes as you say to switch if needed!

@m3nu
Copy link
Contributor

m3nu commented Feb 9, 2026

If mypy already support pyqt then that's a big plus for us naturally.

I think there are one or two others that are also widely used. From FB or MS maybe? Don't recall the name.

Set up mypy with permissive config, regenerate uv.lock for Python >=3.10,
and run mypy as informational CI step to establish a baseline before
gradually tightening checks in future phases.
Annotate store/, network_status/, and scheduler.py with comprehensive
type hints. Add per-module strict mypy override for fully-typed modules.

- Add from __future__ import annotations to all touched files
- Type all functions in store/models.py, connection.py, settings.py
- Type all functions in network_status/abc.py, darwin.py, network_manager.py
- Type all methods in scheduler.py
- Add [[tool.mypy.overrides]] with disallow_untyped_defs=true for clean modules
- Fix incorrect return type in settings.py (List[Dict[str,str]] -> list[dict[str,Any]])
- Fix implicit Optional and bare return in network_manager.py
@mr-raj12 mr-raj12 force-pushed the add-type-checking-phase1 branch from 0427b6d to eeec8b3 Compare February 11, 2026 16:26
@mr-raj12
Copy link
Contributor Author

i guess pyright (Microsoft) and pyre (Meta). pyright is pretty popular but its PyQt6 stub support isn't as mature as mypy's yet, and pyre has a smaller community around it. Either way the annotations are just standard Python, so switching checkers later is no big deal if something better comes along. Btw rebased this onto current master — the requires-python bump from #2384 and the network changes from #2176 are now incorporated. So this PR just adds the mypy config + annotations on top.

@m3nu
Copy link
Contributor

m3nu commented Feb 28, 2026

I see you did the research. Will try to review this today.

Copy link
Contributor

@m3nu m3nu left a comment

Choose a reason for hiding this comment

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

Thanks for working on this! The infrastructure setup (Phase 1) is solid — permissive mypy defaults with strict per-module overrides and an informational CI step is exactly the right gradual approach.

Phase 2 annotations are mostly good, with one must-fix and a few minor items. See inline comments.

Summary

Issue Severity
assert con is not None in connection.py crashes during profile import Must fix
formatted_time -> None cements a broken stub Low
Mixed old/new typing style (List vs list) despite __future__ import Nit
Unused typing imports (Dict, Tuple, Union) in scheduler.py Nit

- Replace assert with elif guard in init_db() to avoid crash when
  called without arguments from profile_export.py
- Remove unused formatted_time() stub from ArchiveModel
- Use modern typing syntax (dict, tuple, X | Y) in scheduler.py
  and remove unused Dict, Tuple, Union, Optional imports
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