stouputils 1.5.3__tar.gz → 1.5.4__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.
Files changed (107) hide show
  1. {stouputils-1.5.3 → stouputils-1.5.4}/PKG-INFO +1 -1
  2. {stouputils-1.5.3 → stouputils-1.5.4}/pyproject.toml +1 -1
  3. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/print.py +37 -11
  4. {stouputils-1.5.3 → stouputils-1.5.4}/.gitignore +0 -0
  5. {stouputils-1.5.3 → stouputils-1.5.4}/LICENSE +0 -0
  6. {stouputils-1.5.3 → stouputils-1.5.4}/README.md +0 -0
  7. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/__init__.py +0 -0
  8. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/__main__.py +0 -0
  9. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/all_doctests.py +0 -0
  10. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/applications/__init__.py +0 -0
  11. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/applications/automatic_docs.py +0 -0
  12. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/applications/upscaler/__init__.py +0 -0
  13. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/applications/upscaler/config.py +0 -0
  14. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/applications/upscaler/image.py +0 -0
  15. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/applications/upscaler/video.py +0 -0
  16. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/archive.py +0 -0
  17. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/backup.py +0 -0
  18. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/collections.py +0 -0
  19. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/continuous_delivery/__init__.py +0 -0
  20. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/continuous_delivery/cd_utils.py +0 -0
  21. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/continuous_delivery/github.py +0 -0
  22. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/continuous_delivery/pypi.py +0 -0
  23. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/continuous_delivery/pyproject.py +0 -0
  24. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/ctx.py +0 -0
  25. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/config/get.py +0 -0
  26. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/config/set.py +0 -0
  27. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/__init__.py +0 -0
  28. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/auto_contrast.py +0 -0
  29. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/axis_flip.py +0 -0
  30. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/bias_field_correction.py +0 -0
  31. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/binary_threshold.py +0 -0
  32. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/blur.py +0 -0
  33. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/brightness.py +0 -0
  34. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/canny.py +0 -0
  35. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/clahe.py +0 -0
  36. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/common.py +0 -0
  37. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/contrast.py +0 -0
  38. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/curvature_flow_filter.py +0 -0
  39. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/denoise.py +0 -0
  40. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/histogram_equalization.py +0 -0
  41. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/invert.py +0 -0
  42. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/laplacian.py +0 -0
  43. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/median_blur.py +0 -0
  44. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/noise.py +0 -0
  45. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/normalize.py +0 -0
  46. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/random_erase.py +0 -0
  47. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/resize.py +0 -0
  48. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/rotation.py +0 -0
  49. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/salt_pepper.py +0 -0
  50. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/sharpening.py +0 -0
  51. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/shearing.py +0 -0
  52. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/threshold.py +0 -0
  53. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/translation.py +0 -0
  54. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image/zoom.py +0 -0
  55. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image_augmentation.py +0 -0
  56. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/image_preprocess.py +0 -0
  57. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/prosthesis_detection.py +0 -0
  58. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/data_processing/technique.py +0 -0
  59. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/dataset/__init__.py +0 -0
  60. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/dataset/dataset.py +0 -0
  61. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/dataset/dataset_loader.py +0 -0
  62. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/dataset/grouping_strategy.py +0 -0
  63. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/dataset/image_loader.py +0 -0
  64. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/dataset/xy_tuple.py +0 -0
  65. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/metric_dictionnary.py +0 -0
  66. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/metric_utils.py +0 -0
  67. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/mlflow_utils.py +0 -0
  68. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/abstract_model.py +0 -0
  69. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/all.py +0 -0
  70. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/base_keras.py +0 -0
  71. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras/all.py +0 -0
  72. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras/convnext.py +0 -0
  73. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras/densenet.py +0 -0
  74. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras/efficientnet.py +0 -0
  75. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras/mobilenet.py +0 -0
  76. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras/resnet.py +0 -0
  77. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras/squeezenet.py +0 -0
  78. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras/vgg.py +0 -0
  79. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras/xception.py +0 -0
  80. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras_utils/callbacks/__init__.py +0 -0
  81. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras_utils/callbacks/colored_progress_bar.py +0 -0
  82. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras_utils/callbacks/learning_rate_finder.py +0 -0
  83. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras_utils/callbacks/model_checkpoint_v2.py +0 -0
  84. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras_utils/callbacks/progressive_unfreezing.py +0 -0
  85. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras_utils/callbacks/warmup_scheduler.py +0 -0
  86. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras_utils/losses/__init__.py +0 -0
  87. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras_utils/losses/next_generation_loss.py +0 -0
  88. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/keras_utils/visualizations.py +0 -0
  89. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/model_interface.py +0 -0
  90. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/models/sandbox.py +0 -0
  91. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/range_tuple.py +0 -0
  92. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/scripts/augment_dataset.py +0 -0
  93. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/scripts/exhaustive_process.py +0 -0
  94. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/scripts/preprocess_dataset.py +0 -0
  95. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/scripts/routine.py +0 -0
  96. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/data_science/utils.py +0 -0
  97. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/decorators.py +0 -0
  98. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/image.py +0 -0
  99. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/installer/__init__.py +0 -0
  100. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/installer/common.py +0 -0
  101. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/installer/downloader.py +0 -0
  102. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/installer/linux.py +0 -0
  103. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/installer/main.py +0 -0
  104. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/installer/windows.py +0 -0
  105. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/io.py +0 -0
  106. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/parallel.py +0 -0
  107. {stouputils-1.5.3 → stouputils-1.5.4}/stouputils/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stouputils
3
- Version: 1.5.3
3
+ Version: 1.5.4
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
  Project-URL: Homepage, https://github.com/Stoupy51/stouputils
6
6
  Project-URL: Issues, https://github.com/Stoupy51/stouputils/issues
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
5
5
 
6
6
  [project]
7
7
  name = "stouputils"
8
- version = "1.5.3"
8
+ version = "1.5.4"
9
9
  description = "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."
10
10
  readme = "README.md"
11
11
  requires-python = ">=3.10"
@@ -279,17 +279,23 @@ class TeeMultiOutput:
279
279
 
280
280
  Examples:
281
281
  >>> f = open("logfile.txt", "w")
282
- >>> original_stdout = sys.stdout
283
282
  >>> sys.stdout = TeeMultiOutput(sys.stdout, f)
284
283
  >>> print("Hello World") # Output goes to both console and file
285
284
  Hello World
286
- >>> sys.stdout = original_stdout
287
- >>> f.close()
285
+ >>> f.close() # TeeMultiOutput will handle any future writes to closed files gracefully
288
286
  """
289
287
  def __init__(
290
288
  self, *files: IO[Any], strip_colors: bool = True, ascii_only: bool = True, ignore_lineup: bool = True
291
289
  ) -> None:
292
- self.files: tuple[IO[Any], ...] = files
290
+ # Flatten any TeeMultiOutput instances in files
291
+ flattened_files: list[IO[Any]] = []
292
+ for file in files:
293
+ if isinstance(file, TeeMultiOutput):
294
+ flattened_files.extend(file.files)
295
+ else:
296
+ flattened_files.append(file)
297
+
298
+ self.files: tuple[IO[Any], ...] = tuple(flattened_files)
293
299
  """ File-like objects to write to """
294
300
  self.strip_colors: bool = strip_colors
295
301
  """ Whether to strip ANSI color codes from output sent to non-stdout/stderr files """
@@ -310,18 +316,27 @@ class TeeMultiOutput:
310
316
  except (IndexError, AttributeError):
311
317
  return "utf-8"
312
318
 
313
- def write(self, obj: str) -> None:
319
+ def write(self, obj: str) -> int:
314
320
  """ Write the object to all files while stripping colors if needed.
315
321
 
316
322
  Args:
317
323
  obj (str): String to write
324
+ Returns:
325
+ int: Number of characters written to the first file
318
326
  """
327
+ files_to_remove: list[IO[Any]] = []
328
+ num_chars_written: int = 0
319
329
  for i, f in enumerate(self.files):
320
330
  try:
321
- content = obj
322
- if i != 0:
323
- # First file (i = 0) (often stdout/stderr) gets the original content
324
- # Other files (i != 0) get processed content
331
+ # Check if file is closed
332
+ if hasattr(f, "closed") and f.closed:
333
+ files_to_remove.append(f)
334
+ continue
335
+
336
+ # Check if this file is a terminal/console or a regular file
337
+ content: str = obj
338
+ if not (hasattr(f, "isatty") and f.isatty()):
339
+ # Non-terminal files get processed content (stripped colors, ASCII-only, etc.)
325
340
 
326
341
  # Skip content if it contains LINE_UP and ignore_lineup is True
327
342
  if self.ignore_lineup and (LINE_UP in content or "\r" in content):
@@ -338,11 +353,22 @@ class TeeMultiOutput:
338
353
  content = ''.join(c if ord(c) < 128 else '?' for c in content)
339
354
 
340
355
  # Write content to file
341
- f.write(content)
342
-
356
+ if i == 0:
357
+ num_chars_written = f.write(content)
358
+ else:
359
+ f.write(content)
360
+
361
+ except ValueError:
362
+ # ValueError is raised when writing to a closed file
363
+ files_to_remove.append(f)
343
364
  except Exception:
344
365
  pass
345
366
 
367
+ # Remove closed files from the list
368
+ if files_to_remove:
369
+ self.files = tuple(f for f in self.files if f not in files_to_remove)
370
+ return num_chars_written
371
+
346
372
  def flush(self) -> None:
347
373
  """ Flush all files. """
348
374
  for f in self.files:
File without changes
File without changes
File without changes
File without changes
File without changes