Skip to content

Commit d768106

Browse files
committed
Updated documentation main page + associated tests.
Fixed class name in readme
1 parent 7589cef commit d768106

File tree

3 files changed

+128
-97
lines changed

3 files changed

+128
-97
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ The generated code contains functions that generate functions when called, such
2323

2424
```python
2525
def __gt__(self, other):
26-
""" Returns a new _InputEvaluator performing '<r> > other' on the result <r> of this evaluator's evaluation """
26+
""" Returns a new _LambdaExpression performing '<r> > other' on the result <r> of this evaluator's evaluation """
2727
def ___gt__(input):
2828
# first evaluate the inner function
2929
r = self.evaluate(input)
3030
# then call the method
3131
return r > evaluate(other, input)
3232

33-
# return a new InputEvaluator of the same type than self, with the new function as inner function
33+
# return a new _LambdaExpression of the same type than self, with the new function as inner function
3434
return type(self)(___gt__)
3535
```
3636

docs/index.md

Lines changed: 27 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ This idea initially comes from the [valid8](https://smarie.github.io/python-vali
1010
* or to provide users with the capability to write custom validation functions, in particular using lambdas. *Drawback*: the `lambda x:` prefix has to be present everywhere, and users still have to write the exception messages for validation failures.
1111

1212

13-
The `mini_lambda` library provides an answer to the second item: it allows developers to write simple functions
13+
The `mini_lambda` library provides an answer to the second item: it allows developers to write simple functions with a subset of standard python syntax, without the `lambda x:` prefix.
1414

1515
Although initially developed in the context of validation, this library is now fully independent and can serve other use cases.
1616

@@ -23,69 +23,54 @@ Although initially developed in the context of validation, this library is now f
2323

2424
## Usage
2525

26-
The idea is that you start from a magic variable such as `x`, `s`, `l`, `df`... and you write expressions using it:
26+
Three basic steps:
2727

28-
```python
29-
from mini_lambda import x, s
30-
from math import log
31-
32-
# here are some lambda functions:
33-
is_lowercase = s.islower()
34-
say_hello = 'Hello, ' + s + ' !'
35-
get_prefix_upper_shebang = s[0:4].upper() + ' !'
36-
numeric_test_1 = -x > x ** 2
37-
numeric_test_2 = ((1 - 2 * x) <= -x) | (-x > x ** 2)
38-
```
39-
40-
If you know python you should feel at home here, except for the fact that `|` is used instead of `or`. We will come back to this later.
41-
42-
Once you have created a function, it is still in "edit" mode. It means that calling it will create a new function, it will not evaluate it:
28+
* import or create a 'magic variable' such as `x`, `s`, `l`, `df`...
29+
* write an expression using it
30+
* transform the expression into a function by wrapping it with `_()` or its alias `L()`.
4331

4432
```python
45-
say_hello_hardcoded = say_hello('world')
33+
# create or import a magic variable, here we import 's'
34+
from mini_lambda import s
4635

47-
type(say_hello_hardcoded) # <class 'mini_lambda.main._InputEvaluator'>: still a function!
48-
print(say_hello_hardcoded) # NotImplementedError: __str__ is not supported by _InputEvaluator
49-
```
36+
# write an expression and wrap it with _() to make a function
37+
from mini_lambda import _
38+
say_hello_function = _('Hello, ' + s + ' !')
5039

51-
That's the first main difference with traditional python lambda functions. In order to use your functions, you can either use the explicit `evaluate` method :
40+
# use the function with any input
41+
say_hello_function('world') # Returns "Hello, world !"
5242

53-
```python
54-
is_lowercase.evaluate('Hello') # returns False
55-
say_hello.evaluate('world') # returns 'Hello, world !'
56-
get_prefix_upper_shebang.evaluate('hello') # returns 'HELL !'
57-
numeric_test_1.evaluate(0.5) # returns False
58-
numeric_test_2.evaluate(1) # returns True
43+
# the function's string representation is available
44+
print(say_hello_function) # "'Hello, ' + s + ' !'"
5945
```
6046

61-
Or you can get a real function from the lambda function, and then call it. There are several ways to do that:
47+
Most of python syntax can be used in an expression:
6248

6349
```python
64-
from mini_lambda import _, L
50+
from mini_lambda import x, s, _
6551

66-
is_lowercase = is_lowercase.as_function() # explicitly
67-
say_hello = _(say_hello) # _() is a handy operator to do the same thing
68-
get_prefix_upper_shebang = L(get_prefix_upper_shebang) # L() is an alias for _()
69-
numeric_test_1, numeric_test_2 = _(numeric_test_1, numeric_test_2) # both accept multiple inputs
52+
# various lambda functions
53+
is_lowercase = _( s.islower() )
54+
get_prefix_upper_shebang = _( s[0:4].upper() + ' !' )
55+
numeric_test_1 = _( -x > x ** 2 )
56+
numeric_test_2 = _( ((1 - 2 * x) <= -x) | (-x > x ** 2) )
7057

71-
# you can now use the functions directly
58+
# use the functions
7259
is_lowercase('Hello') # returns False
73-
say_hello('world') # returns 'Hello, world !'
7460
get_prefix_upper_shebang('hello') # returns 'HELL !'
7561
numeric_test_1(0.5) # returns False
76-
```
77-
78-
Finally, the functions that you have created are printable:
62+
numeric_test_2(1) # returns True
7963

80-
```python
64+
# string representation
8165
print(is_lowercase) # s.islower()
82-
print(say_hello) # 'Hello, ' + s + ' !'
8366
print(get_prefix_upper_shebang) # s[0:4].upper() + ' !'
8467
print(numeric_test_1) # -x > x ** 2
8568
print(numeric_test_2) # (1 - 2 * x <= -x) | (-x > x ** 2)
8669
```
8770

88-
Note that the printed version of `numeric_test_2` got rid of my useless parenthesis :)
71+
If you know python you should feel at home here, except for the fact that `or` and `and` should be replaced with their bitwise equivalents `|` and `&`.
72+
73+
Note that the printed version provides the minimal equivalent representation taking into account the operator precedence. Hence `numeric_test_2` got rid of my useless parenthesis. This is **not** a mathematical simplification like in SymPy, i.e. `x - x` will not be simplified to `0`.
8974

9075
There are of course a few limitations to `mini_lambda` as compared to full-flavoured python `lambda` functions, the main one being that you can't mix more than one variable in the same expression for now. Check the [Usage](./usage/) page for more details.
9176

mini_lambda/tests/test_readme.py

Lines changed: 99 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,108 @@
11
import pytest
22

33
from mini_lambda import FunctionDefinitionError
4-
from mini_lambda.main import _InputEvaluator
5-
6-
7-
def test_readme_1():
8-
9-
from mini_lambda import x, s #, Log
10-
11-
# some lambda functions:
12-
is_lowercase = s.islower()
13-
say_hello = 'Hello, ' + s + ' !'
14-
get_prefix_upper_shebang = s[0:4].upper() + ' !'
15-
numeric_test_1 = -x > x ** 2
16-
numeric_test_2 = ((1 - 2 * x) <= -x) | (-x > x ** 2)
17-
# complex_identity = Log(10 ** x, 10)
18-
19-
# -------- Still in edit mode
20-
say_hello_hardcoded = say_hello('world')
21-
assert type(say_hello_hardcoded) == _InputEvaluator # <class 'mini_lambda.main._InputEvaluator'>
22-
with pytest.raises(FunctionDefinitionError):
23-
print(say_hello_hardcoded) # NotImplementedError: __str__ is not supported by _InputEvaluator
24-
25-
# -------- Explicit evaluation
26-
assert not is_lowercase.evaluate('Hello')
27-
assert say_hello.evaluate('world') == 'Hello, world !'
28-
assert get_prefix_upper_shebang.evaluate('hello') == 'HELL !'
29-
assert not numeric_test_1.evaluate(0.5)
30-
assert numeric_test_2.evaluate(1)
31-
# assert complex_identity.evaluate(2.5) # returns 2.5
32-
33-
# ------- Go to 'usage' mode
34-
from mini_lambda import _, L
35-
is_lowercase = is_lowercase.as_function() # explicitly
36-
say_hello = _(say_hello) # _() is a handy operator to do the same thing
37-
get_prefix_upper_shebang = L(get_prefix_upper_shebang) # L() is an alias for _()
38-
numeric_test_1, numeric_test_2 = _(numeric_test_1, numeric_test_2)
39-
# numeric_test_1, complex_identity = _(numeric_test_1, complex_identity) # both accept multiple inputs
40-
41-
# you can now use the functions directly
42-
assert not is_lowercase('Hello')
43-
assert say_hello('world') == 'Hello, world !'
4+
from mini_lambda.main import _LambdaExpression
5+
6+
7+
def test_doc_index_1():
8+
""" Tests that the first example in the documentation main page works """
9+
10+
# import magic variable 's'
11+
from mini_lambda import s
12+
13+
# write an expression and wrap it with _() to make a function
14+
from mini_lambda import _
15+
say_hello_function = _('Hello, ' + s + ' !')
16+
17+
# use the function
18+
print(say_hello_function('world')) # 'Hello, world !'
19+
assert say_hello_function('world') == 'Hello, world !'
20+
print(say_hello_function)
21+
assert str(say_hello_function) == "'Hello, ' + s + ' !'"
22+
23+
24+
def test_doc_index_2():
25+
""" Tests that the second example in the documentation main page works """
26+
27+
from mini_lambda import s, x, _
28+
29+
# various lambda functions
30+
is_lowercase = _(s.islower())
31+
get_prefix_upper_shebang = _(s[0:4].upper() + ' !')
32+
numeric_test_1 = _(-x > x ** 2)
33+
numeric_test_2 = _(((1 - 2 * x) <= -x) | (-x > x ** 2))
34+
35+
# use the functions
36+
assert is_lowercase('Hello') is False
4437
assert get_prefix_upper_shebang('hello') == 'HELL !'
45-
assert not numeric_test_1(0.5)
46-
assert numeric_test_2(1)
47-
# assert complex_identity(2.5) # returns 2.5
48-
49-
# finally, printable
50-
print(is_lowercase)
51-
print(say_hello)
52-
print(get_prefix_upper_shebang)
53-
print(numeric_test_1)
54-
print(numeric_test_2)
55-
# print(complex_identity)
38+
assert numeric_test_1(0.5) is False
39+
assert numeric_test_2(1) is True
40+
41+
# string representation
42+
print(is_lowercase) # s.islower()
43+
print(get_prefix_upper_shebang) # s[0:4].upper() + ' !'
44+
print(numeric_test_1) # -x > x ** 2
45+
print(numeric_test_2) # (1 - 2 * x <= -x) | (-x > x ** 2)
5646

5747
assert str(is_lowercase) == 's.islower()'
58-
assert str(say_hello) == "'Hello, ' + s + ' !'"
5948
assert str(get_prefix_upper_shebang) == "s[0:4].upper() + ' !'"
6049
assert str(numeric_test_1) == '-x > x ** 2'
6150
assert str(numeric_test_2) == '(1 - 2 * x <= -x) | (-x > x ** 2)'
62-
# print(complex_identity)
51+
52+
53+
# def test_readme_1():
54+
#
55+
# from mini_lambda import x, s # Log
56+
#
57+
# # some lambda functions:
58+
# is_lowercase = s.islower()
59+
# say_hello = 'Hello, ' + s + ' !'
60+
# get_prefix_upper_shebang = s[0:4].upper() + ' !'
61+
# numeric_test_1 = -x > x ** 2
62+
# numeric_test_2 = ((1 - 2 * x) <= -x) | (-x > x ** 2)
63+
# # complex_identity = Log(10 ** x, 10)
64+
#
65+
# # -------- Still in edit mode
66+
# say_hello_hardcoded = say_hello('world')
67+
# assert type(say_hello_hardcoded) == _LambdaExpression # <class 'mini_lambda.main._LambdaExpression'>
68+
# with pytest.raises(FunctionDefinitionError):
69+
# print(say_hello_hardcoded) # NotImplementedError: __str__ is not supported by _LambdaExpression
70+
#
71+
# # -------- Explicit evaluation
72+
# assert not is_lowercase.evaluate('Hello')
73+
# assert say_hello.evaluate('world') == 'Hello, world !'
74+
# assert get_prefix_upper_shebang.evaluate('hello') == 'HELL !'
75+
# assert not numeric_test_1.evaluate(0.5)
76+
# assert numeric_test_2.evaluate(1)
77+
# # assert complex_identity.evaluate(2.5) # returns 2.5
78+
#
79+
# # ------- Go to 'usage' mode
80+
# from mini_lambda import _, L
81+
# is_lowercase = is_lowercase.as_function() # explicitly
82+
# say_hello = _(say_hello) # _() is a handy operator to do the same thing
83+
# get_prefix_upper_shebang = L(get_prefix_upper_shebang) # L() is an alias for _()
84+
# numeric_test_1, numeric_test_2 = _(numeric_test_1, numeric_test_2)
85+
# # numeric_test_1, complex_identity = _(numeric_test_1, complex_identity) # both accept multiple inputs
86+
#
87+
# # you can now use the functions directly
88+
# assert is_lowercase('Hello') is False
89+
# assert say_hello('world') == 'Hello, world !'
90+
# assert get_prefix_upper_shebang('hello') == 'HELL !'
91+
# assert numeric_test_1(0.5) is False
92+
# assert numeric_test_2(1) is True
93+
# # assert complex_identity(2.5) # returns 2.5
94+
#
95+
# # finally, printable
96+
# print(is_lowercase)
97+
# print(say_hello)
98+
# print(get_prefix_upper_shebang)
99+
# print(numeric_test_1)
100+
# print(numeric_test_2)
101+
# # print(complex_identity)
102+
#
103+
# assert str(is_lowercase) == 's.islower()'
104+
# assert str(say_hello) == "'Hello, ' + s + ' !'"
105+
# assert str(get_prefix_upper_shebang) == "s[0:4].upper() + ' !'"
106+
# assert str(numeric_test_1) == '-x > x ** 2'
107+
# assert str(numeric_test_2) == '(1 - 2 * x <= -x) | (-x > x ** 2)'
108+
# # print(complex_identity)

0 commit comments

Comments
 (0)