Feature exportdb update 990 (#992)

* Added cloud_guid, #990

* Added fingerprint, cloud_guid to PhotoInfo.json

* Added stub for --migrate-photos-library

* Added --migrate-photos-library option to exportdb, #990
This commit is contained in:
Rhet Turnbull
2023-02-19 22:51:25 -08:00
committed by GitHub
parent 30c036a287
commit 06b02b4a23
11 changed files with 459 additions and 109 deletions

View File

@@ -119,7 +119,7 @@ def rich_echo(
# if not outputting to terminal, use a huge width to avoid wrapping
# otherwise tests fail
width = 10_000
console = get_rich_console() or Console(theme=theme, width=width)
console = get_rich_console() or Console(theme or get_rich_theme(), width=width)
if markdown:
message = Markdown(message)
# Markdown always adds a new line so disable unless explicitly specified

View File

@@ -3,6 +3,7 @@
import json
import pathlib
import sys
from textwrap import dedent
import click
from rich import print
@@ -15,6 +16,7 @@ from osxphotos.export_db import (
ExportDB,
)
from osxphotos.export_db_utils import (
export_db_backup,
export_db_check_signatures,
export_db_get_errors,
export_db_get_last_run,
@@ -23,9 +25,12 @@ from osxphotos.export_db_utils import (
export_db_touch_files,
export_db_update_signatures,
export_db_vacuum,
export_db_migrate_photos_library,
export_db_get_last_library,
)
from osxphotos.utils import pluralize
from .cli_params import THEME_OPTION, TIMESTAMP_OPTION, VERBOSE_OPTION
from .click_rich_echo import (
rich_click_echo,
rich_echo,
@@ -34,7 +39,6 @@ from .click_rich_echo import (
set_rich_theme,
)
from .color_themes import get_theme
from .cli_params import TIMESTAMP_OPTION, VERBOSE_OPTION
from .export import render_and_validate_report
from .param_types import TemplateString
from .report_writer import export_report_writer_factory
@@ -140,6 +144,15 @@ from .verbose import get_verbose_console, verbose_print
metavar="SQL_STATEMENT",
help="Execute SQL_STATEMENT against export database and print results.",
)
@click.option(
"--migrate-photos-library",
metavar="PHOTOS_LIBRARY",
help="Migrate the export database to use the specified Photos library. "
"Use this if you have moved your Photos library to a new location or computer and "
"want to keep using the same export database. "
"This will update the UUIDs in the export database to match the new Photos library.",
type=click.Path(exists=True, file_okay=True, dir_okay=True),
)
@click.option(
"--export-dir",
help="Optional path to export directory (if not parent of export database).",
@@ -153,10 +166,11 @@ from .verbose import get_verbose_console, verbose_print
)
@VERBOSE_OPTION
@TIMESTAMP_OPTION
@THEME_OPTION
@click.option(
"--dry-run",
is_flag=True,
help="Run in dry-run mode (don't actually update files), e.g. for use with --update-signatures.",
help="Run in dry-run mode (don't actually update files); for example, use with --update-signatures or --migrate-photos-library.",
)
@click.argument("export_db", metavar="EXPORT_DATABASE", type=click.Path(exists=True))
def exportdb(
@@ -170,9 +184,11 @@ def exportdb(
last_errors,
last_run,
migrate,
migrate_photos_library,
report,
save_config,
sql,
theme,
timestamp,
touch_file,
update_signatures,
@@ -185,12 +201,12 @@ def exportdb(
version,
):
"""Utilities for working with the osxphotos export database"""
verbose = verbose_print(verbose_flag, timestamp=timestamp)
verbose = verbose_print(verbose=verbose_flag, timestamp=timestamp, theme=theme)
# validate options and args
if append and not report:
rich_echo(
"[error]Error: --append requires --report; ee --help for more information.[/]",
rich_echo_error(
"[error]Error: --append requires --report; see --help for more information.[/]",
file=sys.stderr,
)
sys.exit(1)
@@ -200,7 +216,7 @@ def exportdb(
# assume it's the export folder
export_db = export_db / OSXPHOTOS_EXPORT_DB
if not export_db.is_file():
rich_echo(
rich_echo_error(
f"[error]Error: {OSXPHOTOS_EXPORT_DB} missing from {export_db.parent}[/error]"
)
sys.exit(1)
@@ -226,7 +242,9 @@ def exportdb(
]
]
if sum(sub_commands) > 1:
rich_echo("[error]Only a single sub-command may be specified at a time[/error]")
rich_echo_error(
"[error]Only a single sub-command may be specified at a time[/error]"
)
sys.exit(1)
# process sub-commands
@@ -235,7 +253,7 @@ def exportdb(
try:
osxphotos_ver, export_db_ver = export_db_get_version(export_db)
except Exception as e:
rich_echo(
rich_echo_error(
f"[error]Error: could not read version from {export_db}: {e}[/error]"
)
sys.exit(1)
@@ -250,7 +268,7 @@ def exportdb(
start_size = pathlib.Path(export_db).stat().st_size
export_db_vacuum(export_db)
except Exception as e:
rich_echo(f"[error]Error: {e}[/error]")
rich_echo_error(f"[error]Error: {e}[/error]")
sys.exit(1)
else:
rich_echo(
@@ -264,7 +282,7 @@ def exportdb(
export_db, export_dir, verbose, dry_run
)
except Exception as e:
rich_echo(f"[error]Error: {e}[/error]")
rich_echo_error(f"[error]Error: {e}[/error]")
sys.exit(1)
else:
rich_echo(
@@ -276,7 +294,7 @@ def exportdb(
try:
last_run_info = export_db_get_last_run(export_db)
except Exception as e:
rich_echo(f"[error]Error: {e}[/error]")
rich_echo_error(f"[error]Error: {e}[/error]")
sys.exit(1)
else:
rich_echo(f"last run at [time]{last_run_info[0]}:")
@@ -287,7 +305,7 @@ def exportdb(
try:
export_db_save_config_to_file(export_db, save_config)
except Exception as e:
rich_echo(f"[error]Error: {e}[/error]")
rich_echo_error(f"[error]Error: {e}[/error]")
sys.exit(1)
else:
rich_echo(f"Saved configuration to [filepath]{save_config}")
@@ -299,7 +317,7 @@ def exportdb(
export_db, export_dir, verbose_=verbose
)
except Exception as e:
rich_echo(f"[error]Error: {e}[/error]")
rich_echo_error(f"[error]Error: {e}[/error]")
sys.exit(1)
else:
rich_echo(
@@ -314,7 +332,7 @@ def exportdb(
export_db, export_dir, verbose_=verbose, dry_run=dry_run
)
except Exception as e:
rich_echo(f"[error]Error: {e}[/error]")
rich_echo_error(f"[error]Error: {e}[/error]")
sys.exit(1)
else:
rich_echo(
@@ -328,7 +346,7 @@ def exportdb(
try:
info_rec = exportdb.get_file_record(info)
except Exception as e:
rich_echo(f"[error]Error: {e}[/error]")
rich_echo_error(f"[error]Error: {e}[/error]")
sys.exit(1)
else:
if info_rec:
@@ -343,7 +361,7 @@ def exportdb(
try:
error_list = export_db_get_errors(export_db)
except Exception as e:
rich_echo(f"[error]Error: {e}[/error]")
rich_echo_error(f"[error]Error: {e}[/error]")
sys.exit(1)
else:
if error_list:
@@ -375,7 +393,7 @@ def exportdb(
try:
info_rec = exportdb.get_photoinfo_for_uuid(uuid_info)
except Exception as e:
rich_echo(f"[error]Error: {e}[/error]")
rich_echo_error(f"[error]Error: {e}[/error]")
sys.exit(1)
else:
if info_rec:
@@ -393,7 +411,7 @@ def exportdb(
try:
file_list = exportdb.get_files_for_uuid(uuid_files)
except Exception as e:
rich_echo(f"[error]Error: {e}[/error]")
rich_echo_error(f"[error]Error: {e}[/error]")
sys.exit(1)
else:
if file_list:
@@ -433,12 +451,14 @@ def exportdb(
report_filename = render_and_validate_report(report_template, "", export_dir)
export_results = exportdb.get_export_results(run_id)
if not export_results:
rich_echo(f"[error]No report results found for run ID {run_id}[/error]")
rich_echo_error(
f"[error]No report results found for run ID {run_id}[/error]"
)
sys.exit(1)
try:
report_writer = export_report_writer_factory(report_filename, append=append)
except ValueError as e:
rich_echo(f"[error]Error: {e}[/error]")
rich_echo_error(f"[error]Error: {e}[/error]")
sys.exit(1)
report_writer.write(export_results)
report_writer.close()
@@ -463,9 +483,39 @@ def exportdb(
c = exportdb._conn.cursor()
results = c.execute(sql)
except Exception as e:
rich_echo(f"[error]Error: {e}[/error]")
rich_echo_error(f"[error]Error: {e}[/error]")
sys.exit(1)
else:
for row in results:
print(row)
sys.exit(0)
if migrate_photos_library:
# migrate Photos library to new library and update UUIDs in export database
last_library = export_db_get_last_library(export_db)
rich_echo(
dedent(
f"""
[warning]:warning-emoji: This command will update your export database ([filepath]{export_db}[/])
to use [filepath]{migrate_photos_library}[/] as the new source library.
The last library used was [filepath]{last_library}[/].
This will allow you to use the export database with the new library but it will
no longer work correctly with the old library unless you run the `--migrate-photos-library`
command again to update the export database to use the previous library.
A backup of the export database will be created in the same directory as the export database.
"""
)
)
if not click.confirm("Do you want to continue?"):
sys.exit(0)
if not dry_run:
backup_file = export_db_backup(export_db)
verbose(f"Backed up export database to [filepath]{backup_file}[/]")
migrated, notmigrated = export_db_migrate_photos_library(
export_db, migrate_photos_library, verbose, dry_run
)
rich_echo(
f"Migrated [num]{migrated}[/] {pluralize(migrated, 'photo', 'photos')}, "
f"[num]{notmigrated}[/] not migrated."
)

View File

@@ -200,15 +200,17 @@ def _verbose_print_function(
Returns:
function to print output
"""
if not verbose:
return noop
# configure console even if verbose is False so that rich_echo will work correctly
global _console
if file:
_console.console = Console(theme=theme, file=file)
else:
_console.console = Console(theme=theme, width=10_000)
if not verbose:
return noop
# closure to capture timestamp
def verbose_(*args, level: int = 1):
"""print output if verbose flag set"""