-
Notifications
You must be signed in to change notification settings - Fork 121
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
Fix mypy support #337
Fix mypy support #337
Conversation
Codecov Report
@@ Coverage Diff @@
## main #337 +/- ##
==========================================
- Coverage 88.59% 88.57% -0.02%
==========================================
Files 36 36
Lines 4629 4632 +3
==========================================
+ Hits 4101 4103 +2
- Misses 528 529 +1
Continue to review full report at Codecov.
|
The The mypy compliance changes are fine, but are mostly working around mypy not being able to infer types that shouldn't necessarily be stated (e.g. all of the ExtensionHooks additions). I was however suprised to see that Pyright missed some lack of return statements in the item_assets extension. I wonder if there's some settings to fiddle around with for Pyright to not let something like that pass. I don't feel super strongly about the need to pass in types, and am mildly against having to satisfy mypy's lack of ability to infer types or handle passing runtime types; however seeing that pyright missed something pretty obvious it does feel like having the addition of mypy may be worth having to work around these things. If we want to move forward, then I'll ask that you add mypy to the requirements-dev.txt and to the |
Based on the As for the issue regarding the
- def _get_property(self, prop_name: str, typ: Type[P] = Type[Any]) -> Optional[P]:
- result: Optional[typ] = self.properties.get(prop_name)
+ def _get_property(self, prop_name: str, typ: Type[P]) -> Optional[P]:
+ result = self.properties.get(prop_name) I tested this by passing a I would support @lossyrob 's suggestion that we move forward by adding |
👍 @l0b0 do you want to add mypy to the CI and move this from RFC to ready to merge? Thanks! |
d40c711
to
fb1aef1
Compare
Thank you @duckontheweb, that worked! |
@lossyrob I tried using the non-deprecated |
Not type checking setup.py is totally reasonable to me - I think we'll probably want to change that import in the future anyway. |
There was a conflict with a recent PR around test_pointcloud, resolved and merged that via the GitHub UI |
The CI failures are due to type errors in the pointcloud tests introduced from the merge. It looks like a couple of the functions just need their return types annotated. The successful builds on Windows are due to a problem with the CI. The CI script doesn't seem to be running at all, so it isn't returning a non-zero exit code. I'll fix that in a separate PR. |
Yep, the merge conflict didn't account for some of the missing return types; I just added them and pushed that change so this should be ready to go soon 🤞 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good. I have one request to avoid changing library behavior, and a question around the possibility maintaining the use of lambda.
pystac/collection.py
Outdated
self.intervals = [cast(List[Optional[Datetime]], intervals)] | ||
else: | ||
self.intervals = cast(List[List[Optional[Datetime]]], intervals) | ||
def __init__(self, intervals: List[List[Optional[Datetime]]]): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This changes behavior; I'd prefer to keep this PR to the type changes. If we want to remove this nicety, which was put in place based on user requests, we can discuss in a follow up PR or issue.
@@ -188,10 +188,11 @@ def data_type(self) -> Optional[List[FileDataType]]: | |||
Returns: | |||
FileDataType | |||
""" | |||
return map_opt( | |||
lambda x: [FileDataType(t) for t in x], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it the case that mypy doesn't allow lambdas? Is there a flag for this? I find this style of short lambda useful and more readable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it allows lambdas; it's just simpler to type a function. I'm not sure you can type lambdas, but I expect it'd be a mess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah right, I think Pyright is OK with inferring types in lambdas without annotations where mypy isn't...a bit of inconvenience but worth it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this may actually be an indicator that we're not adequately typing something in the second argument to map_opt
. I left a comment on pystac.extensions.eo
to illustrate this in more detail, but I think we may want to keep the untyped lambdas here and track down the typing issues in more detail.
I think the solution from the other comment will also solve this case and allow us to keep the untyped lambda here.
@@ -59,7 +58,7 @@ class ObservationDirection(enum.Enum): | |||
|
|||
|
|||
class SarExtension( | |||
Generic[T], ProjectionExtension[T], ExtensionManagementMixin[pystac.Item] | |||
Generic[T], PropertiesExtension, ExtensionManagementMixin[pystac.Item] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch
2cd0a8c
to
163286e
Compare
How's this @lossyrob? |
@@ -188,10 +188,11 @@ def data_type(self) -> Optional[List[FileDataType]]: | |||
Returns: | |||
FileDataType | |||
""" | |||
return map_opt( | |||
lambda x: [FileDataType(t) for t in x], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah right, I think Pyright is OK with inferring types in lambdas without annotations where mypy isn't...a bit of inconvenience but worth it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@l0b0 Thanks so much for this PR, it's uncovered some subtle typing issues that we never would have caught otherwise.
My only requested changes are related to the change from untyped lambdas to defined functions that @lossyrob commented on, other than that this looks great and thanks for bearing with all of the changes.
.gitignore
Outdated
@@ -14,6 +14,7 @@ stdout* | |||
.idea/ | |||
docs/_build/ | |||
coverage.xml | |||
venv/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this environment location is specific to the developer and not the project, I think it would be best to handle these in the developer's global gititnore rather than something committed to the project.
Since we don't mention anything about this in the Contributing docs and we already had the .idea
line creep in above, this shouldn't be a blocker, but if you're making changes related to my other comments then we might as well do this as well.
I'll also make a note to update our Contributing docs to make this clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll remove it, but I consider using the global .gitignore for anything is a bad idea. You never know when it will conflict with the needs of some project, at which point you need a custom !foo
line in the project .gitignore or !/path/to/project/foo
in the global .gitignore.
pystac/extensions/eo.py
Outdated
lambda bands: [Band(b) for b in bands], | ||
construct_bands, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the reason that mypy can infer a type for the lambda in the _get_bands
method above but not here is due to the way the 2nd argument to map_opt
is typed.
In this case, we didn't have a type annotation on SummariesExtension
for the summaries
property. Adding the following type annotation in pystac.extensions.base.SummariesExtension
allows us to keep an untyped lambda here:
from pystac.collection import Collection, Summaries
...
class SummariesExtension:
summaries: Summaries
Since it seems like mypy
is actually catching cases where we haven't adequately typed things, this might be a better solution that creating a typed function.
@@ -188,10 +188,11 @@ def data_type(self) -> Optional[List[FileDataType]]: | |||
Returns: | |||
FileDataType | |||
""" | |||
return map_opt( | |||
lambda x: [FileDataType(t) for t in x], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this may actually be an indicator that we're not adequately typing something in the second argument to map_opt
. I left a comment on pystac.extensions.eo
to illustrate this in more detail, but I think we may want to keep the untyped lambdas here and track down the typing issues in more detail.
I think the solution from the other comment will also solve this case and allow us to keep the untyped lambda here.
Allows ignoring more specific errors as in `# type: ignore[ERROR]` rather than just `# type: ignore`.
I think this latest version should cover your comments, @duckontheweb. Thanks for working out how to keep the original lambda code! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, thanks again for contributing this!
Related Issue(s): #332
Description: Fixes most typing issues which mypy complain about in current main branch. I'm unsure about the remaining issue:
Since types aren't enforced at runtime, and I don't believe mypy will assert the type of
result
at the various call sites (verified by changingreturn self._get_property(CLOUD_COVER_PROP, float)
toreturn self._get_property(CLOUD_COVER_PROP, str)
and seeing no change in the mypy output), the_get_property
typ
argument should probably be removed, unless it is enforced by Pyright. I'd like to hear your opinion on this before going forward with that change though.PR Checklist:
scripts/format
)scripts/test
)