Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
bdbad71b
Unverified
Kaydet (Commit)
bdbad71b
authored
Haz 01, 2019
tarafından
Serhiy Storchaka
Kaydeden (comit)
GitHub
Haz 01, 2019
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
bpo-20092. Use __index__ in constructors of int, float and complex. (GH-13108)
üst
1a4d9ffa
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
180 additions
and
22 deletions
+180
-22
complex.rst
Doc/c-api/complex.rst
+7
-1
float.rst
Doc/c-api/float.rst
+4
-0
functions.rst
Doc/library/functions.rst
+19
-2
datamodel.rst
Doc/reference/datamodel.rst
+3
-5
3.8.rst
Doc/whatsnew/3.8.rst
+10
-1
test_cmath.py
Lib/test/test_cmath.py
+3
-4
test_complex.py
Lib/test/test_complex.py
+18
-0
test_float.py
Lib/test/test_float.py
+15
-0
test_getargs2.py
Lib/test/test_getargs2.py
+6
-0
test_index.py
Lib/test/test_index.py
+1
-1
test_int.py
Lib/test/test_int.py
+59
-5
2019-05-31-11-55-49.bpo-20092.KIMjBW.rst
...ore and Builtins/2019-05-31-11-55-49.bpo-20092.KIMjBW.rst
+4
-0
abstract.c
Objects/abstract.c
+19
-0
complexobject.c
Objects/complexobject.c
+3
-3
floatobject.c
Objects/floatobject.c
+9
-0
No files found.
Doc/c-api/complex.rst
Dosyayı görüntüle @
bdbad71b
...
...
@@ -129,4 +129,10 @@ Complex Numbers as Python Objects
If *op* is not a Python complex number object but has a :meth:`__complex__`
method, this method will first be called to convert *op* to a Python complex
number object. Upon failure, this method returns ``-1.0`` as a real value.
number object. If ``__complex__()`` is not defined then it falls back to
:meth:`__float__`. If ``__float__()`` is not defined then it falls back
to :meth:`__index__`. Upon failure, this method returns ``-1.0`` as a real
value.
.. versionchanged:: 3.8
Use :meth:`__index__` if available.
Doc/c-api/float.rst
Dosyayı görüntüle @
bdbad71b
...
...
@@ -47,9 +47,13 @@ Floating Point Objects
Return a C :c:type:`double` representation of the contents of *pyfloat*. If
*pyfloat* is not a Python floating point object but has a :meth:`__float__`
method, this method will first be called to convert *pyfloat* into a float.
If ``__float__()`` is not defined then it falls back to :meth:`__index__`.
This method returns ``-1.0`` upon failure, so one should call
:c:func:`PyErr_Occurred` to check for errors.
.. versionchanged:: 3.8
Use :meth:`__index__` if available.
.. c:function:: double PyFloat_AS_DOUBLE(PyObject *pyfloat)
...
...
Doc/library/functions.rst
Dosyayı görüntüle @
bdbad71b
...
...
@@ -318,6 +318,11 @@ are always available. They are listed here in alphabetical order.
:class:`int` and :class:`float`. If both arguments are omitted, returns
``0j``.
For a general Python object ``x``, ``complex(x)`` delegates to
``x.__complex__()``. If ``__complex__()`` is not defined then it falls back
to :meth:`__float__`. If ``__float__()`` is not defined then it falls back
to :meth:`__index__`.
.. note::
When converting from a string, the string must not contain whitespace
...
...
@@ -330,6 +335,10 @@ are always available. They are listed here in alphabetical order.
.. versionchanged:: 3.6
Grouping digits with underscores as in code literals is allowed.
.. versionchanged:: 3.8
Falls back to :meth:`__index__` if :meth:`__complex__` and
:meth:`__float__` are not defined.
.. function:: delattr(object, name)
...
...
@@ -584,7 +593,8 @@ are always available. They are listed here in alphabetical order.
float, an :exc:`OverflowError` will be raised.
For a general Python object ``x``, ``float(x)`` delegates to
``x.__float__()``.
``x.__float__()``. If ``__float__()`` is not defined then it falls back
to :meth:`__index__`.
If no argument is given, ``0.0`` is returned.
...
...
@@ -609,6 +619,9 @@ are always available. They are listed here in alphabetical order.
.. versionchanged:: 3.7
*x* is now a positional-only parameter.
.. versionchanged:: 3.8
Falls back to :meth:`__index__` if :meth:`__float__` is not defined.
.. index::
single: __format__
...
...
@@ -780,7 +793,8 @@ are always available. They are listed here in alphabetical order.
Return an integer object constructed from a number or string *x*, or return
``0`` if no arguments are given. If *x* defines :meth:`__int__`,
``int(x)`` returns ``x.__int__()``. If *x* defines :meth:`__trunc__`,
``int(x)`` returns ``x.__int__()``. If *x* defines :meth:`__index__`,
it returns ``x.__index__()``. If *x* defines :meth:`__trunc__`,
it returns ``x.__trunc__()``.
For floating point numbers, this truncates towards zero.
...
...
@@ -812,6 +826,9 @@ are always available. They are listed here in alphabetical order.
.. versionchanged:: 3.7
*x* is now a positional-only parameter.
.. versionchanged:: 3.8
Falls back to :meth:`__index__` if :meth:`__int__` is not defined.
.. function:: isinstance(object, classinfo)
...
...
Doc/reference/datamodel.rst
Dosyayı görüntüle @
bdbad71b
...
...
@@ -2394,11 +2394,9 @@ left undefined.
functions). Presence of this method indicates that the numeric object is
an integer type. Must return an integer.
.. note::
In order to have a coherent integer type class, when :meth:`__index__` is
defined :meth:`__int__` should also be defined, and both should return
the same value.
If :meth:`__int__`, :meth:`__float__` and :meth:`__complex__` are not
defined then corresponding built-in functions :func:`int`, :func:`float`
and :func:`complex` fall back to :meth:`__index__`.
.. method:: object.__round__(self, [,ndigits])
...
...
Doc/whatsnew/3.8.rst
Dosyayı görüntüle @
bdbad71b
...
...
@@ -250,6 +250,12 @@ Other Language Changes
compatible with the existing :meth:`float.as_integer_ratio` method.
(Contributed by Lisa Roach in :issue:`33073`.)
* Constructors of :class:`int`, :class:`float` and :class:`complex` will now
use the :meth:`~object.__index__` special method, if available and the
corresponding method :meth:`~object.__int__`, :meth:`~object.__float__`
or :meth:`~object.__complex__` is not available.
(Contributed by Serhiy Storchaka in :issue:`20092`.)
* Added support of ``\N{name}`` escapes in :mod:`regular expressions <re>`.
(Contributed by Jonathan Eunice and Serhiy Storchaka in :issue:`30688`.)
...
...
@@ -868,7 +874,10 @@ Build and C API Changes
``__index__()`` method (like :class:`~decimal.Decimal` and
:class:`~fractions.Fraction`). :c:func:`PyNumber_Check` will now return
``1`` for objects implementing ``__index__()``.
(Contributed by Serhiy Storchaka in :issue:`36048`.)
:c:func:`PyNumber_Long`, :c:func:`PyNumber_Float` and
:c:func:`PyFloat_AsDouble` also now use the ``__index__()`` method if
available.
(Contributed by Serhiy Storchaka in :issue:`36048` and :issue:`20092`.)
* Heap-allocated type objects will now increase their reference count
in :c:func:`PyObject_Init` (and its parallel macro ``PyObject_INIT``)
...
...
Lib/test/test_cmath.py
Dosyayı görüntüle @
bdbad71b
...
...
@@ -220,12 +220,11 @@ class CMathTests(unittest.TestCase):
pass
class
NeitherComplexNorFloatOS
:
pass
class
MyInt
(
object
)
:
class
Index
:
def
__int__
(
self
):
return
2
def
__index__
(
self
):
return
2
class
MyInt
OS
:
class
MyInt
:
def
__int__
(
self
):
return
2
def
__index__
(
self
):
return
2
# other possible combinations of __float__ and __complex__
# that should work
...
...
@@ -255,6 +254,7 @@ class CMathTests(unittest.TestCase):
self
.
assertEqual
(
f
(
FloatAndComplexOS
()),
f
(
cx_arg
))
self
.
assertEqual
(
f
(
JustFloat
()),
f
(
flt_arg
))
self
.
assertEqual
(
f
(
JustFloatOS
()),
f
(
flt_arg
))
self
.
assertEqual
(
f
(
Index
()),
f
(
int
(
Index
())))
# TypeError should be raised for classes not providing
# either __complex__ or __float__, even if they provide
# __int__ or __index__. An old-style class
...
...
@@ -263,7 +263,6 @@ class CMathTests(unittest.TestCase):
self
.
assertRaises
(
TypeError
,
f
,
NeitherComplexNorFloat
())
self
.
assertRaises
(
TypeError
,
f
,
MyInt
())
self
.
assertRaises
(
Exception
,
f
,
NeitherComplexNorFloatOS
())
self
.
assertRaises
(
Exception
,
f
,
MyIntOS
())
# non-complex return value from __complex__ -> TypeError
for
bad_complex
in
non_complexes
:
self
.
assertRaises
(
TypeError
,
f
,
MyComplex
(
bad_complex
))
...
...
Lib/test/test_complex.py
Dosyayı görüntüle @
bdbad71b
...
...
@@ -368,6 +368,24 @@ class ComplexTest(unittest.TestCase):
self
.
assertAlmostEqual
(
complex
(
real
=
float2
(
17.
),
imag
=
float2
(
23.
)),
17
+
23
j
)
self
.
assertRaises
(
TypeError
,
complex
,
float2
(
None
))
class
MyIndex
:
def
__init__
(
self
,
value
):
self
.
value
=
value
def
__index__
(
self
):
return
self
.
value
self
.
assertAlmostEqual
(
complex
(
MyIndex
(
42
)),
42.0
+
0.0
j
)
self
.
assertAlmostEqual
(
complex
(
123
,
MyIndex
(
42
)),
123.0
+
42.0
j
)
self
.
assertRaises
(
OverflowError
,
complex
,
MyIndex
(
2
**
2000
))
self
.
assertRaises
(
OverflowError
,
complex
,
123
,
MyIndex
(
2
**
2000
))
class
MyInt
:
def
__int__
(
self
):
return
42
self
.
assertRaises
(
TypeError
,
complex
,
MyInt
())
self
.
assertRaises
(
TypeError
,
complex
,
123
,
MyInt
())
class
complex0
(
complex
):
"""Test usage of __complex__() when inheriting from 'complex'"""
def
__complex__
(
self
):
...
...
Lib/test/test_float.py
Dosyayı görüntüle @
bdbad71b
...
...
@@ -223,6 +223,21 @@ class GeneralFloatCases(unittest.TestCase):
with
self
.
assertWarns
(
DeprecationWarning
):
self
.
assertIs
(
type
(
FloatSubclass
(
F
())),
FloatSubclass
)
class
MyIndex
:
def
__init__
(
self
,
value
):
self
.
value
=
value
def
__index__
(
self
):
return
self
.
value
self
.
assertEqual
(
float
(
MyIndex
(
42
)),
42.0
)
self
.
assertRaises
(
OverflowError
,
float
,
MyIndex
(
2
**
2000
))
class
MyInt
:
def
__int__
(
self
):
return
42
self
.
assertRaises
(
TypeError
,
float
,
MyInt
())
def
test_keyword_args
(
self
):
with
self
.
assertRaisesRegex
(
TypeError
,
'keyword argument'
):
float
(
x
=
'3.14'
)
...
...
Lib/test/test_getargs2.py
Dosyayı görüntüle @
bdbad71b
...
...
@@ -457,6 +457,8 @@ class Float_TestCase(unittest.TestCase):
with
self
.
assertWarns
(
DeprecationWarning
):
self
.
assertEqual
(
getargs_f
(
BadFloat2
()),
4.25
)
self
.
assertEqual
(
getargs_f
(
BadFloat3
(
7.5
)),
7.5
)
self
.
assertEqual
(
getargs_f
(
Index
()),
99.0
)
self
.
assertRaises
(
TypeError
,
getargs_f
,
Int
())
for
x
in
(
FLT_MIN
,
-
FLT_MIN
,
FLT_MAX
,
-
FLT_MAX
,
INF
,
-
INF
):
self
.
assertEqual
(
getargs_f
(
x
),
x
)
...
...
@@ -489,6 +491,8 @@ class Float_TestCase(unittest.TestCase):
with
self
.
assertWarns
(
DeprecationWarning
):
self
.
assertEqual
(
getargs_d
(
BadFloat2
()),
4.25
)
self
.
assertEqual
(
getargs_d
(
BadFloat3
(
7.5
)),
7.5
)
self
.
assertEqual
(
getargs_d
(
Index
()),
99.0
)
self
.
assertRaises
(
TypeError
,
getargs_d
,
Int
())
for
x
in
(
DBL_MIN
,
-
DBL_MIN
,
DBL_MAX
,
-
DBL_MAX
,
INF
,
-
INF
):
self
.
assertEqual
(
getargs_d
(
x
),
x
)
...
...
@@ -511,6 +515,8 @@ class Float_TestCase(unittest.TestCase):
with
self
.
assertWarns
(
DeprecationWarning
):
self
.
assertEqual
(
getargs_D
(
BadComplex2
()),
4.25
+
0.5
j
)
self
.
assertEqual
(
getargs_D
(
BadComplex3
(
7.5
+
0.25
j
)),
7.5
+
0.25
j
)
self
.
assertEqual
(
getargs_D
(
Index
()),
99.0
+
0
j
)
self
.
assertRaises
(
TypeError
,
getargs_D
,
Int
())
for
x
in
(
DBL_MIN
,
-
DBL_MIN
,
DBL_MAX
,
-
DBL_MAX
,
INF
,
-
INF
):
c
=
complex
(
x
,
1.0
)
...
...
Lib/test/test_index.py
Dosyayı görüntüle @
bdbad71b
...
...
@@ -60,7 +60,7 @@ class BaseTestCase(unittest.TestCase):
# subclasses. See issue #17576.
class
MyInt
(
int
):
def
__index__
(
self
):
return
int
(
s
elf
)
+
1
return
int
(
s
tr
(
self
)
)
+
1
my_int
=
MyInt
(
7
)
direct_index
=
my_int
.
__index__
()
...
...
Lib/test/test_int.py
Dosyayı görüntüle @
bdbad71b
...
...
@@ -378,14 +378,22 @@ class IntTestCases(unittest.TestCase):
int
(
ExceptionalTrunc
())
for
trunc_result_base
in
(
object
,
Classic
):
class
In
tegral
(
trunc_result_base
):
def
__in
t
__
(
self
):
class
In
dex
(
trunc_result_base
):
def
__in
dex
__
(
self
):
return
42
class
TruncReturnsNonInt
(
base
):
def
__trunc__
(
self
):
return
Integral
()
with
self
.
assertWarns
(
DeprecationWarning
):
return
Index
()
self
.
assertEqual
(
int
(
TruncReturnsNonInt
()),
42
)
class
Intable
(
trunc_result_base
):
def
__int__
(
self
):
return
42
class
TruncReturnsNonIndex
(
base
):
def
__trunc__
(
self
):
return
Intable
()
self
.
assertEqual
(
int
(
TruncReturnsNonInt
()),
42
)
class
NonIntegral
(
trunc_result_base
):
...
...
@@ -418,6 +426,21 @@ class IntTestCases(unittest.TestCase):
with
self
.
assertRaises
(
TypeError
):
int
(
TruncReturnsBadInt
())
def
test_int_subclass_with_index
(
self
):
class
MyIndex
(
int
):
def
__index__
(
self
):
return
42
class
BadIndex
(
int
):
def
__index__
(
self
):
return
42.0
my_int
=
MyIndex
(
7
)
self
.
assertEqual
(
my_int
,
7
)
self
.
assertEqual
(
int
(
my_int
),
7
)
self
.
assertEqual
(
int
(
BadIndex
()),
0
)
def
test_int_subclass_with_int
(
self
):
class
MyInt
(
int
):
def
__int__
(
self
):
...
...
@@ -431,9 +454,19 @@ class IntTestCases(unittest.TestCase):
self
.
assertEqual
(
my_int
,
7
)
self
.
assertEqual
(
int
(
my_int
),
42
)
self
.
assertRaises
(
TypeError
,
int
,
BadInt
())
my_int
=
BadInt
(
7
)
self
.
assertEqual
(
my_int
,
7
)
self
.
assertRaises
(
TypeError
,
int
,
my_int
)
def
test_int_returns_int_subclass
(
self
):
class
BadIndex
:
def
__index__
(
self
):
return
True
class
BadIndex2
(
int
):
def
__index__
(
self
):
return
True
class
BadInt
:
def
__int__
(
self
):
return
True
...
...
@@ -442,6 +475,10 @@ class IntTestCases(unittest.TestCase):
def
__int__
(
self
):
return
True
class
TruncReturnsBadIndex
:
def
__trunc__
(
self
):
return
BadIndex
()
class
TruncReturnsBadInt
:
def
__trunc__
(
self
):
return
BadInt
()
...
...
@@ -450,6 +487,17 @@ class IntTestCases(unittest.TestCase):
def
__trunc__
(
self
):
return
True
bad_int
=
BadIndex
()
with
self
.
assertWarns
(
DeprecationWarning
):
n
=
int
(
bad_int
)
self
.
assertEqual
(
n
,
1
)
self
.
assertIs
(
type
(
n
),
int
)
bad_int
=
BadIndex2
()
n
=
int
(
bad_int
)
self
.
assertEqual
(
n
,
0
)
self
.
assertIs
(
type
(
n
),
int
)
bad_int
=
BadInt
()
with
self
.
assertWarns
(
DeprecationWarning
):
n
=
int
(
bad_int
)
...
...
@@ -462,6 +510,12 @@ class IntTestCases(unittest.TestCase):
self
.
assertEqual
(
n
,
1
)
self
.
assertIs
(
type
(
n
),
int
)
bad_int
=
TruncReturnsBadIndex
()
with
self
.
assertWarns
(
DeprecationWarning
):
n
=
int
(
bad_int
)
self
.
assertEqual
(
n
,
1
)
self
.
assertIs
(
type
(
n
),
int
)
bad_int
=
TruncReturnsBadInt
()
with
self
.
assertWarns
(
DeprecationWarning
):
n
=
int
(
bad_int
)
...
...
Misc/NEWS.d/next/Core and Builtins/2019-05-31-11-55-49.bpo-20092.KIMjBW.rst
0 → 100644
Dosyayı görüntüle @
bdbad71b
Constructors of :class:`int`, :class:`float` and :class:`complex` will now
use the :meth:`~object.__index__` special method, if available and the
corresponding method :meth:`~object.__int__`, :meth:`~object.__float__`
or :meth:`~object.__complex__` is not available.
Objects/abstract.c
Dosyayı görüntüle @
bdbad71b
...
...
@@ -1373,6 +1373,13 @@ PyNumber_Long(PyObject *o)
}
return
result
;
}
if
(
m
&&
m
->
nb_index
)
{
result
=
_PyLong_FromNbIndexOrNbInt
(
o
);
if
(
result
!=
NULL
&&
!
PyLong_CheckExact
(
result
))
{
Py_SETREF
(
result
,
_PyLong_Copy
((
PyLongObject
*
)
result
));
}
return
result
;
}
trunc_func
=
_PyObject_LookupSpecial
(
o
,
&
PyId___trunc__
);
if
(
trunc_func
)
{
result
=
_PyObject_CallNoArg
(
trunc_func
);
...
...
@@ -1480,6 +1487,18 @@ PyNumber_Float(PyObject *o)
Py_DECREF
(
res
);
return
PyFloat_FromDouble
(
val
);
}
if
(
m
&&
m
->
nb_index
)
{
PyObject
*
res
=
PyNumber_Index
(
o
);
if
(
!
res
)
{
return
NULL
;
}
double
val
=
PyLong_AsDouble
(
res
);
Py_DECREF
(
res
);
if
(
val
==
-
1
.
0
&&
PyErr_Occurred
())
{
return
NULL
;
}
return
PyFloat_FromDouble
(
val
);
}
if
(
PyFloat_Check
(
o
))
{
/* A float subclass with nb_float == NULL */
return
PyFloat_FromDouble
(
PyFloat_AS_DOUBLE
(
o
));
}
...
...
Objects/complexobject.c
Dosyayı görüntüle @
bdbad71b
...
...
@@ -984,7 +984,7 @@ complex_new_impl(PyTypeObject *type, PyObject *r, PyObject *i)
}
nbr
=
r
->
ob_type
->
tp_as_number
;
if
(
nbr
==
NULL
||
nbr
->
nb_float
==
NULL
)
{
if
(
nbr
==
NULL
||
(
nbr
->
nb_float
==
NULL
&&
nbr
->
nb_index
==
NULL
)
)
{
PyErr_Format
(
PyExc_TypeError
,
"complex() first argument must be a string or a number, "
"not '%.200s'"
,
...
...
@@ -996,7 +996,7 @@ complex_new_impl(PyTypeObject *type, PyObject *r, PyObject *i)
}
if
(
i
!=
NULL
)
{
nbi
=
i
->
ob_type
->
tp_as_number
;
if
(
nbi
==
NULL
||
nbi
->
nb_float
==
NULL
)
{
if
(
nbi
==
NULL
||
(
nbi
->
nb_float
==
NULL
&&
nbi
->
nb_index
==
NULL
)
)
{
PyErr_Format
(
PyExc_TypeError
,
"complex() second argument must be a number, "
"not '%.200s'"
,
...
...
@@ -1052,7 +1052,7 @@ complex_new_impl(PyTypeObject *type, PyObject *r, PyObject *i)
/* The "imag" part really is entirely imaginary, and
contributes nothing in the real direction.
Just treat it as a double. */
tmp
=
(
*
nbi
->
nb_float
)
(
i
);
tmp
=
PyNumber_Float
(
i
);
if
(
tmp
==
NULL
)
return
NULL
;
ci
.
real
=
PyFloat_AsDouble
(
tmp
);
...
...
Objects/floatobject.c
Dosyayı görüntüle @
bdbad71b
...
...
@@ -246,6 +246,15 @@ PyFloat_AsDouble(PyObject *op)
nb
=
Py_TYPE
(
op
)
->
tp_as_number
;
if
(
nb
==
NULL
||
nb
->
nb_float
==
NULL
)
{
if
(
nb
&&
nb
->
nb_index
)
{
PyObject
*
res
=
PyNumber_Index
(
op
);
if
(
!
res
)
{
return
-
1
;
}
double
val
=
PyLong_AsDouble
(
res
);
Py_DECREF
(
res
);
return
val
;
}
PyErr_Format
(
PyExc_TypeError
,
"must be real number, not %.50s"
,
op
->
ob_type
->
tp_name
);
return
-
1
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment