stouputils 1.19.4__py3-none-any.whl → 1.20.0__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.
@@ -28,6 +28,7 @@ def multiprocessing[T, R](
28
28
  capture_output: bool = False,
29
29
  delay_first_calls: float = 0,
30
30
  nice: int | None = None,
31
+ process_title: str | None = None,
31
32
  color: str = MAGENTA,
32
33
  bar_format: str = BAR_FORMAT,
33
34
  ascii: bool = False,
@@ -61,6 +62,7 @@ def multiprocessing[T, R](
61
62
  Positive values reduce priority, negative values increase it.
62
63
  Automatically converted to appropriate priority class on Windows.
63
64
  If None, no priority adjustment is made.
65
+ process_title (str | None): If provided, sets the process title for worker processes.
64
66
  color (str): Color of the progress bar (Defaults to MAGENTA)
65
67
  bar_format (str): Format of the progress bar (Defaults to BAR_FORMAT)
66
68
  ascii (bool): Whether to use ASCII or Unicode characters for the progress bar
@@ -139,6 +141,11 @@ def multiprocessing[T, R](
139
141
  wrapped_args = args
140
142
  wrapped_func = func
141
143
 
144
+ # Wrap function with process_title if specified
145
+ if process_title is not None:
146
+ wrapped_args = [(process_title, i, wrapped_func, arg) for i, arg in enumerate(wrapped_args)]
147
+ wrapped_func = process_title_wrapper
148
+
142
149
  # Capture output if specified
143
150
  capturer: CaptureOutput | None = None
144
151
  if capture_output:
@@ -307,3 +314,20 @@ def capture_subprocess_output[T, R](args: tuple[CaptureOutput, Callable[[T], R],
307
314
  capturer.redirect()
308
315
  return func(arg)
309
316
 
317
+
318
+ # "Private" function for setting process title in multiprocessing subprocess
319
+ def process_title_wrapper[T, R](args: tuple[str, int, Callable[[T], R], T]) -> R:
320
+ """ Wrapper function to set the process title before executing the target function.
321
+
322
+ Args:
323
+ tuple[str,int,Callable,T]: Tuple containing:
324
+ str: Process title to set
325
+ int: Worker index to append to title
326
+ Callable: Target function to execute
327
+ T: Argument to pass to the target function
328
+ """
329
+ process_title, index, func, arg = args
330
+ import setproctitle
331
+ setproctitle.setproctitle(f"{process_title} #{index}")
332
+ return func(arg)
333
+
@@ -7,7 +7,7 @@ from typing import Any
7
7
 
8
8
  def doctest_square(x: int) -> int: ...
9
9
  def doctest_slow(x: int) -> int: ...
10
- def multiprocessing[T, R](func: Callable[..., R] | list[Callable[..., R]], args: Iterable[T], use_starmap: bool = False, chunksize: int = 1, desc: str = '', max_workers: int | float = ..., capture_output: bool = False, delay_first_calls: float = 0, nice: int | None = None, color: str = ..., bar_format: str = ..., ascii: bool = False, smooth_tqdm: bool = True, **tqdm_kwargs: Any) -> list[R]:
10
+ def multiprocessing[T, R](func: Callable[..., R] | list[Callable[..., R]], args: Iterable[T], use_starmap: bool = False, chunksize: int = 1, desc: str = '', max_workers: int | float = ..., capture_output: bool = False, delay_first_calls: float = 0, nice: int | None = None, process_title: str | None = None, color: str = ..., bar_format: str = ..., ascii: bool = False, smooth_tqdm: bool = True, **tqdm_kwargs: Any) -> list[R]:
11
11
  ''' Method to execute a function in parallel using multiprocessing
12
12
 
13
13
  \t- For CPU-bound operations where the GIL (Global Interpreter Lock) is a bottleneck.
@@ -35,6 +35,7 @@ def multiprocessing[T, R](func: Callable[..., R] | list[Callable[..., R]], args:
35
35
  \t\t\tPositive values reduce priority, negative values increase it.
36
36
  \t\t\tAutomatically converted to appropriate priority class on Windows.
37
37
  \t\t\tIf None, no priority adjustment is made.
38
+ \t\tprocess_title\t\t(str | None):\t\tIf provided, sets the process title for worker processes.
38
39
  \t\tcolor\t\t\t\t(str):\t\t\t\tColor of the progress bar (Defaults to MAGENTA)
39
40
  \t\tbar_format\t\t\t(str):\t\t\t\tFormat of the progress bar (Defaults to BAR_FORMAT)
40
41
  \t\tascii\t\t\t\t(bool):\t\t\t\tWhether to use ASCII or Unicode characters for the progress bar
@@ -136,3 +137,13 @@ def capture_subprocess_output[T, R](args: tuple[CaptureOutput, Callable[[T], R],
136
137
  \t\t\tCallable: Target function to execute
137
138
  \t\t\tT: Argument to pass to the target function
138
139
  \t"""
140
+ def process_title_wrapper[T, R](args: tuple[str, int, Callable[[T], R], T]) -> R:
141
+ """ Wrapper function to set the process title before executing the target function.
142
+
143
+ \tArgs:
144
+ \t\ttuple[str,int,Callable,T]: Tuple containing:
145
+ \t\t\tstr: Process title to set
146
+ \t\t\tint: Worker index to append to title
147
+ \t\t\tCallable: Target function to execute
148
+ \t\t\tT: Argument to pass to the target function
149
+ \t"""
@@ -24,6 +24,7 @@ def run_in_subprocess[R](
24
24
  timeout: float | None = None,
25
25
  no_join: bool = False,
26
26
  capture_output: bool = False,
27
+ process_title: str | None = None,
27
28
  **kwargs: Any
28
29
  ) -> R:
29
30
  """ Execute a function in a subprocess with positional and keyword arguments.
@@ -38,10 +39,11 @@ def run_in_subprocess[R](
38
39
  *args (Any): Positional arguments to pass to the function.
39
40
  timeout (float | None): Maximum time in seconds to wait for the subprocess.
40
41
  If None, wait indefinitely. If the subprocess exceeds this time, it will be terminated.
41
- no_join (bool): If True, do not wait for the subprocess to finish (fire-and-forget).
42
+ no_join (bool): If True, do not wait for the subprocess to finish (fire-and-forget) and return the Process object.
42
43
  capture_output (bool): If True, capture the subprocess' stdout/stderr and relay it
43
44
  in real time to the parent's stdout. This enables seeing print() output
44
45
  from the subprocess in the main process.
46
+ process_title (str | None): If provided, sets the process title visible in process lists.
45
47
  **kwargs (Any): Keyword arguments to pass to the function.
46
48
 
47
49
  Returns:
@@ -60,10 +62,10 @@ def run_in_subprocess[R](
60
62
  25
61
63
 
62
64
  > # Function with multiple arguments
63
- > def add(a: int, b: int) -> int:
64
- . return a + b
65
- > run_in_subprocess(add, 10, 20)
66
- 30
65
+ > def add(a: int, b: int, c: int) -> int:
66
+ . return a + b + c
67
+ > run_in_subprocess(add, 10, 20, c=30)
68
+ 60
67
69
 
68
70
  > # Function with keyword arguments
69
71
  > def greet(name: str, greeting: str = "Hello") -> str:
@@ -89,10 +91,19 @@ def run_in_subprocess[R](
89
91
  process: mp.Process = mp.Process(
90
92
  target=_subprocess_wrapper,
91
93
  args=(result_queue, func, args, kwargs),
92
- kwargs={"_capturer": capturer}
94
+ kwargs={"capturer": capturer, "process_title": process_title}
93
95
  )
94
96
  process.start()
95
97
 
98
+ # Function to kill the process safely
99
+ def kill_process() -> None:
100
+ if process.is_alive():
101
+ process.terminate()
102
+ time.sleep(0.5)
103
+ if process.is_alive():
104
+ process.kill()
105
+ process.join()
106
+
96
107
  # For capture_output we must close the parent's copy of the write fd and start listener
97
108
  if capturer is not None:
98
109
  capturer.parent_close_write()
@@ -101,36 +112,24 @@ def run_in_subprocess[R](
101
112
  # Detach process if no_join (fire-and-forget)
102
113
  if result_queue is None:
103
114
  # If capturing, leave listener running in background (daemon)
104
- return None # type: ignore
115
+ return process # type: ignore
105
116
 
106
117
  # Use a single try/finally to ensure we always drain the listener once
107
118
  # and avoid repeating join calls in multiple branches.
108
119
  try:
109
- process.join(timeout=timeout)
110
-
111
- # Check if process is still alive (timed out)
112
- if process.is_alive():
113
- process.terminate()
114
- time.sleep(0.5) # Give it a moment to terminate gracefully
115
- if process.is_alive():
116
- process.kill()
117
- process.join()
118
- raise TimeoutError(f"Subprocess exceeded timeout of {timeout} seconds and was terminated")
119
-
120
- # Retrieve the payload if present
121
- result_payload: JsonDict | None = result_queue.get_nowait() if not result_queue.empty() else None
120
+ try:
121
+ result_payload: JsonDict = result_queue.get(timeout=timeout)
122
+ except Exception as e:
123
+ # Queue.get timed out or failed
124
+ raise TimeoutError(f"Subprocess exceeded timeout of {timeout} seconds and was terminated") from e
125
+ finally:
126
+ kill_process()
122
127
 
123
128
  # If the child sent a structured exception, raise it with the formatted traceback
124
- if isinstance(result_payload, dict):
125
- if result_payload.pop("ok", False) is False:
126
- raise RemoteSubprocessError(**result_payload)
127
- else:
128
- return result_payload["result"]
129
-
130
- # Raise an error according to the exit code presence
131
- if process.exitcode != 0:
132
- raise RuntimeError(f"Subprocess failed with exit code {process.exitcode}")
133
- raise RuntimeError("Subprocess did not return any result")
129
+ if result_payload.pop("ok", False) is False:
130
+ raise RemoteSubprocessError(**result_payload)
131
+ else:
132
+ return result_payload["result"]
134
133
 
135
134
  # Finally, ensure we drain/join the listener if capturing output
136
135
  finally:
@@ -144,7 +143,8 @@ def _subprocess_wrapper[R](
144
143
  func: Callable[..., R],
145
144
  args: tuple[Any, ...],
146
145
  kwargs: dict[str, Any],
147
- _capturer: CaptureOutput | None = None
146
+ capturer: CaptureOutput | None = None,
147
+ process_title: str | None = None
148
148
  ) -> None:
149
149
  """ Wrapper function to execute the target function and store the result in the queue.
150
150
 
@@ -155,12 +155,18 @@ def _subprocess_wrapper[R](
155
155
  func (Callable): The target function to execute.
156
156
  args (tuple): Positional arguments for the function.
157
157
  kwargs (dict): Keyword arguments for the function.
158
- _capturer (CaptureOutput | None): Optional CaptureOutput instance for stdout capture.
158
+ capturer (CaptureOutput | None): Optional CaptureOutput instance for stdout capture.
159
+ process_title (str | None): Optional process title to set.
159
160
  """
160
161
  try:
162
+ # Set process title if provided
163
+ if process_title is not None:
164
+ import setproctitle
165
+ setproctitle.setproctitle(process_title)
166
+
161
167
  # If a CaptureOutput instance was passed, redirect stdout/stderr to the pipe.
162
- if _capturer is not None:
163
- _capturer.redirect()
168
+ if capturer is not None:
169
+ capturer.redirect()
164
170
 
165
171
  # Execute the target function and put the result in the queue
166
172
  result: R = func(*args, **kwargs)
@@ -11,7 +11,7 @@ class RemoteSubprocessError(RuntimeError):
11
11
  remote_traceback: Incomplete
12
12
  def __init__(self, exc_type: str, exc_repr: str, traceback_str: str) -> None: ...
13
13
 
14
- def run_in_subprocess[R](func: Callable[..., R], *args: Any, timeout: float | None = None, no_join: bool = False, capture_output: bool = False, **kwargs: Any) -> R:
14
+ def run_in_subprocess[R](func: Callable[..., R], *args: Any, timeout: float | None = None, no_join: bool = False, capture_output: bool = False, process_title: str | None = None, **kwargs: Any) -> R:
15
15
  ''' Execute a function in a subprocess with positional and keyword arguments.
16
16
 
17
17
  \tThis is useful when you need to run a function in isolation to avoid memory leaks,
@@ -24,10 +24,11 @@ def run_in_subprocess[R](func: Callable[..., R], *args: Any, timeout: float | No
24
24
  \t\t*args (Any): Positional arguments to pass to the function.
25
25
  \t\ttimeout (float | None): Maximum time in seconds to wait for the subprocess.
26
26
  \t\t\tIf None, wait indefinitely. If the subprocess exceeds this time, it will be terminated.
27
- \t\tno_join (bool): If True, do not wait for the subprocess to finish (fire-and-forget).
27
+ \t\tno_join (bool): If True, do not wait for the subprocess to finish (fire-and-forget) and return the Process object.
28
28
  \t\tcapture_output (bool): If True, capture the subprocess\' stdout/stderr and relay it
29
29
  \t\t\tin real time to the parent\'s stdout. This enables seeing print() output
30
30
  \t\t\tfrom the subprocess in the main process.
31
+ \t\tprocess_title (str | None): If provided, sets the process title visible in process lists.
31
32
  \t\t**kwargs (Any): Keyword arguments to pass to the function.
32
33
 
33
34
  \tReturns:
@@ -46,10 +47,10 @@ def run_in_subprocess[R](func: Callable[..., R], *args: Any, timeout: float | No
46
47
  \t\t\t25
47
48
 
48
49
  \t\t\t> # Function with multiple arguments
49
- \t\t\t> def add(a: int, b: int) -> int:
50
- \t\t\t. return a + b
51
- \t\t\t> run_in_subprocess(add, 10, 20)
52
- \t\t\t30
50
+ \t\t\t> def add(a: int, b: int, c: int) -> int:
51
+ \t\t\t. return a + b + c
52
+ \t\t\t> run_in_subprocess(add, 10, 20, c=30)
53
+ \t\t\t60
53
54
 
54
55
  \t\t\t> # Function with keyword arguments
55
56
  \t\t\t> def greet(name: str, greeting: str = "Hello") -> str:
@@ -60,7 +61,7 @@ def run_in_subprocess[R](func: Callable[..., R], *args: Any, timeout: float | No
60
61
  \t\t\t> # With timeout to prevent hanging
61
62
  \t\t\t> run_in_subprocess(some_gpu_func, data, timeout=300.0)
62
63
  \t'''
63
- def _subprocess_wrapper[R](result_queue: Any, func: Callable[..., R], args: tuple[Any, ...], kwargs: dict[str, Any], _capturer: CaptureOutput | None = None) -> None:
64
+ def _subprocess_wrapper[R](result_queue: Any, func: Callable[..., R], args: tuple[Any, ...], kwargs: dict[str, Any], capturer: CaptureOutput | None = None, process_title: str | None = None) -> None:
64
65
  """ Wrapper function to execute the target function and store the result in the queue.
65
66
 
66
67
  \tMust be at module level to be pickable on Windows (spawn context).
@@ -70,5 +71,6 @@ def _subprocess_wrapper[R](result_queue: Any, func: Callable[..., R], args: tupl
70
71
  \t\tfunc (Callable): The target function to execute.
71
72
  \t\targs (tuple): Positional arguments for the function.
72
73
  \t\tkwargs (dict): Keyword arguments for the function.
73
- \t\t_capturer (CaptureOutput | None): Optional CaptureOutput instance for stdout capture.
74
+ \t\tcapturer (CaptureOutput | None): Optional CaptureOutput instance for stdout capture.
75
+ \t\tprocess_title (str | None): Optional process title to set.
74
76
  \t"""
stouputils/print.py CHANGED
@@ -375,49 +375,29 @@ def info(
375
375
  else:
376
376
  print(message, *values, RESET, file=file, **print_kwargs)
377
377
 
378
- def debug(*values: Any, flush: bool = True, **print_kwargs: Any) -> None:
378
+ def debug(*values: Any, flush: bool = True, color: str = CYAN, text: str = "DEBUG", **print_kwargs: Any) -> None:
379
379
  """ Print a debug message looking like "[DEBUG HH:MM:SS] message" in cyan by default. """
380
- if "text" not in print_kwargs:
381
- print_kwargs["text"] = "DEBUG"
382
- if "color" not in print_kwargs:
383
- print_kwargs["color"] = CYAN
384
- info(*values, flush=flush, **print_kwargs)
380
+ info(*values, flush=flush, color=color, text=text, **print_kwargs)
385
381
 
386
- def alt_debug(*values: Any, flush: bool = True, **print_kwargs: Any) -> None:
382
+ def alt_debug(*values: Any, flush: bool = True, color: str = BLUE, text: str = "DEBUG", **print_kwargs: Any) -> None:
387
383
  """ Print a debug message looking like "[DEBUG HH:MM:SS] message" in blue by default. """
388
- if "text" not in print_kwargs:
389
- print_kwargs["text"] = "DEBUG"
390
- if "color" not in print_kwargs:
391
- print_kwargs["color"] = BLUE
392
- info(*values, flush=flush, **print_kwargs)
384
+ info(*values, flush=flush, color=color, text=text, **print_kwargs)
393
385
 
394
- def suggestion(*values: Any, flush: bool = True, **print_kwargs: Any) -> None:
386
+ def suggestion(*values: Any, flush: bool = True, color: str = CYAN, text: str = "SUGGESTION", **print_kwargs: Any) -> None:
395
387
  """ Print a suggestion message looking like "[SUGGESTION HH:MM:SS] message" in cyan by default. """
396
- if "text" not in print_kwargs:
397
- print_kwargs["text"] = "SUGGESTION"
398
- if "color" not in print_kwargs:
399
- print_kwargs["color"] = CYAN
400
- info(*values, flush=flush, **print_kwargs)
388
+ info(*values, flush=flush, color=color, text=text, **print_kwargs)
401
389
 
402
- def progress(*values: Any, flush: bool = True, **print_kwargs: Any) -> None:
390
+ def progress(*values: Any, flush: bool = True, color: str = MAGENTA, text: str = "PROGRESS", **print_kwargs: Any) -> None:
403
391
  """ Print a progress message looking like "[PROGRESS HH:MM:SS] message" in magenta by default. """
404
- if "text" not in print_kwargs:
405
- print_kwargs["text"] = "PROGRESS"
406
- if "color" not in print_kwargs:
407
- print_kwargs["color"] = MAGENTA
408
- info(*values, flush=flush, **print_kwargs)
392
+ info(*values, flush=flush, color=color, text=text, **print_kwargs)
409
393
 
410
- def warning(*values: Any, flush: bool = True, **print_kwargs: Any) -> None:
394
+ def warning(*values: Any, flush: bool = True, color: str = YELLOW, text: str = "WARNING", **print_kwargs: Any) -> None:
411
395
  """ Print a warning message looking like "[WARNING HH:MM:SS] message" in yellow by default and in sys.stderr. """
412
396
  if "file" not in print_kwargs:
413
397
  print_kwargs["file"] = sys.stderr
414
- if "text" not in print_kwargs:
415
- print_kwargs["text"] = "WARNING"
416
- if "color" not in print_kwargs:
417
- print_kwargs["color"] = YELLOW
418
- info(*values, flush=flush, **print_kwargs)
398
+ info(*values, flush=flush, color=color, text=text, **print_kwargs)
419
399
 
420
- def error(*values: Any, exit: bool = False, flush: bool = True, **print_kwargs: Any) -> None:
400
+ def error(*values: Any, exit: bool = False, flush: bool = True, color: str = RED, text: str = "ERROR", **print_kwargs: Any) -> None:
421
401
  """ Print an error message (in sys.stderr and in red by default)
422
402
  and optionally ask the user to continue or stop the program.
423
403
 
@@ -425,6 +405,9 @@ def error(*values: Any, exit: bool = False, flush: bool = True, **print_kwargs:
425
405
  values (Any): Values to print (like the print function)
426
406
  exit (bool): Whether to ask the user to continue or stop the program,
427
407
  false to ignore the error automatically and continue
408
+ flush (bool): Whether to flush the output
409
+ color (str): Color of the message (default: RED)
410
+ text (str): Text in the message (replaces "ERROR ")
428
411
  print_kwargs (dict): Keyword arguments to pass to the print function
429
412
  """
430
413
  file: TextIO = sys.stderr
@@ -433,11 +416,7 @@ def error(*values: Any, exit: bool = False, flush: bool = True, **print_kwargs:
433
416
  file = cast(TextIO, print_kwargs["file"][0])
434
417
  else:
435
418
  file = print_kwargs["file"]
436
- if "text" not in print_kwargs:
437
- print_kwargs["text"] = "ERROR"
438
- if "color" not in print_kwargs:
439
- print_kwargs["color"] = RED
440
- info(*values, flush=flush, **print_kwargs)
419
+ info(*values, flush=flush, color=color, text=text, **print_kwargs)
441
420
  if exit:
442
421
  try:
443
422
  print("Press enter to ignore error and continue, or 'CTRL+C' to stop the program... ", file=file)
@@ -452,6 +431,7 @@ def whatisit(
452
431
  flush: bool = True,
453
432
  max_length: int = 250,
454
433
  color: str = CYAN,
434
+ text: str = "What is it?",
455
435
  **print_kwargs: Any,
456
436
  ) -> None:
457
437
  """ Print the type of each value and the value itself, with its id and length/shape.
@@ -463,6 +443,7 @@ def whatisit(
463
443
  print_function (Callable): Function to use to print the values (default: debug())
464
444
  max_length (int): Maximum length of the value string to print (default: 250)
465
445
  color (str): Color of the message (default: CYAN)
446
+ text (str): Text in the message (replaces "DEBUG")
466
447
  print_kwargs (dict): Keyword arguments to pass to the print function
467
448
  """
468
449
  def _internal(value: Any) -> str:
@@ -471,15 +452,22 @@ def whatisit(
471
452
  # Build metadata parts list
472
453
  metadata_parts: list[str] = []
473
454
 
474
- # Get the dtype if available
475
- try:
476
- metadata_parts.append(f"dtype: {value.dtype}")
477
- except (AttributeError, TypeError):
478
- pass
455
+ # Get attributes if available (with priority order)
456
+ for attributes in [("dtype","dtypes"),("nbytes","memory_usage"),("device",)]:
457
+ # Find the first available attribute of the current tuple
458
+ for attr in attributes:
459
+ try:
460
+ attr_value = getattr(value, attr)
461
+ if attr_value is not None:
462
+ metadata_parts.append(f"{attr}: {attr_value}")
463
+ break
464
+ except (AttributeError, TypeError):
465
+ continue
479
466
 
480
467
  # Get the shape or length of the value
481
468
  try:
482
- metadata_parts.append(f"shape: {value.shape}")
469
+ if value.shape:
470
+ metadata_parts.append(f"shape: {value.shape}")
483
471
  except (AttributeError, TypeError):
484
472
  try:
485
473
  metadata_parts.append(f"length: {len(value)}")
@@ -511,37 +499,28 @@ def whatisit(
511
499
  # Return the formatted string
512
500
  return f"{type(value)}, <id {id(value)}>: {metadata_str}{value_str}"
513
501
 
514
- # Add the color to the message
515
- if "color" not in print_kwargs:
516
- print_kwargs["color"] = color
517
-
518
- # Set text to "What is it?" if not already set
519
- if "text" not in print_kwargs:
520
- print_kwargs["text"] = "What is it?"
521
-
522
502
  # Print the values
523
503
  if len(values) > 1:
524
- print_function("".join(f"\n {_internal(value)}" for value in values), flush=flush, **print_kwargs)
504
+ print_function("".join(f"\n {_internal(value)}" for value in values), flush=flush, color=color, text=text, **print_kwargs)
525
505
  elif len(values) == 1:
526
- print_function(_internal(values[0]), flush=flush, **print_kwargs)
506
+ print_function(_internal(values[0]), flush=flush, color=color, text=text, **print_kwargs)
527
507
 
528
- def breakpoint(*values: Any, print_function: Callable[..., None] = warning, flush: bool = True, **print_kwargs: Any) -> None:
508
+ def breakpoint(*values: Any, print_function: Callable[..., None] = warning, flush: bool = True, text: str = "BREAKPOINT (press Enter)", **print_kwargs: Any) -> None:
529
509
  """ Breakpoint function, pause the program and print the values.
530
510
 
531
511
  Args:
532
512
  values (Any): Values to print
533
513
  print_function (Callable): Function to use to print the values (default: warning())
514
+ text (str): Text in the message (replaces "WARNING")
534
515
  print_kwargs (dict): Keyword arguments to pass to the print function
535
516
  """
536
- if "text" not in print_kwargs:
537
- print_kwargs["text"] = "BREAKPOINT (press Enter)"
538
517
  file: TextIO = sys.stderr
539
518
  if "file" in print_kwargs:
540
519
  if isinstance(print_kwargs["file"], list):
541
520
  file = cast(TextIO, print_kwargs["file"][0])
542
521
  else:
543
522
  file = print_kwargs["file"]
544
- whatisit(*values, print_function=print_function, flush=flush, **print_kwargs)
523
+ whatisit(*values, print_function=print_function, flush=flush, text=text, **print_kwargs)
545
524
  try:
546
525
  input()
547
526
  except (KeyboardInterrupt, EOFError):
@@ -700,24 +679,24 @@ def current_time() -> str:
700
679
  return time.strftime("%H:%M:%S")
701
680
 
702
681
  # Convenience colored functions
703
- def infoc(*args: Any, **kwargs: Any) -> None:
704
- return info(*args, use_colored=True, **kwargs)
705
- def debugc(*args: Any, **kwargs: Any) -> None:
706
- return debug(*args, use_colored=True, **kwargs)
707
- def alt_debugc(*args: Any, **kwargs: Any) -> None:
708
- return alt_debug(*args, use_colored=True, **kwargs)
709
- def warningc(*args: Any, **kwargs: Any) -> None:
710
- return warning(*args, use_colored=True, **kwargs)
711
- def errorc(*args: Any, **kwargs: Any) -> None:
712
- return error(*args, use_colored=True, **kwargs)
713
- def progressc(*args: Any, **kwargs: Any) -> None:
714
- return progress(*args, use_colored=True, **kwargs)
715
- def suggestionc(*args: Any, **kwargs: Any) -> None:
716
- return suggestion(*args, use_colored=True, **kwargs)
717
- def whatisitc(*args: Any, **kwargs: Any) -> None:
718
- return whatisit(*args, use_colored=True, **kwargs)
719
- def breakpointc(*args: Any, **kwargs: Any) -> None:
720
- return breakpoint(*args, use_colored=True, **kwargs)
682
+ def infoc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None:
683
+ return info(*args, use_colored=use_colored, **kwargs)
684
+ def debugc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None:
685
+ return debug(*args, use_colored=use_colored, **kwargs)
686
+ def alt_debugc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None:
687
+ return alt_debug(*args, use_colored=use_colored, **kwargs)
688
+ def warningc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None:
689
+ return warning(*args, use_colored=use_colored, **kwargs)
690
+ def errorc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None:
691
+ return error(*args, use_colored=use_colored, **kwargs)
692
+ def progressc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None:
693
+ return progress(*args, use_colored=use_colored, **kwargs)
694
+ def suggestionc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None:
695
+ return suggestion(*args, use_colored=use_colored, **kwargs)
696
+ def whatisitc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None:
697
+ return whatisit(*args, use_colored=use_colored, **kwargs)
698
+ def breakpointc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None:
699
+ return breakpoint(*args, use_colored=use_colored, **kwargs)
721
700
 
722
701
 
723
702
  # Test the print functions
@@ -747,7 +726,7 @@ if __name__ == "__main__":
747
726
  # Test whatisit with different types
748
727
  import numpy as np
749
728
  print()
750
- whatisit(
729
+ whatisitc(
751
730
  123,
752
731
  "Hello World",
753
732
  [1, 2, 3, 4, 5],
stouputils/print.pyi CHANGED
@@ -147,27 +147,30 @@ def info(*values: Any, color: str = ..., text: str = 'INFO ', prefix: str = '',
147
147
  \t\tuse_colored\t\t(bool):\t\t\t\t\tWhether to use the colored() function to format the message
148
148
  \t\tprint_kwargs\t(dict):\t\t\t\t\tKeyword arguments to pass to the print function
149
149
  \t'''
150
- def debug(*values: Any, flush: bool = True, **print_kwargs: Any) -> None:
150
+ def debug(*values: Any, flush: bool = True, color: str = ..., text: str = 'DEBUG', **print_kwargs: Any) -> None:
151
151
  ''' Print a debug message looking like "[DEBUG HH:MM:SS] message" in cyan by default. '''
152
- def alt_debug(*values: Any, flush: bool = True, **print_kwargs: Any) -> None:
152
+ def alt_debug(*values: Any, flush: bool = True, color: str = ..., text: str = 'DEBUG', **print_kwargs: Any) -> None:
153
153
  ''' Print a debug message looking like "[DEBUG HH:MM:SS] message" in blue by default. '''
154
- def suggestion(*values: Any, flush: bool = True, **print_kwargs: Any) -> None:
154
+ def suggestion(*values: Any, flush: bool = True, color: str = ..., text: str = 'SUGGESTION', **print_kwargs: Any) -> None:
155
155
  ''' Print a suggestion message looking like "[SUGGESTION HH:MM:SS] message" in cyan by default. '''
156
- def progress(*values: Any, flush: bool = True, **print_kwargs: Any) -> None:
156
+ def progress(*values: Any, flush: bool = True, color: str = ..., text: str = 'PROGRESS', **print_kwargs: Any) -> None:
157
157
  ''' Print a progress message looking like "[PROGRESS HH:MM:SS] message" in magenta by default. '''
158
- def warning(*values: Any, flush: bool = True, **print_kwargs: Any) -> None:
158
+ def warning(*values: Any, flush: bool = True, color: str = ..., text: str = 'WARNING', **print_kwargs: Any) -> None:
159
159
  ''' Print a warning message looking like "[WARNING HH:MM:SS] message" in yellow by default and in sys.stderr. '''
160
- def error(*values: Any, exit: bool = False, flush: bool = True, **print_kwargs: Any) -> None:
161
- """ Print an error message (in sys.stderr and in red by default)
160
+ def error(*values: Any, exit: bool = False, flush: bool = True, color: str = ..., text: str = 'ERROR', **print_kwargs: Any) -> None:
161
+ ''' Print an error message (in sys.stderr and in red by default)
162
162
  \tand optionally ask the user to continue or stop the program.
163
163
 
164
164
  \tArgs:
165
165
  \t\tvalues\t\t\t(Any):\t\tValues to print (like the print function)
166
166
  \t\texit\t\t\t(bool):\t\tWhether to ask the user to continue or stop the program,
167
167
  \t\t\tfalse to ignore the error automatically and continue
168
+ \t\tflush\t\t\t(bool):\t\tWhether to flush the output
169
+ \t\tcolor\t\t\t(str):\t\tColor of the message (default: RED)
170
+ \t\ttext\t\t\t(str):\t\tText in the message (replaces "ERROR ")
168
171
  \t\tprint_kwargs\t(dict):\t\tKeyword arguments to pass to the print function
169
- \t"""
170
- def whatisit(*values: Any, print_function: Callable[..., None] = ..., flush: bool = True, max_length: int = 250, color: str = ..., **print_kwargs: Any) -> None:
172
+ \t'''
173
+ def whatisit(*values: Any, print_function: Callable[..., None] = ..., flush: bool = True, max_length: int = 250, color: str = ..., text: str = 'What is it?', **print_kwargs: Any) -> None:
171
174
  ''' Print the type of each value and the value itself, with its id and length/shape.
172
175
 
173
176
  \tThe output format is: "type, <id id_number>:\t(length/shape) value"
@@ -177,16 +180,18 @@ def whatisit(*values: Any, print_function: Callable[..., None] = ..., flush: boo
177
180
  \t\tprint_function\t(Callable):\tFunction to use to print the values (default: debug())
178
181
  \t\tmax_length\t\t(int):\t\tMaximum length of the value string to print (default: 250)
179
182
  \t\tcolor\t\t\t(str):\t\tColor of the message (default: CYAN)
183
+ \t\ttext\t\t\t(str):\t\tText in the message (replaces "DEBUG")
180
184
  \t\tprint_kwargs\t(dict):\t\tKeyword arguments to pass to the print function
181
185
  \t'''
182
- def breakpoint(*values: Any, print_function: Callable[..., None] = ..., flush: bool = True, **print_kwargs: Any) -> None:
183
- """ Breakpoint function, pause the program and print the values.
186
+ def breakpoint(*values: Any, print_function: Callable[..., None] = ..., flush: bool = True, text: str = 'BREAKPOINT (press Enter)', **print_kwargs: Any) -> None:
187
+ ''' Breakpoint function, pause the program and print the values.
184
188
 
185
189
  \tArgs:
186
190
  \t\tvalues\t\t\t(Any):\t\tValues to print
187
191
  \t\tprint_function\t(Callable):\tFunction to use to print the values (default: warning())
192
+ \t\ttext\t\t\t(str):\t\tText in the message (replaces "WARNING")
188
193
  \t\tprint_kwargs\t(dict):\t\tKeyword arguments to pass to the print function
189
- \t"""
194
+ \t'''
190
195
 
191
196
  class TeeMultiOutput:
192
197
  ''' File-like object that duplicates output to multiple file-like objects.
@@ -235,12 +240,12 @@ def is_same_print(*args: Any, **kwargs: Any) -> bool:
235
240
  """ Checks if the current print call is the same as the previous one. """
236
241
  def current_time() -> str:
237
242
  ''' Get the current time as "HH:MM:SS" if less than 24 hours since import, else "YYYY-MM-DD HH:MM:SS" '''
238
- def infoc(*args: Any, **kwargs: Any) -> None: ...
239
- def debugc(*args: Any, **kwargs: Any) -> None: ...
240
- def alt_debugc(*args: Any, **kwargs: Any) -> None: ...
241
- def warningc(*args: Any, **kwargs: Any) -> None: ...
242
- def errorc(*args: Any, **kwargs: Any) -> None: ...
243
- def progressc(*args: Any, **kwargs: Any) -> None: ...
244
- def suggestionc(*args: Any, **kwargs: Any) -> None: ...
245
- def whatisitc(*args: Any, **kwargs: Any) -> None: ...
246
- def breakpointc(*args: Any, **kwargs: Any) -> None: ...
243
+ def infoc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None: ...
244
+ def debugc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None: ...
245
+ def alt_debugc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None: ...
246
+ def warningc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None: ...
247
+ def errorc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None: ...
248
+ def progressc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None: ...
249
+ def suggestionc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None: ...
250
+ def whatisitc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None: ...
251
+ def breakpointc(*args: Any, use_colored: bool = True, **kwargs: Any) -> None: ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: stouputils
3
- Version: 1.19.4
3
+ Version: 1.20.0
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
@@ -17,6 +17,7 @@ Requires-Dist: msgspec[toml,yaml]>=0.20.0
17
17
  Requires-Dist: pillow>=12.0.0
18
18
  Requires-Dist: python-box>=7.0.0
19
19
  Requires-Dist: argcomplete>=3.0.0
20
+ Requires-Dist: setproctitle
20
21
  Requires-Dist: numpy
21
22
  Requires-Dist: opencv-python ; extra == 'data-science'
22
23
  Requires-Dist: scikit-image ; extra == 'data-science'
@@ -145,18 +145,18 @@ stouputils/parallel/capturer.py,sha256=s4x_o8Awe-RYyyYxTzgQSm1N2shDjFhENkJBdW-WH
145
145
  stouputils/parallel/capturer.pyi,sha256=UdhhJFdyBsBUyEAltaG3Im13GvZlNXi-ScQDXezFI1Q,2141
146
146
  stouputils/parallel/common.py,sha256=niDcAiEX3flX0ow91gXOB4umlOrR8PIYvpcKPClJHfM,4910
147
147
  stouputils/parallel/common.pyi,sha256=jbyftOYHKP2qaA8YC1f1f12-BDBkhfsQsnPdsR4oet8,2493
148
- stouputils/parallel/multi.py,sha256=tHJgcQJwsI6QeKEHoGJC4tsVK_6t1Fazkb06i1u-W_8,12610
149
- stouputils/parallel/multi.pyi,sha256=DWolZn1UoXxOfuw7LqEJcU8aQJsN-_DRhPGJlJCA5pQ,8021
150
- stouputils/parallel/subprocess.py,sha256=LWbwwAmnz54dCz9TAcKNg1TOMCVSP0C-0GIXaS5nVx0,6728
151
- stouputils/parallel/subprocess.pyi,sha256=gzRtpTslvoENLtSNk79fe3Xz8lV3IwuopT9uMHW9BTU,3680
152
- stouputils/print.py,sha256=86Qjyyj_riU7w3RQdYIHTlPVICUzKsfEBF6NBwZc20g,26745
153
- stouputils/print.pyi,sha256=qu7Pr1c6let2fLcBvbfrrcfCg0s3rf_1jD8FDhR1bgk,11188
148
+ stouputils/parallel/multi.py,sha256=aFcv0QwwptvHhMQSGZ3oDP9WtStgUug6d7yekc-m3rw,13574
149
+ stouputils/parallel/multi.pyi,sha256=VocXgaZGQmpMu52_wYBbU8oacXgTM2tCA88sa3xT8iM,8563
150
+ stouputils/parallel/subprocess.py,sha256=xkQmNfhXxbAzNwgtwDrTOehniDLFPLuV5F3sXPXlU6Y,6899
151
+ stouputils/parallel/subprocess.pyi,sha256=oANLSRmmtWUXTmzhHheZE1uV7gL1zc6Dra9K2aPy73I,3975
152
+ stouputils/print.py,sha256=za33LhqrWgWdeg7unzHRNoXaZbpETXliEN7erfFQ8LA,27036
153
+ stouputils/print.pyi,sha256=iR5vcbf5-3H3kAkX84TMPtwI7_bylWWAKru4n2VMTwQ,12045
154
154
  stouputils/py.typed,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
155
155
  stouputils/typing.py,sha256=9sj6-_lW9pyQFmxW2K1SinGCy7IWeRouUfWjPU2qDsk,2205
156
156
  stouputils/typing.pyi,sha256=XRKhGA7jWjcE-DtS2UznevBxBIFqj8IZI8-J48_3GQc,1341
157
157
  stouputils/version_pkg.py,sha256=Jsp-s03L14DkiZ94vQgrlQmaxApfn9DC8M_nzT1SJLk,7014
158
158
  stouputils/version_pkg.pyi,sha256=QPvqp1U3QA-9C_CC1dT9Vahv1hXEhstbM7x5uzMZSsQ,755
159
- stouputils-1.19.4.dist-info/WHEEL,sha256=fAguSjoiATBe7TNBkJwOjyL1Tt4wwiaQGtNtjRPNMQA,80
160
- stouputils-1.19.4.dist-info/entry_points.txt,sha256=tx0z9VOnE-sfkmbFbA93zaBMzV3XSsKEJa_BWIqUzxw,57
161
- stouputils-1.19.4.dist-info/METADATA,sha256=UdM9eb2MdkC1t42azf7_UT8603Nafg0m7T9i6gERTko,13931
162
- stouputils-1.19.4.dist-info/RECORD,,
159
+ stouputils-1.20.0.dist-info/WHEEL,sha256=fAguSjoiATBe7TNBkJwOjyL1Tt4wwiaQGtNtjRPNMQA,80
160
+ stouputils-1.20.0.dist-info/entry_points.txt,sha256=tx0z9VOnE-sfkmbFbA93zaBMzV3XSsKEJa_BWIqUzxw,57
161
+ stouputils-1.20.0.dist-info/METADATA,sha256=Cfc3uFEGai_NXMr3RTPp12Cj0fBsOLAuCbdtBOKo9Wk,13959
162
+ stouputils-1.20.0.dist-info/RECORD,,