Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cython
Commits
8a46a866
Commit
8a46a866
authored
7 years ago
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '0.27.x'
parents
f85ddd19
924599d6
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
189 additions
and
47 deletions
+189
-47
CHANGES.rst
CHANGES.rst
+3
-0
Cython/Compiler/TypeSlots.py
Cython/Compiler/TypeSlots.py
+1
-1
docs/src/reference/extension_types.rst
docs/src/reference/extension_types.rst
+4
-2
docs/src/userguide/special_methods.rst
docs/src/userguide/special_methods.rst
+36
-18
tests/run/ext_auto_richcmp.py
tests/run/ext_auto_richcmp.py
+145
-26
No files found.
CHANGES.rst
View file @
8a46a866
...
...
@@ -11,6 +11,9 @@ Bugs fixed
* Comprehensions could incorrectly be optimised away when they appeared in boolean
test contexts. (Github issue #1920)
* The special methods ``__eq__``, ``__lt__`` etc. in extension types did not type
their first argument as the type of the class but ``object``. (Github issue #1935)
* Crash on first lookup of "cline_in_traceback" option during exception handling.
(Github issue #1907)
...
...
This diff is collapsed.
Click to expand it.
Cython/Compiler/TypeSlots.py
View file @
8a46a866
...
...
@@ -576,7 +576,7 @@ def get_special_method_signature(name):
if
slot
:
return
slot
.
signature
elif
name
in
richcmp_special_methods
:
return
binaryfunc
return
i
binaryfunc
else
:
return
None
...
...
This diff is collapsed.
Click to expand it.
docs/src/reference/extension_types.rst
View file @
8a46a866
...
...
@@ -276,8 +276,10 @@ Arithmetic Methods
Rich Comparisons
================
* Starting with Cython 0.27, the Python special methods ``__eq__``, ``__lt__``, etc. can be implemented.
In previous versions, ``__richcmp__`` was the only way to implement rich comparisons.
* Starting with Cython 0.27, the Python
`special methods <https://docs.python.org/3/reference/datamodel.html#basic-customization>`_
``__eq__``, ``__lt__``, etc. can be implemented. In previous versions, ``__richcmp__`` was
the only way to implement rich comparisons.
* A single special method called ``__richcmp__()`` can be used to implement all the individual
rich compare, special method types.
* ``__richcmp__()`` takes an integer argument, indicating which operation is to be performed
...
...
This diff is collapsed.
Click to expand it.
docs/src/userguide/special_methods.rst
View file @
8a46a866
...
...
@@ -127,9 +127,11 @@ take `self` as the first argument.
Rich comparisons
-----------------
Starting with Cython 0.27, the Python special methods :meth:``__eq__``, :meth:``__lt__``, etc.
can be implemented. In previous versions, :meth:``__richcmp__`` was the only way to implement
rich comparisons. It takes an integer indicating which operation is to be performed, as follows:
Starting with Cython 0.27, the Python
`special methods <https://docs.python.org/3/reference/datamodel.html#basic-customization>`_
:meth:``__eq__``, :meth:``__lt__``, etc. can be implemented. In previous versions,
:meth:``__richcmp__`` was the only way to implement rich comparisons. It takes an integer
indicating which operation is to be performed, as follows:
+-----+-----+-------+
| < | 0 | Py_LT |
...
...
@@ -170,6 +172,8 @@ declare different types, conversions will be performed as necessary.
General
^^^^^^^
https://docs.python.org/3/reference/datamodel.html#special-method-names
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| Name | Parameters | Return type | Description |
+=======================+=======================================+=============+=====================================================+
...
...
@@ -203,25 +207,29 @@ General
Rich comparison operators
^^^^^^^^^^^^^^^^^^^^^^^^^
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| __richcmp__ |x, y, int op | object | Rich comparison (no direct Python equivalent) |
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| __eq__ |x, y | object | x == y |
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| __ne__ |x, y | object | x != y (falls back to ``__eq__`` if not available) |
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| __lt__ |x, y | object | x < y |
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| __gt__ |x, y | object | x > y |
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| __le__ |x, y | object | x <= y |
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| __ge__ |x, y | object | x >= y |
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
https://docs.python.org/3/reference/datamodel.html#basic-customization
+-----------------------+---------------------------------------+-------------+--------------------------------------------------------+
| __richcmp__ |x, y, int op | object | Rich comparison (no direct Python equivalent) |
+-----------------------+---------------------------------------+-------------+--------------------------------------------------------+
| __eq__ |self, y | object | self == y |
+-----------------------+---------------------------------------+-------------+--------------------------------------------------------+
| __ne__ |self, y | object | self != y (falls back to ``__eq__`` if not available) |
+-----------------------+---------------------------------------+-------------+--------------------------------------------------------+
| __lt__ |self, y | object | self < y |
+-----------------------+---------------------------------------+-------------+--------------------------------------------------------+
| __gt__ |self, y | object | self > y |
+-----------------------+---------------------------------------+-------------+--------------------------------------------------------+
| __le__ |self, y | object | self <= y |
+-----------------------+---------------------------------------+-------------+--------------------------------------------------------+
| __ge__ |self, y | object | self >= y |
+-----------------------+---------------------------------------+-------------+--------------------------------------------------------+
Arithmetic operators
^^^^^^^^^^^^^^^^^^^^
https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| Name | Parameters | Return type | Description |
+=======================+=======================================+=============+=====================================================+
...
...
@@ -267,6 +275,8 @@ Arithmetic operators
Numeric conversions
^^^^^^^^^^^^^^^^^^^
https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| Name | Parameters | Return type | Description |
+=======================+=======================================+=============+=====================================================+
...
...
@@ -286,6 +296,8 @@ Numeric conversions
In-place arithmetic operators
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| Name | Parameters | Return type | Description |
+=======================+=======================================+=============+=====================================================+
...
...
@@ -319,6 +331,8 @@ In-place arithmetic operators
Sequences and mappings
^^^^^^^^^^^^^^^^^^^^^^
https://docs.python.org/3/reference/datamodel.html#emulating-container-types
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| Name | Parameters | Return type | Description |
+=======================+=======================================+=============+=====================================================+
...
...
@@ -342,6 +356,8 @@ Sequences and mappings
Iterators
^^^^^^^^^
https://docs.python.org/3/reference/datamodel.html#emulating-container-types
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| Name | Parameters | Return type | Description |
+=======================+=======================================+=============+=====================================================+
...
...
@@ -377,6 +393,8 @@ Buffer interface [legacy] (no Python equivalents - see note 1)
Descriptor objects (see note 2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
https://docs.python.org/3/reference/datamodel.html#emulating-container-types
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| Name | Parameters | Return type | Description |
+=======================+=======================================+=============+=====================================================+
...
...
This diff is collapsed.
Click to expand it.
tests/run/ext_auto_richcmp.py
View file @
8a46a866
...
...
@@ -9,7 +9,7 @@ IS_PY2 = sys.version_info[0] == 2
@
cython
.
cclass
class
X
(
object
):
x
=
cython
.
declare
(
cython
.
int
,
visibility
=
"public"
)
x
=
cython
.
declare
(
cython
.
int
)
def
__init__
(
self
,
x
):
self
.
x
=
x
...
...
@@ -18,6 +18,12 @@ class X(object):
return
"<%d>"
%
self
.
x
@
cython
.
cfunc
@
cython
.
locals
(
x
=
X
)
def
x_of
(
x
):
return
x
.
x
@
cython
.
cclass
class
ClassEq
(
X
):
"""
...
...
@@ -74,9 +80,12 @@ class ClassEq(X):
TypeError...
"""
def
__eq__
(
self
,
other
):
if
isinstance
(
self
,
X
):
if
isinstance
(
other
,
X
):
return
self
.
x
==
other
.
x
assert
1
<=
self
.
x
<=
2
assert
isinstance
(
self
,
ClassEq
),
type
(
self
)
if
isinstance
(
other
,
X
):
return
self
.
x
==
x_of
(
other
)
elif
isinstance
(
other
,
int
):
return
self
.
x
<
other
return
NotImplemented
...
...
@@ -134,9 +143,12 @@ class ClassEqNe(ClassEq):
TypeError...
"""
def
__ne__
(
self
,
other
):
if
isinstance
(
self
,
X
):
if
isinstance
(
other
,
X
):
return
self
.
x
!=
other
.
x
assert
1
<=
self
.
x
<=
2
assert
isinstance
(
self
,
ClassEqNe
),
type
(
self
)
if
isinstance
(
other
,
X
):
return
self
.
x
!=
x_of
(
other
)
elif
isinstance
(
other
,
int
):
return
self
.
x
<
other
return
NotImplemented
...
...
@@ -208,11 +220,34 @@ class ClassEqNeGe(ClassEqNe):
... else: a > b
Traceback (most recent call last):
TypeError...
"""
>>> 2 <= a
False
>>> a >= 2
False
>>> 1 <= a
True
>>> a >= 1
True
>>> a >= 2
False
>>> if IS_PY2: raise TypeError # doctest: +ELLIPSIS
... else: 'x' <= a
Traceback (most recent call last):
TypeError...
>>> if IS_PY2: raise TypeError # doctest: +ELLIPSIS
... else: a >= 'x'
Traceback (most recent call last):
TypeError...
"""
def
__ge__
(
self
,
other
):
if
isinstance
(
self
,
X
):
if
isinstance
(
other
,
X
):
return
self
.
x
>=
other
.
x
assert
1
<=
self
.
x
<=
2
assert
isinstance
(
self
,
ClassEqNeGe
),
type
(
self
)
if
isinstance
(
other
,
X
):
return
self
.
x
>=
x_of
(
other
)
elif
isinstance
(
other
,
int
):
return
self
.
x
>=
other
return
NotImplemented
...
...
@@ -274,11 +309,34 @@ class ClassLe(X):
True
>>> b >= c
True
>>> 2 >= a
True
>>> a <= 2
True
>>> 1 >= a
True
>>> a <= 1
True
>>> a <= 0
False
>>> if IS_PY2: raise TypeError # doctest: +ELLIPSIS
... else: 'x' >= a
Traceback (most recent call last):
TypeError...
>>> if IS_PY2: raise TypeError # doctest: +ELLIPSIS
... else: a <= 'x'
Traceback (most recent call last):
TypeError...
"""
def
__le__
(
self
,
other
):
if
isinstance
(
self
,
X
):
if
isinstance
(
other
,
X
):
return
self
.
x
<=
other
.
x
assert
1
<=
self
.
x
<=
2
assert
isinstance
(
self
,
ClassLe
),
type
(
self
)
if
isinstance
(
other
,
X
):
return
self
.
x
<=
x_of
(
other
)
elif
isinstance
(
other
,
int
):
return
self
.
x
<=
other
return
NotImplemented
...
...
@@ -320,11 +378,37 @@ class ClassLt(X):
[<1>, <1>, <2>]
>>> sorted([b, a, c])
[<1>, <1>, <2>]
>>> 2 > a
True
>>> a < 2
True
>>> 1 > a
False
>>> a < 1
False
>>> if IS_PY2: raise TypeError # doctest: +ELLIPSIS
... else: 1 < a
Traceback (most recent call last):
TypeError...
>>> if IS_PY2: raise TypeError # doctest: +ELLIPSIS
... else: 'x' > a
Traceback (most recent call last):
TypeError...
>>> if IS_PY2: raise TypeError # doctest: +ELLIPSIS
... else: a < 'x'
Traceback (most recent call last):
TypeError...
"""
def
__lt__
(
self
,
other
):
if
isinstance
(
self
,
X
):
if
isinstance
(
other
,
X
):
return
self
.
x
<
other
.
x
assert
1
<=
self
.
x
<=
2
assert
isinstance
(
self
,
ClassLt
),
type
(
self
)
if
isinstance
(
other
,
X
):
return
self
.
x
<
x_of
(
other
)
elif
isinstance
(
other
,
int
):
return
self
.
x
<
other
return
NotImplemented
...
...
@@ -368,9 +452,12 @@ class ClassLtGtInherited(X):
[<1>, <1>, <2>]
"""
def
__gt__
(
self
,
other
):
if
isinstance
(
self
,
X
):
if
isinstance
(
other
,
X
):
return
self
.
x
>
other
.
x
assert
1
<=
self
.
x
<=
2
assert
isinstance
(
self
,
ClassLtGtInherited
),
type
(
self
)
if
isinstance
(
other
,
X
):
return
self
.
x
>
x_of
(
other
)
elif
isinstance
(
other
,
int
):
return
self
.
x
>
other
return
NotImplemented
...
...
@@ -412,17 +499,49 @@ class ClassLtGt(X):
[<1>, <1>, <2>]
>>> sorted([b, a, c])
[<1>, <1>, <2>]
>>> 2 > a
True
>>> 2 < a
False
>>> a < 2
True
>>> a > 2
False
>>> if IS_PY2: raise TypeError # doctest: +ELLIPSIS
... else: 'x' > a
Traceback (most recent call last):
TypeError...
>>> if IS_PY2: raise TypeError # doctest: +ELLIPSIS
... else: 'x' < a
Traceback (most recent call last):
TypeError...
>>> if IS_PY2: raise TypeError # doctest: +ELLIPSIS
... else: a < 'x'
Traceback (most recent call last):
TypeError...
>>> if IS_PY2: raise TypeError # doctest: +ELLIPSIS
... else: a > 'x'
Traceback (most recent call last):
TypeError...
"""
def
__lt__
(
self
,
other
):
if
isinstance
(
self
,
X
):
if
isinstance
(
other
,
X
):
return
self
.
x
<
other
.
x
assert
1
<=
self
.
x
<=
2
assert
isinstance
(
self
,
ClassLtGt
),
type
(
self
)
if
isinstance
(
other
,
X
):
return
self
.
x
<
x_of
(
other
)
elif
isinstance
(
other
,
int
):
return
self
.
x
<
other
return
NotImplemented
def
__gt__
(
self
,
other
):
if
isinstance
(
self
,
X
):
if
isinstance
(
other
,
X
):
return
self
.
x
>
other
.
x
assert
1
<=
self
.
x
<=
2
assert
isinstance
(
self
,
ClassLtGt
),
type
(
self
)
if
isinstance
(
other
,
X
):
return
self
.
x
>
x_of
(
other
)
elif
isinstance
(
other
,
int
):
return
self
.
x
>
other
return
NotImplemented
...
...
This diff is collapsed.
Click to expand it.
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