Added places command to CLI

This commit is contained in:
Rhet Turnbull
2020-03-29 23:03:12 -07:00
parent c02953ef5f
commit fd5e748dca
5 changed files with 84 additions and 3 deletions

View File

@@ -57,7 +57,14 @@ Then you should be able to run `osxphotos` on the command line:
Usage: osxphotos [OPTIONS] COMMAND [ARGS]...
Options:
--db <Photos database path> Specify database file.
--db <Photos database path> Specify Photos database path. Path to Photos
library/database can be specified using either
--db or directly as PHOTOS_LIBRARY positional
argument. If neither --db or PHOTOS_LIBRARY
provided, will attempt to find the library to
use in the following order: 1. last opened
library, 2. system library, 3.
~/Pictures/Photos Library.photoslibrary
--json Print output in JSON format.
-v, --version Show the version and exit.
-h, --help Show this message and exit.
@@ -71,6 +78,7 @@ Commands:
keywords Print out keywords found in the Photos library.
list Print list of Photos libraries found on the system.
persons Print out persons (faces) found in the Photos library.
places Print out places found in the Photos library.
query Query the Photos database using 1 or more search options; if...
```

View File

@@ -18,7 +18,7 @@ from pathvalidate import (
import osxphotos
from ._constants import _EXIF_TOOL_URL, _PHOTOS_5_VERSION
from ._constants import _EXIF_TOOL_URL, _PHOTOS_5_VERSION, _UNKNOWN_PLACE
from ._version import __version__
from .exiftool import get_exiftool_path
from .template import render_filepath_template, TEMPLATE_SUBSTITUTIONS
@@ -479,6 +479,56 @@ def info(ctx, cli_obj, db, json_, photos_library):
click.echo(yaml.dump(info, sort_keys=False))
@cli.command()
@DB_OPTION
@JSON_OPTION
@DB_ARGUMENT
@click.pass_obj
@click.pass_context
def places(ctx, cli_obj, db, json_, photos_library):
""" Print out places found in the Photos library. """
# below needed for to make CliRunner work for testing
cli_db = cli_obj.db if cli_obj is not None else None
db = get_photos_db(*photos_library, db, cli_db)
if db is None:
click.echo(cli.commands["places"].get_help(ctx), err=True)
click.echo("\n\nLocated the following Photos library databases: ", err=True)
_list_libraries()
return
photosdb = osxphotos.PhotosDB(dbfile=db)
place_names = {}
for photo in photosdb.photos(movies=True):
if photo.place:
try:
place_names[photo.place.name] += 1
except:
place_names[photo.place.name] = 1
else:
try:
place_names[_UNKNOWN_PLACE] += 1
except:
place_names[_UNKNOWN_PLACE] = 1
# sort by place count
places = {
"places": {
name: place_names[name]
for name in sorted(
place_names.keys(), key=lambda key: place_names[key], reverse=True
)
}
}
# below needed for to make CliRunner work for testing
cli_json = cli_obj.json if cli_obj is not None else None
if json_ or cli_json:
click.echo(json.dumps(places))
else:
click.echo(yaml.dump(places, sort_keys=False))
@cli.command()
@DB_OPTION
@JSON_OPTION

View File

@@ -25,6 +25,9 @@ _TESTED_OS_VERSIONS = ["12", "13", "14", "15"]
# Photos 5 has persons who are empty string if unidentified face
_UNKNOWN_PERSON = "_UNKNOWN_"
# photos with no reverse geolocation info (place)
_UNKNOWN_PLACE = "_UNKNOWN_"
_EXIF_TOOL_URL = "https://exiftool.org/"
# Where are shared iCloud photos located?

View File

@@ -1,3 +1,3 @@
""" version info """
__version__ = "0.24.2"
__version__ = "0.24.3"

View File

@@ -4,6 +4,7 @@ from click.testing import CliRunner
CLI_PHOTOS_DB = "tests/Test-10.15.1.photoslibrary"
LIVE_PHOTOS_DB = "tests/Test-Cloud-10.15.1.photoslibrary/database/photos.db"
RAW_PHOTOS_DB = "tests/Test-RAW-10.15.1.photoslibrary"
PLACES_PHOTOS_DB = "tests/Test-Places-Catalina-10_15_1.photoslibrary"
CLI_OUTPUT_NO_SUBCOMMAND = [
"Options:",
@@ -85,6 +86,8 @@ CLI_EXPORT_RAW_EDITED = [
]
CLI_EXPORT_RAW_EDITED_ORIGINAL = ["IMG_0476_2.CR2", "IMG_0476_2_edited.jpeg"]
CLI_PLACES_JSON = """{"places": {"_UNKNOWN_": 1, "Maui, Wailea, Hawai'i, United States": 1, "Washington, District of Columbia, United States": 1}}"""
def test_osxphotos():
import osxphotos
@@ -408,3 +411,20 @@ def test_export_directory_template_3():
workdir = os.getcwd()
for filepath in CLI_EXPORTED_DIRECTORY_TEMPLATE_FILENAMES3:
assert os.path.isfile(os.path.join(workdir, filepath))
def test_places():
import json
import os
import os.path
import osxphotos
from osxphotos.__main__ import places
runner = CliRunner()
cwd = os.getcwd()
# pylint: disable=not-context-manager
with runner.isolated_filesystem():
result = runner.invoke(places, [os.path.join(cwd, PLACES_PHOTOS_DB), "--json"])
assert result.exit_code == 0
json_got = json.loads(result.output)
assert json_got == json.loads(CLI_PLACES_JSON)