Document Python type annotations and checks.#2072
Document Python type annotations and checks.#2072TimothyEDawson wants to merge 2 commits intoCantera:mainfrom
Conversation
|
Note: The |
bryanwweber
left a comment
There was a problem hiding this comment.
Thanks Tim! I have a few fairly small comments. The only bigger one is to add some examples where we have # type: ignore and what their justification is.
|
Alright, I think we're a lot closer now! |
There was a problem hiding this comment.
Thanks, @TimothyEDawson, for tackling this. I have independently played with type annotations in my own code bases and wanted to share some of my conclusions:
.pyifiles are a very limited band-aid. Other than convenience to third party software or end-users of our package there is no benefit to code quality (i.e., I am challenging the 'secondary benefit' you mention in your description; rather,.pyistub files make code maintenance harder).- Direct type annotations in
.pyfiles is a different subject matter, as there is an actual analysis happening. There's the obvious caveat of Cython in its current form. - It has been my experience that making
mypy/pyrightpass for.pyis relatively straightforward (as in: can be taken care of by coding agents). Addingstubtestruntime checks into the mix, however, makes things dicey, and involves exceedingly ugly hacks (--allowlist) for silly reasons. - If we are concerned about code quality, I'd rather like to see
ruff checkthan tracking down ways to makemypy/pyrightplusstubtesthappy. It's doable to add some of this in with stubs retroactively into our codebase (as has been done), but is not reasonable with.py. I'd rather wait until those tools get better.
I think you've misread. The stub files are not where the secondary benefit applies, they only apply to the native Python code. In fact, that's the entire point of that paragraph.
Sure, but stubtest is the only way to verify stubs. Without it, you can put whatever you want in the stubs with no regard for actual runtime behavior, and only manual checks would catch errors and mistakes. As long as we have stub files we need stubtest, and as long as we have Cython-syntax code we need stub files.
Ruff is a linter, not a type checker. It is not a replacement for Two side notes:
|
|
Agreed that I'll grudgingly agree on |
bryanwweber
left a comment
There was a problem hiding this comment.
Thanks again @TimothyEDawson I had a chance to pull this down and try the commands, so I have a few suggestions for clarifying and making this more self contained. I think that will make for a better experience for devs who might not be as familiar with Python type hinting.
| These are omitted from the results by adding the `--ignoreexternal` option: | ||
|
|
||
| ```sh | ||
| pyright --ignoreexternal --verifytypes cantera |
There was a problem hiding this comment.
This produced a bunch of error outputs in the with_units interface, is that expected?
There was a problem hiding this comment.
Yes, I haven't attempted to get Pyright passing as it tends to be much more strict than Mypy. It prints error messages during this check, but it does not actually error, and only the last bit about the coverage is the relevant output of the --verifytypes command.
|
|
||
| A secondary benefit of type annotations is to facilitate static analysis of Cantera's | ||
| Python code in order to catch potential typing-related errors using tools like | ||
| [mypy](https://mypy.readthedocs.io/en/latest/index.html), |
There was a problem hiding this comment.
I appreciate listing all the type checkers here, but we really only support mypy and pyright, right? At least, I tried to run ty and got a bunch of errors. I think listing everything is confusing if we don't support those type checkers, so I think we should remove those links. I think it would be helpful to show the CLI commands for the other checkers, but I don't expect you to handle that.
There was a problem hiding this comment.
In the future, once we have more of the code actually being checked at all (i.e. if we can convert the Cython syntax to Python syntax), I think it would be great to include all of these type checkers in the CI. In the interim I think it's worth mentioning them to show they've been considered, and let contributors know they exist.
It's also good practice for contributors to try multiple checkers and get their code passing, even when Mypy is the only one currently enforced. I use Pyrefly quite a lot, myself. I don't think that's necessarily worth recommending in the developer guide, though.
|
|
||
| Due to the use of compiled Cython code, most checks are performed on the built library | ||
| rather than running directly against the source code. It is thus recommended to follow | ||
| [](sec-using-build-dir). |
There was a problem hiding this comment.
I see this link here, but it's easy to miss. I think we should describe one way to do everything in this file (i.e., if any steps require the built library, we should set it up so all of them use the built library) and include any necessary configuration (e.g., exporting environment variables) as code snippets in this doc page, in addition to this link. I know that will be some duplication, but typing is esoteric enough that I want to make this page as easy to understand on its own as possible.
There was a problem hiding this comment.
I'm open to laying out the directions more explicitly here, it's a good idea. I do think it's important to be explicit about which checks don't require a local build at all, as that has a significant impact on the developer workflow. Specifically, you really shouldn't be rebuilding between checks, as it adds an unnecessary step and extra time. Static type checking should be performed in a tight loop during development, and ideally most of it is happening as you type using a language server. Meanwhile, the checks on built libraries are a necessary evil right now, but mostly just when dealing with the stub files, and hopefully they can be eliminated in the future.
There was a problem hiding this comment.
Specifically, you really shouldn't be rebuilding between checks, as it adds an unnecessary step and extra time... ideally most of it is happening as you type using a language server.
Please correct me if I'm wrong, but the only way to check the runtime types is by rebuilding until and if we are able to put hints into Cython? Insofar as this is a guide for developers of Cantera and not developers using Cantera, I really think we should focus on the steps that require the build step and just accept that it's not ideal right now.
| When not inside the cython directory, the `-p` option will attempt to check the built | ||
| library instead. Note that the configuration settings for `mypy` are included within | ||
| the `pyproject.toml` file in the `interfaces/cython` folder, which from the | ||
| root directory can be passed in on the command line like so: | ||
|
|
||
| ```sh | ||
| mypy --config-file interfaces/cython/pyproject.toml -p cantera | ||
| ``` |
There was a problem hiding this comment.
I mentioned this in the previous comment, I think this is the only way we should show to users. I could maybe be convinced that we can show the "no built library" in an expandable tab if you really want to keep it.
There was a problem hiding this comment.
I would argue the "no built library" is the only one which should be shown.
|
@bryanwweber / @TimothyEDawson … what is the status on this PR? |
|
Thanks for the ping Ingmar! I'm waiting for Tim to reply to me or make the suggested changes. |
Changes proposed in this pull request
environment.yamlfile.If applicable, fill in the issue number this pull request is fixing
Closes Cantera/enhancements#251
AI Statement (required)
Checklist
scons build&scons test) and unit tests address code coverage