Ajout option --set-file-date pour modifier le mtime des fichiers
Permet de modifier la date de modification des fichiers images selon la date de prise de vue du frame, utile pour le tri par date dans les gestionnaires de fichiers. Utilise os.utime() pour modifier atime et mtime. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -39,9 +39,10 @@ source venv/bin/activate
|
|||||||
python -m json_to_metadata <fichier.json> -d <dossier_images>
|
python -m json_to_metadata <fichier.json> -d <dossier_images>
|
||||||
|
|
||||||
# Options CLI
|
# Options CLI
|
||||||
# -v, --verbose Mode verbeux (DEBUG)
|
# -v, --verbose Mode verbeux (DEBUG)
|
||||||
# --dry-run Affiche sans exécuter
|
# --dry-run Affiche sans exécuter
|
||||||
# --force-xmp Force création XMP même pour TIFF/JPEG
|
# --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
|
# Tests
|
||||||
pytest tests/ -v
|
pytest tests/ -v
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ des métadonnées EXIF.
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from . import __version__
|
from . import __version__
|
||||||
@@ -18,7 +20,7 @@ from .exif_writer import (
|
|||||||
write_exif_with_fallback,
|
write_exif_with_fallback,
|
||||||
)
|
)
|
||||||
from .json_parser import ValidationError, load_json, validate_roll
|
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
|
from .xmp_writer import write_xmp_sidecar
|
||||||
|
|
||||||
# Configuration du logging
|
# 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(
|
def find_image_for_frame(
|
||||||
frame: dict,
|
frame: dict,
|
||||||
directory: Path,
|
directory: Path,
|
||||||
@@ -95,7 +126,8 @@ def process_roll(
|
|||||||
roll: dict,
|
roll: dict,
|
||||||
image_dir: Path,
|
image_dir: Path,
|
||||||
dry_run: bool = False,
|
dry_run: bool = False,
|
||||||
force_xmp: bool = False
|
force_xmp: bool = False,
|
||||||
|
set_file_date: bool = False
|
||||||
) -> tuple[int, int, int]:
|
) -> tuple[int, int, int]:
|
||||||
"""
|
"""
|
||||||
Traite un roll complet : valide et écrit les métadonnées pour chaque frame.
|
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.
|
image_dir: Répertoire contenant les images.
|
||||||
dry_run: Mode simulation.
|
dry_run: Mode simulation.
|
||||||
force_xmp: Force la création de fichiers XMP.
|
force_xmp: Force la création de fichiers XMP.
|
||||||
|
set_file_date: Modifie la date de modification du fichier.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple (succès, échecs, images non trouvées).
|
Tuple (succès, échecs, images non trouvées).
|
||||||
@@ -144,10 +177,12 @@ def process_roll(
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# Écrire les métadonnées
|
# Écrire les métadonnées
|
||||||
|
write_success = False
|
||||||
try:
|
try:
|
||||||
if force_xmp:
|
if force_xmp:
|
||||||
xmp_path = write_xmp_sidecar(image_path, tags, dry_run)
|
xmp_path = write_xmp_sidecar(image_path, tags, dry_run)
|
||||||
if xmp_path:
|
if xmp_path:
|
||||||
|
write_success = True
|
||||||
success_count += 1
|
success_count += 1
|
||||||
logger.info(f"Frame {frame_id} : XMP créé ({image_path.name})")
|
logger.info(f"Frame {frame_id} : XMP créé ({image_path.name})")
|
||||||
else:
|
else:
|
||||||
@@ -158,6 +193,7 @@ def process_roll(
|
|||||||
dry_run
|
dry_run
|
||||||
)
|
)
|
||||||
if success:
|
if success:
|
||||||
|
write_success = True
|
||||||
success_count += 1
|
success_count += 1
|
||||||
logger.info(f"Frame {frame_id} : métadonnées écrites via {method}")
|
logger.info(f"Frame {frame_id} : métadonnées écrites via {method}")
|
||||||
else:
|
else:
|
||||||
@@ -171,6 +207,14 @@ def process_roll(
|
|||||||
logger.error(f"Erreur I/O pour le frame {frame_id} : {e}")
|
logger.error(f"Erreur I/O pour le frame {frame_id} : {e}")
|
||||||
failure_count += 1
|
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
|
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'
|
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(
|
parser.add_argument(
|
||||||
'--version',
|
'--version',
|
||||||
action='version',
|
action='version',
|
||||||
@@ -302,7 +352,8 @@ def main(args: list[str] | None = None) -> int:
|
|||||||
roll,
|
roll,
|
||||||
image_dir,
|
image_dir,
|
||||||
dry_run=parsed_args.dry_run,
|
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_success += success
|
||||||
total_failure += failure
|
total_failure += failure
|
||||||
|
|||||||
Reference in New Issue
Block a user