1+ from inspect import isclass
12from sys import getsizeof
2- from typing import Tuple , Set , Optional , Any
3+ from typing import Tuple , Set , Optional , Any , List
34
45import os
6+ import math
57
68# from quik import Template
9+ import decimal
710from mako import exceptions
811from mako .template import Template
912
1013# from sortedcontainers import SortedSet
1114from ordered_set import OrderedSet
1215
13- from autoclass import autoclass
16+ from autoclass import autoclass , getmembers
1417from enforce import runtime_validation
1518
1619
@@ -27,7 +30,7 @@ def __init__(self, method_name: str,
2730 """
2831 A descriptor for a method to override in _InputEvaluatorGenerated.
2932 * If only method_name is provided, the overriden method adds itself to the stack
30- (see StackableFunctionEvaluator )
33+ (see _LambdaExpressionBase )
3134 * If unbound_method is provided, the overriden method adds the provided unbound method to the stack
3235 * If operator and is_operator_left are provided, the overriden method adds a method performing
3336 (args <operator> x) if is_operator_left=False or (x <operator> args) if is_operator_left=True.
@@ -70,7 +73,7 @@ def __init__(self, method_name: str,
7073 replacement method needs to be provided.
7174
7275 The method_name will raise an exception and indicate that module_method_name is the replacement method. The
73- latter will implement by adding method_name to the stack (see StackableFunctionEvaluator ). If unbound_method is
76+ latter will implement by adding method_name to the stack (see _LambdaExpressionBase ). If unbound_method is
7477 provided, the module method will add unbound_method to the stack instead of method_name.
7578
7679 By default module_method_name is equal to a capitalized, underscores-removed, version of the method name.
@@ -90,36 +93,79 @@ def __str__(self):
9093 return 'Exception {} replaced by module method {}' .format (self .method_name , self .module_method_name )
9194
9295
96+ @runtime_validation
97+ @autoclass
98+ class Goodie :
99+ def __init__ (self , item_name : str , function_name : Optional [str ] = None ,
100+ constant_name : Optional [str ] = None , class_name : Optional [str ] = None ):
101+ pass
102+
103+ def __str__ (self ):
104+ if self .function_name :
105+ return 'Function {} replaced with {}' .format (self .function_name , self .item_name )
106+ elif self .constant_name :
107+ return 'Constant {} replaced with {}' .format (self .constant_name , self .item_name )
108+ else :
109+ return 'Class {} replaced with {}' .format (self .class_name , self .item_name )
110+
111+
93112def generate_code ():
94113 """
95114 This method reads the template file, fills it with the appropriate contents, and writes the result in the
96115 mini_lambda_generated.py file. All contents of the destination file are overriden by this operation.
97116 :return:
98117 """
99118
100- # generate the to-do list
119+ # (1) generate the to-do list for the first template
101120 to_override , to_override_with_exception = define_what_needs_to_be_written ()
121+
102122 # check outside of the template that it works:
103123 for o in to_override :
104124 print (o )
105125 for o in to_override_with_exception :
106126 print (o )
107127
128+ # generate
129+ generate_from_template ('mini_lambda_template.mako' , 'generated.py' ,
130+ dict (to_override = to_override , to_override_with_exception = to_override_with_exception ))
131+
132+ # (2) to-do list for the second template
133+ import_lines , to_create = define_goodies ()
134+
135+ # check outside of the template that it works:
136+ for o in import_lines :
137+ print (o )
138+ for o in to_create :
139+ print (o )
140+
141+ # generate
142+ generate_from_template ('goodies_template.mako' , 'goodies_generated.py' ,
143+ dict (import_lines = import_lines , to_create = to_create ))
144+
145+
146+ def generate_from_template (src_file , dst_file , template_vars ):
147+ """
148+ Routine to open a source template file, load the variables inside and dump the result in the destination file
149+
150+ :param dst_file:
151+ :param src_file:
152+ :param template_vars:
153+ :return:
154+ """
108155 # open the mako template file
109156 THIS_DIR = os .path .dirname (__file__ )
110- template_file = os .path .join (THIS_DIR , 'mini_lambda_template.mako' )
157+ template_file = os .path .join (THIS_DIR , src_file )
111158 with open (template_file ) as f :
112159 body = f .read ()
113-
114160 try :
115161 # create the template
116162 temp = Template (text = body ) # , module_directory=os.path.join(THIS_DIR, 'tmp'))
117163
118164 # fill it with the variables contents
119- res = temp .render (to_override = to_override , to_override_with_exception = to_override_with_exception )
165+ res = temp .render (** template_vars )
120166
121167 # write the result to the destination file
122- dest_file = os .path .join (THIS_DIR , os .pardir , 'mini_lambda' , 'generated.py' )
168+ dest_file = os .path .join (THIS_DIR , os .pardir , 'mini_lambda' , dst_file )
123169 with open (dest_file , 'wt' ) as f :
124170 f .write (res )
125171 except :
@@ -177,18 +223,19 @@ def define_what_needs_to_be_written() -> Tuple[Set[Override], Set[OverExc]]:
177223 to_override_with_exception .add (OverExc ('__str__' , unbound_method = str ))
178224 to_override_with_exception .add (OverExc ('__repr__' , unbound_method = repr ))
179225 to_override_with_exception .add (OverExc ('__bytes__' , unbound_method = bytes ))
226+ # this is a special case
180227 to_override_with_exception .add (OverExc ('__format__' , unbound_method = format ))
181228 to_override_with_exception .add (OverExc ('__sizeof__' , unbound_method = getsizeof ))
182229
183230 # ** Comparable Objects **
184231 # .__lt__, .__le__, .__eq__, .__ne__, .__gt__, .__ge__
185232 # to_override.update(__get_all_magic_methods(Set))
186- to_override .add (Override ('__lt__' , pair_operator = '<' , precedence_level = 'PRECEDENCE_COMPARISON ' ))
187- to_override .add (Override ('__le__' , pair_operator = '<=' , precedence_level = 'PRECEDENCE_COMPARISON ' ))
188- to_override .add (Override ('__eq__' , pair_operator = '==' , precedence_level = 'PRECEDENCE_COMPARISON ' ))
189- to_override .add (Override ('__ne__' , pair_operator = '!=' , precedence_level = 'PRECEDENCE_COMPARISON ' ))
190- to_override .add (Override ('__gt__' , pair_operator = '>' , precedence_level = 'PRECEDENCE_COMPARISON ' ))
191- to_override .add (Override ('__ge__' , pair_operator = '>=' , precedence_level = 'PRECEDENCE_COMPARISON ' ))
233+ to_override .add (Override ('__lt__' , pair_operator = '<' , precedence_level = '_PRECEDENCE_COMPARISON ' ))
234+ to_override .add (Override ('__le__' , pair_operator = '<=' , precedence_level = '_PRECEDENCE_COMPARISON ' ))
235+ to_override .add (Override ('__eq__' , pair_operator = '==' , precedence_level = '_PRECEDENCE_COMPARISON ' ))
236+ to_override .add (Override ('__ne__' , pair_operator = '!=' , precedence_level = '_PRECEDENCE_COMPARISON ' ))
237+ to_override .add (Override ('__gt__' , pair_operator = '>' , precedence_level = '_PRECEDENCE_COMPARISON ' ))
238+ to_override .add (Override ('__ge__' , pair_operator = '>=' , precedence_level = '_PRECEDENCE_COMPARISON ' ))
192239
193240 # ** Hashable Object **
194241 # .__hash__
@@ -255,34 +302,35 @@ def define_what_needs_to_be_written() -> Tuple[Set[Override], Set[OverExc]]:
255302 # .__lshift__, .__rshift__, __rlshift__, __rrshift__
256303 # .__neg__, .__pos__, .__abs__, .__invert__
257304 # to_override.update(__get_all_magic_methods(Integral))
258- to_override .add (Override ('__add__' , pair_operator = '+' , precedence_level = 'PRECEDENCE_ADD_SUB ' ))
259- to_override .add (Override ('__radd__' , pair_operator = '+' , is_operator_left = False , precedence_level = 'PRECEDENCE_ADD_SUB ' ))
260- to_override .add (Override ('__sub__' , pair_operator = '-' , precedence_level = 'PRECEDENCE_ADD_SUB ' ))
261- to_override .add (Override ('__rsub__' , pair_operator = '-' , is_operator_left = False , precedence_level = 'PRECEDENCE_ADD_SUB ' ))
262- to_override .add (Override ('__mul__' , pair_operator = '*' , precedence_level = 'PRECEDENCE_MUL_DIV_ETC ' ))
263- to_override .add (Override ('__rmul__' , pair_operator = '*' , is_operator_left = False , precedence_level = 'PRECEDENCE_MUL_DIV_ETC ' ))
264- to_override .add (Override ('__truediv__' , pair_operator = '/' , precedence_level = 'PRECEDENCE_MUL_DIV_ETC ' ))
265- to_override .add (Override ('__rtruediv__' , pair_operator = '/' , is_operator_left = False , precedence_level = 'PRECEDENCE_MUL_DIV_ETC ' ))
266- to_override .add (Override ('__mod__' , pair_operator = '%' , precedence_level = 'PRECEDENCE_MUL_DIV_ETC ' ))
267- to_override .add (Override ('__rmod__' , pair_operator = '%' , is_operator_left = False , precedence_level = 'PRECEDENCE_MUL_DIV_ETC ' ))
305+ to_override .add (Override ('__add__' , pair_operator = '+' , precedence_level = '_PRECEDENCE_ADD_SUB ' ))
306+ to_override .add (Override ('__radd__' , pair_operator = '+' , is_operator_left = False , precedence_level = '_PRECEDENCE_ADD_SUB ' ))
307+ to_override .add (Override ('__sub__' , pair_operator = '-' , precedence_level = '_PRECEDENCE_ADD_SUB ' ))
308+ to_override .add (Override ('__rsub__' , pair_operator = '-' , is_operator_left = False , precedence_level = '_PRECEDENCE_ADD_SUB ' ))
309+ to_override .add (Override ('__mul__' , pair_operator = '*' , precedence_level = '_PRECEDENCE_MUL_DIV_ETC ' ))
310+ to_override .add (Override ('__rmul__' , pair_operator = '*' , is_operator_left = False , precedence_level = '_PRECEDENCE_MUL_DIV_ETC ' ))
311+ to_override .add (Override ('__truediv__' , pair_operator = '/' , precedence_level = '_PRECEDENCE_MUL_DIV_ETC ' ))
312+ to_override .add (Override ('__rtruediv__' , pair_operator = '/' , is_operator_left = False , precedence_level = '_PRECEDENCE_MUL_DIV_ETC ' ))
313+ to_override .add (Override ('__mod__' , pair_operator = '%' , precedence_level = '_PRECEDENCE_MUL_DIV_ETC ' ))
314+ to_override .add (Override ('__rmod__' , pair_operator = '%' , is_operator_left = False , precedence_level = '_PRECEDENCE_MUL_DIV_ETC ' ))
268315 to_override .add (Override ('__divmod__' ))
269316 to_override .add (Override ('__rdivmod__' ))
270- to_override .add (Override ('__pow__' , pair_operator = '**' , precedence_level = 'PRECEDENCE_EXPONENTIATION ' ))
271- to_override .add (Override ('__rpow__' , pair_operator = '**' , is_operator_left = False , precedence_level = 'PRECEDENCE_EXPONENTIATION ' ))
272- to_override .add (Override ('__matmul__' , pair_operator = '@' , precedence_level = 'PRECEDENCE_MUL_DIV_ETC ' ))
317+ to_override .add (Override ('__pow__' , pair_operator = '**' , precedence_level = '_PRECEDENCE_EXPONENTIATION ' ))
318+ to_override .add (Override ('__rpow__' , pair_operator = '**' , is_operator_left = False , precedence_level = '_PRECEDENCE_EXPONENTIATION ' ))
319+ to_override .add (Override ('__matmul__' , pair_operator = '@' , precedence_level = '_PRECEDENCE_MUL_DIV_ETC ' ))
273320 # Override('__rmatmul__', operator='@', is_operator_left=False),
274- to_override .add (Override ('__floordiv__' , pair_operator = '//' , precedence_level = 'PRECEDENCE_MUL_DIV_ETC ' ))
275- to_override .add (Override ('__rfloordiv__' , pair_operator = '//' , is_operator_left = False , precedence_level = 'PRECEDENCE_MUL_DIV_ETC ' ))
276- to_override .add (Override ('__lshift__' , pair_operator = '<<' , precedence_level = 'PRECEDENCE_SHIFTS ' ))
277- to_override .add (Override ('__rlshift__' , pair_operator = '<<' , is_operator_left = False , precedence_level = 'PRECEDENCE_SHIFTS ' ))
278- to_override .add (Override ('__rshift__' , pair_operator = '>>' , precedence_level = 'PRECEDENCE_SHIFTS ' ))
279- to_override .add (Override ('__rrshift__' , pair_operator = '>>' , is_operator_left = False , precedence_level = 'PRECEDENCE_SHIFTS ' ))
280- to_override .add (Override ('__rshift__' , pair_operator = '>>' , precedence_level = 'PRECEDENCE_SHIFTS ' ))
281- to_override .add (Override ('__rshift__' , pair_operator = '>>' , precedence_level = 'PRECEDENCE_SHIFTS ' ))
282- to_override .add (Override ('__neg__' , uni_operator = '-' , precedence_level = 'PRECEDENCE_POS_NEG_BITWISE_NOT ' ))
283- to_override .add (Override ('__pos__' , uni_operator = '+' , precedence_level = 'PRECEDENCE_POS_NEG_BITWISE_NOT ' ))
321+ to_override .add (Override ('__floordiv__' , pair_operator = '//' , precedence_level = '_PRECEDENCE_MUL_DIV_ETC ' ))
322+ to_override .add (Override ('__rfloordiv__' , pair_operator = '//' , is_operator_left = False , precedence_level = '_PRECEDENCE_MUL_DIV_ETC ' ))
323+ to_override .add (Override ('__lshift__' , pair_operator = '<<' , precedence_level = '_PRECEDENCE_SHIFTS ' ))
324+ to_override .add (Override ('__rlshift__' , pair_operator = '<<' , is_operator_left = False , precedence_level = '_PRECEDENCE_SHIFTS ' ))
325+ to_override .add (Override ('__rshift__' , pair_operator = '>>' , precedence_level = '_PRECEDENCE_SHIFTS ' ))
326+ to_override .add (Override ('__rrshift__' , pair_operator = '>>' , is_operator_left = False , precedence_level = '_PRECEDENCE_SHIFTS ' ))
327+ to_override .add (Override ('__rshift__' , pair_operator = '>>' , precedence_level = '_PRECEDENCE_SHIFTS ' ))
328+ to_override .add (Override ('__rshift__' , pair_operator = '>>' , precedence_level = '_PRECEDENCE_SHIFTS ' ))
329+ to_override .add (Override ('__neg__' , uni_operator = '-' , precedence_level = '_PRECEDENCE_POS_NEG_BITWISE_NOT ' ))
330+ to_override .add (Override ('__pos__' , uni_operator = '+' , precedence_level = '_PRECEDENCE_POS_NEG_BITWISE_NOT ' ))
284331 to_override .add (Override ('__abs__' , unbound_method = abs ))
285- to_override .add (Override ('__invert__' , uni_operator = '~' , precedence_level = 'PRECEDENCE_POS_NEG_BITWISE_NOT' ))
332+ to_override .add (Override ('__invert__' , uni_operator = '~' , precedence_level = '_PRECEDENCE_POS_NEG_BITWISE_NOT' ))
333+ to_override .add (Override ('__round__' , unbound_method = round ))
286334
287335 # ** Boolean types **
288336 # .__and__, .__xor__, .__or__, __rand__, __rxor__, __ror__
@@ -321,5 +369,48 @@ def define_what_needs_to_be_written() -> Tuple[Set[Override], Set[OverExc]]:
321369 return to_override_2 , to_override_with_exception_2
322370
323371
372+ def define_goodies () -> Tuple [List [str ], List [Goodie ]]:
373+ """
374+
375+ :return:
376+ """
377+ packages = [math , decimal ]
378+ built_in_functions = ['abs' , 'all' , 'any' , 'ascii' , 'bin' , 'bool' , 'bytearray' , 'bytes' , 'callable' , 'chr' ,
379+ 'classmethod' , 'compile' , 'complex' , 'delattr' , 'dict' , 'dir' , 'divmod' , 'enumerate' ,
380+ 'eval' , 'exec' , 'filter' , 'float' , 'format' , 'frozenset' , 'getattr' , 'globals' , 'hasattr' ,
381+ 'hash' , 'help' , 'hex' , 'id' , 'input' , 'int' , 'isinstance' , 'issubclass' , 'iter' , 'len' ,
382+ 'list' , 'locals' , 'map' , 'max' , 'memoryview' , 'min' , 'next' , 'object' , 'oct' , 'open' , 'ord' ,
383+ 'pow' , 'print' , 'property' , 'range' , 'repr' , 'reversed' , 'round' , 'set' , 'setattr' , 'slice' ,
384+ 'sorted' , 'staticmethod' , 'str' , 'sum' , 'super' , 'tuple' , 'type' , 'vars' , 'zip' ]
385+
386+ import_list = list ()
387+ goodies_list = list ()
388+
389+ for package in packages :
390+ # import pprint
391+ # pprint(getmembers(math, callable))
392+ import_string = "from " + package .__name__ + " import"
393+ for item_name , item in getmembers (package ):
394+ if not item_name .startswith ('_' ):
395+ import_string += ' ' + item_name + ','
396+ if isclass (item ):
397+ new_class_name = item_name [0 ].upper () + item_name
398+ goodies_list .append (Goodie (item_name = new_class_name , class_name = item_name ))
399+ elif callable (item ):
400+ goodies_list .append (Goodie (item_name = item_name .capitalize (), function_name = item_name ))
401+ else :
402+ new_item_name = item_name .capitalize ()
403+ if new_item_name == item_name :
404+ new_item_name = new_item_name [0 ] + new_item_name
405+ goodies_list .append (Goodie (item_name = new_item_name , constant_name = item_name ))
406+
407+ import_list .append (import_string [0 :- 1 ])
408+
409+ for function_name in built_in_functions :
410+ goodies_list .append (Goodie (item_name = function_name .capitalize (), function_name = function_name ))
411+
412+ return import_list , goodies_list
413+
414+
324415if __name__ == '__main__' :
325416 generate_code ()
0 commit comments