Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add type hints, enable Mypy checks for all production code #1313

Merged
merged 6 commits into from
Oct 19, 2021

Conversation

gonzalo-bulnes
Copy link
Contributor

@gonzalo-bulnes gonzalo-bulnes commented Oct 19, 2021

Description

Fixes #25
See also: #1300 and #1312

It's also mostly about me getting familiar with Mypy. 🙂

Test Plan

  • Verify that all files are checked (24 26 of them)
  • CI succeeds
  • Review the # type: ignore ... comments to ensure they're reasonnable

Checklist

If these changes modify code paths involving cryptography, the opening of files in VMs or network (via the RPC service) traffic, Qubes testing in the staging environment is required. For fine tuning of the graphical user interface, testing in any environment in Qubes is required. Please check as applicable:

  • I have tested these changes in the appropriate Qubes environment
  • I do not have an appropriate Qubes OS workstation set up (the reviewer will need to test these changes)
  • These changes should not need testing in Qubes

If these changes add or remove files other than client code, the AppArmor profile may need to be updated. Please check as applicable:

  • I have updated the AppArmor profile
  • No update to the AppArmor profile is required for these changes
  • I don't know and would appreciate guidance

If these changes modify the database schema, you should include a database migration. Please check as applicable:

  • I have written a migration and upgraded a test database based on main and confirmed that the migration applies cleanly
  • I have written a migration but have not upgraded a test database based on main and would like the reviewer to do so
  • I need help writing a database migration
  • No database schema changes are needed

I came to really appreciate from Go that the type hints
in function signatures are often sufficient to understand
what each of the parameters and return values are.

Besides allowing precise type-checking, that allows
local variable names to become simpler (because their
type conveys information about what they are already).

Additionally, while I haven't implemented that idea
systematically yet, I find interesting that custom types
can be defined to make sense to anyone familiar with
the domain, and used to facilitate cross-functional
collaboration through shared vocabulary.
See Domain Modeling Made Functional by Scott Wlaschin
https://www.youtube.com/watch?v=2JB1_e5wZmU

As far as I understand, typing.NewType is safe to introduce
gradually because the variable will be cast automatically
when str is required. That allow to benefit from type checking
where LanguageCode is required, while keeping the change local.

See https://www.python.org/dev/peps/pep-0484#newtype-helper-function
I don't know yet how to deal with the ArgumentParser expectations
for expand_to_absolute.
Specifying when functions do not return allows Mypy to warn
when unreachable code is introduced.

Note: that feature is enabled by the option --warn-unreachable
which is not currently used. I also noticed that enabling type
ceking on this file uncovers errors in the GUI code, so I'll
address those before modifying the Mypy options.

See https://www.pyhton.org/dev/peps/pep-0484#the-noreturn-type
I added "ignore" comments when hinting at functions types
was necessary (don't know how to do that yet), or I wasn't
sure about what an approriate hint would be.
Examples: window, data, parent sometimes, datetimes...

    In the face of ambiguity, refuse the temptation to guess. ;)

Interesting cases:

- logic.Controller.authenticated_user: without the type hint, some
  code futher down was deemed unreachable by Mypy, likely because
  it inferred a User type that always evaluates to True

- gui.main.Window.login_dialog: type checking FTW! That could have
  been a runtime error.

- gui.widgets.SourceList.get_selected_source: that one could have been
  a runtime error too.

- gui.widgets.SourceListWidgetItem: the class definition contains
  a reference to itself in a type hint. Can be passed as a string.
  See https://www.python.org/dev/peps/pep-0484#forward-references

See https://doc.qt.io/qt-5/qwidget.html
and https://adamj.eu/tech/2021/05/25/python-type-hints-specific-type-ignore
@gonzalo-bulnes gonzalo-bulnes requested a review from a team as a code owner October 19, 2021 01:46
Copy link
Contributor

@sssoleileraaa sssoleileraaa left a comment

Choose a reason for hiding this comment

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

one suggestion below, otherwise looks great!

Makefile Outdated Show resolved Hide resolved
Copy link
Contributor

@sssoleileraaa sssoleileraaa left a comment

Choose a reason for hiding this comment

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

  • Verify that all files are checked (24 26 of them)
  • CI succeeds
  • Review the # type: ignore ... comments to ensure they're reasonnable

@sssoleileraaa sssoleileraaa merged commit faee12d into freedomofpress:main Oct 19, 2021
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.

Complete type annotation in current Python code
2 participants