Slot wrappers#

A slot wrapper is installed in the dict of an extension type to access a special method implemented in C. For example, object.__init__ or Integer.__lt__. Note that slot wrappers are always unbound (there is a bound variant called method-wrapper).


sage: int.__add__
<slot wrapper '__add__' of 'int' objects>

Pure Python classes have normal methods, not slot wrappers:

sage: class X():
....:     def __add__(self, other):
....:         return NotImplemented
sage: X.__add__
<function X.__add__ at ...>
sage.cpython.wrapperdescr.wrapperdescr_call(slotwrapper, self, *args, **kwds)#

Call a slot wrapper without any type checks.

The main reason to use this is to call arithmetic slots like __mul__ without having to worry about whether to call T.__mul__(a, b) or T.__rmul__(b, a).


  • slotwrapper – a slot wrapper (for example int.__add__).

  • self – the first positional argument. Normally, this should be of the correct type (an int when calling int.__add__). However, this check is skipped: you can pass an arbitrary object.

  • *args, **kwds – further arguments.


Since this skips type checks, it can easily crash Python if used incorrectly.


sage: from sage.cpython.wrapperdescr import wrapperdescr_call
sage: wrapperdescr_call(Integer.__mul__, 6, 9)
sage: wrapperdescr_call(Integer.__mul__, 7/5, 9)
sage: from sage.structure.element import Element
sage: wrapperdescr_call(Element.__mul__, 6, 9)
sage: wrapperdescr_call(Element.__mul__, 7/5, 9)
sage: from sage.numerical.mip import MixedIntegerLinearProgram                  # needs sage.numerical.mip
sage: wrapperdescr_call(type.__call__,                                          # needs sage.numerical.mip
....:                   MixedIntegerLinearProgram, maximization=False)
Mixed Integer Program (no objective, 0 variables, 0 constraints)