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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: onekit
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: One package for utility functions.
5
5
  Home-page: https://github.com/estripling/onekit
6
6
  License: BSD 3-Clause
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "onekit"
3
- version = "0.6.0"
3
+ version = "0.7.0"
4
4
  description = "One package for utility functions."
5
5
  authors = ["onekit developers"]
6
6
  license = "BSD 3-Clause"
@@ -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
- "all_predicate_true",
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 all_predicate_true(*predicates: Sequence[Predicate]) -> Predicate:
52
- """Evaluate if every predicate is true.
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.all_predicate_true(lambda x: x % 2 == 0, lambda x: x % 5 == 0)(10)
74
+ >>> pytlz.are_predicates_true(all, lambda x: x % 2 == 0, lambda x: x % 5 == 0)(10)
60
75
  True
61
76
 
62
- >>> is_divisible_by_3_and_5 = pytlz.all_predicate_true(
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.any_predicate_true(
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 any(predicate(x) for predicate in flatten(predicates))
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 flatten(*items: Sequence[Any]) -> Generator:
431
- """Flatten sequence of items.
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: Sequence[set]) -> set:
546
- """Apply function of two set arguments to reduce a sequence of sets.
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)(x, y, z)
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
- >>> set_union = pytlz.reduce_sets(set.union)
568
- >>> set_union(*sets)
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 Sequence
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: Sequence[SparkDF]) -> SparkDF:
14
- """Union sequence of Spark dataframes by name.
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