Skip to content

Add tests for type annotations with mypy #1042

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 31 commits into from
Mar 23, 2021
Merged

Add tests for type annotations with mypy #1042

merged 31 commits into from
Mar 23, 2021

Conversation

stefsmeets
Copy link
Contributor

@stefsmeets stefsmeets commented Mar 12, 2021

Description

Hi everyone, this PR adds mypy as an additional test in pytest.
It also fixes all the type annotations where possible.


Before you get started

Checklist


To help with the number pull requests:

@stefsmeets stefsmeets marked this pull request as ready for review March 15, 2021 14:46
@stefsmeets stefsmeets requested a review from jvegreg as a code owner March 15, 2021 14:46
@stefsmeets stefsmeets requested a review from nielsdrost March 15, 2021 14:46
@stefsmeets
Copy link
Contributor Author

stefsmeets commented Mar 15, 2021

Hi @nielsdrost @bouweandela , this PR is ready to be reviewed. Could one of you have a look?

@stefsmeets stefsmeets requested a review from bouweandela March 15, 2021 14:47
@bouweandela
Copy link
Member

Sure, I'd be happy to review!

Did you try if it works with Python 3.6? Because I would expect the worst support for type annotations there. Up until now, we weren't using any new Python features, but I believe that type annotations are a more recent addition to the language.

Copy link
Member

@bouweandela bouweandela left a comment

Choose a reason for hiding this comment

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

Very nice contribution!

Did you also try the mypy plugin for prospector?

Comment on lines +14 to +17
CFG_DEVELOPER = esmvalcore._config.read_config_developer_file()
esmvalcore._config._config.CFG = CFG_DEVELOPER
# Initialize CMOR tables
read_cmor_tables(esmvalcore._config.CFG)
read_cmor_tables(CFG_DEVELOPER)
Copy link
Member

Choose a reason for hiding this comment

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

This is unsafe code, because it changes a loaded module (esmvalcore._config._config.CFG) so it can potentially mess up that module. Line 14-17 can be replaced with a safer:

esmvalcore._config.load_config_developer()

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 also don't like that code, but that is how it is at the moment in master and should be fixed in a separate PR.

Copy link
Member

Choose a reason for hiding this comment

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

You're changing the code in this pull request, so you might as well improve it while you're at it

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'd love to improve it, but that is not the goal of this PR. I only fixed what was necessary to pass the type checks with mypy👍 If this needs more fixing, then let's do it in a separate issue/PR.

@@ -224,7 +225,7 @@ def test_config_class():
assert isinstance(cfg['output_dir'], Path)
assert isinstance(cfg['auxiliary_data_dir'], Path)

from esmvalcore._config import CFG as CFG_DEV
from esmvalcore._config._config import CFG as CFG_DEV
Copy link
Member

Choose a reason for hiding this comment

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

Has the location of this import moved in this pull request?

Copy link
Contributor Author

@stefsmeets stefsmeets Mar 16, 2021

Choose a reason for hiding this comment

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

No, as you mentioned in the comment above, this code is unsafe. This test depended on the config developer to be set as esmvalcore._config.CFG in test_data_finder.py. The location of _config was changed in #939.

Copy link
Member

Choose a reason for hiding this comment

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

But why are the tests passing with the old import, if this was changed 2 months ago?

Copy link
Contributor Author

@stefsmeets stefsmeets Mar 16, 2021

Choose a reason for hiding this comment

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

Because test_data_finder sets the variable:
test_data_finder.py: esmvalcore._config.CFG = esmvalcore._config.read_config_developer_file()

and then test_config imports it:
test_config.py: from esmvalcore._config import CFG as CFG_DEV

When I changed one, I had to change the other. I don't know the reason why it was done this way, but it seemed like I missed this one in #939, so I updated it.

@bouweandela
Copy link
Member

While trying out this pull request, I noticed that sometimes when I run mypy it automatically adds the entry /.mypy_cache/ to my .gitignore file, which then shows as changed. It would be nice to add that entry in this pull request, so other people aren't bothered with it.

@stefsmeets
Copy link
Contributor Author

stefsmeets commented Mar 16, 2021

Did you try if it works with Python 3.6?

I have not tried Python 3.6. Is that part of our test specification? The tests on CircleCI are only with 3.7 afaik. I'm not sure it makes sense to test it with Python3.6, because we will never see the errors.

@stefsmeets
Copy link
Contributor Author

stefsmeets commented Mar 16, 2021

Did you also try the mypy plugin for prospector?

I have not. I will add it to prospector / pre-commit, that may be nice. The check is very fast anyway 👍

Update: seems to work as intended. 😁

@bouweandela
Copy link
Member

I have not tried Python 3.6. Is that part of our test specification?

Yes, ESMValTool and ESMValCore support Python 3.6 and up

The tests on CircleCI are only with 3.7 afaik.

They are run with a recent Python version, Python 3.9 at the moment, see e.g. here

I'm not sure it makes sense to test it with Python3.6, because we will never see the errors.

It makes sense to test, because if we say we support Python 3.6 and up, we should be sure it works. There is already a nightly GitHub Action run on the master branch that tests all supported Python versions on all supported platforms, see e.g. here. So if there are any errors, we will start seeing them there as soon as this pull request is merged into master.

Depending on how easy it is to mess up because type hints are less well supported by older Python versions, it would probably make sense to add a test job that runs on every pull request with the lowest Python version we support.

@bouweandela
Copy link
Member

If it makes life easier, I think we could drop Python 3.6 support because it's almost end of life anyway. It looks like Python 3.7 and up have better support.

@stefsmeets
Copy link
Contributor Author

stefsmeets commented Mar 16, 2021

If it makes life easier, I think we could drop Python 3.6 support because it's almost end of life anyway. It looks like Python 3.7 and up have better support.

Either works for me, but if we are supporting 3.6 then I think it would be best if we run our CI tests in the PR on 3.6 to ensure that people do not add unsupported code.

@bouweandela
Copy link
Member

It would be best to run them with both Python 3.9 (to see that things work the Python version that most people will use and that we're not using too old features that have been removed) and Python 3.6 (to check that we're not using features that are too new and not available yet). Would it be OK with you if I added an extra CircleCI test for Python 3.6 in this pull request? Or would you like to do this yourself?

@stefsmeets
Copy link
Contributor Author

stefsmeets commented Mar 18, 2021

It would be best to run them with both Python 3.9 (to see that things work the Python version that most people will use and that we're not using too old features that have been removed) and Python 3.6 (to check that we're not using features that are too new and not available yet). Would it be OK with you if I added an extra CircleCI test for Python 3.6 in this pull request? Or would you like to do this yourself?

I think it is more transparent to add a new CircleCI test for python 3.6 in a separate PR. And then merge that here.

EDIT: made an issue here #1055

@bouweandela
Copy link
Member

@stefsmeets Could you please fix the issues reported by Codacy and the failing CircleCI tests?

@stefsmeets
Copy link
Contributor Author

stefsmeets commented Mar 22, 2021

@stefsmeets Could you please fix the issues reported by Codacy and the failing CircleCI tests?

Done. The other codacy issue was already there, because the function arguments need to match the original one.

CircleCI fails are because of the conda_build related to fiona, and a segmentation fault 🤷‍♂️

@bouweandela
Copy link
Member

The other codacy issue was already there, because the function arguments need to match the original one.

I think you are referring to the warnings from file esmvalcore/experimental/_warnings.py here, right?

What about

esmvalcore/experimental/config/_validated_config.py
Method '__delitem__' is abstract in class 'MutableMapping' but is not overridden (abstract-method)

class ValidatedConfig(MutableMapping, dict):

and

esmvalcore/experimental/recipe_output.py
No value for argument 'files' in constructor call

return cls(name=task.name, output=product_attributes)

Unexpected keyword argument 'output' in constructor call

return cls(name=task.name, output=product_attributes)

? These look like things that would need to be solved.

CircleCI fails are because of the conda_build related to fiona, and a segmentation fault man_shrugging

The fiona test problem has been fixed #1046, so you can solve it by merging master into this branch. The segmentation fault can be usually be avoided by clicking the re-run button on CircleCI, see #644.

@stefsmeets
Copy link
Contributor Author

stefsmeets commented Mar 23, 2021

Sorry @bouweandela , but I don't see those issues in Codacy. Afaik I already fixed those a long time ago.

@stefsmeets
Copy link
Contributor Author

stefsmeets commented Mar 23, 2021

I already re-ran the tests, and now test passes, but conda_build fails with OSError: [Errno 28] No space left on device: '/opt/conda/conda-bld/linux-64/repodata_from_packages.json.7a93cac9-76ed-4f08-88f8-57fe3851d589' 🤷‍♂️

@bouweandela
Copy link
Member

I already re-ran the tests, and now test passes, but conda_build fails with OSError: [Errno 28] No space left on device: '/opt/conda/conda-bld/linux-64/repodata_from_packages.json.7a93cac9-76ed-4f08-88f8-57fe3851d589' man_shrugging

The tests pass now, so that should be fine, thanks!

@bouweandela bouweandela merged commit 09ff7c9 into master Mar 23, 2021
@bouweandela bouweandela deleted the mypy_test branch March 23, 2021 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add mypy checks to pytest
2 participants