From 04930c3644da99c1923c4e3aaa9213902aeadfd1 Mon Sep 17 00:00:00 2001 From: Rhet Turnbull Date: Fri, 31 Dec 2021 08:35:26 -0800 Subject: [PATCH] Added --skip-uuid, --skip-uuid-from-file, #563 --- README.md | 12 +++-- docs/.buildinfo | 2 +- docs/_static/documentation_options.js | 2 +- docs/cli.html | 2 +- docs/genindex.html | 2 +- docs/index.html | 2 +- docs/modules.html | 2 +- docs/reference.html | 2 +- docs/search.html | 2 +- osxphotos/_version.py | 2 +- osxphotos/cli.py | 50 ++++++++++++++++--- tests/skip_uuid_from_file.txt | 6 +++ tests/test_cli.py | 69 +++++++++++++++++++++++++++ 13 files changed, 137 insertions(+), 18 deletions(-) create mode 100644 tests/skip_uuid_from_file.txt diff --git a/README.md b/README.md index 92ce73c3..48325e7f 100644 --- a/README.md +++ b/README.md @@ -615,7 +615,8 @@ Options: FILENAME. If more than one --name options is specified, they are treated as "OR", e.g. find photos matching any FILENAME. - --uuid UUID Search for photos with UUID(s). + --uuid UUID Search for photos with UUID(s). May be + repeated to include multiple UUIDs. --uuid-from-file FILE Search for photos with UUID(s) loaded from FILE. Format is a single UUID per line. Lines preceded with # are ignored. @@ -837,6 +838,11 @@ Options: photos if the RAW photo does not have an associated JPEG image (e.g. the RAW file was imported to Photos without a JPEG preview). + --skip-uuid UUID Skip photos with UUID(s) during export. May be + repeated to include multiple UUIDs. + --skip-uuid-from-file FILE Skip photos with UUID(s) loaded from FILE. + Format is a single UUID per line. Lines + preceded with # are ignored. --current-name Use photo's current filename instead of original filename for export. Note: Starting with Photos 5, all photos are renamed upon @@ -1715,7 +1721,7 @@ Substitution Description {lf} A line feed: '\n', alias for {newline} {cr} A carriage return: '\r' {crlf} a carriage return + line feed: '\r\n' -{osxphotos_version} The osxphotos version, e.g. '0.44.0' +{osxphotos_version} The osxphotos version, e.g. '0.44.1' {osxphotos_cmd_line} The full command line used to run osxphotos The following substitutions may result in multiple values. Thus if specified for @@ -3617,7 +3623,7 @@ The following template field substitutions are availabe for use the templating s |{lf}|A line feed: '\n', alias for {newline}| |{cr}|A carriage return: '\r'| |{crlf}|a carriage return + line feed: '\r\n'| -|{osxphotos_version}|The osxphotos version, e.g. '0.44.0'| +|{osxphotos_version}|The osxphotos version, e.g. '0.44.1'| |{osxphotos_cmd_line}|The full command line used to run osxphotos| |{album}|Album(s) photo is contained in| |{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder| diff --git a/docs/.buildinfo b/docs/.buildinfo index 719f4af2..4d9fcd77 100644 --- a/docs/.buildinfo +++ b/docs/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 4b8efce5e11b970d619d6d5988967d84 +config: 58505ca56d322ccc59c38bc440ccc347 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/_static/documentation_options.js b/docs/_static/documentation_options.js index 8810dcbd..5360877f 100644 --- a/docs/_static/documentation_options.js +++ b/docs/_static/documentation_options.js @@ -1,6 +1,6 @@ var DOCUMENTATION_OPTIONS = { URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), - VERSION: '0.44.0', + VERSION: '0.44.1', LANGUAGE: 'None', COLLAPSE_INDEX: false, BUILDER: 'html', diff --git a/docs/cli.html b/docs/cli.html index 2b1dd641..246a725d 100644 --- a/docs/cli.html +++ b/docs/cli.html @@ -6,7 +6,7 @@ - osxphotos command line interface (CLI) — osxphotos 0.44.0 documentation + osxphotos command line interface (CLI) — osxphotos 0.44.1 documentation diff --git a/docs/genindex.html b/docs/genindex.html index caa12d53..67bfe1d4 100644 --- a/docs/genindex.html +++ b/docs/genindex.html @@ -5,7 +5,7 @@ - Index — osxphotos 0.44.0 documentation + Index — osxphotos 0.44.1 documentation diff --git a/docs/index.html b/docs/index.html index 5271b030..e43d6680 100644 --- a/docs/index.html +++ b/docs/index.html @@ -6,7 +6,7 @@ - Welcome to osxphotos’s documentation! — osxphotos 0.44.0 documentation + Welcome to osxphotos’s documentation! — osxphotos 0.44.1 documentation diff --git a/docs/modules.html b/docs/modules.html index 7ea94dfb..2c111daa 100644 --- a/docs/modules.html +++ b/docs/modules.html @@ -6,7 +6,7 @@ - osxphotos — osxphotos 0.44.0 documentation + osxphotos — osxphotos 0.44.1 documentation diff --git a/docs/reference.html b/docs/reference.html index b89383c6..fb378733 100644 --- a/docs/reference.html +++ b/docs/reference.html @@ -6,7 +6,7 @@ - osxphotos package — osxphotos 0.44.0 documentation + osxphotos package — osxphotos 0.44.1 documentation diff --git a/docs/search.html b/docs/search.html index 280bc1cb..24be17ec 100644 --- a/docs/search.html +++ b/docs/search.html @@ -5,7 +5,7 @@ - Search — osxphotos 0.44.0 documentation + Search — osxphotos 0.44.1 documentation diff --git a/osxphotos/_version.py b/osxphotos/_version.py index ed56f193..cc4a19be 100644 --- a/osxphotos/_version.py +++ b/osxphotos/_version.py @@ -1,3 +1,3 @@ """ version info """ -__version__ = "0.44.0" +__version__ = "0.44.1" diff --git a/osxphotos/cli.py b/osxphotos/cli.py index 54af9c97..7a1f1df4 100644 --- a/osxphotos/cli.py +++ b/osxphotos/cli.py @@ -298,7 +298,8 @@ def QUERY_OPTIONS(f): metavar="UUID", default=None, multiple=True, - help="Search for photos with UUID(s).", + help="Search for photos with UUID(s). " + "May be repeated to include multiple UUIDs.", ), o( "--uuid-from-file", @@ -699,6 +700,23 @@ def cli(ctx, db, json_, debug): "Note: this does not skip RAW photos if the RAW photo does not have an associated JPEG image " "(e.g. the RAW file was imported to Photos without a JPEG preview).", ) +@click.option( + "--skip-uuid", + metavar="UUID", + default=None, + multiple=True, + help="Skip photos with UUID(s) during export. " + "May be repeated to include multiple UUIDs.", +) +@click.option( + "--skip-uuid-from-file", + metavar="FILE", + default=None, + multiple=False, + help="Skip photos with UUID(s) loaded from FILE. " + "Format is a single UUID per line. Lines preceded with # are ignored.", + type=click.Path(exists=True), +) @click.option( "--current-name", is_flag=True, @@ -1124,6 +1142,8 @@ def export( skip_bursts, skip_live, skip_raw, + skip_uuid, + skip_uuid_from_file, person_keyword, album_keyword, keyword_template, @@ -1292,6 +1312,8 @@ def export( skip_bursts = cfg.skip_bursts skip_live = cfg.skip_live skip_raw = cfg.skip_raw + skip_uuid = cfg.skip_uuid + skip_uuid_from_file = cfg.skip_uuid_from_file person_keyword = cfg.person_keyword album_keyword = cfg.album_keyword keyword_template = cfg.keyword_template @@ -1703,6 +1725,13 @@ def export( else: raise ValueError(e) + if skip_uuid: + photos = [p for p in photos if p.uuid not in skip_uuid] + + if skip_uuid_from_file: + skip_uuid_list = load_uuid_from_file(skip_uuid_from_file) + photos = [p for p in photos if p.uuid not in skip_uuid_list] + if photos and only_new: # ignore previously exported files previous_uuids = {uuid: 1 for uuid in export_db.get_previous_uuids()} @@ -2807,7 +2836,8 @@ def _render_suffix_template( rendered_suffix, unmatched = photo.render_template(suffix_template, options) except ValueError as e: raise click.BadOptionUsage( - var_name, f"Invalid template for {option_name} '{suffix_template}': {e}", + var_name, + f"Invalid template for {option_name} '{suffix_template}': {e}", ) if not rendered_suffix or unmatched: raise click.BadOptionUsage( @@ -3499,7 +3529,12 @@ def write_finder_tags( def write_extended_attributes( - photo, files, xattr_template, strip=False, export_dir=None, export_db=None, + photo, + files, + xattr_template, + strip=False, + export_dir=None, + export_db=None, ): """Writes extended attributes to exported files @@ -3653,7 +3688,8 @@ def uninstall(packages, yes): @click.option( "--uuid", metavar="UUID", - help="Use with '--dump photos' to dump only certain UUIDs", + help="Use with '--dump photos' to dump only certain UUIDs. " + "May be repeated to include multiple UUIDs.", multiple=True, ) @click.option("--verbose", "-V", "verbose", is_flag=True, help="Print verbose output.") @@ -4085,7 +4121,9 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMA @cli.command(name="tutorial") @click.argument( - "WIDTH", nargs=-1, type=click.INT, + "WIDTH", + nargs=-1, + type=click.INT, ) @click.pass_obj @click.pass_context @@ -4172,7 +4210,7 @@ def repl(ctx, cli_obj, db, emacs): logger = logging.getLogger() logger.disabled = True - + pretty.install() print(f"python version: {sys.version}") print(f"osxphotos version: {osxphotos._version.__version__}") diff --git a/tests/skip_uuid_from_file.txt b/tests/skip_uuid_from_file.txt new file mode 100644 index 00000000..d82b7952 --- /dev/null +++ b/tests/skip_uuid_from_file.txt @@ -0,0 +1,6 @@ +# test file for --skip-uuid-from-file +# wedding.jpg +E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51 + +# Tulips.jpg + 6191423D-8DB8-4D4C-92BE-9BBBA308AAC4 \ No newline at end of file diff --git a/tests/test_cli.py b/tests/test_cli.py index 2e3032d9..f1ed6e58 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -49,6 +49,7 @@ UUID_SKIP_LIVE_PHOTOKIT = { UUID_DOWNLOAD_MISSING = "C6C712C5-9316-408D-A3C3-125661422DA9" # IMG_8844.JPG UUID_FILE = "tests/uuid_from_file.txt" +SKIP_UUID_FILE = "tests/skip_uuid_from_file.txt" CLI_OUTPUT_NO_SUBCOMMAND = [ "Options:", @@ -767,6 +768,14 @@ CLI_EXPORT_UUID_FROM_FILE_FILENAMES = [ "wedding_edited.jpeg", ] +CLI_EXPORT_SKIP_UUID = ["E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51", "6191423D-8DB8-4D4C-92BE-9BBBA308AAC4"] +CLI_EXPORT_SKIP_UUID_FILENAMES = [ + "Tulips.jpg", + "Tulips_edited.jpeg", + "wedding.jpg", + "wedding_edited.jpeg", +] + UUID_HAS_COMMENTS = [ "4E4944A0-3E5C-4028-9600-A8709F2FA1DB", "4AD7C8EF-2991-4519-9D3A-7F44A6F031BE", @@ -1423,6 +1432,66 @@ def test_export_uuid_from_file(): files = glob.glob("*") assert sorted(files) == sorted(CLI_EXPORT_UUID_FROM_FILE_FILENAMES) +def test_export_skip_uuid_from_file(): + """Test export with --skip-uuid-from-file""" + import glob + import os + import os.path + + import osxphotos + from osxphotos.cli import export + + runner = CliRunner() + cwd = os.getcwd() + # pylint: disable=not-context-manager + with runner.isolated_filesystem(): + result = runner.invoke( + export, + [ + os.path.join(cwd, PHOTOS_DB_15_7), + ".", + "-V", + "--skip-uuid-from-file", + os.path.join(cwd, SKIP_UUID_FILE), + ], + ) + assert result.exit_code == 0 + files = glob.glob("*") + for skipped_file in CLI_EXPORT_SKIP_UUID_FILENAMES: + assert skipped_file not in files + +def test_export_skip_uuid(): + """Test export with --skip-uuid""" + import glob + import os + import os.path + + import osxphotos + from osxphotos.cli import export + + runner = CliRunner() + cwd = os.getcwd() + # pylint: disable=not-context-manager + uuid_option = [] + for uuid in CLI_EXPORT_SKIP_UUID: + uuid_option.append("--skip-uuid") + uuid_option.append(uuid) + + with runner.isolated_filesystem(): + result = runner.invoke( + export, + [ + os.path.join(cwd, PHOTOS_DB_15_7), + ".", + "-V", + *uuid_option, + ], + ) + assert result.exit_code == 0 + files = glob.glob("*") + for skipped_file in CLI_EXPORT_SKIP_UUID_FILENAMES: + assert skipped_file not in files + def test_export_preview(): """test export with --preview"""