Skip to content

Enable mypy analysis for all files. #593

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

Merged
merged 25 commits into from
Nov 7, 2022
Merged

Enable mypy analysis for all files. #593

merged 25 commits into from
Nov 7, 2022

Conversation

ianyfan
Copy link
Contributor

@ianyfan ianyfan commented Oct 26, 2022

Description

EDIT: remaining issues have been resolved. The issues with env.horizon and evaluate_policy are to be taken upstream, and then depending on how quickly the turnaround is on those, either wait for them to be merged before merging this, or ignore the issues for now and un-ignore them once the fixes are done.

ORIGINAL:

Fixes #573 by adding the remaining type annotations. Some of the issues in mce_irl.py is resolved by changing env.horizon to int(env.horizon) which indicates that there would be a problem if env.horizon was not an integer (I think it can be np.inf?). Does this occur in practice (since this should necessitate a runtime check)?

One other issue in mce_irl.py I fixed by using a cast, which I guarded behind if TYPE_CHECKING:. I don't think there is a better way of doing this, since there is no other way of restricting the type to what we want.

Remaining issues:

src/imitation/algorithms/preference_comparisons.py:121: error: Argument 1 to "shuffle" of "Generator" has incompatible type "List[TrajectoryWithRew]"; expected "Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]]]"  [arg-type]
src/imitation/algorithms/preference_comparisons.py:644: error: Argument 1 to "choice" of "Generator" has incompatible type "List[TrajectoryWithRew]"; expected "Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]]]"  [arg-type]
tests/algorithms/test_bc.py:133: error: Item "None" of "Optional[Cache]" has no attribute "mkdir"  [union-attr]
tests/algorithms/test_bc.py:163: error: Item "None" of "Optional[Cache]" has no attribute "mkdir"  [union-attr]
tests/algorithms/test_bc.py:186: error: Argument 1 to "evaluate_policy" has incompatible type "ActorCriticPolicy"; expected "BaseAlgorithm"  [arg-type]
tests/algorithms/test_bc.py:196: error: Argument 1 to "evaluate_policy" has incompatible type "ActorCriticPolicy"; expected "BaseAlgorithm"  [arg-type]

The ones in preference_comparisons.py appear to be due to an over-conservative annotation in numpythough I may have missed something. If it is due to this, then I'm not sure if there is a better way to deal with the issue than to type: ignore it.

The issues in test_bc.py are also weird and may just be worth ignoring.
pytestconfig.cache is typed as Optional[Cache] so I'm not sure whether this implies that it could actually be None sometimes, or whether it is just typed that way. If the latter, either an extra assert is not None may be sufficient; if the former, some extra logic may be required to run the tests properly.

Testing

Ran mypy over relevant files, as well as ci/code_checks.sh.

@codecov
Copy link

codecov bot commented Oct 26, 2022

Codecov Report

Merging #593 (a4b080f) into master (f64f5f8) will increase coverage by 0.00%.
The diff coverage is 100.00%.

❗ Current head a4b080f differs from pull request most recent head 0cd35d7. Consider uploading reports for the commit 0cd35d7 to get more accurate results

@@           Coverage Diff           @@
##           master     #593   +/-   ##
=======================================
  Coverage   97.46%   97.47%           
=======================================
  Files          85       85           
  Lines        8203     8233   +30     
=======================================
+ Hits         7995     8025   +30     
  Misses        208      208           
Impacted Files Coverage Δ
src/imitation/data/rollout.py 100.00% <ø> (ø)
src/imitation/algorithms/base.py 98.78% <100.00%> (ø)
src/imitation/algorithms/bc.py 98.33% <100.00%> (ø)
src/imitation/algorithms/dagger.py 100.00% <100.00%> (ø)
src/imitation/algorithms/density.py 94.48% <100.00%> (ø)
src/imitation/algorithms/mce_irl.py 96.17% <100.00%> (+0.21%) ⬆️
src/imitation/algorithms/preference_comparisons.py 99.13% <100.00%> (ø)
src/imitation/data/types.py 98.20% <100.00%> (+0.01%) ⬆️
src/imitation/rewards/serialize.py 100.00% <100.00%> (ø)
tests/algorithms/test_bc.py 100.00% <100.00%> (ø)
... and 1 more

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

Copy link
Member

@AdamGleave AdamGleave left a comment

Choose a reason for hiding this comment

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

Largely looks good, only some minor changes needed.

@@ -45,7 +56,7 @@ def mce_partition_fh(
\pi is a 3d array, indexed \pi[t,s,a].
"""
# shorthand
horizon = env.horizon
horizon = int(env.horizon)
Copy link
Member

Choose a reason for hiding this comment

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

Can we add a TODO here so we remember to fix this before merge (if the plan is to fix it in a seals PR first), or open a GH issue to track it (if we want to merge this PR before fixing it upstream)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've opened a PR and added an extra check that should still be relevant even once the upstream has been changed, but can still add an extra comment if that would be helpful

@@ -183,7 +185,7 @@ def test_that_bc_improves_rewards(
):
# GIVEN
novice_rewards, _ = evaluation.evaluate_policy(
cartpole_bc_trainer.policy,
cartpole_bc_trainer.policy, # type: ignore[arg-type]
Copy link
Member

Choose a reason for hiding this comment

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

Similar to with the seals upstream issue, let's add a TODO or GH issue for this.

@AdamGleave
Copy link
Member

On upstream: I don't think we're going to have time to turnaround the SB3 change before you wrap up. The seals one should be a short fix, and I can review and merge same-day, so let's push for fixing that one upstream though.

@ianyfan ianyfan changed the title [WIP] remaining mypy annotations Enable mypy analysis for all files. Oct 28, 2022
@ianyfan ianyfan marked this pull request as ready for review October 28, 2022 14:55
@ianyfan
Copy link
Contributor Author

ianyfan commented Oct 28, 2022

There's more places that are missing type annotations, but since they don't cause errors in mypy, I will leave them be, so as not to add any more noise to this PR.

Copy link
Member

@AdamGleave AdamGleave left a comment

Choose a reason for hiding this comment

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

@ianyfan
Copy link
Contributor Author

ianyfan commented Oct 31, 2022

New changes look good to me, at least

@Rocamonde
Copy link
Member

Apologies, this did not show up on my GitHub PR notifications. Will review tomorrow.

Copy link
Member

@Rocamonde Rocamonde left a comment

Choose a reason for hiding this comment

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

Looks good, just one thing I noticed that might be a bug, do take a look.

@Rocamonde
Copy link
Member

Yay! Thanks for doing this @ianyfan , nice to see what we started being nicely completed. This will certainly make our codebase more robust to random bugs and errors.

@AdamGleave AdamGleave requested a review from Rocamonde November 2, 2022 00:57
@AdamGleave
Copy link
Member

Thanks for the review @Rocamonde, issues should be resolved now

Copy link
Member

@Rocamonde Rocamonde left a comment

Choose a reason for hiding this comment

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

This is excellent work! LGTM. I left some comments with suggestions and questions, worth looking over them before merging to make sure we're happy with the direction of things.

@@ -343,7 +343,7 @@ def __call__(
rew_array = np.asarray(rew_list, dtype="float32")
return rew_array

def train_policy(self, n_timesteps: int = int(1e6), **kwargs):
def train_policy(self, n_timesteps: int = int(1e6), **kwargs: Any) -> None:
Copy link
Member

Choose a reason for hiding this comment

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

We could try to be more specific than this, but ParamSpec is not (yet) a very well supported feature by most type checkers, and it might not be worth the effort of typing it.

Copy link
Member

Choose a reason for hiding this comment

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

I've not used ParamSpec much so may be missing something, but how would it help us here? It seems designed in cases where the P = ParamSpec("P") variable is reused, like decorators or other higher-order functions. But if we're returning None I don't think it makes a difference.

Copy link
Member

Choose a reason for hiding this comment

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

I meant for Any, not for None haha. The problem with this is that any subtype has to take any kwarg in the signature, but you only really want it to take the kwargs that .learn() can take. But not sure how you can use ParamSpec for this now I think about it. I think it was designed as a generic that is filled in implicitly at the callsite, not for extracting the type signature of an explicit method (which tbh should be a valid use case).

@@ -182,7 +192,7 @@ def forward(
self,
observation: th.Tensor,
deterministic: bool = False,
):
) -> NoReturn:
Copy link
Member

Choose a reason for hiding this comment

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

Interesting . Is this type not incompatible with the superclass? How does that work?

Copy link
Member

Choose a reason for hiding this comment

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

I think it works because NoReturn is the bottom type: i.e. a type that is a subtype of all other types. There's a good discussion at python/mypy#4116

Copy link
Member

Choose a reason for hiding this comment

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

Type theory is quite cool. I remember attending a talk in Cambridge recently on some people working on re-constructing the foundations of mathematics using a flavor of type theory.

@AdamGleave AdamGleave requested a review from Rocamonde November 4, 2022 05:22
@AdamGleave
Copy link
Member

@Rocamonde I believe I've addressed all outstanding comments on this, please do re-review when you have a moment. Note we'll need to merge this one before #603 because that removes the mypy excludes.

@Rocamonde
Copy link
Member

Sorry about this. I reviewed the PRs sequentially from my inbox and only saw this should have been merged before now.

@Rocamonde
Copy link
Member

Actually it was fine, the merge was trivial. Will wait for tests to run and then merge.

Copy link
Member

@Rocamonde Rocamonde left a comment

Choose a reason for hiding this comment

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

LGTM

@AdamGleave AdamGleave merged commit 23fae17 into master Nov 7, 2022
@AdamGleave AdamGleave deleted the ianyfan/typing branch November 7, 2022 17:45
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.

Fix mypy type erorrs in skipped files
3 participants