Skip to content

Commit c008a17

Browse files
committed
Issue python#1717, continued: remove PyObject_Compare and Py_CmpToRich declarations
from object.h; don't inherit tp_compare slot on subclasses; and raise TypeError when initializing a type that has a nonzero tp_compare slot. Fix up comparison-related comments in object.c and code.h.
1 parent f02e0aa commit c008a17

5 files changed

Lines changed: 24 additions & 38 deletions

File tree

Include/code.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ typedef struct {
2020
PyObject *co_varnames; /* tuple of strings (local variable names) */
2121
PyObject *co_freevars; /* tuple of strings (free variable names) */
2222
PyObject *co_cellvars; /* tuple of strings (cell variable names) */
23-
/* The rest doesn't count for hash/cmp */
23+
/* The rest doesn't count for hash or comparisons */
2424
PyObject *co_filename; /* unicode (where it was loaded from) */
2525
PyObject *co_name; /* unicode (name, for reference) */
2626
int co_firstlineno; /* first source line number */

Include/object.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,10 +426,8 @@ PyAPI_FUNC(PyObject *) PyObject_Repr(PyObject *);
426426
PyAPI_FUNC(PyObject *) PyObject_Str(PyObject *);
427427
PyAPI_FUNC(PyObject *) PyObject_ASCII(PyObject *);
428428
PyAPI_FUNC(PyObject *) PyObject_Bytes(PyObject *);
429-
PyAPI_FUNC(int) PyObject_Compare(PyObject *, PyObject *);
430429
PyAPI_FUNC(PyObject *) PyObject_RichCompare(PyObject *, PyObject *, int);
431430
PyAPI_FUNC(int) PyObject_RichCompareBool(PyObject *, PyObject *, int);
432-
PyAPI_FUNC(PyObject *) Py_CmpToRich(int op, int cmp);
433431
PyAPI_FUNC(PyObject *) PyObject_GetAttrString(PyObject *, const char *);
434432
PyAPI_FUNC(int) PyObject_SetAttrString(PyObject *, const char *, PyObject *);
435433
PyAPI_FUNC(int) PyObject_HasAttrString(PyObject *, const char *);

Misc/NEWS

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ What's New in Python 3.1 alpha 0
1212
Core and Builtins
1313
-----------------
1414

15-
- Issue #1717: Remove builtin cmp() function, C-API functions
16-
PyObject_Cmp and PyObject_Compare, and the support function
17-
Py_CmpToRich.
15+
- Issue #1717: Removed builtin cmp() function, dropped tp_compare
16+
slot, the C API functions PyObject_Compare and PyUnicode_Compare and
17+
the type definition cmpfunc. The tp_compare slot is reserved for
18+
future usage. An attempt to initialize a type with a nonzero
19+
tp_compare slot will raise TypeError.
1820

1921
- Issue #4707: round(x, n) now returns an integer if x is an integer.
2022
Previously it returned a float.

Objects/object.c

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -500,35 +500,19 @@ PyObject_Bytes(PyObject *v)
500500
return PyBytes_FromObject(v);
501501
}
502502

503-
/* The new comparison philosophy is: we completely separate three-way
504-
comparison from rich comparison. That is, PyObject_Compare() and
505-
PyObject_Cmp() *just* use the tp_compare slot. And PyObject_RichCompare()
506-
and PyObject_RichCompareBool() *just* use the tp_richcompare slot.
503+
/* For Python 3.0.1 and later, the old three-way comparison has been
504+
completely removed in favour of rich comparisons. PyObject_Compare() and
505+
PyObject_Cmp() are gone, and the builtin cmp function no longer exists.
506+
The old tp_compare slot will be renamed to tp_reserved, and should no
507+
longer be used. Use tp_richcompare instead.
507508
508509
See (*) below for practical amendments.
509510
510-
IOW, only cmp() uses tp_compare; the comparison operators (==, !=, <=, <,
511-
>=, >) only use tp_richcompare. Note that list.sort() only uses <.
511+
tp_richcompare gets called with a first argument of the appropriate type
512+
and a second object of an arbitrary type. We never do any kind of
513+
coercion.
512514
513-
(And yes, eventually we'll rip out cmp() and tp_compare.)
514-
515-
The calling conventions are different: tp_compare only gets called with two
516-
objects of the appropriate type; tp_richcompare gets called with a first
517-
argument of the appropriate type and a second object of an arbitrary type.
518-
We never do any kind of coercion.
519-
520-
The return conventions are also different.
521-
522-
The tp_compare slot should return a C int, as follows:
523-
524-
-1 if a < b or if an exception occurred
525-
0 if a == b
526-
+1 if a > b
527-
528-
No other return values are allowed. PyObject_Compare() has the same
529-
calling convention.
530-
531-
The tp_richcompare slot should return an object, as follows:
515+
The tp_richcompare slot should return an object, as follows:
532516
533517
NULL if an exception occurred
534518
NotImplemented if the requested comparison is not implemented
@@ -544,9 +528,6 @@ PyObject_Bytes(PyObject *v)
544528
comparing the object pointer (i.e. falling back to the base object
545529
implementation).
546530
547-
- If three-way comparison is not implemented, it falls back on rich
548-
comparison (but not the other way around!).
549-
550531
*/
551532

552533
/* Map rich comparison operators to their swapped version, e.g. LT <--> GT */

Objects/typeobject.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3662,20 +3662,18 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
36623662
type->tp_setattr = base->tp_setattr;
36633663
type->tp_setattro = base->tp_setattro;
36643664
}
3665-
/* tp_compare see tp_richcompare */
3665+
/* tp_compare is ignored, see tp_richcompare */
36663666
COPYSLOT(tp_repr);
36673667
/* tp_hash see tp_richcompare */
36683668
COPYSLOT(tp_call);
36693669
COPYSLOT(tp_str);
36703670
{
36713671
/* Copy comparison-related slots only when
36723672
not overriding them anywhere */
3673-
if (type->tp_compare == NULL &&
3674-
type->tp_richcompare == NULL &&
3673+
if (type->tp_richcompare == NULL &&
36753674
type->tp_hash == NULL &&
36763675
!overrides_hash(type))
36773676
{
3678-
type->tp_compare = base->tp_compare;
36793677
type->tp_richcompare = base->tp_richcompare;
36803678
type->tp_hash = base->tp_hash;
36813679
}
@@ -3888,6 +3886,13 @@ PyType_Ready(PyTypeObject *type)
38883886
goto error;
38893887
}
38903888

3889+
/* Check reserved slots */
3890+
if (type->tp_compare) {
3891+
PyErr_Format(PyExc_TypeError,
3892+
"type %s has tp_compare",
3893+
type->tp_name);
3894+
}
3895+
38913896
/* All done -- set the ready flag */
38923897
assert(type->tp_dict != NULL);
38933898
type->tp_flags =

0 commit comments

Comments
 (0)