Uh oh!
There was an error while loading. Please reload this page.
Fix decimal - #2323
Conversation
srittau
commented
Jul 12, 2018
mypy crash reported as python/mypy#5347. |
srittau
commented
Jul 13, 2018
Crash is now fixed in mypy master. |
JelleZijlstra
commented
Jul 13, 2018
Thanks! I restarted Travis, will take another look after it passes. |
JelleZijlstra
left a comment
There was a problem hiding this comment.
Thanks! Left a few comments.
| _ComparableNum = Union[Decimal, int, float] | ||
| _DecimalNew = Union[Decimal, int, float, Text, Tuple[int, Sequence[int], int]] | ||
| if sys.version_info >= (3,): | ||
| _ComparableNum = Union[Decimal, numbers.Rational, float] |
There was a problem hiding this comment.
This conditional definition makes it look confusingly like int is not supported in Python 3. In fact, it is redundant in Python 2 too, because it's automatically promoted to float. It would be clearer to have int either in both or in neither of the branches.
| def __delattr__(self, name): ... | ||
| def __reduce__(self): ... | ||
| def clear_flags(self): ... | ||
| def __setattr__(self, name: str, value: Any) -> Any: ... |
There was a problem hiding this comment.
I think this should actually be omitted because the effect of having it is that the type checker will think setting any attribute is allowed. However, the implementation actually only allows the attributes that are known to exist on the class.
There was a problem hiding this comment.
I replaced it with a comment saying so, for future reference.
| def is_canonical(self, a: _Decimal) -> Decimal: ... | ||
| def is_finite(self, a: _Decimal) -> Decimal: ... | ||
| def is_infinite(self, a: _Decimal) -> Decimal: ... | ||
| def is_nan(self, a: _Decimal) -> Decimal: ... |
There was a problem hiding this comment.
Most of these return bool, although I haven't checked all of those. I'm guessing divmod returns a Tuple[Decimal, Decimal].
There was a problem hiding this comment.
Good catch. I am rechecking the return values of all Context methods.
srittau
commented
Jul 14, 2018
I am not sure why the travis build does not start automatically after the latest patches. |
JelleZijlstra
commented
Jul 14, 2018
I closed and reopened, and now Travis seems to be running. |
gvanrossum
commented
Jul 26, 2018
I wonder if this broke something. I've got code that's essentially (though not quite) (Though that example doesn't provoke it.) The if/else expression's type is revealed as object, and I kind of suspect #2323, since |
srittau
commented
Jul 26, 2018
I think it's reasonable to assume that this change triggered the problem, although I suspect a bug in mypy. Since SupportsAbs and SupportsFloat are protocols, they should not be needed as base classes. The following test cast demonstrates the problem: fromtypingimportSupportsFloatclassFloaty:
def__float__(self): ...
classSupporter(SupportsFloat):
def__float__(self): ...
reveal_type(Floaty() ifbool() else0)
reveal_type(Supporter() ifbool() else0)The former is revealed as |
JukkaL
commented
Jul 27, 2018
@srittau Mypy works like by design, though it's clearly suboptimal in this case. It's not clear how this should be fixed in mypy. It's easy to imagine how this could work in simple cases, but a general solution seems difficult to define -- so that it's both practical and has the desired theoretical properties. Luckily the problems seem to arise pretty infrequently, and they can often be worked around by adding an explicit protocol base class. Can we add the base classes back? We should probably add a comment explaining why they are there so that they won't be removed again in the future. If you want to propose a mypy fix, I'm happy to discuss it. I've looked into this a bit but gave up as it didn't seem worth the effort at the time. |
srittau
commented
Jul 27, 2018
The problem I have with that is that it basically makes protocols useless, because the |
JukkaL
commented
Jul 30, 2018
This is the first time I've seen this cause problems, so it's a bit unfair to say that it makes protocols basically useless. I proposed a potential mypy improvement in python/mypy#5392 (comment), which could partially address the issue. |
srittau
commented
Jul 30, 2018
Well, useless in the sense that whenever someone comes up with a case where a protocol is used in an But just implementing the suggestion from typing/issues#564 would likely make this problem more pronounced. |
* Use Tuple field in DecimalTuple * Remove unnecessary base classes from Decimal * Decimal.__init__ -> __new__ * Decimal.__ne__ is not defined in Python 3 * Add Decimal.as_integer_ratio() * Annotate DecimalException.handle() * Correct types of Decimal method arguments * Add missing arguments and optional markers to Decimal * Add missing arguments to Context * Remove spurious int from Unions with float * Remove Context.__setattr__() * Fix return types of Context methods
Fix various problems with decimal and add missing annotations.