-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtpl_magic_methods.mako
More file actions
166 lines (149 loc) · 9.56 KB
/
tpl_magic_methods.mako
File metadata and controls
166 lines (149 loc) · 9.56 KB
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# ----
# This file is generated by mini_lambda_methods_generation.py - do not modify it !
# ----
try: # python 3.5+
from typing import Any
except ImportError:
pass
from math import trunc
from mini_lambda.base import _LambdaExpressionBase, evaluate, get_repr, FunctionDefinitionError, \
_get_root_var
from mini_lambda.base import _PRECEDENCE_ADD_SUB, _PRECEDENCE_MUL_DIV_ETC, _PRECEDENCE_COMPARISON, \
_PRECEDENCE_EXPONENTIATION, _PRECEDENCE_SHIFTS, _PRECEDENCE_POS_NEG_BITWISE_NOT, \
_PRECEDENCE_SUBSCRIPTION_SLICING_CALL_ATTRREF
class _LambdaExpressionGenerated(_LambdaExpressionBase):
"""
This generated class implements a bunch of magic methods, so that calling these magic methods on an object will
result in adding that magic method to the _LambdaExpressionBase's stack.
This allows for example x[1] to return a new _LambdaExpressionGenerated whose stack is able to call [1] (getitem(1))
on the result of the current stack's evaluation
The methods added below belong to two categories
* All magic methods that 'just' need to be implemented (for example __add__), or remapped to the original method
calling them because on some built-in data types the magic method does not exist (for example, __getattr__ should
not add __getattr__ to the stack but getattr)
* All magic methods that do not work because the python framework does not allow them to return another type than
the expected one. For all of them there are two methods: one in the class throwing an exception, and one at
package-level to provide a replacement (The exception message provides the replacement method name).
"""
# ******* All magic methods that need to be implemented ********
## For each method to override
% for o in to_override:
% if o.uni_operator:
## ----------unitary operator such as '-'-------------------
def ${o.method_name}(self):
""" Returns a new LambdaExpression performing '${o.uni_operator}<r>' on the result <r> of this evaluator's evaluation """
## def _${o.method_name}(r, input):
## return ${o.uni_operator}r
## return self.add_unbound_method_to_stack(_${o.method_name})
def _${o.method_name}(input):
# first evaluate the inner function
res = self.evaluate(input)
# then call the method
return ${o.uni_operator}res
# return a new LambdaExpression of the same type than self, with the new function as inner function
string_expr = '${o.uni_operator}' + get_repr(self, ${o.precedence_level})
return type(self)(fun=_${o.method_name}, precedence_level=${o.precedence_level}, str_expr=string_expr, root_var=self._root_var, repr_on=self.repr_on)
## -----------------------------
% elif o.pair_operator:
% if o.is_operator_left:
## --------pairwise operator - left---------------------
def ${o.method_name}(self, other):
""" Returns a new LambdaExpression performing '<r> ${o.pair_operator} other' on the result <r> of this evaluator's evaluation """
## def _${o.method_name}(r, input):
## return r ${o.pair_operator} evaluate(other, input)
## return self.add_unbound_method_to_stack(_${o.method_name})
root_var, _ = _get_root_var(self, other)
def _${o.method_name}(input):
# first evaluate the inner function
r = self.evaluate(input)
# then call the method
return r ${o.pair_operator} evaluate(other, input)
# return a new LambdaExpression of the same type than self, with the new function as inner function
string_expr = get_repr(self, ${o.precedence_level}) + ' ${o.pair_operator} ' + get_repr(other, ${o.precedence_level})
return type(self)(fun=_${o.method_name}, precedence_level=${o.precedence_level}, str_expr=string_expr,
root_var=root_var, repr_on=self.repr_on)
## -----------------------------
% else:
## --------pairwise operator - right ---------------------
def ${o.method_name}(self, other):
""" Returns a new LambdaExpression performing 'other ${o.pair_operator} <r>' on the result <r> of this evaluator's evaluation """
## def _${o.method_name}(r, input):
## return evaluate(other, input) ${o.pair_operator} r
## return self.add_unbound_method_to_stack(_${o.method_name})
root_var, _ = _get_root_var(self, other)
def _${o.method_name}(input):
# first evaluate the inner function
r = self.evaluate(input)
# then call the method
return evaluate(other, input) ${o.pair_operator} r
# return a new LambdaExpression of the same type than self, with the new function as inner function
string_expr = get_repr(other, ${o.precedence_level}) + ' ${o.pair_operator} ' + get_repr(self, ${o.precedence_level})
return type(self)(fun=_${o.method_name}, precedence_level=${o.precedence_level}, str_expr=string_expr,
root_var=root_var, repr_on=self.repr_on)
## -----------------------------
% endif
% elif o.unbound_method:
## --------unbound method---------------------
def ${o.method_name}(self, *args, **kwargs):
""" Returns a new LambdaExpression performing '${o.unbound_method.__name__}(<r>, *args, **kwargs)' on the result <r> of this evaluator's evaluation """
## def _${o.method_name}(r, input, *args, **kwargs):
## return ${o.unbound_method.__name__}(r, input, *args, **kwargs)
## return self.add_unbound_method_to_stack(_${o.method_name}, *args, **kwargs)
root_var, _ = _get_root_var(self, *args, **kwargs)
def _${o.method_name}(input):
# first evaluate the inner function
r = self.evaluate(input)
# then call the method
return ${o.unbound_method.__name__}(r, *[evaluate(other, input) for other in args],
**{arg_name: evaluate(other, input) for arg_name, other in kwargs.items()})
# return a new LambdaExpression of the same type than self, with the new function as inner function
# Note: we use precedence=None for coma-separated items inside the parenthesis
string_expr = ('${o.unbound_method.__name__}(' + get_repr(self, None)
+ (', ' if (len(args) > 0 and len(kwargs) > 0) else '')
+ ', '.join([get_repr(arg, None) for arg in args])
+ ', '.join([arg_name + '=' + get_repr(arg, None) for arg_name, arg in kwargs.items()])
+ ')')
return type(self)(fun=_${o.method_name}, precedence_level=_PRECEDENCE_SUBSCRIPTION_SLICING_CALL_ATTRREF,
str_expr=string_expr, root_var=root_var, repr_on=self.repr_on)
## -----------------------------
% else:
## --------general case---------------------
def ${o.method_name}(self, *args, **kwargs):
""" Returns a new LambdaExpression performing '<r>.${o.method_name}(*args, **kwargs)' on the result <r> of this evaluator's evaluation """
# return self.add_bound_method_to_stack('${o.method_name}', *args, **kwargs)
root_var, _ = _get_root_var(self, *args, **kwargs)
def _${o.method_name}(input):
# first evaluate the inner function
r = self.evaluate(input)
# then call the method
return r.${o.method_name}(*[evaluate(other, input) for other in args],
**{arg_name: evaluate(other, input) for arg_name, other in kwargs.items()})
# return a new LambdaExpression of the same type than self, with the new function as inner function
# Note: we use precedence=None for coma-separated items inside the parenthesis
string_expr = get_repr(self, _PRECEDENCE_SUBSCRIPTION_SLICING_CALL_ATTRREF) + '.${o.method_name}(' \
+ ', '.join([get_repr(arg, None) for arg in args]) \
+ (', ' if (len(args) > 0 and len(kwargs) > 0) else '') \
+ ', '.join([arg_name + '=' + get_repr(arg, None) for arg_name, arg in kwargs.items()]) \
+ ')'
return type(self)(fun=_${o.method_name}, precedence_level=_PRECEDENCE_SUBSCRIPTION_SLICING_CALL_ATTRREF,
str_expr=string_expr, root_var=root_var, repr_on=self.repr_on)
## -----------------------------
% endif
% endfor
# ******* All magic methods that need to raise an exception ********
## For each method to override
% for o in to_override_with_exception:
def ${o.method_name}(self, *args, **kwargs):
"""
This magic method can not be used on an LambdaExpression, because unfortunately python checks the
result type and does not allow it to be a custom type.
"""
raise FunctionDefinitionError('${o.method_name} is not supported by mini-lambda expressions, since python '
'raises an'
' error when its output is not directly an object of the type it expects.'
'Please use the ${o.module_method_name}() method provided at mini_lambda package'
' level instead. If you did not use ${o.method_name} in your expression, you '
'probably used a standard method such as math.log(x) instead of a method '
' converted to mini_lambda such as Log(x). Please check the documentation for '
'details.')
% endfor