Skip to content

Upgrade dependencies to latest stable and modernize for Python 3.11 - #825

Open
ebubekirrcihangirr6060 wants to merge 5 commits into
Election-Tech-Initiative:mainfrom
ebubekirrcihangirr6060:chore/upgrade-deps-refactor
Open

ebubekirrcihangirr6060 wants to merge 5 commits into
Election-Tech-Initiative:mainfrom
ebubekirrcihangirr6060:chore/upgrade-deps-refactor

Conversation

@ebubekirrcihangirr6060

Copy link
Copy Markdown

Upgrade dependencies to latest stable and modernize for Python 3.11
⚠️ Breaking change: minimum Python is now 3.11
Python 3.9 and 3.10 are end-of-life, and several of the latest releases require 3.11 (ipython 9, ipykernel 7, pymongo 4.19, hypothesis). requires-python is now >=3.11,<4.0.0; CI workflows, black/mypy targets and the README/docs are updated to match.
Commit 1: dependency upgrade

  • All runtime and dev dependencies bumped to their latest stable releases, e.g. pydantic 2.14.1, mypy 2.4.0, black 26.10.1, pylint 4.1.3, ipython 9.17, ipykernel 7.4, pymongo 4.19, dependency-injector 4.49.1, gmpy2 2.3.2, and uv_build 0.13. uv.lock regenerated.
  • pytest-mock and types-python-dateutil moved from runtime dependencies to the dev group (only tests and mypy use them).
  • pylint import-self and cyclic-import disabled: pylint 4.1 reports false positives on the mkinit-generated __init__.py files when a submodule name starts with the package name (e.g. encrypt_ballots/encrypt_ballots_*). Noted in pyproject.toml; the trade-off is that real import cycles are no longer reported until this is fixed upstream in pylint.

Commit 2: refactor

  • PEP 585/604 annotations (list[...], X | None), collections.abc imports, datetime.UTC. __init__.py re-exports are untouched.
  • Bug fix in Singleton: all subclasses shared one instance slot, so get_instance() returned the base Singleton object rather than the subclass. It now keeps one instance per class and is typed as returning Self. Added a regression test that fails on the old code.
  • Simplified redundant comprehensions, nested ifs, boolean returns and dict.keys() checks.
  • Moved broad-exception-caught pylint pragmas onto the except line (pylint 4.1 no longer applies the preceding-line form to the except clause) and use the current message name.
  • test_utc_to_str_with_valid_utc_date no longer depends on the local timezone (it failed in UTC+3, where the hour has two digits).

Commit 3: GitHub Actions

  • actions/checkout, actions/setup-python → v7, actions/upload-artifact → v7, github/codeql-action → v4, nick-fields/retry → v4, astral-sh/setup-uv → v10.3.0 (still pinned by SHA). The previous codeql-action@v2 and upload-artifact@v2 have been retired by GitHub, so CI could not run with them.
  • The archived actions/create-release + actions/upload-release-asset pair is replaced by softprops/action-gh-release@v3. The release is now created after the PyPI upload, together with its zip asset.

Commit 4: design pattern fixes
An audit of the library's patterns (Singleton, Context Manager, Repository, Mediator, Builder, CLI step pipeline, GUI dependency injection) found these defects. Each fix comes with a test that fails on the old code:

  • DiscreteLog (Singleton): call sites created a throwaway instance with DiscreteLog(), so set_max_exponent / set_lazy_evaluation never took effect. The library now uses DiscreteLog.get_instance(). precompute_cache_async filled a module-level dict instead of the instance cache; it now fills the instance cache.
  • Scheduler (Context Manager): with Scheduler() opened the pools twice and leaked the first set, and tally.py / decryption.py created a scheduler per call (per contest during decryption) without ever closing it. Added use_scheduler(), which reuses a caller's scheduler or closes the one it creates. close() is now idempotent. The docstring no longer claims the class guarantees a single set of pools.
  • ReadOnlyDataStore (Repository view): __eq__ called itself (RecursionError), __iter__ yielded (key, value) pairs, and __getitem__ returned None instead of raising KeyError. As a result in, keys(), items() and dict(view) were all wrong. It now follows the Mapping contract.
  • The Mediators, Builder, CLI step pipeline and GUI DI container were reviewed; no defects found.
  • The remaining Union[...] type aliases now use | syntax.

Verification

  • pytest tests: 231 passed, 1 skipped on both Python 3.11.17 and 3.13 (Windows). Before these changes: 221 passed, 1 failed (the timezone test).
  • black, mypy (170 files) and pylint (10.00/10) clean; uv build, twine check and mkdocs build --strict pass; workflow YAML validated.
  • Not yet run on Linux/macOS CI.

- Bump all runtime and dev dependencies to their latest stable releases
  (pydantic 2.14, mypy 2.4, black 26.10, ipython 9, ipykernel 7, pymongo 4.19, ...)
- Raise requires-python to >=3.11 (3.9/3.10 are EOL and several latest releases need 3.11)
- Move pytest-mock and types-python-dateutil from runtime to dev dependencies
- Bump uv_build backend to 0.13 and CI Python to 3.11
- Disable pylint import-self (false positive on mkinit __init__ files in pylint 4.1)

Co-authored-by: GaziFe <233933832+GaziFe@users.noreply.github.com>
Co-authored-by: Abdullah Kadir Çelik <207906693+Kadircelik-stack@users.noreply.github.com>
- Use PEP 585/604 annotations (list[...], X | None) and collections.abc imports
- Use datetime.UTC, drop redundant open modes and super() arguments
- Fix Singleton: keep one instance per subclass and type get_instance as Self
  (previously all subclasses shared a single slot and returned the base instance)
- Simplify redundant comprehensions, nested ifs and boolean returns
- Move broad-exception pylint pragmas inline (pylint 4.1 no longer applies the
  preceding-line form to the except clause) and use the current message name
- Make the utc_to_str test independent of the local timezone

Co-authored-by: GaziFe <233933832+GaziFe@users.noreply.github.com>
Co-authored-by: Abdullah Kadir Çelik <207906693+Kadircelik-stack@users.noreply.github.com>
- checkout/setup-python v7, upload-artifact v7, codeql-action v4, retry v4, setup-uv v10.3.0
  (codeql-action@v2 and upload-artifact@v2 are retired, so CI could not run)
- Replace archived create-release/upload-release-asset with softprops/action-gh-release@v3

Co-authored-by: GaziFe <233933832+GaziFe@users.noreply.github.com>
Co-authored-by: Abdullah Kadir Çelik <207906693+Kadircelik-stack@users.noreply.github.com>
Co-authored-by: GaziFe <233933832+GaziFe@users.noreply.github.com>
Co-authored-by: Abdullah Kadir Çelik <207906693+Kadircelik-stack@users.noreply.github.com>
- DiscreteLog: use get_instance() so set_max_exponent/set_lazy_evaluation take effect;
  precompute_cache_async now fills the instance cache instead of a module-level dict
- Scheduler: stop opening pools twice in __enter__, make close() idempotent and add
  use_scheduler() so tally/decryption close the schedulers they create
- ReadOnlyDataStore: follow the Mapping contract (iterate keys, raise KeyError) and
  remove the self-recursive __eq__
- Add regression tests for each defect

Co-authored-by: GaziFe <233933832+GaziFe@users.noreply.github.com>
Co-authored-by: Abdullah Kadir Çelik <207906693+Kadircelik-stack@users.noreply.github.com>

This branch has not been deployed

No deployments
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.

1 participant