stouputils 1.3.19__tar.gz → 1.3.20__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.
- {stouputils-1.3.19 → stouputils-1.3.20}/PKG-INFO +1 -3
- {stouputils-1.3.19 → stouputils-1.3.20}/README.md +0 -2
- {stouputils-1.3.19 → stouputils-1.3.20}/pyproject.toml +1 -1
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/archive.py +156 -11
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/io.py +3 -3
- stouputils-1.3.19/stouputils/dont_look/zip_file_override.py +0 -122
- {stouputils-1.3.19 → stouputils-1.3.20}/.gitignore +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/LICENSE +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/__init__.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/all_doctests.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/applications/__init__.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/applications/automatic_docs.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/applications/upscaler/__init__.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/applications/upscaler/config.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/applications/upscaler/image.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/applications/upscaler/video.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/backup.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/collections.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/continuous_delivery/__init__.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/continuous_delivery/cd_utils.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/continuous_delivery/github.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/continuous_delivery/pypi.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/continuous_delivery/pyproject.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/ctx.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/config/get.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/config/set.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/__init__.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/auto_contrast.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/axis_flip.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/bias_field_correction.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/binary_threshold.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/blur.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/brightness.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/canny.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/clahe.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/common.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/contrast.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/curvature_flow_filter.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/denoise.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/histogram_equalization.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/invert.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/laplacian.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/median_blur.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/noise.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/normalize.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/random_erase.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/resize.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/rotation.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/salt_pepper.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/sharpening.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/shearing.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/threshold.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/translation.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/zoom.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image_augmentation.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image_preprocess.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/prosthesis_detection.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/technique.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/dataset/__init__.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/dataset/dataset.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/dataset/dataset_loader.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/dataset/grouping_strategy.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/dataset/image_loader.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/dataset/xy_tuple.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/metric_dictionnary.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/metric_utils.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/mlflow_utils.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/abstract_model.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/all.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/base_keras.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras/all.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras/convnext.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras/densenet.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras/efficientnet.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras/mobilenet.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras/resnet.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras/squeezenet.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras/vgg.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras/xception.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras_utils/callbacks/__init__.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras_utils/callbacks/colored_progress_bar.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras_utils/callbacks/learning_rate_finder.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras_utils/callbacks/model_checkpoint_v2.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras_utils/callbacks/progressive_unfreezing.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras_utils/callbacks/warmup_scheduler.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras_utils/losses/__init__.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras_utils/losses/next_generation_loss.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras_utils/visualizations.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/model_interface.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/sandbox.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/range_tuple.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/scripts/augment_dataset.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/scripts/exhaustive_process.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/scripts/preprocess_dataset.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/scripts/routine.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/utils.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/decorators.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/image.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/installer/__init__.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/installer/common.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/installer/downloader.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/installer/linux.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/installer/main.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/installer/windows.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/parallel.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/print.py +0 -0
- {stouputils-1.3.19 → stouputils-1.3.20}/stouputils/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stouputils
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.20
|
|
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
|
|
@@ -90,8 +90,6 @@ It includes a range of tools for tasks such as execution of doctests, display ut
|
|
|
90
90
|
│ ├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.data_science.mlflow_utils.html">mlflow_utils.py</a> <span class="comment"># 📊 MLflow integration utilities</span>
|
|
91
91
|
│ └── ...
|
|
92
92
|
│
|
|
93
|
-
├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.dont_look.html">dont_look/</a> <span class="comment"># 🙈 Internal utilities (zip_file_override)</span>
|
|
94
|
-
│
|
|
95
93
|
├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.installer.html">installer/</a>
|
|
96
94
|
│ ├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.installer.common.html">common.py</a> <span class="comment"># 🔧 Common installer utilities</span>
|
|
97
95
|
│ ├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.installer.downloader.html">downloader.py</a> <span class="comment"># ⬇️ File download utilities</span>
|
|
@@ -66,8 +66,6 @@ It includes a range of tools for tasks such as execution of doctests, display ut
|
|
|
66
66
|
│ ├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.data_science.mlflow_utils.html">mlflow_utils.py</a> <span class="comment"># 📊 MLflow integration utilities</span>
|
|
67
67
|
│ └── ...
|
|
68
68
|
│
|
|
69
|
-
├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.dont_look.html">dont_look/</a> <span class="comment"># 🙈 Internal utilities (zip_file_override)</span>
|
|
70
|
-
│
|
|
71
69
|
├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.installer.html">installer/</a>
|
|
72
70
|
│ ├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.installer.common.html">common.py</a> <span class="comment"># 🔧 Common installer utilities</span>
|
|
73
71
|
│ ├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.installer.downloader.html">downloader.py</a> <span class="comment"># ⬇️ File download utilities</span>
|
|
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
|
|
|
5
5
|
|
|
6
6
|
[project]
|
|
7
7
|
name = "stouputils"
|
|
8
|
-
version = "1.3.
|
|
8
|
+
version = "1.3.20"
|
|
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"
|
|
@@ -8,13 +8,13 @@ This module provides functions for creating and managing archives.
|
|
|
8
8
|
:alt: stouputils archive examples
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
+
# pyright: reportUnusedVariable=false
|
|
11
12
|
# Imports
|
|
12
13
|
import fnmatch
|
|
13
14
|
import os
|
|
14
15
|
from zipfile import ZIP_DEFLATED, ZipFile, ZipInfo
|
|
15
16
|
|
|
16
17
|
from .decorators import LogLevels, handle_error
|
|
17
|
-
from .dont_look.zip_file_override import ZipFileOverride
|
|
18
18
|
from .io import clean_path, super_copy
|
|
19
19
|
|
|
20
20
|
|
|
@@ -124,6 +124,10 @@ def make_archive(
|
|
|
124
124
|
def repair_zip_file(file_path: str, destination: str) -> bool:
|
|
125
125
|
""" Try to repair a corrupted zip file by ignoring some of the errors
|
|
126
126
|
|
|
127
|
+
This function manually parses the ZIP file structure to extract files
|
|
128
|
+
even when the ZIP file is corrupted. It reads the central directory
|
|
129
|
+
entries and attempts to decompress each file individually.
|
|
130
|
+
|
|
127
131
|
Args:
|
|
128
132
|
file_path (str): Path of the zip file to repair
|
|
129
133
|
destination (str): Destination of the new file
|
|
@@ -136,6 +140,9 @@ def repair_zip_file(file_path: str, destination: str) -> bool:
|
|
|
136
140
|
|
|
137
141
|
> repair_zip_file("/path/to/source.zip", "/path/to/destination.zip")
|
|
138
142
|
"""
|
|
143
|
+
import struct
|
|
144
|
+
import zlib
|
|
145
|
+
|
|
139
146
|
# Check
|
|
140
147
|
if not os.path.exists(file_path):
|
|
141
148
|
raise FileNotFoundError(f"File '{file_path}' not found")
|
|
@@ -143,20 +150,158 @@ def repair_zip_file(file_path: str, destination: str) -> bool:
|
|
|
143
150
|
if dirname and not os.path.exists(dirname):
|
|
144
151
|
raise FileNotFoundError(f"Directory '{dirname}' not found")
|
|
145
152
|
|
|
146
|
-
# Read
|
|
147
|
-
with
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
153
|
+
# Read the entire ZIP file into memory
|
|
154
|
+
with open(file_path, 'rb') as f:
|
|
155
|
+
data = f.read()
|
|
156
|
+
|
|
157
|
+
# Find central directory entries
|
|
158
|
+
CENTRAL_SIG = b'PK\x01\x02'
|
|
159
|
+
entries: list[dict[str, int | str]] = []
|
|
160
|
+
idx = 0
|
|
161
|
+
|
|
162
|
+
while True:
|
|
163
|
+
idx = data.find(CENTRAL_SIG, idx)
|
|
164
|
+
if idx == -1:
|
|
165
|
+
break
|
|
166
|
+
# Ensure enough length for central directory header
|
|
167
|
+
if idx + 46 > len(data):
|
|
168
|
+
break
|
|
169
|
+
|
|
170
|
+
header = data[idx:idx+46]
|
|
171
|
+
try:
|
|
172
|
+
(
|
|
173
|
+
sig,
|
|
174
|
+
ver_made, ver_needed, flags, comp_method, mtime, mdate,
|
|
175
|
+
crc, csize, usize,
|
|
176
|
+
name_len, extra_len, comm_len,
|
|
177
|
+
disk_start, int_attr,
|
|
178
|
+
ext_attr, local_off
|
|
179
|
+
) = struct.unpack('<4s6H3L3H2H2L', header)
|
|
180
|
+
|
|
181
|
+
name_start = idx + 46
|
|
182
|
+
if name_start + name_len > len(data):
|
|
183
|
+
idx += 4
|
|
184
|
+
continue
|
|
185
|
+
|
|
186
|
+
name = data[name_start:name_start+name_len].decode('utf-8', errors='replace')
|
|
187
|
+
entries.append({
|
|
188
|
+
'name': name,
|
|
189
|
+
'comp_method': comp_method,
|
|
190
|
+
'csize': csize,
|
|
191
|
+
'usize': usize,
|
|
192
|
+
'local_offset': local_off,
|
|
193
|
+
'crc': crc
|
|
194
|
+
})
|
|
195
|
+
except (struct.error, UnicodeDecodeError):
|
|
196
|
+
# Skip corrupted entries
|
|
197
|
+
pass
|
|
198
|
+
|
|
199
|
+
idx += 4
|
|
200
|
+
|
|
201
|
+
# Create a new ZIP file with recovered entries
|
|
202
|
+
with ZipFile(destination, "w", compression=ZIP_DEFLATED) as new_zip_file:
|
|
203
|
+
for entry in entries:
|
|
204
|
+
try:
|
|
205
|
+
# Get the local header to find data start
|
|
206
|
+
lo: int = int(entry['local_offset'])
|
|
207
|
+
if lo + 30 > len(data):
|
|
208
|
+
continue
|
|
151
209
|
|
|
152
|
-
|
|
153
|
-
with ZipFileOverride(destination, "w", compression=ZIP_DEFLATED) as new_zip_file:
|
|
154
|
-
for file_name in file_list:
|
|
210
|
+
lh = data[lo:lo+30]
|
|
155
211
|
try:
|
|
156
|
-
|
|
157
|
-
except
|
|
212
|
+
_, _, _, _, _, _, _, _, _, name_len, extra_len = struct.unpack('<4sHHHHHLLLHH', lh)
|
|
213
|
+
except struct.error:
|
|
214
|
+
continue
|
|
215
|
+
|
|
216
|
+
data_start: int = lo + 30 + name_len + extra_len
|
|
217
|
+
if data_start + int(entry['csize']) > len(data):
|
|
158
218
|
continue
|
|
159
219
|
|
|
220
|
+
comp_data = data[data_start:data_start+int(entry['csize'])]
|
|
221
|
+
|
|
222
|
+
# Decompress the data
|
|
223
|
+
try:
|
|
224
|
+
if int(entry['comp_method']) == 0: # No compression
|
|
225
|
+
content = comp_data[:int(entry['usize'])]
|
|
226
|
+
elif int(entry['comp_method']) == 8: # Deflate compression
|
|
227
|
+
content = zlib.decompress(comp_data, -zlib.MAX_WBITS)
|
|
228
|
+
else:
|
|
229
|
+
# Unsupported compression method, skip
|
|
230
|
+
continue
|
|
231
|
+
|
|
232
|
+
# Write to new ZIP file
|
|
233
|
+
new_zip_file.writestr(str(entry['name']), content)
|
|
234
|
+
|
|
235
|
+
except (zlib.error, Exception):
|
|
236
|
+
# If decompression fails, try to write raw data as a fallback
|
|
237
|
+
try:
|
|
238
|
+
new_zip_file.writestr(f"{entry['name']!s}.corrupted", comp_data)
|
|
239
|
+
except Exception:
|
|
240
|
+
# Skip completely corrupted entries
|
|
241
|
+
continue
|
|
242
|
+
|
|
243
|
+
except Exception:
|
|
244
|
+
# Skip any entries that cause errors
|
|
245
|
+
continue
|
|
246
|
+
|
|
160
247
|
return True
|
|
161
248
|
|
|
162
249
|
|
|
250
|
+
# CLI functionality
|
|
251
|
+
if __name__ == "__main__":
|
|
252
|
+
import argparse
|
|
253
|
+
import sys
|
|
254
|
+
|
|
255
|
+
parser = argparse.ArgumentParser(description="Archive utilities")
|
|
256
|
+
subparsers = parser.add_subparsers(dest="command", help="Available commands")
|
|
257
|
+
|
|
258
|
+
# Repair command
|
|
259
|
+
repair_parser = subparsers.add_parser("repair", help="Repair a corrupted zip file")
|
|
260
|
+
repair_parser.add_argument("input_file", help="Path to the corrupted zip file")
|
|
261
|
+
repair_parser.add_argument("output_file", nargs="?", help="Path to the repaired zip file (optional, defaults to input_file with '_repaired' suffix)")
|
|
262
|
+
|
|
263
|
+
# Make archive command
|
|
264
|
+
archive_parser = subparsers.add_parser("make", help="Create a zip archive")
|
|
265
|
+
archive_parser.add_argument("source", help="Source directory to archive")
|
|
266
|
+
archive_parser.add_argument("destination", help="Destination zip file")
|
|
267
|
+
archive_parser.add_argument("--ignore", help="Glob patterns to ignore (comma-separated)")
|
|
268
|
+
archive_parser.add_argument("--create-dir", action="store_true", help="Create destination directory if it doesn't exist")
|
|
269
|
+
|
|
270
|
+
args = parser.parse_args()
|
|
271
|
+
|
|
272
|
+
if args.command == "repair":
|
|
273
|
+
input_file = args.input_file
|
|
274
|
+
if args.output_file:
|
|
275
|
+
output_file = args.output_file
|
|
276
|
+
else:
|
|
277
|
+
# Generate default output filename
|
|
278
|
+
base, ext = os.path.splitext(input_file)
|
|
279
|
+
output_file = f"{base}_repaired{ext}"
|
|
280
|
+
|
|
281
|
+
print(f"Repairing '{input_file}' to '{output_file}'...")
|
|
282
|
+
try:
|
|
283
|
+
repair_zip_file(input_file, output_file)
|
|
284
|
+
print(f"Successfully repaired zip file: {output_file}")
|
|
285
|
+
except Exception as e:
|
|
286
|
+
print(f"Error repairing zip file: {e}", file=sys.stderr)
|
|
287
|
+
sys.exit(1)
|
|
288
|
+
|
|
289
|
+
elif args.command == "make":
|
|
290
|
+
print(f"Creating archive from '{args.source}' to '{args.destination}'...")
|
|
291
|
+
try:
|
|
292
|
+
make_archive(
|
|
293
|
+
source=args.source,
|
|
294
|
+
destinations=args.destination,
|
|
295
|
+
create_dir=args.create_dir,
|
|
296
|
+
ignore_patterns=args.ignore
|
|
297
|
+
)
|
|
298
|
+
print(f"Successfully created archive: {args.destination}")
|
|
299
|
+
except Exception as e:
|
|
300
|
+
print(f"Error creating archive: {e}", file=sys.stderr)
|
|
301
|
+
sys.exit(1)
|
|
302
|
+
|
|
303
|
+
else:
|
|
304
|
+
parser.print_help()
|
|
305
|
+
sys.exit(1)
|
|
306
|
+
|
|
307
|
+
|
|
@@ -117,7 +117,7 @@ def get_root_path(relative_path: str, go_up: int = 0) -> str:
|
|
|
117
117
|
return clean_path(
|
|
118
118
|
os.path.dirname(os.path.abspath(relative_path))
|
|
119
119
|
+ "/.." * go_up
|
|
120
|
-
)
|
|
120
|
+
) or "."
|
|
121
121
|
|
|
122
122
|
|
|
123
123
|
# Function that returns the relative path of a file
|
|
@@ -139,9 +139,9 @@ def relative_path(file_path: str, relative_to: str = os.getcwd()) -> str:
|
|
|
139
139
|
file_path = clean_path(file_path)
|
|
140
140
|
relative_to = clean_path(relative_to)
|
|
141
141
|
if file_path.startswith(relative_to):
|
|
142
|
-
return clean_path(os.path.relpath(file_path, relative_to))
|
|
142
|
+
return clean_path(os.path.relpath(file_path, relative_to)) or "."
|
|
143
143
|
else:
|
|
144
|
-
return file_path
|
|
144
|
+
return file_path or "."
|
|
145
145
|
|
|
146
146
|
|
|
147
147
|
# For easy file management
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
This module provides a zip file override to handle some corrupted zip files.
|
|
3
|
-
|
|
4
|
-
For instance, some Minecraft servers resource packs are slightly corrupted
|
|
5
|
-
and cannot be opened with the standard zipfile module.
|
|
6
|
-
See the archive.py module for more information.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
# Imports
|
|
10
|
-
from zipfile import (
|
|
11
|
-
_FH_EXTRA_FIELD_LENGTH, # type: ignore
|
|
12
|
-
ZipExtFile,
|
|
13
|
-
ZipFile,
|
|
14
|
-
ZipInfo,
|
|
15
|
-
_SharedFile, # type: ignore
|
|
16
|
-
crc32, # type: ignore
|
|
17
|
-
sizeFileHeader, # type: ignore
|
|
18
|
-
struct, # type: ignore
|
|
19
|
-
structFileHeader, # type: ignore
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# Class overrides
|
|
24
|
-
class ZipExtFileOverride(ZipExtFile):
|
|
25
|
-
""" Override of the ZipExtFile class """
|
|
26
|
-
|
|
27
|
-
def _update_crc(self, newdata) -> None: # type: ignore
|
|
28
|
-
""" Override of the _update_crc method """
|
|
29
|
-
# Update the CRC using the given data.
|
|
30
|
-
if self._expected_crc is None: # type: ignore
|
|
31
|
-
# No need to compute the CRC if we don't have a reference value
|
|
32
|
-
return
|
|
33
|
-
self._running_crc = crc32(newdata, self._running_crc) # type: ignore
|
|
34
|
-
|
|
35
|
-
class ZipFileOverride(ZipFile):
|
|
36
|
-
""" Override of the ZipFile class """
|
|
37
|
-
|
|
38
|
-
def open(self, name, mode="r", pwd=None, *, force_zip64=False): # type: ignore
|
|
39
|
-
"""Return file-like object for 'name'.
|
|
40
|
-
|
|
41
|
-
name is a string for the file name within the ZIP file, or a ZipInfo
|
|
42
|
-
object.
|
|
43
|
-
|
|
44
|
-
mode should be 'r' to read a file already in the ZIP file, or 'w' to
|
|
45
|
-
write to a file newly added to the archive.
|
|
46
|
-
|
|
47
|
-
pwd is the password to decrypt files (only used for reading).
|
|
48
|
-
|
|
49
|
-
When writing, if the file size is not known in advance but may exceed
|
|
50
|
-
2 GiB, pass force_zip64 to use the ZIP64 format, which can handle large
|
|
51
|
-
files. If the size is known in advance, it is best to pass a ZipInfo
|
|
52
|
-
instance for name, with zinfo.file_size set.
|
|
53
|
-
"""
|
|
54
|
-
if mode not in {"r", "w"}:
|
|
55
|
-
raise ValueError('open() requires mode "r" or "w"')
|
|
56
|
-
if pwd and (mode == "w"):
|
|
57
|
-
raise ValueError("pwd is only supported for reading files")
|
|
58
|
-
if not self.fp:
|
|
59
|
-
raise ValueError(
|
|
60
|
-
"Attempt to use ZIP archive that was already closed")
|
|
61
|
-
|
|
62
|
-
# Make sure we have an info object
|
|
63
|
-
if isinstance(name, ZipInfo):
|
|
64
|
-
# 'name' is already an info object
|
|
65
|
-
zinfo = name
|
|
66
|
-
elif mode == 'w':
|
|
67
|
-
zinfo = ZipInfo(name)
|
|
68
|
-
zinfo.compress_type = self.compression
|
|
69
|
-
zinfo._compresslevel = self.compresslevel # type: ignore
|
|
70
|
-
else:
|
|
71
|
-
# Get info object for name
|
|
72
|
-
zinfo = self.getinfo(name)
|
|
73
|
-
|
|
74
|
-
if mode == 'w':
|
|
75
|
-
return self._open_to_write(zinfo, force_zip64=force_zip64) # type: ignore
|
|
76
|
-
|
|
77
|
-
if self._writing: # type: ignore
|
|
78
|
-
raise ValueError("Can't read from the ZIP file while there "
|
|
79
|
-
"is an open writing handle on it. "
|
|
80
|
-
"Close the writing handle before trying to read.")
|
|
81
|
-
|
|
82
|
-
# Open for reading:
|
|
83
|
-
self._fileRefCnt += 1 # type: ignore
|
|
84
|
-
zef_file = _SharedFile(self.fp, zinfo.header_offset, # type: ignore
|
|
85
|
-
self._fpclose, self._lock, lambda: self._writing) # type: ignore
|
|
86
|
-
try:
|
|
87
|
-
# Skip the file header:
|
|
88
|
-
fheader = zef_file.read(sizeFileHeader) # type: ignore
|
|
89
|
-
fheader = struct.unpack(structFileHeader, fheader) # type: ignore
|
|
90
|
-
|
|
91
|
-
if fheader[_FH_EXTRA_FIELD_LENGTH]:
|
|
92
|
-
zef_file.seek(fheader[_FH_EXTRA_FIELD_LENGTH], whence=1) # type: ignore
|
|
93
|
-
|
|
94
|
-
if zinfo.flag_bits & 0x20:
|
|
95
|
-
# Zip 2.7: compressed patched data
|
|
96
|
-
raise NotImplementedError("compressed patched data (flag bit 5)")
|
|
97
|
-
|
|
98
|
-
if zinfo.flag_bits & 0x40:
|
|
99
|
-
# strong encryption
|
|
100
|
-
raise NotImplementedError("strong encryption (flag bit 6)")
|
|
101
|
-
|
|
102
|
-
# if (zinfo._end_offset is not None and
|
|
103
|
-
# zef_file.tell() + zinfo.compress_size > zinfo._end_offset):
|
|
104
|
-
# raise BadZipFile(f"Overlapped entries: {zinfo.orig_filename!r} (possible zip bomb)")
|
|
105
|
-
|
|
106
|
-
# check for encrypted flag & handle password
|
|
107
|
-
is_encrypted = zinfo.flag_bits & 0x1
|
|
108
|
-
if is_encrypted:
|
|
109
|
-
if not pwd:
|
|
110
|
-
pwd = self.pwd
|
|
111
|
-
if pwd and not isinstance(pwd, bytes): # type: ignore
|
|
112
|
-
raise TypeError(f"pwd: expected bytes, got {type(pwd).__name__}")
|
|
113
|
-
if not pwd:
|
|
114
|
-
raise RuntimeError(f"File {name!r} is encrypted, password required for extraction")
|
|
115
|
-
else:
|
|
116
|
-
pwd = None
|
|
117
|
-
|
|
118
|
-
return ZipExtFileOverride(zef_file, mode, zinfo, pwd, True) # type: ignore
|
|
119
|
-
except:
|
|
120
|
-
zef_file.close() # type: ignore
|
|
121
|
-
raise
|
|
122
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/axis_flip.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/blur.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/brightness.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/canny.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/clahe.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/common.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/contrast.py
RENAMED
|
File without changes
|
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/denoise.py
RENAMED
|
File without changes
|
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/invert.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/laplacian.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/median_blur.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/noise.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/normalize.py
RENAMED
|
File without changes
|
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/resize.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/rotation.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/salt_pepper.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/sharpening.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/shearing.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/threshold.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/translation.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image/zoom.py
RENAMED
|
File without changes
|
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/image_preprocess.py
RENAMED
|
File without changes
|
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/data_processing/technique.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/dataset/grouping_strategy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras/efficientnet.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/models/keras_utils/visualizations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/scripts/exhaustive_process.py
RENAMED
|
File without changes
|
{stouputils-1.3.19 → stouputils-1.3.20}/stouputils/data_science/scripts/preprocess_dataset.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|