Skip to content

Commit 423fee8

Browse files
authored
Merge pull request #5 from TheArtur128/development for 2.2.0 version
Code for 2.2.0 version
2 parents 0b35e14 + 19be05e commit 423fee8

17 files changed

+743
-295
lines changed

README.md

Lines changed: 218 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,15 @@ formattly_sum = "{} {}{}".format
4242
post_partial(formattly_sum, "world", '!')("Hello")
4343
```
4444

45-
not necessarily now
45+
using pseudo operators
46+
```python
47+
(formattly_sum |to| "Hello")("world", '!')
48+
(formattly_sum |to* ("Hello", "world"))('!')
49+
50+
(formattly_sum |by| '!')("Hello", "world")
51+
```
52+
53+
or not necessarily now
4654
```python
4755
container = close(formattly_sum)
4856
opened_container = container("Hello")
@@ -77,26 +85,44 @@ or input values
7785
from functools import partial
7886

7987

80-
eventually(partial(print, 42))(2, 4, 8, 16, 32)
88+
eventually(partial(print, 16))(1, 2, 3)
8189
```
8290
```
83-
42
91+
16
8492
```
8593

8694
### Atomic functions
87-
Use any python atomic operations as functions
95+
Use synonyms for operators
8896
```python
89-
(lambda reource: (raise_ if isinstance(reource, Exception) else return_)(reource))("no error") # "no error"
90-
91-
execute_operation(60, '+', 4) # 64
97+
return_(256)
98+
raise_(Exception("Something is wrong"))
99+
```
100+
```
101+
256
92102
93-
transform_by('not', str()) # True
103+
Traceback ...
104+
Exception: Something is wrong
105+
```
94106

95-
call(range, 16) # range(16)
107+
for atomic operations
108+
```python
109+
execute_operation(60, '+', 4)
110+
transform(str(), 'not')
111+
```
112+
```
113+
64
114+
True
115+
```
96116

97-
getitem_of({"some-key": "some-value"}, "some-key") # "some-value"
117+
for syntax operations
118+
```python
119+
call(range, 16)
98120

99-
take(42) # lambda *_, **__: 42
121+
getitem_of({"some-key": "some-value"}, "some-key")
122+
```
123+
```
124+
range(16)
125+
some-value
100126
```
101127

102128
### Annotating
@@ -111,7 +137,7 @@ is_number_even: checker_of[number] = lambda number: number % 2 == 0
111137

112138
add_hundert_to: reformer_of[number] = lambda number: number + 100
113139

114-
format_lines: merger_of[str] = "{first} {second}{end_symbol}".format
140+
format_lines: merger_of[str] = "{} {}!".format
115141
```
116142

117143
or annotations themselves
@@ -134,7 +160,7 @@ total_sum: Callable[[Iterable[many_or_one[number]]], number] = documenting_by(
134160
"""
135161
)(
136162
close(map |then>> tuple)(
137-
on_condition(post_partial(isinstance, Iterable), sum, else_=return_)
163+
on_condition(isinstance |by| Iterable, sum, else_=return_)
138164
)
139165
|then>> sum
140166
)
@@ -211,7 +237,7 @@ optionally_exponentiate: Callable[[number], number | BadResourceWrapper] = docum
211237
)
212238

213239

214-
-16 >= optionally_exponentiate |then>> print
240+
optionally_exponentiate(-16)
215241
```
216242
```
217243
<Wrapper of bad -16>
@@ -221,8 +247,8 @@ with the possibility of returning a "bad" resource
221247
```python
222248
main: dirty[reformer_of[number]] = optionally_exponentiate |then>> optionally_get_bad_resource_from
223249

224-
8 >= optionally_exponentiate |then>> print
225-
-16 >= optionally_exponentiate |then>> print
250+
main(8)
251+
main(-16)
226252
```
227253
```
228254
64
@@ -246,7 +272,7 @@ main: Callable[[number], number | BadResourceError] = (
246272
)
247273

248274

249-
256 >= main |then>> print
275+
main(256)
250276
```
251277
```
252278
BadResourceError('Resource "256" could not be handled due to ZeroDivisionError: division by zero')
@@ -255,20 +281,192 @@ BadResourceError('Resource "256" could not be handled due to ZeroDivisionError:
255281
with corresponding possibilities
256282
```python
257283
main: reformer_of[number] = (
258-
partial(map |then>> maybe, post_partial(returnly_rollbackable, take(True)))(
284+
partial(map |then>> maybe, returnly_rollbackable |by| take(True))(
259285
post_partial(execute_operation, '*', 2)
260286
|then>> div_by_zero
261287
)
262288
|then>> optionally_get_bad_resource_from
263289
)
264290

265291

266-
16 >= main |then>> print
292+
main(16)
293+
```
294+
```
295+
32
296+
```
297+
298+
### Batteries
299+
Use out-of-the-box functions to abstract from input arguments
300+
```python
301+
take(256)(1, 2, 3)
302+
event_as(execute_operation, 30, '+', 2)(1, 2, 3)
267303
```
268304
```
305+
256
269306
32
270307
```
271308

309+
to create a collection via call
310+
```python
311+
collection_from(1, 2, 3)
312+
```
313+
```
314+
(1, 2, 3)
315+
```
316+
317+
to connect collections
318+
```python
319+
summed_collection_from((1, 2), (3, 4))
320+
```
321+
```
322+
(1, 2, 3, 4)
323+
```
324+
325+
to manage collection nesting
326+
```python
327+
wrap_in_collection(8)
328+
open_collection_items(((1, 2), [3], 4))
329+
```
330+
```
331+
(8, )
332+
(1, 2, 3, 4)
333+
```
334+
335+
to represent something as a collection
336+
```python
337+
as_collection(64)
338+
as_collection([1, 2, 3])
339+
```
340+
```
341+
(64, )
342+
(1, 2, 3)
343+
```
344+
345+
to confirm something multiple times
346+
```python
347+
runner = times(3)
348+
tuple(runner() for _ in range(8))
349+
```
350+
```
351+
(True, True, True, False, True, True, True, False)
352+
```
353+
354+
to raise only a specific error
355+
```python
356+
optional_raise = optional_raising_of(ZeroDivisionError)
357+
358+
optional_raise(TypeError())
359+
optional_raise(ZeroDivisionError("can't divide by zero"))
360+
```
361+
```
362+
TypeError()
363+
364+
Traceback ...
365+
ZeroDivisionError: can't divide by zero
366+
```
367+
368+
to execute operations
369+
```python
370+
operation_by('*', 4)(64)
371+
callmethod(', ', 'join', ("first", "second"))
372+
```
373+
```
374+
256
375+
first, second
376+
```
377+
378+
to decoratively create action chains
379+
```python
380+
next_action_decorator_of(operation_by('**', 4))(operation_by('+', 1))(3)
381+
previous_action_decorator_of(operation_by('+', 2))(operation_by('**', 2))(6)
382+
```
383+
```
384+
256
385+
64
386+
```
387+
388+
to stop the chain when an error occurs
389+
```python
390+
breakable_chain = chain_breaking_on_error_that(isinstance |by| ZeroDivisionError)(
391+
(execute_operation |by* ('+', 4)) |then>> div_by_zero
392+
)
393+
394+
breakable_chain(12)
395+
```
396+
```
397+
BadResourceError('Resource "16" could not be handled due to ZeroDivisionError: division by zero')
398+
```
399+
400+
to use shortcuts of routine options
401+
```python
402+
yes(1, 2, 3)
403+
no(1, 2, 3)
404+
```
405+
```
406+
True
407+
False
408+
```
409+
410+
### Immutable classes
411+
Create immutable classes
412+
```python
413+
from typing import Iterable, Callable
414+
415+
416+
@publicly_immutable
417+
class CallingPublisher:
418+
name = DelegatingProperty('_name')
419+
followers = DelegatingProperty('_followers', getting_converter=tuple)
420+
421+
def __init__(self, name: int, followers: Iterable[Callable] = tuple()):
422+
self._name = name
423+
self._followers = list(followers)
424+
425+
def __repr__(self) -> str:
426+
return f"Publisher {self._name} with followers {self._followers}"
427+
428+
def __call__(self, *args, **kwargs) -> None:
429+
for follower in self._followers:
430+
follower(*args, **kwargs)
431+
432+
@to_clone
433+
def with_follower(self, follower: Callable) -> None:
434+
self._followers.append(follower)
435+
436+
437+
original = CallingPublisher("Some publisher", [print])
438+
```
439+
440+
that can't change any public attribute
441+
```python
442+
original.some_attr = "some value"
443+
```
444+
```
445+
Traceback ...
446+
AttributeError: Type CallingPublisher is immutable
447+
```
448+
449+
and automatically clone without manual creation
450+
```python
451+
other = original.with_follower(operation_by('**', 4) |then>> print)
452+
453+
original.followers
454+
other.followers
455+
```
456+
```
457+
(<built-in function print>,)
458+
(<built-in function print>, ActionChain(...))
459+
```
460+
461+
what would eventually
462+
```python
463+
other(4)
464+
```
465+
```
466+
4
467+
256
468+
```
469+
272470
### Debugging
273471
Display intermediate results
274472
```python
@@ -292,4 +490,4 @@ print(*logger.logs, sep='\n')
292490
[2023-01-24 21:38:28.791516] [[2, 10], [15, 15]]
293491
[2023-01-24 21:38:28.791516] (12, 30)
294492
[2023-01-24 21:38:28.791516] 42
295-
```
493+
```

pyhandling/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from pyhandling.annotations import dirty
21
from pyhandling.binders import *
32
from pyhandling.branchers import *
3+
from pyhandling.language import *
4+
from pyhandling.shortcuts import *
45
from pyhandling.synonyms import *
56
from pyhandling.tools import *
67
from pyhandling.utils import *

pyhandling/annotations.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,6 @@
3838

3939
decorator = reformer_of[Callable]
4040

41-
event = event_for[Any]
41+
event = event_for[Any]
42+
43+
binder = Callable[[Callable, ...], Callable]

pyhandling/binders.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,12 @@
11
from functools import wraps, partial
2-
from typing import Callable, Any, Iterable
2+
from typing import Callable, Any
33

44
from pyannotating import method_of
55

66
from pyhandling.annotations import handler_of
77
from pyhandling.tools import ArgumentPack
88

99

10-
def bind(func: Callable, argument_name: str, argument_value: Any) -> Callable:
11-
"""
12-
Atomic partial function for a single keyword argument whose name and value
13-
are separate input arguments.
14-
"""
15-
16-
return wraps(func)(partial(func, **{argument_name: argument_value}))
17-
18-
1910
def post_partial(func: Callable, *args, **kwargs) -> Callable:
2011
"""
2112
Function equivalent to functools.partial but with the difference that

0 commit comments

Comments
 (0)