Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" Metaclass for inheriting comparison functions
This module defines a metaclass :class:`InheritComparisonMetaclass` to inherit comparison functions in Cython extension types. In Python 2, the special methods ``__richcmp__``, ``__cmp__`` and ``__hash__`` are only inherited as a whole: defining just 1 or 2 of these will prevent the others from being inherited.
To solve this issue, you can use :class:`InheritComparisonMetaclass` as a Cython "metaclass" (see :mod:`sage.cpython.cython_metaclass` for the general mechanism). If you do this for an extension type which defines neither ``__richcmp__`` nor ``__cmp__``, then both these methods are inherited from the base class (the MRO is not used).
In Sage, this is in particular used for :class:`sage.structure.element.Element` to support comparisons using the coercion framework.
None of this is relevant to Python classes, which inherit comparison methods anyway.
AUTHOR:
- Jeroen Demeyer (2015-05-22): initial version, see :trac:`18329` """
#***************************************************************************** # Copyright (C) 2015 Jeroen Demeyer <jdemeyer@cage.ugent.be> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # http://www.gnu.org/licenses/ #*****************************************************************************
from cpython.object cimport PyTypeObject from sage.misc.classcall_metaclass cimport ClasscallMetaclass
cdef extern from "inherit_comparison_impl.c": void inherit_comparison(PyTypeObject* dst, PyTypeObject* src)
cdef class InheritComparisonMetaclass(type): """ If the type does not define ``__richcmp__`` nor ``__cmp__``, inherit both these methods from the base class. The difference with plain extension types is that comparison is inherited even if ``__hash__`` is defined.
EXAMPLES::
sage: cython(''' ....: from sage.misc.inherit_comparison cimport InheritComparisonMetaclass ....: ....: cdef class Base(object): ....: def __richcmp__(left, right, int op): ....: print("Calling Base.__richcmp__") ....: return left is right ....: ....: cdef class Derived(Base): ....: def __hash__(self): ....: return 1 ....: ....: cdef class DerivedWithRichcmp(Base): ....: def __getmetaclass__(_): ....: from sage.misc.inherit_comparison import InheritComparisonMetaclass ....: return InheritComparisonMetaclass ....: def __hash__(self): ....: return 1 ....: ''') sage: a = Derived() sage: a == a True sage: b = DerivedWithRichcmp() sage: b == b Calling Base.__richcmp__ True """ def __init__(self, *args):
class InheritComparisonClasscallMetaclass(ClasscallMetaclass, InheritComparisonMetaclass): """ Combine :class:`ClasscallMetaclass` with :class:`InheritComparisonMetaclass`.
TESTS::
sage: from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass as M sage: M.__new__(M, "myclass", (object,), {}) <class '__main__.myclass'> """ |