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 to codebase #6742

Closed
4 of 5 tasks
Eric-Arellano opened this issue Nov 8, 2018 · 3 comments
Closed
4 of 5 tasks

Add type hints to codebase #6742

Eric-Arellano opened this issue Nov 8, 2018 · 3 comments

Comments

@Eric-Arellano
Copy link
Contributor

Eric-Arellano commented Nov 8, 2018

Hello, as discussed via Slack and google group, I'm hoping to set us up with type hints in our codebase (PEP 484). I led a similar project while at Foursquare, and think the scope is achievable.

This wouldn't start until we finish the Python 3 port (#6062).

Why type hints

  • Catch bugs at lint time.
  • Improved documentation.
  • More confidence while refactoring.

Scope

  • Allow any new or refactored code to use type hints.
  • Enforce type safety through CI integration.
  • Add type hints to core code.

This issue does not entail 100% type coverage.

Incremental type safety

Rather than trying to rewrite our entire codebase at once, we'd take a more incremental approach. Core code would be ported so that any dependee has some level of type safety. Over time, we would expect any new code and refactored code to have type hints, leading to an incremental increase in coverage.

This is the approach taken by most organizations, including Foursquare and Dropbox (author of MyPy).

Specific approach: type_checked and partially_type_checked tags

We only run MyPy against targets with either of these two tags. (As a consequence, MyPy will check any transitive dependencies).

type_checked signals that the file is completely typed and good to go.

partially_type_checked signals that the file is not completely typed, but we still want to ensure that MyPy runs against the file (and its dependencies). This is useful to allow someone to add 1-2 type hints to a target without feeling the pressure of having to type the whole target.

Tasks

  • Setup MyPy config and script as a starting point (Setup MyPy config and enforce types for build-support scripts #7704)
  • Get MyPy to stop complaining when used against Your Typical Pants Target™️. This requires fixing several issues, including replacing objects.py with standard library alternatives that MyPy understands.
  • Add type hints to core code, meaning code that has many dependees: https://docs.google.com/spreadsheets/d/1MKg82Fs3uIMOZDoWeNUBD-VirVkOzHU8Tte7oY6ypP0/edit?usp=sharing
    • Easier to add this to targets that also have few dependencies, such as the util folder
  • Get as much of the repo running with partially_type_checked as possible
    • Add this tag even if we don't add any type hints to the file! So long as it passes w/ MyPy, we should add the tag. This allows us to ensure the correctness of any new hints we add.
  • Incrementally convert partially_type_checked to type_checked
@cosmicexplorer
Copy link
Contributor

cosmicexplorer commented Jan 21, 2019

We should absolutely figure out how to represent type hints such as Union[string, bytes] in python docstring syntax as per this comment on #7120. I think we should probably add that to the checklist? The comment mentions a link which describes how python docstring conventions work, but doesn't answer how type hints should.

@cosmicexplorer
Copy link
Contributor

One additional thought is that if we wanted to look at type hints before we're fully py3-compatible, we could start creating stub files to get most of the benefits before we can put them into the code itself.

Eric-Arellano added a commit that referenced this issue May 14, 2019
### Problem
We would like to use type hints throughout our code base, per #6742.

However, we must configure it with sensible defaults to make it easier to use and to provide a consistent interface for developers.

We should also enforce as much type safety as we can via our `pre-commit` check.

### Solution
* Add new `mypy.ini` file with fairly loose defaults that are good for first time codebases. Eventually, we will want to do things like require all functions to be typed, but for now we loosen our expectations.
* Link to the config file in `pants.ini`, along with using the most modern MyPy release which gives us  the `strict_equality` check.
* Run `mypy.py` over the build-support scripts, which are fully typed.
   * Acts as a proof of concept for how this will be integrated into CI.

### Result
`./pants mypy` is now a bit more useful on our codebase, even though it will still fail because of pre-existing issues.

Further, the build-support folder will not have any typing regressions now.
Eric-Arellano added a commit to Eric-Arellano/pants that referenced this issue May 14, 2019
…uild#7704)

### Problem
We would like to use type hints throughout our code base, per pantsbuild#6742.

However, we must configure it with sensible defaults to make it easier to use and to provide a consistent interface for developers.

We should also enforce as much type safety as we can via our `pre-commit` check.

### Solution
* Add new `mypy.ini` file with fairly loose defaults that are good for first time codebases. Eventually, we will want to do things like require all functions to be typed, but for now we loosen our expectations.
* Link to the config file in `pants.ini`, along with using the most modern MyPy release which gives us  the `strict_equality` check.
* Run `mypy.py` over the build-support scripts, which are fully typed.
   * Acts as a proof of concept for how this will be integrated into CI.

### Result
`./pants mypy` is now a bit more useful on our codebase, even though it will still fail because of pre-existing issues.

Further, the build-support folder will not have any typing regressions now.
Eric-Arellano added a commit that referenced this issue Jun 17, 2019
### Problem
Per #6742, we will be _incrementally_ adding type hints to Pants.

We need some way to mark to our CI that the target should be checked against, to make sure that any gains we make in type hints are actually enforced.

### Solution
Introduce a new tag `type_checked`, which indicates to our CI that `./pants mypy` should be ran against that target.

Also introduce a helper script `build-support/bin/mypy.py` that runs `./pants mypy` over _all_ eligible targets in Pants. To run over a select few targets, users should instead simply run `./pants mypy path/to:target`.

#### Alternative solution considered: centralized whitelist file
It was decided that a decentralized system will work better in this particular case, for some of these reasons:

1) There's a convention for keeping it decentralized: the `integration` tag.
2) `BUILD` files are more accessible to modify, e.g. being closer to the source.
3) We want to type check the entire codebase eventually. One centralized file would risk becoming too large and difficult to maintain.
cattibrie pushed a commit to cattibrie/pants that referenced this issue Jun 19, 2019
…d#7886)

### Problem
Per pantsbuild#6742, we will be _incrementally_ adding type hints to Pants.

We need some way to mark to our CI that the target should be checked against, to make sure that any gains we make in type hints are actually enforced.

### Solution
Introduce a new tag `type_checked`, which indicates to our CI that `./pants mypy` should be ran against that target.

Also introduce a helper script `build-support/bin/mypy.py` that runs `./pants mypy` over _all_ eligible targets in Pants. To run over a select few targets, users should instead simply run `./pants mypy path/to:target`.

#### Alternative solution considered: centralized whitelist file
It was decided that a decentralized system will work better in this particular case, for some of these reasons:

1) There's a convention for keeping it decentralized: the `integration` tag.
2) `BUILD` files are more accessible to modify, e.g. being closer to the source.
3) We want to type check the entire codebase eventually. One centralized file would risk becoming too large and difficult to maintain.
mabdi3 pushed a commit to mabdi3/pants that referenced this issue Jul 23, 2019
Registers MyPy as a 'lint' goal, and implements opt-in 'whitelist' system for type checking.
Targets to be type checked are tagged according to the '--whitelisted-tag-name' option, defaults to `type_checked`
as used from pantsbuild#7886. Add new mypy_tests for new logic, and update old tests and mypy instances to reflect lint goal change.

New mypy logic added to accomodate new opt-in strategy. Mypy will acts according to the following:
1. Filter out non-whitelisted target root
2. Check if all targets now in context are whitelisted, if not we throw an error
3. Continue as normal, collecting python source files and running mypy

See pantsbuild#7886 and pantsbuild#6742 for more context
mabdi3 pushed a commit to mabdi3/pants that referenced this issue Jul 30, 2019
Registers MyPy as a 'lint' goal, and implements opt-in 'whitelist' system for type checking.
Targets to be type checked are tagged according to the '--whitelisted-tag-name' option, defaults to `type_checked`
as used from pantsbuild#7886. Add new mypy_tests for new logic, and update old tests and mypy instances to reflect lint goal change.

New mypy logic added to accomodate new opt-in strategy. Mypy will acts according to the following:
1. Filter out non-whitelisted target root
2. Check if all targets now in context are whitelisted, if not we throw an error
3. Continue as normal, collecting python source files and running mypy

See pantsbuild#7886 and pantsbuild#6742 for more context
wisechengyi pushed a commit that referenced this issue Aug 7, 2019
…opt-in type checking (#8099)

### Problem

We want to move MyPy into the lint goal and allow for users to opt-in into type_checking
for the new whitelisting/opt-in logic, we can make use of the lint goal capabilities instead of rebuilding the wheel
See #7886 and #6742 for more context.

### Solution

Registers MyPy as a 'lint' goal, and implements opt-in 'whitelist' system for type checking.
Targets to be type checked are tagged according to the `--whitelisted-tag-name` option, defaults to `type_checked` as used from #7886. Add new mypy_tests for new logic, and update old tests and mypy instances to reflect lint goal change.

New mypy logic added to accommodate new opt-in strategy. Mypy will acts according to the following:
1. Filter out non-whitelisted target roots
2. Check if the transitive deps from the filtered roots are whitelisted, if not we throw a warning
3. Continue as normal, collecting python source files and running mypy
stuhood pushed a commit to twitter/pants that referenced this issue Aug 7, 2019
…opt-in type checking (pantsbuild#8099)

### Problem

We want to move MyPy into the lint goal and allow for users to opt-in into type_checking
for the new whitelisting/opt-in logic, we can make use of the lint goal capabilities instead of rebuilding the wheel
See pantsbuild#7886 and pantsbuild#6742 for more context.

### Solution

Registers MyPy as a 'lint' goal, and implements opt-in 'whitelist' system for type checking.
Targets to be type checked are tagged according to the `--whitelisted-tag-name` option, defaults to `type_checked` as used from pantsbuild#7886. Add new mypy_tests for new logic, and update old tests and mypy instances to reflect lint goal change.

New mypy logic added to accommodate new opt-in strategy. Mypy will acts according to the following:
1. Filter out non-whitelisted target roots
2. Check if the transitive deps from the filtered roots are whitelisted, if not we throw a warning
3. Continue as normal, collecting python source files and running mypy
wisechengyi pushed a commit that referenced this issue Aug 8, 2019
…opt-in type checking (#8099)

### Problem

We want to move MyPy into the lint goal and allow for users to opt-in into type_checking
for the new whitelisting/opt-in logic, we can make use of the lint goal capabilities instead of rebuilding the wheel
See #7886 and #6742 for more context.

### Solution

Registers MyPy as a 'lint' goal, and implements opt-in 'whitelist' system for type checking.
Targets to be type checked are tagged according to the `--whitelisted-tag-name` option, defaults to `type_checked` as used from #7886. Add new mypy_tests for new logic, and update old tests and mypy instances to reflect lint goal change.

New mypy logic added to accommodate new opt-in strategy. Mypy will acts according to the following:
1. Filter out non-whitelisted target roots
2. Check if the transitive deps from the filtered roots are whitelisted, if not we throw a warning
3. Continue as normal, collecting python source files and running mypy
Eric-Arellano added a commit that referenced this issue Oct 15, 2019
…s repo (#8464)

### Problem
Currently, to have MyPy run against a target, you must mark it with `type_checked` or it must be a dependency of a target marked with this tag.

Often, Pants devs want to add 1-2 type hints but don't have time to type check the whole target. So, they must decide if they should still add `type_checked` even though the target is not fully typed. If they add it, it now becomes much harder for us to track what work remains.

We want some way to:

1. Have MyPy check partially typed targets, even if the target is not entirely typed.
1. Track what is partially vs. fully typed.

### Solution
Introduce the `partially_type_checked` tag and have `mypy.py` run against any targets with `partially_type_checked` or `type_checked`.

### Result
The barrier to entry becomes much lower to adding some type hints to a target and enforcing that they work.

This PR allows us to pursue a new strategy for the type hint migration (#6742): get as many targets as possible to work with `partially_type_checked`. **Even if a target has zero type hints, we should add `partially_type_checked` to it** so that we enforce that we do not introduce any new errors and so that when we add do add type hints, we know the rest of the codebase is using things correctly.
@Eric-Arellano
Copy link
Contributor Author

Closing this out as a substantial portion of our code base now uses type hints.

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

No branches or pull requests

2 participants