Hide keyboard shortcuts

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

""" 

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). 

  

EXAMPLES:: 

  

sage: int.__add__ 

<slot wrapper '__add__' of 'int' objects> 

  

Pure Python classes have normal methods, not slot wrappers:: 

  

sage: class X(object): 

....: def __add__(self, other): 

....: return NotImplemented 

sage: X.__add__ 

<unbound method X.__add__> 

""" 

  

#***************************************************************************** 

# Copyright (C) 2017 Jeroen Demeyer <J.Demeyer@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 .string import bytes_to_str 

  

  

def 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)``. 

  

INPUT: 

  

- ``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. 

  

.. WARNING:: 

  

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

used incorrectly. 

  

EXAMPLES:: 

  

sage: from sage.cpython.wrapperdescr import wrapperdescr_call 

sage: wrapperdescr_call(Integer.__mul__, 6, 9) 

54 

sage: wrapperdescr_call(Integer.__mul__, 7/5, 9) 

63/5 

sage: from sage.structure.element import Element 

sage: wrapperdescr_call(Element.__mul__, 6, 9) 

54 

sage: wrapperdescr_call(Element.__mul__, 7/5, 9) 

63/5 

sage: from sage.numerical.mip import MixedIntegerLinearProgram 

sage: wrapperdescr_call(type.__call__, MixedIntegerLinearProgram, maximization=False) 

Mixed Integer Program (no objective, 0 variables, 0 constraints) 

  

TESTS:: 

  

sage: wrapperdescr_call(Integer.__mul__, 1, 2, 3) 

Traceback (most recent call last): 

... 

TypeError: expected 1 arguments, got 2 

sage: wrapperdescr_call(Integer.__mul__, 6, other=9) 

Traceback (most recent call last): 

... 

TypeError: wrapper __mul__ slotdef doesn't take keyword arguments 

""" 

return wrapperdescr_fastcall(slotwrapper, self, args, kwds) 

  

  

cdef wrapperdescr_fastcall(wrapper_descriptor slotwrapper, self, args, kwds): 

# Cython implementation of wrapperdescr_call 

cdef wrapperbase* slotdef = slotwrapper.d_base 

  

cdef wrapperfunc_kwds wk 

if slotdef.flags & PyWrapperFlag_KEYWORDS: 

wk = <wrapperfunc_kwds>(slotdef.wrapper) 

return wk(self, args, slotwrapper.d_wrapped, kwds) 

  

if <PyObject*>kwds is not NULL and kwds: 

raise TypeError(f"wrapper {bytes_to_str(slotdef.name)} slotdef " 

"doesn't take keyword arguments") 

  

return slotdef.wrapper(self, args, slotwrapper.d_wrapped)