osxphotos/examples/post_function.py
Rhet Turnbull b833cde599
Feature post function return 1136 (#1147)
* Changed return signature for post_function

* Updated post_function.py example

* Added tests for post_function returns ExportResults
2023-08-06 08:47:42 -07:00

89 lines
4.8 KiB
Python

""" Example function for use with osxphotos export --post-function option """
from __future__ import annotations
import pathlib
from typing import Any, Callable
from osxphotos import ExportResults, PhotoInfo
from osxphotos.cli import echo_error
def post_function(
photo: PhotoInfo, results: ExportResults, verbose: Callable[[Any], None], **kwargs
) -> ExportResults | None:
"""Call this with osxphotos export /path/to/export --post-function post_function.py::post_function
This will get called immediately after the photo has been exported
Args:
photo: PhotoInfo instance for the photo that's just been exported
see https://rhettbull.github.io/osxphotos/reference.html#osxphotos.PhotoInfo for details
results: ExportResults instance with information about the files associated with the exported photo
see https://rhettbull.github.io/osxphotos/reference.html#osxphotos.ExportResults for details
verbose: A function to print verbose output if --verbose is set; if --verbose is not set, acts as a no-op (nothing gets printed)
**kwargs: reserved for future use; recommend you include **kwargs so your function still works if additional arguments are added in future versions
Returns:
ExportResults instance or None
If returning an ExportResults instance, it must be a new instance; do not modify the instance passed in as an argument.
You should set only the following values in ExportResults:
user_written: list[str], list of files written by your function
user_skipped: list[str], list of files skipped by your function
user_error: list[tuple[str, str]], list of tuples of (filename, error) for any errors generated by your function
For full description of ExportResults see: https://rhettbull.github.io/osxphotos/reference.html#osxphotos.ExportResults
Notes:
Use verbose(str) instead of print if you want your function to conditionally output text depending on --verbose flag
Any string printed with verbose that contains "warning" or "error" (case-insensitive) will be printed with the appropriate warning or error color
The function will not be called if --dry-run flag is enabled
The function be called immediately after export and before any --post-command commands are executed
If your function does not write any files, you can optionally return None instead of an ExportResults instance
If you return ExportResults, any files in user_written or user_skipped will be included when
writing reports and will be preserved when using --cleanup
If you want files previously written by the post_function, but not written this time,
to be preserved when using --cleanup, you should include them in user_skipped
If the function raises an exception, osxphotos will abort the export and exit with an error.
If you want the export to continue, you should catch any exceptions and return an ExportResults instance
with the error(s) in specified in ExportResults.user_error which is a list of tuples of (filename, error)
The verbose function can be used to print text to stdout if --verbose is set
If --verbose is not set, verbose acts as a no-op (nothing gets printed)
Verbose output may be stylized with tags as follows; tags must be enclosed in square brackets
and closed with [/] to end the style:
[change]: something change
[no_change]: indicate no change
[count]: a count
[error]: an error
[filename]: a filename
[filepath]: a filepath
[num]: a number
[time]: a time or date
[tz]: a timezone
[warning]: a warning
[uuid]: a uuid
"""
post_results = ExportResults()
for filename in results.exported + results.skipped:
# do your processing here
# simulate doing some processing
new_filename = pathlib.Path(f"{filename}.new")
if new_filename.exists():
verbose(f"Skipping file [filepath]{new_filename}[/] as it already exists")
post_results.user_skipped.append(new_filename)
else:
verbose(f"Writing new file [filepath]{new_filename}[/]")
new_filename.touch()
post_results.user_written.append(new_filename)
# if you encounter an error, add it to user_error
# echo_error will print the error to stderr with the appropriate formatting
# echo_error(f"Encountered an error processing [filepath]{filename}[/]: [error]some error[/]")
# post_results.user_error.append((filename, "some error"))
# if your function does not write any files, you can return None
return post_results