normalizar-case

This commit is contained in:
2026-02-20 17:37:12 +01:00
parent 8d83d27bd3
commit ab056c342e
7 changed files with 149 additions and 1 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
# core/constants.py
IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".webp"}
IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".webp", ".gif"}
TRASH_FILES = {
"thumbs.db",
+47
View File
@@ -20,6 +20,7 @@ from processors.checks import (
check_comicinfo,
check_foreign,
check_nested,
check_extension_case,
)
from processors.page_normalizer import normalize_pages, preview_normalize_pages
from processors.image_normalizer import (
@@ -28,6 +29,7 @@ from processors.image_normalizer import (
uniformize_images,
preview_uniformize_images,
)
from processors.case_normalizer import normalize_case, preview_normalize_case
class Pipeline:
@@ -38,12 +40,14 @@ class Pipeline:
desired_image_format: str = ".jpg",
collision_policy: str = CollisionPolicy.ABORT,
dry_run: bool = False,
case_mode: str = "lower",
):
self.steps = steps
self.desired_format = desired_format
self.desired_image_format = desired_image_format
self.collision_policy = collision_policy
self.dry_run = dry_run
self.case_mode = case_mode
def _compute_preview(self, step: str, temp_dir: str, step_results: list) -> dict:
if step == "clean":
@@ -82,6 +86,10 @@ class Pipeline:
conversions = preview_normalize_images(temp_dir, self.desired_image_format)
return {"conversions": conversions, "target_ext": self.desired_image_format}
elif step == "normalize_case":
renames = preview_normalize_case(temp_dir, self.case_mode)
return {"renames": renames, "mode": self.case_mode}
elif step == "convert":
return {"target_format": self.desired_format.upper()}
@@ -91,6 +99,10 @@ class Pipeline:
for step in self.steps:
if step in ("normalize_pages", "normalize_images", "convert_images"):
return True
if step == "normalize_case":
case_r = next((r for r in step_results if r.step == "check_extension_case"), None)
if case_r and case_r.warnings:
return True
if step == "convert":
if needs_conversion(real_format, self.desired_format):
return True
@@ -134,8 +146,34 @@ class Pipeline:
check_comicinfo(names),
check_foreign(names),
check_nested(names),
check_extension_case(names, self.case_mode),
]
# 3b. Corrección del case de la extensión exterior (renombrado en-sitio, sin repack)
if "normalize_case" in self.steps:
outer_ext = os.path.splitext(path)[1]
target_outer_ext = outer_ext.lower() if self.case_mode == "lower" else outer_ext.upper()
if outer_ext != target_outer_ext:
base_no_ext = os.path.splitext(path)[0]
new_outer_path = base_no_ext + target_outer_ext
try:
safe_outer = resolve_collision(new_outer_path, self.collision_policy)
if not self.dry_run:
os.rename(path, safe_outer)
path = safe_outer
step_results.append(StepResult(
step="normalize_case_outer",
changed=True,
details=[f"Extensión exterior corregida: {outer_ext}{target_outer_ext}"],
))
except (FileExistsError, OSError) as exc:
step_results.append(StepResult(
step="normalize_case_outer",
changed=False,
errors=[str(exc)],
))
return ComicResult(original_path=path, final_path=None, steps=step_results)
# 4. Pre-flight: si ningún step necesita extracción, salir sin tocar el archivo
if not self._needs_extraction(step_results, real_format, path):
return ComicResult(original_path=path, final_path=path, steps=step_results)
@@ -198,6 +236,15 @@ class Pipeline:
if img_result.changed:
any_changed = True
if "normalize_case" in self.steps:
preview = self._compute_preview("normalize_case", temp_dir, step_results)
if preview.get("renames"):
if confirm_fn is None or confirm_fn("normalize_case", preview):
case_result = normalize_case(temp_dir, self.case_mode)
step_results.append(case_result)
if case_result.changed:
any_changed = True
if "convert" in self.steps:
preview = self._compute_preview("convert", temp_dir, step_results)
if confirm_fn is None or confirm_fn("convert", preview):
+4
View File
@@ -58,6 +58,7 @@ class SummaryCollector:
pages_normalized = count_step(["normalize_pages"])
images_converted = count_step(["normalize_images", "convert_images"])
format_converted = count_step(["convert"])
case_normalized = count_step(["normalize_case", "normalize_case_outer"])
lines = [
_BORDER,
@@ -76,6 +77,8 @@ class SummaryCollector:
lines.append(f" · Imágenes convertidas : {images_converted:>3}")
if format_converted:
lines.append(f" · Formato convertido : {format_converted:>3}")
if case_normalized:
lines.append(f" · Case normalizado : {case_normalized:>3}")
lines.append(f" Advertencias : {len(warnings_only):>3}")
lines.append(f" Errores : {len(errors):>3}")
if errors:
@@ -137,6 +140,7 @@ class SummaryCollector:
("Numeración de páginas", "check_page_numbering", lambda w: True, ["normalize_pages"], "renumerado"),
("Imágenes mezcladas", "check_image_extensions", lambda w: True, ["normalize_images", "convert_images"], "normalizado"),
("Sin ComicInfo.xml", "check_comicinfo", lambda w: True, [], None),
("Case de extensión", "check_extension_case", lambda w: True, ["normalize_case"], "normalizado"),
]
output = []
for label, step_name, predicate, resolver_steps, fix_label in categories: