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
C implementation of Decimal.from_float() bypasses __new__ and __init__ #71193
Comments
Python implementation of Decimal.from_float() calls __new__ and __init__ methods of subclass. >>> from _pydecimal import Decimal
>>> class D(Decimal):
... def __new__(cls, *args, **kwargs):
... print('__new__')
... return Decimal.__new__(cls, *args, **kwargs)
... def __init__(self, *args, **kwargs):
... print('__init__')
...
>>> print(type(D.from_float(42)))
__new__
__init__
<class '__main__.D'>
>>> print(type(D.from_float(42.0)))
__new__
__init__
<class '__main__.D'> But C implementation doesn't. >>> from decimal import Decimal
>>> class D(Decimal):
... def __new__(cls, *args, **kwargs):
... print('__new__')
... return Decimal.__new__(cls, *args, **kwargs)
... def __init__(self, *args, **kwargs):
... print('__init__')
...
>>> print(type(D.from_float(42)))
<class '__main__.D'>
>>> print(type(D.from_float(42.0)))
<class '__main__.D'> This means that resulting instance of Decimal subclass can be in not valid state. Example is Decimal enums (see also bpo-23640). >>> from decimal import Decimal
>>> from enum import Enum
>>> class D(Decimal, Enum):
... A = Decimal('3.25')
...
>>> D(Decimal(3.25))
<D.A: Decimal('3.25')>
>>> D(3.25)
<D.A: Decimal('3.25')>
>>> D.from_float(3.25)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/serhiy/py/cpython/Lib/enum.py", line 486, in __repr__
self.__class__.__name__, self._name_, self._value_)
AttributeError: 'D' object has no attribute '_name_' A solution is to reproduce Python implementation in C code:
|
New changeset dd3f48f1df86 by Stefan Krah in branch '3.5': |
Thank you for the detailed summary! |
PyDec_CheckExact(type) always return 0. Should be PyDec_CheckExact(result). And what about other calls of PyDecType_FromFloatExact()? Can they produce broken instance of Decimal subtype? |
New changeset 51a7a97c3ed4 by Stefan Krah in branch '3.5': |
'result' is always an exact decimal, because your enum example won't work otherwise.
The PyDecType* functions handle calling the correct allocator, they don't handle calling __new__(). Why should they? The regular non-class-method enum examples worked. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: