diff --git a/CLAUDE.md b/CLAUDE.md index eb2f1d3..1653d02 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -39,9 +39,10 @@ source venv/bin/activate python -m json_to_metadata -d # Options CLI -# -v, --verbose Mode verbeux (DEBUG) -# --dry-run Affiche sans exécuter -# --force-xmp Force création XMP même pour TIFF/JPEG +# -v, --verbose Mode verbeux (DEBUG) +# --dry-run Affiche sans exécuter +# --force-xmp Force création XMP même pour TIFF/JPEG +# --set-file-date Modifie le mtime des fichiers selon la date de prise de vue # Tests pytest tests/ -v diff --git a/json_to_metadata/cli.py b/json_to_metadata/cli.py index ad8de47..6e3753c 100644 --- a/json_to_metadata/cli.py +++ b/json_to_metadata/cli.py @@ -7,7 +7,9 @@ des métadonnées EXIF. import argparse import logging +import os import sys +from datetime import datetime from pathlib import Path from . import __version__ @@ -18,7 +20,7 @@ from .exif_writer import ( write_exif_with_fallback, ) from .json_parser import ValidationError, load_json, validate_roll -from .metadata_mapper import map_frame_to_exif +from .metadata_mapper import map_frame_to_exif, parse_date from .xmp_writer import write_xmp_sidecar # Configuration du logging @@ -45,6 +47,35 @@ def setup_logging(verbose: bool = False) -> None: ) +def set_file_mtime(filepath: Path, dt: datetime, dry_run: bool = False) -> bool: + """ + Modifie la date de modification (mtime) d'un fichier. + + Args: + filepath: Chemin vers le fichier. + dt: Date/heure à appliquer. + dry_run: Si True, affiche sans modifier. + + Returns: + True si la modification a réussi. + """ + try: + timestamp = dt.timestamp() + + if dry_run: + logger.info(f"[DRY-RUN] Modification date fichier : {filepath.name} → {dt}") + return True + + # Modifie atime et mtime + os.utime(filepath, (timestamp, timestamp)) + logger.debug(f"Date fichier modifiée : {filepath.name} → {dt}") + return True + + except (OSError, ValueError) as e: + logger.warning(f"Impossible de modifier la date du fichier {filepath.name} : {e}") + return False + + def find_image_for_frame( frame: dict, directory: Path, @@ -95,7 +126,8 @@ def process_roll( roll: dict, image_dir: Path, dry_run: bool = False, - force_xmp: bool = False + force_xmp: bool = False, + set_file_date: bool = False ) -> tuple[int, int, int]: """ Traite un roll complet : valide et écrit les métadonnées pour chaque frame. @@ -105,6 +137,7 @@ def process_roll( image_dir: Répertoire contenant les images. dry_run: Mode simulation. force_xmp: Force la création de fichiers XMP. + set_file_date: Modifie la date de modification du fichier. Returns: Tuple (succès, échecs, images non trouvées). @@ -144,10 +177,12 @@ def process_roll( continue # Écrire les métadonnées + write_success = False try: if force_xmp: xmp_path = write_xmp_sidecar(image_path, tags, dry_run) if xmp_path: + write_success = True success_count += 1 logger.info(f"Frame {frame_id} : XMP créé ({image_path.name})") else: @@ -158,6 +193,7 @@ def process_roll( dry_run ) if success: + write_success = True success_count += 1 logger.info(f"Frame {frame_id} : métadonnées écrites via {method}") else: @@ -171,6 +207,14 @@ def process_roll( logger.error(f"Erreur I/O pour le frame {frame_id} : {e}") failure_count += 1 + # Modifier la date du fichier si demandé + if write_success and set_file_date and frame.get('date'): + try: + frame_date = parse_date(frame['date']) + set_file_mtime(image_path, frame_date, dry_run) + except ValueError as e: + logger.warning(f"Date invalide pour le frame {frame_id} : {e}") + return success_count, failure_count, not_found_count @@ -221,6 +265,12 @@ def main(args: list[str] | None = None) -> int: help='Force la création de fichiers XMP même pour les formats supportant EXIF' ) + parser.add_argument( + '--set-file-date', + action='store_true', + help='Modifie la date de modification des fichiers selon la date de prise de vue' + ) + parser.add_argument( '--version', action='version', @@ -302,7 +352,8 @@ def main(args: list[str] | None = None) -> int: roll, image_dir, dry_run=parsed_args.dry_run, - force_xmp=parsed_args.force_xmp + force_xmp=parsed_args.force_xmp, + set_file_date=parsed_args.set_file_date ) total_success += success total_failure += failure