Skip to content

Commit ddbde67

Browse files
author
Sylvain MARIE
committed
Submodules structure and init file refactoring. In particular preconstructed symbols are now each in a dedicated package, and there is not anymore a dynamic init file - that was too much against python best practices.
1 parent 985f0e3 commit ddbde67

File tree

13 files changed

+130
-134
lines changed

13 files changed

+130
-134
lines changed

code_generation/mini_lambda_methods_generation.py

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from __future__ import print_function
12
from inspect import isclass
23
from sys import getsizeof
34
try:
@@ -139,13 +140,15 @@ def generate_code():
139140
print(o)
140141

141142
# generate
142-
generate_from_template('mini_lambda_template.mako', 'generated.py',
143-
dict(to_override=to_override, to_override_with_exception=to_override_with_exception))
144-
generate_from_template('mini_lambda_template_2.mako', 'generated2.py',
143+
generate_from_template('tpl_magic_methods.mako', 'generated_magic.py',
145144
dict(to_override=to_override, to_override_with_exception=to_override_with_exception))
145+
generate_from_template('tpl_magic_methods_replacements.mako', 'generated_magic_replacements.py',
146+
dict(to_override=to_override, to_override_with_exception=to_override_with_exception,
147+
generate_all=True))
146148

147149
# (2) to-do list for the second template
148-
import_lines, to_create = define_goodies()
150+
# --(a) builtins
151+
import_lines, to_create = define_goodies_builtins()
149152

150153
# check outside of the template that it works:
151154
for o in import_lines:
@@ -154,8 +157,23 @@ def generate_code():
154157
print(o)
155158

156159
# generate
157-
generate_from_template('goodies_template.mako', 'goodies_generated.py',
158-
dict(import_lines=import_lines, to_create=to_create))
160+
generate_from_template('tpl_preconverted_symbols.mako', 'symbols/builtins.py',
161+
dict(import_lines=import_lines, to_create=to_create, generate_all=True))
162+
163+
# --(b) math
164+
for pkg in [math, decimal]:
165+
import_lines, to_create = define_goodies(packages=[pkg])
166+
167+
# check outside of the template that it works:
168+
for o in import_lines:
169+
print(o)
170+
for o in to_create:
171+
print(o)
172+
173+
# generate but without the '__all__' symbol since packages may not contain the same symbols across versions of
174+
# python
175+
generate_from_template('tpl_preconverted_symbols.mako', 'symbols/%s_.py' % pkg.__name__,
176+
dict(import_lines=import_lines, to_create=to_create, generate_all=False))
159177

160178

161179
def generate_from_template(src_file, dst_file, template_vars):
@@ -399,25 +417,36 @@ def define_what_needs_to_be_written():
399417
return to_override_2, to_override_with_exception_2
400418

401419

402-
def define_goodies():
403-
# type: (...) -> Tuple[List[str], List[Goodie]]
404-
"""
405-
406-
:return:
407-
"""
408-
packages = [math, decimal]
420+
def define_goodies_builtins():
421+
import_list = list()
422+
goodies_list = list()
409423
built_in_functions = ['abs', 'all', 'any', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr',
410424
'classmethod', 'compile', 'complex', 'delattr', 'dict', 'dir', 'divmod', 'enumerate',
411425
'eval', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
412426
'hash', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len',
413427
'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord',
414428
'pow', 'print', 'property', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
415429
'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
416-
# these do not work in python 2
417-
protected_functions = ['ascii', 'help', 'exec']
430+
# these do not work in python 2: the statement is reserved.
431+
# protected_functions = ['ascii', 'help', 'exec']
432+
433+
for function_name in built_in_functions:
434+
if isclass(eval(function_name)):
435+
goodies_list.append(Goodie(item_name=function_name.capitalize(), class_name=function_name))
436+
else:
437+
goodies_list.append(Goodie(item_name=function_name.capitalize(), function_name=function_name))
438+
439+
return import_list, goodies_list
440+
441+
442+
def define_goodies(packages):
443+
# type: (...) -> Tuple[List[str], List[Goodie]]
444+
"""
445+
446+
:return:
447+
"""
418448
import_list = list()
419449
goodies_list = list()
420-
421450
for package in packages:
422451
# import pprint
423452
# pprint(getmembers(math, callable))
@@ -442,9 +471,6 @@ def define_goodies():
442471
# we do not import anymore at the top but in each one so as to put additional try/catch around them
443472
# import_list.append(import_string[0:-1])
444473

445-
for function_name in built_in_functions:
446-
goodies_list.append(Goodie(item_name=function_name.capitalize(), function_name=function_name))
447-
448474
return import_list, goodies_list
449475

450476

code_generation/mini_lambda_template_2.mako renamed to code_generation/tpl_magic_methods_replacements.mako

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@
44
from mini_lambda.main import _LambdaExpression
55
from sys import getsizeof
66

7+
% if generate_all:
8+
__all__ = [
9+
% for o in to_override_with_exception:
10+
% if o.module_method_name != 'Format':
11+
'${o.module_method_name}',
12+
% endif
13+
% endfor
14+
]
15+
% endif
16+
717

818
# ******* All replacement methods for the magic methods throwing exceptions ********
919
% for o in to_override_with_exception:

code_generation/goodies_template.mako renamed to code_generation/tpl_preconverted_symbols.mako

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ from mini_lambda.main import C, make_lambda_friendly_class, make_lambda_friendly
99
${o}
1010
% endfor
1111

12+
% if generate_all:
13+
__all__ = [
14+
% for o in to_create:
15+
'${o.item_name}',
16+
% endfor
17+
]
18+
% endif
19+
1220
% for o in to_create:
1321
% if o.import_line is None or len(o.import_line) == 0:
1422
% if o.constant_name:

mini_lambda/__init__.py

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,29 @@
1-
from mini_lambda.utils_init import __remove_all_external_symbols, __get_all_submodules_symbols
1+
from mini_lambda.base import FunctionDefinitionError, evaluate, get_repr
22

3-
__PACKAGE_NAME = 'mini_lambda'
4-
__SUBMODULES_TO_EXPORT = ['base', 'generated', 'generated2', 'goodies', 'goodies_generated', 'main']
5-
# TODO we could rather rely on a regexp mechanism
3+
# this one only exports one private class, no need
4+
# from mini_lambda.generated import *
65

7-
# (1) allow users to do
8-
# import <package> as p and then p.<symbol>
9-
__all__ = __get_all_submodules_symbols(__PACKAGE_NAME, __SUBMODULES_TO_EXPORT)
10-
__all__ += ['numpy_', 'pandas_']
11-
# Note: this is one way to do it, but it would be simpler to check the names in globals() at the end of this file.
6+
from mini_lambda.main import _, L, F, C, Not, And, Or, Format, Get, In, Slice, InputVar, Constant, \
7+
make_lambda_friendly, make_lambda_friendly_method, make_lambda_friendly_class
128

13-
# (2) allow users to do
14-
# from <package> import <symbol>
15-
#
16-
# The following works, but unfortunately IDE like pycharm do not understand
17-
from mini_lambda.base import *
18-
from mini_lambda.generated import *
19-
from mini_lambda.goodies_generated import *
20-
from mini_lambda.main import *
21-
from mini_lambda.main import _
22-
from mini_lambda.generated2 import *
23-
from mini_lambda.goodies import *
9+
__all__ = [
10+
# submodules
11+
'base', 'generated_magic', 'generated_magic_replacements', 'main', 'symbols', 'vars',
12+
# symbols
13+
'FunctionDefinitionError', 'evaluate', 'get_repr',
14+
'_', 'L', 'F', 'C', 'InputVar', 'Constant', 'make_lambda_friendly', 'make_lambda_friendly_method',
15+
'make_lambda_friendly_class',
16+
'Not', 'And', 'Or', 'Format', 'Get', 'In', 'Slice',
17+
]
2418

25-
# remove all symbols that were imported above but do not belong in this package
26-
__remove_all_external_symbols(__PACKAGE_NAME, globals())
19+
# for these two ones we can, there is a `__all__` inside
20+
from mini_lambda.vars import *
21+
from mini_lambda.vars import __all__ as vall
2722

28-
# Otherwise exhaustive list would be required, which is sad
29-
# ...
23+
from mini_lambda.generated_magic_replacements import *
24+
from mini_lambda.generated_magic_replacements import __all__ as gall
3025

31-
# print(__all__)
32-
# print(globals().keys())
33-
# print('Done')
26+
from mini_lambda.symbols import *
27+
from mini_lambda.symbols import __all__ as sall
3428

29+
__all__ = __all__ + vall + gall + sall

mini_lambda/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
from mini_lambda.base import get_repr, _PRECEDENCE_BITWISE_AND, _PRECEDENCE_BITWISE_OR, _PRECEDENCE_BITWISE_XOR, \
1111
_PRECEDENCE_SUBSCRIPTION_SLICING_CALL_ATTRREF, evaluate, _PRECEDENCE_EXPONENTIATION, \
12-
_PRECEDENCE_POS_NEG_BITWISE_NOT, _get_root_var
13-
from mini_lambda.generated import _LambdaExpressionGenerated, FunctionDefinitionError
12+
_PRECEDENCE_POS_NEG_BITWISE_NOT, _get_root_var, FunctionDefinitionError
13+
from mini_lambda.generated_magic import _LambdaExpressionGenerated
1414

1515

1616
this_module = sys.modules[__name__]

mini_lambda/symbols/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from .builtins import *
2+
3+
# no need to import them, they'll be imported on demand
4+
# from mini_lambda import preconverted_math
5+
# from mini_lambda import preconverted_decimal
6+
7+
__all__ = [
8+
'builtins', 'math_', 'decimal_'
9+
]
10+
11+
from .builtins import __all__ as ball
12+
__all__ += ball

mini_lambda/tests/test_mini_lambda.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ def test_evaluator_int_convertible():
613613

614614
def test_evaluator_maths():
615615
""" """
616-
from mini_lambda import Floor, Ceil
616+
from mini_lambda.symbols.math_ import Floor, Ceil
617617
from math import floor, ceil, trunc
618618

619619
x = InputVar('x', float)
@@ -772,7 +772,8 @@ def test_constants_named():
772772
def test_generated_methods():
773773
""" Tests that equivalent methods generated by the package from various packages (currently, only math) work"""
774774

775-
from mini_lambda import x, _, Sin
775+
from mini_lambda import x, _
776+
from mini_lambda.symbols.math_ import Sin
776777
from math import sin
777778

778779
sine = _(Sin(x))

mini_lambda/tests/test_readme.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ def test_doc_index_1():
2929
def test_doc_index_2():
3030
""" Tests that the second example in the documentation main page works """
3131

32-
from mini_lambda import s, x, _, Log # this is a dynamic creation hence pycharm does not see it
32+
from mini_lambda import s, x, _ # this is a dynamic creation hence pycharm does not see it
33+
from mini_lambda.symbols.math_ import Log
3334

3435
# various lambda functions
3536
is_lowercase = _(s.islower())
@@ -145,7 +146,9 @@ def test_doc_usage_syntax_2():
145146
""" Tests that the second example in doc/usage in the syntax section works """
146147
from mini_lambda import b, i, s, l, x
147148
from mini_lambda import Slice, Get, Not, In
148-
from mini_lambda import Iter, Repr, Format, Len, Int, Any, Log, DDecimal
149+
from mini_lambda import Iter, Repr, Format, Len, Int, Any
150+
from mini_lambda.symbols.math_ import Log
151+
from mini_lambda.symbols.decimal_ import DDecimal
149152
from math import log
150153
from decimal import Decimal
151154

@@ -162,7 +165,7 @@ def test_doc_usage_syntax_2():
162165
expr = log(x) # fails
163166
expr = Log(x) # OK
164167
# constructing with the variable as arg
165-
with pytest.raises(TypeError if version_info >= (3, 0) else FunctionDefinitionError):
168+
with pytest.raises(TypeError):
166169
expr = Decimal(x) # fails
167170
expr = DDecimal(x) # OK
168171
# getting with the variable as the key
@@ -174,6 +177,8 @@ def test_doc_usage_syntax_2():
174177
expr = 'hello'[0:i] # fails
175178
expr = Get('hello', Slice(0, i)) # OK
176179
# representing: Repr/Str/Bytes/Sizeof/Hash
180+
assert repr(l) == '<_LambdaExpression: l>'
181+
l.repr_on = False
177182
with pytest.raises(FunctionDefinitionError):
178183
expr = repr(l) # fails
179184
expr = Repr(l) # OK
@@ -219,7 +224,8 @@ def test_doc_usage_syntax_2():
219224

220225
def test_doc_usage_other_constants():
221226
""" Tests that the example in doc/usage in the others/constants section works """
222-
from mini_lambda import x, _, E, C
227+
from mini_lambda import x, _, C
228+
from mini_lambda.symbols.math_ import E
223229
from math import e
224230

225231
assert str(_(x + e)) == 'x + 2.718281828459045'
@@ -309,7 +315,7 @@ def bar2(cls, times, num, den):
309315
def test_doc_usage_other_classes():
310316
""" Tests that the example in doc/usage in the others/classes section works """
311317
from mini_lambda import _, make_lambda_friendly_class
312-
from mini_lambda.numpy_ import X
318+
from mini_lambda.vars.numpy_ import X
313319
import numpy as np
314320
import pandas as pd
315321

@@ -323,7 +329,7 @@ def test_doc_usage_other_classes():
323329
def test_doc_usage_all_at_once():
324330
""" Tests that the example in doc/usage in the others/anything section works """
325331
from mini_lambda import _, C
326-
from mini_lambda.numpy_ import X
332+
from mini_lambda.vars.numpy_ import X
327333
import numpy as np
328334
import pandas as pd
329335

@@ -336,9 +342,11 @@ def test_doc_usage_all_at_once():
336342
def test_doc_usage_already_imported():
337343
""" Tests that the example in doc/usage in the others/preconverted section works """
338344

339-
from mini_lambda import DDecimal # Decimal class
340345
from mini_lambda import Print # print() function
341-
from mini_lambda import Pi # math.pi constant
346+
347+
from mini_lambda.symbols.decimal_ import DDecimal # Decimal class
348+
from mini_lambda.symbols.builtins import Print # print() function
349+
from mini_lambda.symbols.math_ import Pi # math.pi constant
342350

343351

344352
def test_doc_optional():
@@ -347,9 +355,9 @@ def test_doc_optional():
347355
with pytest.raises(ImportError):
348356
from mini_lambda import X
349357

350-
from mini_lambda.numpy_ import X
358+
from mini_lambda.vars.numpy_ import X
351359

352360
with pytest.raises(ImportError):
353361
from mini_lambda import df
354362

355-
from mini_lambda.pandas_ import df
363+
from mini_lambda.vars.pandas_ import df

0 commit comments

Comments
 (0)