Exposed --use-photos-export and --use-photokit
This commit is contained in:
10
README.md
10
README.md
@@ -356,6 +356,16 @@ Options:
|
|||||||
to a filesystem that doesn't support Mac OS
|
to a filesystem that doesn't support Mac OS
|
||||||
extended attributes. Only use this if you
|
extended attributes. Only use this if you
|
||||||
get an error while exporting.
|
get an error while exporting.
|
||||||
|
--use-photos-export Force the use of AppleScript or PhotoKit to
|
||||||
|
export even if not missing (see also '--
|
||||||
|
download-missing' and '--use-photokit').
|
||||||
|
--use-photokit Use with '--download-missing' or '--use-
|
||||||
|
photos-export' to use direct Photos
|
||||||
|
interface instead of AppleScript to export.
|
||||||
|
Highly experimental alpha feature; does not
|
||||||
|
work with iTerm2 (use with Terminal.app).
|
||||||
|
This is faster and more reliable than the
|
||||||
|
default AppleScript interface.
|
||||||
-h, --help Show this message and exit.
|
-h, --help Show this message and exit.
|
||||||
|
|
||||||
** Export **
|
** Export **
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ from .export_db import ExportDB, ExportDBInMemory
|
|||||||
from .fileutil import FileUtil, FileUtilNoOp
|
from .fileutil import FileUtil, FileUtilNoOp
|
||||||
from .path_utils import is_valid_filepath, sanitize_filename, sanitize_filepath
|
from .path_utils import is_valid_filepath, sanitize_filename, sanitize_filepath
|
||||||
from .photoinfo import ExportResults
|
from .photoinfo import ExportResults
|
||||||
|
from .photokit import check_photokit_authorization, request_photokit_authorization
|
||||||
from .phototemplate import TEMPLATE_SUBSTITUTIONS, TEMPLATE_SUBSTITUTIONS_MULTI_VALUED
|
from .phototemplate import TEMPLATE_SUBSTITUTIONS, TEMPLATE_SUBSTITUTIONS_MULTI_VALUED
|
||||||
|
|
||||||
# global variable to control verbose output
|
# global variable to control verbose output
|
||||||
@@ -1394,15 +1395,15 @@ def query(
|
|||||||
"--use-photos-export",
|
"--use-photos-export",
|
||||||
is_flag=True,
|
is_flag=True,
|
||||||
default=False,
|
default=False,
|
||||||
hidden=True,
|
help="Force the use of AppleScript or PhotoKit to export even if not missing (see also '--download-missing' and '--use-photokit').",
|
||||||
help="Force the use of AppleScript to export even if not missing (see also --download-missing).",
|
|
||||||
)
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"--use-photokit",
|
"--use-photokit",
|
||||||
is_flag=True,
|
is_flag=True,
|
||||||
default=False,
|
default=False,
|
||||||
hidden=True,
|
help="Use with '--download-missing' or '--use-photos-export' to use direct Photos interface instead of AppleScript to export. "
|
||||||
help="Use PhotoKit interface instead of AppleScript to export. Highly experimental alpha feature.",
|
"Highly experimental alpha feature; does not work with iTerm2 (use with Terminal.app). "
|
||||||
|
"This is faster and more reliable than the default AppleScript interface.",
|
||||||
)
|
)
|
||||||
@DB_ARGUMENT
|
@DB_ARGUMENT
|
||||||
@click.argument("dest", nargs=1, type=click.Path(exists=True))
|
@click.argument("dest", nargs=1, type=click.Path(exists=True))
|
||||||
@@ -1545,6 +1546,18 @@ def export(
|
|||||||
click.echo(cli.commands["export"].get_help(ctx), err=True)
|
click.echo(cli.commands["export"].get_help(ctx), err=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if use_photokit and not check_photokit_authorization():
|
||||||
|
click.echo(
|
||||||
|
"Requesting access to use your Photos library. Click 'OK' on the dialog box to grant access."
|
||||||
|
)
|
||||||
|
request_photokit_authorization()
|
||||||
|
click.confirm("Have you granted access?")
|
||||||
|
if not check_photokit_authorization():
|
||||||
|
click.echo(
|
||||||
|
"Failed to get access to the Photos library which is needed with `--use-photokit`."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
# initialize export flags
|
# initialize export flags
|
||||||
# by default, will export all versions of photos unless skip flag is set
|
# by default, will export all versions of photos unless skip flag is set
|
||||||
(export_edited, export_bursts, export_live, export_raw) = [
|
(export_edited, export_bursts, export_live, export_raw) = [
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
""" version info """
|
""" version info """
|
||||||
|
|
||||||
__version__ = "0.36.20"
|
__version__ = "0.36.21"
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,58 @@ def path_to_NSURL(path):
|
|||||||
return url
|
return url
|
||||||
|
|
||||||
|
|
||||||
|
def check_photokit_authorization():
|
||||||
|
""" Check authorization to use user's Photos Library
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if user has authorized access to the Photos library, otherwise False
|
||||||
|
"""
|
||||||
|
|
||||||
|
auth_status = Photos.PHPhotoLibrary.authorizationStatus()
|
||||||
|
return auth_status == Photos.PHAuthorizationStatusAuthorized
|
||||||
|
|
||||||
|
|
||||||
|
def request_photokit_authorization():
|
||||||
|
""" Request authorization to user's Photos Library
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
authorization status
|
||||||
|
|
||||||
|
Note: In actual practice, the terminal process running the python code
|
||||||
|
will do the actual request.
|
||||||
|
"""
|
||||||
|
|
||||||
|
(_, major, _) = _get_os_version()
|
||||||
|
|
||||||
|
def handler(status):
|
||||||
|
pass
|
||||||
|
|
||||||
|
auth_status = 0
|
||||||
|
if int(major) < 16:
|
||||||
|
auth_status = Photos.PHPhotoLibrary.authorizationStatus()
|
||||||
|
if auth_status != Photos.PHAuthorizationStatusAuthorized:
|
||||||
|
# it seems the first try fails after Terminal prompts user for access so try again
|
||||||
|
for _ in range(2):
|
||||||
|
Photos.PHPhotoLibrary.requestAuthorization_(handler)
|
||||||
|
auth_status = Photos.PHPhotoLibrary.authorizationStatus()
|
||||||
|
if auth_status == Photos.PHAuthorizationStatusAuthorized:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# requestAuthorization deprecated in 10.16/11.0
|
||||||
|
# but requestAuthorizationForAccessLevel not yet implemented in pyobjc (will be in ver 7.0)
|
||||||
|
# https://developer.apple.com/documentation/photokit/phphotolibrary/3616053-requestauthorizationforaccesslev?language=objc
|
||||||
|
auth_status = Photos.PHPhotoLibrary.authorizationStatus()
|
||||||
|
if auth_status != Photos.PHAuthorizationStatusAuthorized:
|
||||||
|
# it seems the first try fails after Terminal prompts user for access so try again
|
||||||
|
for _ in range(2):
|
||||||
|
Photos.PHPhotoLibrary.requestAuthorization_(handler)
|
||||||
|
auth_status = Photos.PHPhotoLibrary.authorizationStatus()
|
||||||
|
if auth_status == Photos.PHAuthorizationStatusAuthorized:
|
||||||
|
break
|
||||||
|
|
||||||
|
return auth_status
|
||||||
|
|
||||||
|
|
||||||
### exceptions
|
### exceptions
|
||||||
class PhotoKitError(Exception):
|
class PhotoKitError(Exception):
|
||||||
"""Base class for exceptions in this module. """
|
"""Base class for exceptions in this module. """
|
||||||
@@ -1051,12 +1103,6 @@ class PhotoLibrary:
|
|||||||
# get image manager and request options
|
# get image manager and request options
|
||||||
self._phimagemanager = Photos.PHCachingImageManager.defaultManager()
|
self._phimagemanager = Photos.PHCachingImageManager.defaultManager()
|
||||||
|
|
||||||
def _auth_status(self, status):
|
|
||||||
""" Handler for requestAuthorization_ """
|
|
||||||
# This doesn't actually get called but requestAuthorization needs a callable handler
|
|
||||||
# The Terminal will handle the actual authorization when called
|
|
||||||
pass
|
|
||||||
|
|
||||||
def request_authorization(self):
|
def request_authorization(self):
|
||||||
""" Request authorization to user's Photos Library
|
""" Request authorization to user's Photos Library
|
||||||
|
|
||||||
@@ -1064,33 +1110,8 @@ class PhotoLibrary:
|
|||||||
authorization status
|
authorization status
|
||||||
"""
|
"""
|
||||||
|
|
||||||
(_, major, _) = _get_os_version()
|
self.auth_status = request_photokit_authorization()
|
||||||
|
return self.auth_status
|
||||||
auth_status = 0
|
|
||||||
if int(major) < 16:
|
|
||||||
auth_status = Photos.PHPhotoLibrary.authorizationStatus()
|
|
||||||
if auth_status != Photos.PHAuthorizationStatusAuthorized:
|
|
||||||
# it seems the first try fails after Terminal prompts user for access so try again
|
|
||||||
for _ in range(2):
|
|
||||||
Photos.PHPhotoLibrary.requestAuthorization_(self._auth_status)
|
|
||||||
auth_status = Photos.PHPhotoLibrary.authorizationStatus()
|
|
||||||
if auth_status == Photos.PHAuthorizationStatusAuthorized:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# requestAuthorization deprecated in 10.16/11.0
|
|
||||||
# but requestAuthorizationForAccessLevel not yet implemented in pyobjc (will be in ver 7.0)
|
|
||||||
# https://developer.apple.com/documentation/photokit/phphotolibrary/3616053-requestauthorizationforaccesslev?language=objc
|
|
||||||
auth_status = Photos.PHPhotoLibrary.authorizationStatus()
|
|
||||||
if auth_status != Photos.PHAuthorizationStatusAuthorized:
|
|
||||||
# it seems the first try fails after Terminal prompts user for access so try again
|
|
||||||
for _ in range(2):
|
|
||||||
Photos.PHPhotoLibrary.requestAuthorization_(self._auth_status)
|
|
||||||
auth_status = Photos.PHPhotoLibrary.authorizationStatus()
|
|
||||||
if auth_status == Photos.PHAuthorizationStatusAuthorized:
|
|
||||||
break
|
|
||||||
|
|
||||||
self.auth_status = auth_status
|
|
||||||
return auth_status
|
|
||||||
|
|
||||||
def fetch_uuid_list(self, uuid_list):
|
def fetch_uuid_list(self, uuid_list):
|
||||||
""" fetch PHAssets with uuids in uuid_list
|
""" fetch PHAssets with uuids in uuid_list
|
||||||
|
|||||||
Reference in New Issue
Block a user