-
-
Notifications
You must be signed in to change notification settings - Fork 503
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
Add typing to chart and calculus method #35188
base: develop
Are you sure you want to change the base?
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. |
<!-- 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
<!-- 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, str
is only one of the allowed types, see function body
@@ -3416,7 +3520,7 @@ def _latex_(self): | |||
""" | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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).
@@ -3848,7 +3954,7 @@ def restrict(self, dom1, dom2=None): | |||
return type(self)(self._chart1.restrict(dom1), | |||
self._chart2.restrict(dom2), *(self._transf.expr())) | |||
|
|||
def display(self): | |||
def display(self) -> str: |
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.
not correct; a FormattedExpansion is not an str.
@@ -1320,7 +1326,7 @@ def get_subset(self, name): | |||
|
|||
#### End of accessors | |||
|
|||
def is_subset(self, other): | |||
def is_subset(self, other: TopologicalManifold): |
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.
Not correct. other is allowed to be a mere ManifoldSubset
@@ -553,7 +602,7 @@ def _latex_(self): | |||
description += latex(self._xx[n-1]).strip() + r')\right)' | |||
return description | |||
|
|||
def _first_ngens(self, n): | |||
def _first_ngens(self, n: int): |
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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 anAny
orobject
.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 anAny
orobject
.
+1
With
any
you don't get an error if you pass in a string. Withint
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".
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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).
@@ -3448,7 +3552,7 @@ def __eq__(self, other): | |||
and (self._chart2 == other._chart2) | |||
and (self._transf == other._transf)) | |||
|
|||
def __ne__(self, other): | |||
def __ne__(self, other: CoordChange) -> bool: |
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.
Likewise here
📚 Description
Adds (almost complete) typing information for charts (and the related calculus method).
📝 Checklist
⌛ Dependencies