onekit 0.6.0__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {onekit-0.6.0 → onekit-0.7.0}/PKG-INFO +1 -1
- {onekit-0.6.0 → onekit-0.7.0}/pyproject.toml +1 -1
- {onekit-0.6.0 → onekit-0.7.0}/src/onekit/pytlz.py +195 -35
- {onekit-0.6.0 → onekit-0.7.0}/src/onekit/sparktlz.py +3 -3
- {onekit-0.6.0 → onekit-0.7.0}/LICENSE +0 -0
- {onekit-0.6.0 → onekit-0.7.0}/README.md +0 -0
- {onekit-0.6.0 → onekit-0.7.0}/src/onekit/__init__.py +0 -0
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
"""Python toolz."""
|
|
2
2
|
|
|
3
3
|
import datetime as dt
|
|
4
|
+
import functools
|
|
4
5
|
import inspect
|
|
6
|
+
import itertools
|
|
5
7
|
import math
|
|
8
|
+
import os
|
|
6
9
|
import random
|
|
10
|
+
import re
|
|
11
|
+
import string
|
|
7
12
|
from typing import (
|
|
8
13
|
Any,
|
|
9
14
|
Callable,
|
|
10
15
|
Generator,
|
|
16
|
+
Iterable,
|
|
11
17
|
Iterator,
|
|
12
18
|
Optional,
|
|
13
19
|
Sequence,
|
|
@@ -22,22 +28,28 @@ from toolz.curried import (
|
|
|
22
28
|
)
|
|
23
29
|
|
|
24
30
|
__all__ = (
|
|
25
|
-
"
|
|
26
|
-
"any_predicate_true",
|
|
31
|
+
"are_predicates_true",
|
|
27
32
|
"check_random_state",
|
|
28
33
|
"coinflip",
|
|
29
34
|
"collatz",
|
|
35
|
+
"concat_strings",
|
|
30
36
|
"contrast_sets",
|
|
37
|
+
"create_path",
|
|
31
38
|
"date_to_str",
|
|
32
39
|
"extend_range",
|
|
33
40
|
"fibonacci",
|
|
34
41
|
"flatten",
|
|
42
|
+
"filter_regex",
|
|
35
43
|
"func_name",
|
|
44
|
+
"headline",
|
|
45
|
+
"highlight_string_differences",
|
|
36
46
|
"isdivisibleby",
|
|
37
47
|
"iseven",
|
|
38
48
|
"isodd",
|
|
49
|
+
"map_regex",
|
|
39
50
|
"num_to_str",
|
|
40
51
|
"reduce_sets",
|
|
52
|
+
"remove_punctuation",
|
|
41
53
|
"signif",
|
|
42
54
|
"source_code",
|
|
43
55
|
)
|
|
@@ -48,18 +60,31 @@ Predicate = Callable[[Any], bool]
|
|
|
48
60
|
Seed = Optional[Union[int, random.Random]]
|
|
49
61
|
|
|
50
62
|
|
|
51
|
-
def
|
|
52
|
-
|
|
63
|
+
def are_predicates_true(
|
|
64
|
+
func: Callable[..., bool],
|
|
65
|
+
*predicates: Iterable[Predicate],
|
|
66
|
+
) -> Predicate:
|
|
67
|
+
"""Evaluate if predicates are true.
|
|
53
68
|
|
|
54
69
|
A predicate is of the form :math:`P\\colon X \\rightarrow \\{False, True\\}`
|
|
55
70
|
|
|
56
71
|
Examples
|
|
57
72
|
--------
|
|
58
73
|
>>> from onekit import pytlz
|
|
59
|
-
>>> pytlz.
|
|
74
|
+
>>> pytlz.are_predicates_true(all, lambda x: x % 2 == 0, lambda x: x % 5 == 0)(10)
|
|
60
75
|
True
|
|
61
76
|
|
|
62
|
-
>>>
|
|
77
|
+
>>> pytlz.are_predicates_true(all, lambda x: x % 2 == 0, lambda x: x % 5 == 0)(12)
|
|
78
|
+
False
|
|
79
|
+
|
|
80
|
+
>>> pytlz.are_predicates_true(any, lambda x: x % 2 == 0, lambda x: x % 5 == 0)(12)
|
|
81
|
+
True
|
|
82
|
+
|
|
83
|
+
>>> pytlz.are_predicates_true(any, lambda x: x % 2 == 0, lambda x: x % 5 == 0)(13)
|
|
84
|
+
False
|
|
85
|
+
|
|
86
|
+
>>> is_divisible_by_3_and_5 = pytlz.are_predicates_true(
|
|
87
|
+
... all,
|
|
63
88
|
... pytlz.isdivisibleby(3),
|
|
64
89
|
... pytlz.isdivisibleby(5),
|
|
65
90
|
... )
|
|
@@ -69,27 +94,9 @@ def all_predicate_true(*predicates: Sequence[Predicate]) -> Predicate:
|
|
|
69
94
|
True
|
|
70
95
|
>>> is_divisible_by_3_and_5(9)
|
|
71
96
|
False
|
|
72
|
-
"""
|
|
73
|
-
|
|
74
|
-
def inner(x: Any, /) -> bool:
|
|
75
|
-
"""Evaluate all specified predicates :math:`P_i` for value :math:`x \\in X`."""
|
|
76
|
-
return all(predicate(x) for predicate in flatten(predicates))
|
|
77
|
-
|
|
78
|
-
return inner
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def any_predicate_true(*predicates: Sequence[Predicate]) -> Predicate:
|
|
82
|
-
"""Evaluate if any predicate is true.
|
|
83
|
-
|
|
84
|
-
A predicate is of the form :math:`P\\colon X \\rightarrow \\{False, True\\}`
|
|
85
|
-
|
|
86
|
-
Examples
|
|
87
|
-
--------
|
|
88
|
-
>>> from onekit import pytlz
|
|
89
|
-
>>> pytlz.any_predicate_true(lambda x: x % 2 == 0, lambda x: x % 5 == 0)(10)
|
|
90
|
-
True
|
|
91
97
|
|
|
92
|
-
>>> is_divisible_by_3_or_5 = pytlz.
|
|
98
|
+
>>> is_divisible_by_3_or_5 = pytlz.are_predicates_true(
|
|
99
|
+
... any,
|
|
93
100
|
... pytlz.isdivisibleby(3),
|
|
94
101
|
... pytlz.isdivisibleby(5),
|
|
95
102
|
... )
|
|
@@ -105,7 +112,7 @@ def any_predicate_true(*predicates: Sequence[Predicate]) -> Predicate:
|
|
|
105
112
|
|
|
106
113
|
def inner(x: Any, /) -> bool:
|
|
107
114
|
"""Evaluate all specified predicates :math:`P_i` for value :math:`x \\in X`."""
|
|
108
|
-
return
|
|
115
|
+
return func(predicate(x) for predicate in flatten(predicates))
|
|
109
116
|
|
|
110
117
|
return inner
|
|
111
118
|
|
|
@@ -236,6 +243,27 @@ def collatz(n: int, /) -> Generator:
|
|
|
236
243
|
n = n // 2 if iseven(n) else 3 * n + 1
|
|
237
244
|
|
|
238
245
|
|
|
246
|
+
def concat_strings(sep: str, /, *strings: Iterable[str]) -> str:
|
|
247
|
+
"""Concatenate strings.
|
|
248
|
+
|
|
249
|
+
Examples
|
|
250
|
+
--------
|
|
251
|
+
>>> from functools import partial
|
|
252
|
+
>>> from onekit import pytlz
|
|
253
|
+
>>> pytlz.concat_strings(" ", "Hello", "World")
|
|
254
|
+
'Hello World'
|
|
255
|
+
>>> pytlz.concat_strings(" ", ["Hello", "World"])
|
|
256
|
+
'Hello World'
|
|
257
|
+
|
|
258
|
+
>>> plus_concat = partial(pytlz.concat_strings, " + ")
|
|
259
|
+
>>> plus_concat("Hello", "World")
|
|
260
|
+
'Hello + World'
|
|
261
|
+
>>> plus_concat(["Hello", "World"])
|
|
262
|
+
'Hello + World'
|
|
263
|
+
"""
|
|
264
|
+
return sep.join(toolz.pipe(strings, flatten, map(str)))
|
|
265
|
+
|
|
266
|
+
|
|
239
267
|
def contrast_sets(x: set, y: set, /, *, n: int = 3) -> dict:
|
|
240
268
|
"""Contrast sets.
|
|
241
269
|
|
|
@@ -346,6 +374,21 @@ def contrast_sets(x: set, y: set, /, *, n: int = 3) -> dict:
|
|
|
346
374
|
return output
|
|
347
375
|
|
|
348
376
|
|
|
377
|
+
def create_path(*strings: Iterable[str]) -> str:
|
|
378
|
+
"""Create path by concatenating strings.
|
|
379
|
+
|
|
380
|
+
Examples
|
|
381
|
+
--------
|
|
382
|
+
>>> from onekit import pytlz
|
|
383
|
+
>>> pytlz.create_path("path", "to", "file")
|
|
384
|
+
'path/to/file'
|
|
385
|
+
|
|
386
|
+
>>> pytlz.create_path(["hdfs://", "path", "to", "file"])
|
|
387
|
+
'hdfs://path/to/file'
|
|
388
|
+
"""
|
|
389
|
+
return functools.reduce(os.path.join, flatten(strings))
|
|
390
|
+
|
|
391
|
+
|
|
349
392
|
def date_to_str(d: dt.date, /) -> str:
|
|
350
393
|
"""Cast date to string in ISO format: YYYY-MM-DD.
|
|
351
394
|
|
|
@@ -427,8 +470,39 @@ def fibonacci() -> Generator:
|
|
|
427
470
|
lag2, lag1 = lag1, lag0
|
|
428
471
|
|
|
429
472
|
|
|
430
|
-
def
|
|
431
|
-
|
|
473
|
+
def filter_regex(
|
|
474
|
+
pattern: str,
|
|
475
|
+
/,
|
|
476
|
+
*strings: Iterable[str],
|
|
477
|
+
flags=re.IGNORECASE,
|
|
478
|
+
) -> Generator:
|
|
479
|
+
"""Filter iterable of strings with regex.
|
|
480
|
+
|
|
481
|
+
Examples
|
|
482
|
+
--------
|
|
483
|
+
>>> from functools import partial
|
|
484
|
+
>>> from onekit import pytlz
|
|
485
|
+
>>> list(pytlz.filter_regex("hello", "Hello, World!", "Hi, there!", "Hello!"))
|
|
486
|
+
['Hello, World!', 'Hello!']
|
|
487
|
+
|
|
488
|
+
>>> strings = [
|
|
489
|
+
... "Guiding principles for Python's design: The Zen of Python",
|
|
490
|
+
... "Beautiful is better than ugly.",
|
|
491
|
+
... "Explicit is better than implicit.",
|
|
492
|
+
... "Simple is better than complex.",
|
|
493
|
+
... ]
|
|
494
|
+
>>> list(pytlz.filter_regex("python", strings))
|
|
495
|
+
["Guiding principles for Python's design: The Zen of Python"]
|
|
496
|
+
|
|
497
|
+
>>> filter_regex__hi = partial(pytlz.filter_regex, "hi")
|
|
498
|
+
>>> list(filter_regex__hi("Hello, World!", "Hi, there!", "Hello!"))
|
|
499
|
+
['Hi, there!']
|
|
500
|
+
"""
|
|
501
|
+
return filter(functools.partial(re.findall, pattern, flags=flags), flatten(strings))
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
def flatten(*items: Iterable[Any]) -> Generator:
|
|
505
|
+
"""Flatten iterable of items.
|
|
432
506
|
|
|
433
507
|
Examples
|
|
434
508
|
--------
|
|
@@ -468,6 +542,49 @@ def func_name() -> str:
|
|
|
468
542
|
return inspect.stack()[1].function
|
|
469
543
|
|
|
470
544
|
|
|
545
|
+
def headline(text: str, /, *, n: int = 88, fillchar: str = "-") -> str:
|
|
546
|
+
"""Create headline string.
|
|
547
|
+
|
|
548
|
+
Examples
|
|
549
|
+
--------
|
|
550
|
+
>>> from onekit import pytlz
|
|
551
|
+
>>> pytlz.headline("Hello, World!", n=30)
|
|
552
|
+
'------- Hello, World! --------'
|
|
553
|
+
"""
|
|
554
|
+
return f" {text} ".center(n, fillchar)
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
def highlight_string_differences(lft_str: str, rgt_str: str, /) -> str:
|
|
558
|
+
"""Highlight differences between two strings.
|
|
559
|
+
|
|
560
|
+
Examples
|
|
561
|
+
--------
|
|
562
|
+
>>> from onekit import pytlz
|
|
563
|
+
>>> print(pytlz.highlight_string_differences("hello", "hall"))
|
|
564
|
+
hello
|
|
565
|
+
| |
|
|
566
|
+
hall
|
|
567
|
+
|
|
568
|
+
>>> # no differences when there is no '|' character
|
|
569
|
+
>>> print(pytlz.highlight_string_differences("hello", "hello"))
|
|
570
|
+
hello
|
|
571
|
+
<BLANKLINE>
|
|
572
|
+
hello
|
|
573
|
+
"""
|
|
574
|
+
return concat_strings(
|
|
575
|
+
os.linesep,
|
|
576
|
+
lft_str,
|
|
577
|
+
concat_strings(
|
|
578
|
+
"",
|
|
579
|
+
(
|
|
580
|
+
" " if x == y else "|"
|
|
581
|
+
for x, y in itertools.zip_longest(lft_str, rgt_str, fillvalue="")
|
|
582
|
+
),
|
|
583
|
+
),
|
|
584
|
+
rgt_str,
|
|
585
|
+
)
|
|
586
|
+
|
|
587
|
+
|
|
471
588
|
@toolz.curry
|
|
472
589
|
def isdivisibleby(n: int, x: Union[int, float], /) -> bool:
|
|
473
590
|
"""Evaluate if :math:`x` is evenly divisible by :math:`n`.
|
|
@@ -526,6 +643,37 @@ def isodd(x: Union[int, float], /) -> bool:
|
|
|
526
643
|
return toolz.complement(iseven)(x)
|
|
527
644
|
|
|
528
645
|
|
|
646
|
+
def map_regex(
|
|
647
|
+
pattern: str,
|
|
648
|
+
/,
|
|
649
|
+
*strings: Iterable[str],
|
|
650
|
+
flags=re.IGNORECASE,
|
|
651
|
+
) -> Generator:
|
|
652
|
+
"""Match regex to iterable of strings.
|
|
653
|
+
|
|
654
|
+
Examples
|
|
655
|
+
--------
|
|
656
|
+
>>> from functools import partial
|
|
657
|
+
>>> from onekit import pytlz
|
|
658
|
+
>>> list(pytlz.map_regex("hello", "Hello, World!", "Hi, there!", "Hello!"))
|
|
659
|
+
[['Hello'], [], ['Hello']]
|
|
660
|
+
|
|
661
|
+
>>> strings = [
|
|
662
|
+
... "Guiding principles for Python's design: The Zen of Python",
|
|
663
|
+
... "Beautiful is better than ugly.",
|
|
664
|
+
... "Explicit is better than implicit.",
|
|
665
|
+
... "Simple is better than complex.",
|
|
666
|
+
... ]
|
|
667
|
+
>>> list(pytlz.map_regex("python", strings))
|
|
668
|
+
[['Python', 'Python'], [], [], []]
|
|
669
|
+
|
|
670
|
+
>>> map_regex__hi = partial(pytlz.map_regex, "hi")
|
|
671
|
+
>>> list(map_regex__hi("Hello, World!", "Hi, there!", "Hello!"))
|
|
672
|
+
[[], ['Hi'], []]
|
|
673
|
+
"""
|
|
674
|
+
return map(functools.partial(re.findall, pattern, flags=flags), flatten(strings))
|
|
675
|
+
|
|
676
|
+
|
|
529
677
|
def num_to_str(x: Union[int, float], /) -> str:
|
|
530
678
|
"""Cast number to string with underscores as thousands separator.
|
|
531
679
|
|
|
@@ -542,8 +690,8 @@ def num_to_str(x: Union[int, float], /) -> str:
|
|
|
542
690
|
|
|
543
691
|
|
|
544
692
|
@toolz.curry
|
|
545
|
-
def reduce_sets(func: Callable[[set, set], set], /, *sets:
|
|
546
|
-
"""Apply function of two set arguments to reduce
|
|
693
|
+
def reduce_sets(func: Callable[[set, set], set], /, *sets: Iterable[set]) -> set:
|
|
694
|
+
"""Apply function of two set arguments to reduce iterable of sets.
|
|
547
695
|
|
|
548
696
|
Examples
|
|
549
697
|
--------
|
|
@@ -560,17 +708,29 @@ def reduce_sets(func: Callable[[set, set], set], /, *sets: Sequence[set]) -> set
|
|
|
560
708
|
{0, 1, 3}
|
|
561
709
|
|
|
562
710
|
>>> # function is curried
|
|
563
|
-
>>> pytlz.reduce_sets(set.union)(
|
|
711
|
+
>>> pytlz.reduce_sets(set.union)(*sets)
|
|
564
712
|
{0, 1, 2, 3, 4, 6, 8}
|
|
565
713
|
>>> pytlz.reduce_sets(set.union)(sets)
|
|
566
714
|
{0, 1, 2, 3, 4, 6, 8}
|
|
567
|
-
>>>
|
|
568
|
-
>>>
|
|
715
|
+
>>> union_sets = pytlz.reduce_sets(set.union)
|
|
716
|
+
>>> union_sets(x, y, z)
|
|
569
717
|
{0, 1, 2, 3, 4, 6, 8}
|
|
570
718
|
"""
|
|
571
719
|
return toolz.pipe(sets, flatten, map(set), reduce(func))
|
|
572
720
|
|
|
573
721
|
|
|
722
|
+
def remove_punctuation(text: str, /) -> str:
|
|
723
|
+
"""Remove punctuation from text string.
|
|
724
|
+
|
|
725
|
+
Examples
|
|
726
|
+
--------
|
|
727
|
+
>>> from onekit import pytlz
|
|
728
|
+
>>> pytlz.remove_punctuation("I think, therefore I am. --Descartes")
|
|
729
|
+
'I think therefore I am Descartes'
|
|
730
|
+
"""
|
|
731
|
+
return text.translate(str.maketrans("", "", string.punctuation))
|
|
732
|
+
|
|
733
|
+
|
|
574
734
|
def signif(x: Union[int, float], /, *, n: int = 3) -> Union[int, float]:
|
|
575
735
|
"""Round :math:`x` to its :math:`n` significant digits.
|
|
576
736
|
|
|
@@ -597,7 +757,7 @@ def signif(x: Union[int, float], /, *, n: int = 3) -> Union[int, float]:
|
|
|
597
757
|
|
|
598
758
|
|
|
599
759
|
def source_code(x: object, /) -> str:
|
|
600
|
-
"""Get source code of an object
|
|
760
|
+
"""Get source code of an object :math:`x`.
|
|
601
761
|
|
|
602
762
|
Examples
|
|
603
763
|
--------
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""PySpark toolz."""
|
|
2
2
|
|
|
3
3
|
import functools
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import Iterable
|
|
5
5
|
|
|
6
6
|
from pyspark.sql import DataFrame as SparkDF
|
|
7
7
|
|
|
@@ -10,8 +10,8 @@ from onekit import pytlz
|
|
|
10
10
|
__all__ = ("union",)
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def union(*dataframes:
|
|
14
|
-
"""Union
|
|
13
|
+
def union(*dataframes: Iterable[SparkDF]) -> SparkDF:
|
|
14
|
+
"""Union iterable of Spark dataframes by name.
|
|
15
15
|
|
|
16
16
|
Examples
|
|
17
17
|
--------
|
|
File without changes
|
|
File without changes
|
|
File without changes
|