Add typing to chart and calculus method#35188
Add typing to chart and calculus method#35188tobiasdiez wants to merge 8 commits intosagemath:developfrom
Conversation
Codecov ReportBase: 88.59% // Head: 88.58% // Decreases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## develop #35188 +/- ##
===========================================
- Coverage 88.59% 88.58% -0.02%
===========================================
Files 2140 2140
Lines 396998 397304 +306
===========================================
+ Hits 351740 351943 +203
- Misses 45258 45361 +103
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
sagemathgh-35404: Drop support for Python 3.8 <!-- Please provide a concise, informative and self-explanatory title. --> <!-- Don't put issue numbers in the title. Put it in the Description below. --> <!-- For example, instead of "Fixes sagemath#12345", use "Add a new method to multiply two integers" --> ### 📚 Description In preparation for important package upgrades, we remove support for Python v3.8. (Almost) all occurrences of "Python 3.8" are removed from the codebase. There are still some comments left that essentially say that in newer versions things can be simplified, but I didn't touch those and leave them for follow-up PRs. This will help with: - PRs that require Python 3.9 or above, such as sagemath#34973 and sagemath#35188. - Upgrades of Python packages that have dropped support for Python 3.8 because they follow NEP 29 and have already released a new major version that drops support according to the NEP 29 schedule. - NetworkX 3.2 (expected 2023-??; version 3.1 was released 2023-04, see sagemath#35671) - sagemath#34816 - sagemath#35703 - See also sagemath#32074. Test run: https://github.com/tobiasdiez/sage/actions/runs/4586981626 <!-- Describe your changes here in detail. --> <!-- Why is this change required? What problem does it solve? --> <!-- If this PR resolves an open issue, please link to it here. For example "Fixes sagemath#12345". --> <!-- If your change requires a documentation PR, please link it appropriately. --> ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. It should be `[x]` not `[x ]`. --> - [x] The title is concise, informative, and self-explanatory. - [x] The description explains in detail what this PR is about. - [ ] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [x] I have updated the documentation accordingly. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on - sagemath#12345: short description why this is a dependency - sagemath#34567: ... --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> URL: sagemath#35404 Reported by: Tobias Diez Reviewer(s): Dima Pasechnik, Matthias Köppe
sagemathgh-35404: Drop support for Python 3.8 <!-- Please provide a concise, informative and self-explanatory title. --> <!-- Don't put issue numbers in the title. Put it in the Description below. --> <!-- For example, instead of "Fixes sagemath#12345", use "Add a new method to multiply two integers" --> ### 📚 Description In preparation for important package upgrades, we remove support for Python v3.8. (Almost) all occurrences of "Python 3.8" are removed from the codebase. There are still some comments left that essentially say that in newer versions things can be simplified, but I didn't touch those and leave them for follow-up PRs. This will help with: - PRs that require Python 3.9 or above, such as sagemath#34973 and sagemath#35188. - Upgrades of Python packages that have dropped support for Python 3.8 because they follow NEP 29 and have already released a new major version that drops support according to the NEP 29 schedule. - NetworkX 3.2 (expected 2023-??; version 3.1 was released 2023-04, see sagemath#35671) - sagemath#34816 - sagemath#35703 - See also sagemath#32074. Test run: https://github.com/tobiasdiez/sage/actions/runs/4586981626 <!-- Describe your changes here in detail. --> <!-- Why is this change required? What problem does it solve? --> <!-- If this PR resolves an open issue, please link to it here. For example "Fixes sagemath#12345". --> <!-- If your change requires a documentation PR, please link it appropriately. --> ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. It should be `[x]` not `[x ]`. --> - [x] The title is concise, informative, and self-explanatory. - [x] The description explains in detail what this PR is about. - [ ] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [x] I have updated the documentation accordingly. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on - sagemath#12345: short description why this is a dependency - sagemath#34567: ... --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> URL: sagemath#35404 Reported by: Tobias Diez Reviewer(s): Dima Pasechnik, Matthias Köppe
|
Documentation preview for this PR (built with commit c930dca; changes) is ready! 🎉 |
|
Now that Python 3.8 is dropped, this PR is finally good to go. @egourgoulhon could you please review it? Thanks! (The two failing tests are happening on all PRs right now) |
|
|
||
| # Conversion functions | ||
| def _SR_to_Sympy(expression): | ||
| def _SR_to_Sympy(expression: Expression) -> Expression: |
There was a problem hiding this comment.
The declared return type is wrong. It returns a sympy object, not an Expression.
And also the declared input is wrong because this function first marshals the input into SR. It is allowed to be all kinds of things.
| def is_trivial_zero(self, expression, method=None): | ||
| def is_trivial_zero( | ||
| self, expression: Expression, method: Optional[CalculusMethodName] = None | ||
| ) -> bool: |
There was a problem hiding this comment.
Also here, the type declaration Expression is wrong. It depends on method what type is allowed.
| def __classcall__( | ||
| cls: Type[Chart], | ||
| domain: TopologicalManifold, | ||
| coordinates: str = "", |
There was a problem hiding this comment.
No, str is only one of the allowed types, see function body
| return latex(self._chart1) + r' \rightarrow ' + latex(self._chart2) | ||
|
|
||
| def __eq__(self, other): | ||
| def __eq__(self, other: CoordChange) -> bool: |
There was a problem hiding this comment.
Not correct. It is allowed to pass an object of a different type as other. The method returns False in this case.
There was a problem hiding this comment.
There seems to be two conventions for this. Either you use indeed object for other, or you restrict other to some meaningful subset. The later is employed by e.g numpy and many others. The logic here seems to be that its more helpful to have your static checker complain that you compare apples and bananas, then to correctly handle the relatively rare case of comparing two completely different object (in which case you can ignore the error).
| self._chart2.restrict(dom2), *(self._transf.expr())) | ||
|
|
||
| def display(self): | ||
| def display(self) -> str: |
There was a problem hiding this comment.
not correct; a FormattedExpansion is not an str.
| #### End of accessors | ||
|
|
||
| def is_subset(self, other): | ||
| def is_subset(self, other: TopologicalManifold): |
There was a problem hiding this comment.
Not correct. other is allowed to be a mere ManifoldSubset
| return description | ||
|
|
||
| def _first_ngens(self, n): | ||
| def _first_ngens(self, n: int): |
There was a problem hiding this comment.
int is not correct; here and in many other places. A Sage Integer is definitely allowed.
I'd suggest to use the numeric ABCs; https://docs.python.org/3/library/numbers.html
There was a problem hiding this comment.
these abc's are not supported (in the way you want) by pyright and mypy, see microsoft/pyright#1575 and references therein. We also cannot use Integer since its a cython class and there are no stubs for that (yet). So yeah, its a partial information that is still better than nothing (since ints are allowed).
There was a problem hiding this comment.
I'm pretty sure that the mantra "don't lie to your static checker" should apply.
Acceptable "partial information" would be using a supertype, not a subtype, of what is allowed. If our Integer cannot be represented, then this will just have to be an Any or object.
There was a problem hiding this comment.
@tobiasdiez Do you have an opinion on what tools to use for generating the typing stubs (pyi) for our Cython classes? A quick search led me to https://github.com/RaubCamaioni/CythonPEG, but I'm guessing there must be more available
There was a problem hiding this comment.
Acceptable "partial information" would be using a supertype, not a subtype, of what is allowed. If our
Integercannot be represented, then this will just have to be anAnyorobject.
With any you don't get an error if you pass in a string. With int you can pass in any sage integer (which is treated as any). Since there are so many open challenges with even getting basic type checks to work, the mantra would be more "over time lie less and less to your static checker".
@tobiasdiez Do you have an opinion on what tools to use for generating the typing stubs (pyi) for our Cython classes? A quick search led me to https://github.com/RaubCamaioni/CythonPEG, but I'm guessing there must be more available
There is some movement to implement this directly in Cython. I would wait for this. There is an open issue in the Cython repo (that also compares different workarounds/packages in case you are interested)...
There was a problem hiding this comment.
Acceptable "partial information" would be using a supertype, not a subtype, of what is allowed. If our
Integercannot be represented, then this will just have to be anAnyorobject.
+1
With
anyyou don't get an error if you pass in a string. Withintyou can pass in any sage integer (which is treated as any). Since there are so many open challenges with even getting basic type checks to work, the mantra would be more "over time lie less and less to your static checker".
It's not only that you are lying to your static checker: you are also lying to the user/developer examining the source code. IMHO, no typing information is better than a false one.
There was a problem hiding this comment.
Note that the objective of these type checks is to discover bugs. In this case, that you get notified about passing something wrong into the method. The idea that the types should strictly represent the runtime behavior is not very helpful. The numpy docs for example state
NumPy is very flexible. Trying to describe the full range of possibilities statically would result in types that are not very helpful. For that reason, the typed NumPy API is often stricter than the runtime NumPy API.
But yes, I agree that finding a solution for the integers would be nice. Let me think about it (and propose ideas in case you have some).
| and (self._transf == other._transf)) | ||
|
|
||
| def __ne__(self, other): | ||
| def __ne__(self, other: CoordChange) -> bool: |
📚 Description
Adds (almost complete) typing information for charts (and the related calculus method).
📝 Checklist
⌛ Dependencies