Implemented --post-function, #442

This commit is contained in:
Rhet Turnbull
2021-06-20 08:52:45 -07:00
parent 233942c9b6
commit 987c91a9ff
5 changed files with 398 additions and 56 deletions

View File

@@ -1073,6 +1073,18 @@ Options:
command by repeating the '--post-command'
option with different arguments. See Post
Command below.
--post-function filename.py::function
Run function on exported files. Use this in
format: --post-function filename.py::function
where filename.py is a python file you've
created and function is the name of the
function in the python file you want to call.
The function will be passed information about
the photo that's been exported and a list of
all exported files associated with the photo.
You can run more than one function by
repeating the '--post-function' option with
different arguments. See Post Function below.
--exportdb EXPORTDB_FILE Specify alternate name for database file which
stores state information for export and
--update. If --exportdb is not specified,
@@ -1571,7 +1583,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.42.41'
{osxphotos_version} The osxphotos version, e.g. '0.42.43'
{osxphotos_cmd_line} The full command line used to run osxphotos
The following substitutions may result in multiple values. Thus if specified for
@@ -1729,6 +1741,17 @@ to ensure your commands are as expected. This will not actually run the commands
but will print out the exact command string which would be executed.
** Post Function **
You can run your own python functions on the exported photos for post-processing
using the '--post-function' option. '--post-function' is passed the name a
python file and the name of the function in the file to call using format
'filename.py::function_name'. See the example function at
https://github.com/RhetTbull/osxphotos/blob/master/examples/post_function.py You
may specify multiple functions to run by repeating the --post-function option.
All post functions will be called immediately after export of each photo and
immediately before any --post-command commands. Post functions will not be
called if the --dry-run flag is set.
```
@@ -3359,7 +3382,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.42.41'|
|{osxphotos_version}|The osxphotos version, e.g. '0.42.43'|
|{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|

View File

@@ -1,3 +1,3 @@
""" version info """
__version__ = "0.42.42"
__version__ = "0.42.43"

View File

@@ -57,7 +57,7 @@ from .photokit import check_photokit_authorization, request_photokit_authorizati
from .photosalbum import PhotosAlbum
from .phototemplate import PhotoTemplate, RenderOptions
from .queryoptions import QueryOptions
from .utils import get_preferred_uti_extension
from .utils import get_preferred_uti_extension, load_function
# global variable to control verbose output
# set via --verbose/-V
@@ -120,7 +120,7 @@ class DateTimeISO8601(click.ParamType):
return datetime.datetime.fromisoformat(value)
except Exception:
self.fail(
f"Invalid value for --{param.name}: invalid datetime format {value}. "
f"Invalid datetime format {value}. "
"Valid format: YYYY-MM-DD[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]]"
)
@@ -154,12 +154,35 @@ class TimeISO8601(click.ParamType):
return datetime.time.fromisoformat(value).replace(tzinfo=None)
except Exception:
self.fail(
f"Invalid value for --{param.name}: invalid time format {value}. "
f"Invalid time format {value}. "
"Valid format: HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]] "
"however, note that timezone will be ignored."
)
class FunctionCall(click.ParamType):
name = "FUNCTION"
def convert(self, value, param, ctx):
if "::" not in value:
self.fail(
f"Could not parse function name from '{value}'. "
"Valid format filename.py::function"
)
filename, funcname = value.split("::")
if not pathlib.Path(filename).is_file():
self.fail(f"'{filename}' does not appear to be a file")
try:
function = load_function(filename, funcname)
except Exception as e:
self.fail(f"Could not load function {funcname} from {filename}")
return (function, value)
# Click CLI object & context settings
class CLI_Obj:
def __init__(self, db=None, json=False, debug=False):
@@ -931,6 +954,18 @@ def cli(ctx, db, json_, debug):
"You can run more than one command by repeating the '--post-command' option with different arguments. "
"See Post Command below.",
)
@click.option(
"--post-function",
metavar="filename.py::function",
nargs=1,
type=FunctionCall(),
multiple=True,
help="Run function on exported files. Use this in format: --post-function filename.py::function where filename.py is a python "
"file you've created and function is the name of the function in the python file you want to call. The function will be "
"passed information about the photo that's been exported and a list of all exported files associated with the photo. "
"You can run more than one function by repeating the '--post-function' option with different arguments. "
"See Post Function below.",
)
@click.option(
"--exportdb",
metavar="EXPORTDB_FILE",
@@ -1096,6 +1131,7 @@ def export(
query_eval,
duplicate,
post_command,
post_function,
):
"""Export photos from the Photos database.
Export path DEST is required.
@@ -1252,6 +1288,7 @@ def export(
query_eval = cfg.query_eval
duplicate = cfg.duplicate
post_command = cfg.post_command
post_function = cfg.post_function
# config file might have changed verbose
VERBOSE = bool(verbose)
@@ -1655,6 +1692,20 @@ def export(
export_dir=dest,
)
if post_function:
for function in post_function:
# post function is tuple of (function, filename.py::function_name)
verbose_(f"Calling post-function {function[1]}")
if not dry_run:
try:
function[0](p, export_results, verbose_)
except Exception as e:
click.secho(
f"Error running post-function {function[1]}: {e}",
fg=CLI_COLOR_ERROR,
err=True,
)
run_post_command(
photo=p,
post_command=post_command,

View File

@@ -242,6 +242,19 @@ The following attributes may be used with '--xattr-template':
+ "print out the exact command string which would be executed."
)
formatter.write("\n\n")
formatter.write(
rich_text("[bold]** Post Function **[/bold]", width=formatter.width)
)
formatter.write_text(
"You can run your own python functions on the exported photos for post-processing "
+ "using the '--post-function' option. '--post-function' is passed the name a python file "
+ "and the name of the function in the file to call using format 'filename.py::function_name'. "
+ "See the example function at https://github.com/RhetTbull/osxphotos/blob/master/examples/post_function.py "
+ "You may specify multiple functions to run by repeating the --post-function option. "
+ "All post functions will be called immediately after export of each photo and immediately before any --post-command commands. "
+ "Post functions will not be called if the --dry-run flag is set."
)
formatter.write("\n")
help_text += formatter.getvalue()
return help_text

File diff suppressed because it is too large Load Diff