diff -r adbcba130143 Lib/functools.py --- a/Lib/functools.py Tue Mar 29 12:09:45 2011 -0700 +++ b/Lib/functools.py Sat Apr 02 22:32:39 2011 +0200 @@ -11,7 +11,7 @@ __all__ = ['update_wrapper', 'wraps', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES', 'total_ordering', 'cmp_to_key', 'lru_cache', 'reduce', 'partial'] -from _functools import partial, reduce +from _functools import partial, reduce, cmp_to_key from collections import OrderedDict, namedtuple try: from _thread import allocate_lock as Lock @@ -93,28 +93,6 @@ setattr(cls, opname, opfunc) return cls -def cmp_to_key(mycmp): - """Convert a cmp= function into a key= function""" - class K(object): - __slots__ = ['obj'] - def __init__(self, obj, *args): - self.obj = obj - def __lt__(self, other): - return mycmp(self.obj, other.obj) < 0 - def __gt__(self, other): - return mycmp(self.obj, other.obj) > 0 - def __eq__(self, other): - return mycmp(self.obj, other.obj) == 0 - def __le__(self, other): - return mycmp(self.obj, other.obj) <= 0 - def __ge__(self, other): - return mycmp(self.obj, other.obj) >= 0 - def __ne__(self, other): - return mycmp(self.obj, other.obj) != 0 - def __hash__(self): - raise TypeError('hash not implemented') - return K - _CacheInfo = namedtuple("CacheInfo", "hits misses maxsize currsize") def lru_cache(maxsize=100): diff -r adbcba130143 Modules/_functoolsmodule.c --- a/Modules/_functoolsmodule.c Tue Mar 29 12:09:45 2011 -0700 +++ b/Modules/_functoolsmodule.c Sat Apr 02 22:32:39 2011 +0200 @@ -330,6 +330,116 @@ }; +/* cmp_to_key ***************************************************************/ + +typedef struct { + PyObject_HEAD; + PyObject *cmp; + PyObject *object; +} keyobject; + +static void +keyobject_dealloc(keyobject *ko) +{ + PyObject_FREE(ko); +} + +static PyObject * +keyobject_call(keyobject *ko, PyObject *args, PyObject *kw); + +static PyObject * +keyobject_richcompare(PyObject *ko, PyObject *other, int op) +{ + if (!((keyobject *) ko)->object){ + PyErr_Format(PyExc_AttributeError, "object"); + return NULL; + } + PyObject *res = PyObject_CallFunction(((keyobject *) ko)->cmp, "OO", + ((keyobject *) ko)->object, other); + if (!res) + return NULL; + PyObject *zero = PyLong_FromLong(0); + if (!zero) + return NULL; + PyObject *bool = PyObject_RichCompare(res, zero, op); + if (!bool) + return NULL; + return bool; +} + +static PyMethodDef keyobject_methods[] = { + {NULL, NULL} /* sentinel */ +}; + +static PyTypeObject keyobject_type = { + PyVarObject_HEAD_INIT(NULL, 0) + "functools.K", /* tp_name */ + sizeof(keyobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)keyobject_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)keyobject_call, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + keyobject_richcompare, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + keyobject_methods, /* tp_methods */ + 0 +}; + +static PyObject * +keyobject_call(keyobject *ko, PyObject *args, PyObject *kw) +{ + PyObject *object; + keyobject *result; + + if (!PyArg_UnpackTuple(args, "", 1, 1, &object)) + return NULL; + result = PyObject_New(keyobject, &keyobject_type); + if (!result) + return NULL; + Py_INCREF(ko->cmp); + result->cmp = ko->cmp; + Py_INCREF(object); + result->object = object; + return (PyObject *) result; +} + +static PyObject * +functools_cmp_to_key(PyObject *self, PyObject *args){ + PyObject *cmp = NULL; + + if (!PyArg_UnpackTuple(args, "cmp_to_key", 1, 1, &cmp)) + return NULL; + keyobject *object = PyObject_New(keyobject, &keyobject_type); + if (!object) + return NULL; + object->cmp = cmp; + object->object = NULL; + Py_INCREF(cmp); + return (PyObject *) object; + +} +PyDoc_STRVAR(functools_cmp_to_key_doc, +"Convert a cmp= function into a key= function."); + /* reduce (used to be a builtin) ********************************************/ static PyObject * @@ -413,6 +523,7 @@ static PyMethodDef module_methods[] = { {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc}, + {"cmp_to_key", functools_cmp_to_key, METH_VARARGS, functools_cmp_to_key_doc}, {NULL, NULL} /* sentinel */ };