stouputils 1.16.1__py3-none-any.whl → 1.16.3__py3-none-any.whl

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.
@@ -154,7 +154,7 @@ def launch_tests(root_dir: str, strict: bool = True, pattern: str = "*") -> int:
154
154
  return total_failed
155
155
 
156
156
 
157
- def test_module_with_progress(module: ModuleType, separator: str) -> TestResults:
157
+ def test_module_with_progress(module: "ModuleType", separator: str) -> "TestResults":
158
158
  """ Test a module with testmod and measure the time taken with progress printing.
159
159
 
160
160
  Args:
@@ -165,7 +165,7 @@ def test_module_with_progress(module: ModuleType, separator: str) -> TestResults
165
165
  """
166
166
  from doctest import testmod
167
167
  @measure_time(message=f"Testing module '{module.__name__}' {separator}took")
168
- def internal() -> TestResults:
168
+ def internal() -> "TestResults":
169
169
  return testmod(m=module)
170
170
  return internal()
171
171
 
@@ -141,10 +141,6 @@ def get_sphinx_conf_content(
141
141
  # Imports
142
142
  import sys
143
143
  from typing import Any
144
- import typing
145
-
146
- # Set TYPE_CHECKING to avoid import issues during documentation generation
147
- typing.TYPE_CHECKING = True
148
144
 
149
145
  # Add project_dir directory to Python path for module discovery
150
146
  sys.path.insert(0, "{parent_of_project_dir}")
stouputils/collections.py CHANGED
@@ -2,6 +2,7 @@
2
2
  This module provides utilities for collection manipulation:
3
3
 
4
4
  - unique_list: Remove duplicates from a list while preserving order using object id, hash or str
5
+ - at_least_n: Check if at least n elements in an iterable satisfy a given predicate
5
6
  - sort_dict_keys: Sort dictionary keys using a given order list (ascending or descending)
6
7
  - upsert_in_dataframe: Insert or update a row in a Polars DataFrame based on primary keys
7
8
  - array_to_disk: Easily handle large numpy arrays on disk using zarr for efficient storage and access.
@@ -15,7 +16,7 @@ import atexit
15
16
  import os
16
17
  import shutil
17
18
  import tempfile
18
- from collections.abc import Iterable
19
+ from collections.abc import Callable, Iterable
19
20
  from typing import TYPE_CHECKING, Any, Literal, TypeVar
20
21
 
21
22
  # Lazy imports for typing
@@ -77,6 +78,38 @@ def unique_list[T](list_to_clean: Iterable[T], method: Literal["id", "hash", "st
77
78
  # Return the cleaned list
78
79
  return result
79
80
 
81
+
82
+ def at_least_n(iterable: Iterable[T], predicate: Callable[[T], bool], n: int) -> bool:
83
+ """ Return True if at least n elements in iterable satisfy predicate.
84
+ It's like the built-in any() but for at least n matches.
85
+
86
+ Stops iterating as soon as n matches are found (short-circuit evaluation).
87
+
88
+ Args:
89
+ iterable (Iterable[T]): The iterable to check.
90
+ predicate (Callable[[T], bool]): The predicate to apply to items.
91
+ n (int): Minimum number of matches required.
92
+
93
+ Returns:
94
+ bool: True if at least n elements satisfy predicate, otherwise False.
95
+
96
+ Examples:
97
+ >>> at_least_n([1, 2, 3, 4, *[i for i in range(5, int(1e5))]], lambda x: x % 2 == 0, 2)
98
+ True
99
+ >>> at_least_n([1, 3, 5, 7], lambda x: x % 2 == 0, 1)
100
+ False
101
+ """
102
+ if n <= 0:
103
+ return True
104
+ count: int = 0
105
+ for item in iterable:
106
+ if predicate(item):
107
+ count += 1
108
+ if count >= n:
109
+ return True
110
+ return False
111
+
112
+
80
113
  def sort_dict_keys[T](dictionary: dict[T, Any], order: list[T], reverse: bool = False) -> dict[T, Any]:
81
114
  """ Sort dictionary keys using a given order list (reverse optional)
82
115
 
@@ -1,6 +1,6 @@
1
1
  import polars as pl
2
2
  import zarr
3
- from collections.abc import Iterable
3
+ from collections.abc import Callable as Callable, Iterable
4
4
  from numpy.typing import NDArray as NDArray
5
5
  from typing import Any, Literal, TypeVar
6
6
 
@@ -31,6 +31,26 @@ def unique_list[T](list_to_clean: Iterable[T], method: Literal['id', 'hash', 'st
31
31
  \t\t>>> unique_list([s1, s2, s1, s1, s3, s2, s3], method="str")
32
32
  \t\t[{1, 2, 3}, {2, 3, 4}]
33
33
  \t'''
34
+ def at_least_n(iterable: Iterable[T], predicate: Callable[[T], bool], n: int) -> bool:
35
+ """ Return True if at least n elements in iterable satisfy predicate.
36
+ \tIt's like the built-in any() but for at least n matches.
37
+
38
+ \tStops iterating as soon as n matches are found (short-circuit evaluation).
39
+
40
+ \tArgs:
41
+ \t\titerable\t(Iterable[T]):\t\t\tThe iterable to check.
42
+ \t\tpredicate\t(Callable[[T], bool]):\tThe predicate to apply to items.
43
+ \t\tn\t\t\t(int):\t\t\t\t\tMinimum number of matches required.
44
+
45
+ \tReturns:
46
+ \t\tbool: True if at least n elements satisfy predicate, otherwise False.
47
+
48
+ \tExamples:
49
+ \t\t>>> at_least_n([1, 2, 3, 4, *[i for i in range(5, int(1e5))]], lambda x: x % 2 == 0, 2)
50
+ \t\tTrue
51
+ \t\t>>> at_least_n([1, 3, 5, 7], lambda x: x % 2 == 0, 1)
52
+ \t\tFalse
53
+ \t"""
34
54
  def sort_dict_keys[T](dictionary: dict[T, Any], order: list[T], reverse: bool = False) -> dict[T, Any]:
35
55
  ''' Sort dictionary keys using a given order list (reverse optional)
36
56
 
stouputils/image.py CHANGED
@@ -28,7 +28,7 @@ PIL_Image_or_NDArray = TypeVar("PIL_Image_or_NDArray", bound="Image.Image | NDAr
28
28
  def image_resize[PIL_Image_or_NDArray](
29
29
  image: PIL_Image_or_NDArray,
30
30
  max_result_size: int,
31
- resampling: Image.Resampling | None = None,
31
+ resampling: "Image.Resampling | None" = None,
32
32
  min_or_max: Callable[[int, int], int] = max,
33
33
  return_type: type[PIL_Image_or_NDArray] | str = "same",
34
34
  keep_aspect_ratio: bool = True,
@@ -123,8 +123,8 @@ def image_resize[PIL_Image_or_NDArray](
123
123
 
124
124
  def auto_crop[PIL_Image_or_NDArray](
125
125
  image: PIL_Image_or_NDArray,
126
- mask: NDArray[np.bool_] | None = None,
127
- threshold: int | float | Callable[[NDArray[np.number]], int | float] | None = None,
126
+ mask: "NDArray[np.bool_] | None" = None,
127
+ threshold: int | float | Callable[["NDArray[np.number]"], int | float] | None = None,
128
128
  return_type: type[PIL_Image_or_NDArray] | str = "same",
129
129
  contiguous: bool = True,
130
130
  ) -> Any:
@@ -207,7 +207,7 @@ def auto_crop[PIL_Image_or_NDArray](
207
207
 
208
208
  # Convert to numpy array and store original type
209
209
  original_was_pil: bool = isinstance(image, Image.Image)
210
- image_array: NDArray[np.number] = np.array(image) if original_was_pil else image
210
+ image_array: NDArray[np.number] = np.array(image) if original_was_pil else image # type: ignore
211
211
 
212
212
  # Create mask if not provided
213
213
  if mask is None:
@@ -263,7 +263,7 @@ def auto_crop[PIL_Image_or_NDArray](
263
263
 
264
264
  def numpy_to_gif(
265
265
  path: str,
266
- array: NDArray[np.integer | np.floating | np.bool_],
266
+ array: "NDArray[np.integer | np.floating | np.bool_]",
267
267
  duration: int = 100,
268
268
  loop: int = 0,
269
269
  mkdir: bool = True,
@@ -344,7 +344,7 @@ def numpy_to_gif(
344
344
 
345
345
  def numpy_to_obj(
346
346
  path: str,
347
- array: NDArray[np.integer | np.floating | np.bool_],
347
+ array: "NDArray[np.integer | np.floating | np.bool_]",
348
348
  threshold: float = 0.5,
349
349
  step_size: int = 1,
350
350
  pad_array: bool = True,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: stouputils
3
- Version: 1.16.1
3
+ Version: 1.16.3
4
4
  Summary: Stouputils is a collection of utility modules designed to simplify and enhance the development process. It includes a range of tools for tasks such as execution of doctests, display utilities, decorators, as well as context managers, and many more.
5
5
  Keywords: utilities,tools,helpers,development,python
6
6
  Author: Stoupy51
@@ -93,7 +93,7 @@ Start now by installing the package: `pip install stouputils`.<br>
93
93
  ├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.io.html">io.py</a> <span class="comment"># 💾 Utilities for file management <span class="paren">(json_dump, json_load, csv_dump, csv_load, read_file, super_copy, super_open, clean_path, ...)</span></span>
94
94
  ├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.parallel.html">parallel.py</a> <span class="comment"># 🔀 Utility functions for parallel processing <span class="paren">(multiprocessing, multithreading, run_in_subprocess)</span></span>
95
95
  ├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.image.html">image.py</a> <span class="comment"># 🖼️ Little utilities for image processing <span class="paren">(image_resize, auto_crop, numpy_to_gif, numpy_to_obj)</span></span>
96
- ├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.collections.html">collections.py</a> <span class="comment"># 🧰 Utilities for collection manipulation <span class="paren">(unique_list, sort_dict_keys, upsert_in_dataframe, array_to_disk)</span></span>
96
+ ├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.collections.html">collections.py</a> <span class="comment"># 🧰 Utilities for collection manipulation <span class="paren">(unique_list, at_least_n, sort_dict_keys, upsert_in_dataframe, array_to_disk)</span></span>
97
97
  ├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.typing.html">typing.py</a> <span class="comment"># 📝 Utilities for typing enhancements <span class="paren">(IterAny, JsonDict, JsonList, ..., convert_to_serializable)</span></span>
98
98
  ├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.all_doctests.html">all_doctests.py</a> <span class="comment"># ✅ Run all doctests for all modules in a given directory <span class="paren">(launch_tests, test_module_with_progress)</span></span>
99
99
  ├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.backup.html">backup.py</a> <span class="comment"># 💾 Utilities for backup management <span class="paren">(delta backup, consolidate)</span></span>
@@ -3,11 +3,11 @@ stouputils/__init__.pyi,sha256=as5qRu9FfJdJwb_DheDTq6hA5y4UfIFgPwItNfPHMwU,374
3
3
  stouputils/__main__.py,sha256=MA3jjc1yL8_0Z9oB55BMqrFq1ot_-e5rNqSxFQGsMzs,2910
4
4
  stouputils/_deprecated.py,sha256=Bcq6YjdM9Rk9Vq-WMhc_tuEbPORX6U8HAJ9Vh-VIWTA,1478
5
5
  stouputils/_deprecated.pyi,sha256=6-8YsftJd2fRAdBLsysc6jf-uA8V2wiqkiFAbdfWfJQ,664
6
- stouputils/all_doctests.py,sha256=317v-B4kqf_8lkrw6ul1ZGBgZ75CYIqoDn7kG5k8qyc,6322
6
+ stouputils/all_doctests.py,sha256=PPh081zySANsZme52Bg3DwMqVlQpjrdgO13GctsCtFo,6328
7
7
  stouputils/all_doctests.pyi,sha256=R3FRKaQv3sTZbxLvvsChHZZKygVMhmL6pqrYYLqvZCg,2017
8
8
  stouputils/applications/__init__.py,sha256=dbjwZt8PZF043KoJSItqCpH32FtRxN5sgV-8Q2b1l10,457
9
9
  stouputils/applications/__init__.pyi,sha256=DTYq2Uqq1uLzCMkFByjRqdtREA-9SaQnp4QpgmCEPFg,56
10
- stouputils/applications/automatic_docs.py,sha256=CG63RiPyHTqYCCcYJnOumVAOoATS0wAOblVmo5L2Ay4,20683
10
+ stouputils/applications/automatic_docs.py,sha256=_6XbCuVi2EiSdkiPZ7XHr5mUGh2ZORev8Vd0tJDb0ug,20561
11
11
  stouputils/applications/automatic_docs.pyi,sha256=sfFXpVE5y5Z907HEjKzpZ_9zM34d-jKNDQCdMx7E-9s,6189
12
12
  stouputils/applications/upscaler/__init__.py,sha256=8vrca93OYu5GQJrZO1GvnAbptzyhu_L0DnP3M9unlA0,1142
13
13
  stouputils/applications/upscaler/__init__.pyi,sha256=VSp6Tq09ATCTdfnjhbDnu7lblaLLGbCNi-E22jYxa88,67
@@ -21,8 +21,8 @@ stouputils/archive.py,sha256=uDrPFxbY_C8SwUZRH4FWnYSoJKkFWynCx751zP9AHaY,12144
21
21
  stouputils/archive.pyi,sha256=Z2BbQAiErRYntv53QC9uf_XPw3tx3Oy73wB0Bbil11c,3246
22
22
  stouputils/backup.py,sha256=AE5WKMLiyk0VkRUfhmNfO2EUeUbZY5GTFVIuI5z7axA,20947
23
23
  stouputils/backup.pyi,sha256=-SLVykkR5U8479T84zjNPVBNnV193s0zyWjathY2DDA,4923
24
- stouputils/collections.py,sha256=Zi2OmlPmUPx-isZZpF9xYWU52OtzNqvSHGYM5use0AA,8838
25
- stouputils/collections.pyi,sha256=J6Sb-8oSVeD1K-j5zNBZo_cP5Bi5NDh2qN4n4QBJIZE,3508
24
+ stouputils/collections.py,sha256=rAIz4acCxGjZkuvUrb3u5laD130TaNKbng3AITMWffY,9851
25
+ stouputils/collections.pyi,sha256=g29fctQAjoJmx-CKh4S6buLSwH2SmivrTGYwc92KqxE,4323
26
26
  stouputils/continuous_delivery/__init__.py,sha256=JqPww29xZ-pp6OJDGhUj2dxyV9rgTTMUz0YDDVr9RaA,731
27
27
  stouputils/continuous_delivery/__init__.pyi,sha256=_Sz2D10n1CDEyY8qDFwXNKdr01HVxanY4qdq9aN19cc,117
28
28
  stouputils/continuous_delivery/cd_utils.py,sha256=fkaHk2V3j66uFAUsM2c_UddNhXW2KAQcrh7jVsH79pU,8594
@@ -111,7 +111,7 @@ stouputils/data_science/scripts/routine.py,sha256=FkTLzmcdm_qUp69D-dPAKJm2RfXZZL
111
111
  stouputils/data_science/utils.py,sha256=HFXI2RQZ53RbBOn_4Act2bi0z4xQlTtsuR5Am80v9JU,11084
112
112
  stouputils/decorators.py,sha256=miZ8r2g8VhmQs2_knkKuUagdQabriZe7w0fCOEB69Nw,21838
113
113
  stouputils/decorators.pyi,sha256=vbPRsvox4dotqcln3StgE6iZ1cWCOeAn56M9zMpdw2U,10948
114
- stouputils/image.py,sha256=uGBweT-60JEn4SK5nVAxqiVI4Ijh4YyG_d5uXjXgtCY,16603
114
+ stouputils/image.py,sha256=xojXhpXGee6SjvyJ77f7GBQiLskWAW6RQhB_ZhpVpAk,16628
115
115
  stouputils/image.pyi,sha256=B7aypF1kHsEHHzwTnbcINLam32H4iJJBRxsegwt2n78,8455
116
116
  stouputils/installer/__init__.py,sha256=DBwI9w3xvw0NR_jDMxmURwPi1F79kPLe7EuNjmrxW_U,502
117
117
  stouputils/installer/__init__.pyi,sha256=ZB-8frAUOW-0pCEJL-e2AdbFodivv46v3EBYwEXCxRo,117
@@ -136,7 +136,7 @@ stouputils/typing.py,sha256=TwvxrvxhBRkyHkoOpfyXebN13M3xJb8MAjKXiNIWjew,2205
136
136
  stouputils/typing.pyi,sha256=U2UmFZausMYpnsUQROQE2JOwHcjx2hKV0rJuOdR57Ew,1341
137
137
  stouputils/version_pkg.py,sha256=Jsp-s03L14DkiZ94vQgrlQmaxApfn9DC8M_nzT1SJLk,7014
138
138
  stouputils/version_pkg.pyi,sha256=QPvqp1U3QA-9C_CC1dT9Vahv1hXEhstbM7x5uzMZSsQ,755
139
- stouputils-1.16.1.dist-info/WHEEL,sha256=XV0cjMrO7zXhVAIyyc8aFf1VjZ33Fen4IiJk5zFlC3g,80
140
- stouputils-1.16.1.dist-info/entry_points.txt,sha256=tx0z9VOnE-sfkmbFbA93zaBMzV3XSsKEJa_BWIqUzxw,57
141
- stouputils-1.16.1.dist-info/METADATA,sha256=v2w5_MQbls9c4YUR3tgoJgqCq1fUfCGg50gpG68JPqw,13890
142
- stouputils-1.16.1.dist-info/RECORD,,
139
+ stouputils-1.16.3.dist-info/WHEEL,sha256=XV0cjMrO7zXhVAIyyc8aFf1VjZ33Fen4IiJk5zFlC3g,80
140
+ stouputils-1.16.3.dist-info/entry_points.txt,sha256=tx0z9VOnE-sfkmbFbA93zaBMzV3XSsKEJa_BWIqUzxw,57
141
+ stouputils-1.16.3.dist-info/METADATA,sha256=vrF8jqYs56Ql7uRR7qcSCr17ehLFOwlL9PDL0rwH2VA,13902
142
+ stouputils-1.16.3.dist-info/RECORD,,