Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cad4e1eeff | ||
|
|
ce5145ff85 | ||
|
|
6bf24ad2de | ||
|
|
d6fc8fc3b1 | ||
|
|
003531b052 |
@@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 0.54.3
|
||||
current_version = 0.54.4
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)
|
||||
serialize = {major}.{minor}.{patch}
|
||||
|
||||
|
||||
@@ -2012,7 +2012,7 @@ cog.out(get_template_field_table())
|
||||
|{cr}|A carriage return: '\r'|
|
||||
|{crlf}|A carriage return + line feed: '\r\n'|
|
||||
|{tab}|:A tab: '\t'|
|
||||
|{osxphotos_version}|The osxphotos version, e.g. '0.54.3'|
|
||||
|{osxphotos_version}|The osxphotos version, e.g. '0.54.4'|
|
||||
|{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|
|
||||
|
||||
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file. Dates are d
|
||||
|
||||
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||
|
||||
#### [v0.54.3](https://github.com/RhetTbull/osxphotos/compare/v0.54.2...v0.54.3)
|
||||
|
||||
> 16 November 2022
|
||||
|
||||
- add zephyr325 as a contributor for bug [`#844`](https://github.com/RhetTbull/osxphotos/pull/844)
|
||||
- Version bump [`9ed1b39`](https://github.com/RhetTbull/osxphotos/commit/9ed1b394a9b2df1eca04f489c083ca3a71a7809c)
|
||||
- Fix for timewarp failure on Ventura, #841 [`40de05c`](https://github.com/RhetTbull/osxphotos/commit/40de05c5fdbc8efd8e4bd21eb8b2e17d49f4864e)
|
||||
- Updated search_info test [`f610d3c`](https://github.com/RhetTbull/osxphotos/commit/f610d3cc65a7909cfe3bd9ad4d5209f193c88a87)
|
||||
|
||||
#### [v0.54.2](https://github.com/RhetTbull/osxphotos/compare/v0.54.1...v0.54.2)
|
||||
|
||||
> 14 November 2022
|
||||
|
||||
@@ -2010,7 +2010,7 @@ Substitution Description
|
||||
{cr} A carriage return: '\r'
|
||||
{crlf} A carriage return + line feed: '\r\n'
|
||||
{tab} :A tab: '\t'
|
||||
{osxphotos_version} The osxphotos version, e.g. '0.54.3'
|
||||
{osxphotos_version} The osxphotos version, e.g. '0.54.4'
|
||||
{osxphotos_cmd_line} The full command line used to run osxphotos
|
||||
|
||||
The following substitutions may result in multiple values. Thus if specified
|
||||
@@ -2494,7 +2494,7 @@ The following template field substitutions are availabe for use the templating s
|
||||
|{cr}|A carriage return: '\r'|
|
||||
|{crlf}|A carriage return + line feed: '\r\n'|
|
||||
|{tab}|:A tab: '\t'|
|
||||
|{osxphotos_version}|The osxphotos version, e.g. '0.54.3'|
|
||||
|{osxphotos_version}|The osxphotos version, e.g. '0.54.4'|
|
||||
|{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|
|
||||
|
||||
@@ -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: 9c6fb764dade54d14a6ed536dfc83a4b
|
||||
config: 45f2dda1d3ddb8cbb89b1f561aef11df
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../genindex.html" /><link rel="search" title="Search" href="../search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>Overview: module code - osxphotos 0.54.3 documentation</title>
|
||||
<title>Overview: module code - osxphotos 0.54.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css" />
|
||||
@@ -123,7 +123,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="../index.html"><div class="brand">osxphotos 0.54.3 documentation</div></a>
|
||||
<a href="../index.html"><div class="brand">osxphotos 0.54.4 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -146,7 +146,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="../index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.4 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="../search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
|
||||
@@ -357,7 +357,7 @@ Template Substitutions
|
||||
* - {tab}
|
||||
- :A tab: '\t'
|
||||
* - {osxphotos_version}
|
||||
- The osxphotos version, e.g. '0.54.3'
|
||||
- The osxphotos version, e.g. '0.54.4'
|
||||
* - {osxphotos_cmd_line}
|
||||
- The full command line used to run osxphotos
|
||||
* - {album}
|
||||
|
||||
2
docs/_static/documentation_options.js
vendored
2
docs/_static/documentation_options.js
vendored
@@ -1,6 +1,6 @@
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
||||
VERSION: '0.54.3',
|
||||
VERSION: '0.54.4',
|
||||
LANGUAGE: 'en',
|
||||
COLLAPSE_INDEX: false,
|
||||
BUILDER: 'html',
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos Template System" href="template_help.html" /><link rel="prev" title="OSXPhotos Tutorial" href="tutorial.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>OSXPhotos Command Line Interface (CLI) - osxphotos 0.54.3 documentation</title>
|
||||
<title>OSXPhotos Command Line Interface (CLI) - osxphotos 0.54.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.4 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.4 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -1648,6 +1648,12 @@ to modify this behavior.</p>
|
||||
<dd><p>Set location of imported photo to LATITUDE LONGITUDE. Latitude is a number in the range -90.0 to 90.0; positive latitudes are north of the equator, negative latitudes are south of the equator. Longitude is a number in the range -180.0 to 180.0; positive longitudes are east of the Prime Meridian; negative longitudes are west of the Prime Meridian.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-import-P">
|
||||
<span id="cmdoption-osxphotos-import-p"></span><span id="cmdoption-osxphotos-import-parse-date"></span><span class="sig-name descname"><span class="pre">-P</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--parse-date</span></span><span class="sig-prename descclassname"> <span class="pre"><DATE_PATTERN></span></span><a class="headerlink" href="#cmdoption-osxphotos-import-P" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Parse date from filename using DATE_PATTERN. If file does not match DATE_PATTERN, the date will be set by Photos using Photo’s default behavior. DATE_PATTERN is a strptime-compatible pattern with extensions as pattern described below. If DATE_PATTERN matches time zone information, the time will be set to the local time in the timezone as the import command does not yet support setting time zone information. For example, if your photos are named ‘IMG_1234_2022_11_23_12_34_56.jpg’ where the date/time is ‘2022-11-23 12:34:56’, you could use the pattern ‘%Y_%m_%d_%H_%M_%S’ or ‘IMG_*_%Y_%m_%d_%H_%M_%S’ to further narrow the pattern to only match files with ‘<a href="#id3"><span class="problematic" id="id4">IMG_xxxx_</span></a>’ in the name.See also –check-templates.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-import-C">
|
||||
<span id="cmdoption-osxphotos-import-c"></span><span id="cmdoption-osxphotos-import-clear-metadata"></span><span class="sig-name descname"><span class="pre">-C</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--clear-metadata</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-import-C" title="Permalink to this definition">#</a></dt>
|
||||
@@ -1667,8 +1673,8 @@ to modify this behavior.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-import-p">
|
||||
<span id="cmdoption-osxphotos-import-exiftool-path"></span><span class="sig-name descname"><span class="pre">-p</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--exiftool-path</span></span><span class="sig-prename descclassname"> <span class="pre"><EXIFTOOL_PATH></span></span><a class="headerlink" href="#cmdoption-osxphotos-import-p" title="Permalink to this definition">#</a></dt>
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-import-0">
|
||||
<span id="cmdoption-osxphotos-import-exiftool-path"></span><span class="sig-name descname"><span class="pre">-p</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--exiftool-path</span></span><span class="sig-prename descclassname"> <span class="pre"><EXIFTOOL_PATH></span></span><a class="headerlink" href="#cmdoption-osxphotos-import-0" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Optionally specify path to exiftool; if not provided, will look for exiftool in $PATH.</p>
|
||||
</dd></dl>
|
||||
|
||||
@@ -1741,7 +1747,13 @@ to modify this behavior.</p>
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-import-check-templates">
|
||||
<span class="sig-name descname"><span class="pre">--check-templates</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-osxphotos-import-check-templates" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Don’t actually import anything; renders template strings so you can verify they are correct.</p>
|
||||
<dd><p>Don’t actually import anything; renders template strings and date patterns so you can verify they are correct.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
<dt class="sig sig-object std" id="cmdoption-osxphotos-import-post-function">
|
||||
<span class="sig-name descname"><span class="pre">--post-function</span></span><span class="sig-prename descclassname"> <span class="pre"><filename.py::function></span></span><a class="headerlink" href="#cmdoption-osxphotos-import-post-function" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Run python function after importing file.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 a reference to the photo object and the path to the file that was imported. You can run more than one function by repeating the ‘–post-function’ option with different arguments. See Post Function below.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std option">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="#" /><link rel="search" title="Search" href="search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Index - osxphotos 0.54.3 documentation</title>
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Index - osxphotos 0.54.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
@@ -122,7 +122,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.4 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -145,7 +145,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.4 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -675,7 +675,7 @@
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-exiftool-path">osxphotos-export command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-p">osxphotos-import command line option</a>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-0">osxphotos-import command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-timewarp-e">osxphotos-timewarp command line option</a>
|
||||
</li>
|
||||
@@ -1295,8 +1295,6 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-not-favorite">osxphotos-repl command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li>
|
||||
--not-hdr
|
||||
|
||||
@@ -1308,6 +1306,8 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-not-hdr">osxphotos-repl command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li>
|
||||
--not-hidden
|
||||
|
||||
@@ -1506,6 +1506,13 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-query-panorama">osxphotos-query command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-repl-panorama">osxphotos-repl command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
--parse-date
|
||||
|
||||
<ul>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-P">osxphotos-import command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
@@ -1569,6 +1576,8 @@
|
||||
|
||||
<ul>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-export-post-function">osxphotos-export command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-post-function">osxphotos-import command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
@@ -2300,6 +2309,8 @@
|
||||
-P
|
||||
|
||||
<ul>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-P">osxphotos-import command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-timewarp-P">osxphotos-timewarp command line option</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
@@ -2307,7 +2318,7 @@
|
||||
-p
|
||||
|
||||
<ul>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-p">osxphotos-import command line option</a>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-0">osxphotos-import command line option</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-timewarp-p">osxphotos-timewarp command line option</a>
|
||||
</li>
|
||||
@@ -3651,7 +3662,7 @@
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-e">--exiftool</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-p">--exiftool-path</a>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-0">--exiftool-path</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-g">--glob</a>
|
||||
</li>
|
||||
@@ -3662,6 +3673,10 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-m">--merge-keywords</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-no-progress">--no-progress</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-P">--parse-date</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-post-function">--post-function</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-r">--relative-to</a>
|
||||
</li>
|
||||
@@ -3703,7 +3718,9 @@
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-m">-m</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-p">-p</a>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-P">-P</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-0">-p</a>
|
||||
</li>
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-r">-r</a>
|
||||
</li>
|
||||
@@ -3720,6 +3737,8 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-import-arg-FILES">FILES</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li>
|
||||
osxphotos-info command line option
|
||||
|
||||
@@ -3731,8 +3750,6 @@
|
||||
<li><a href="cli.html#cmdoption-osxphotos-info-arg-PHOTOS_LIBRARY">PHOTOS_LIBRARY</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li>
|
||||
osxphotos-inspect command line option
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos" href="overview.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>osxphotos 0.54.3 documentation</title>
|
||||
<title>osxphotos 0.54.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="#"><div class="brand">osxphotos 0.54.3 documentation</div></a>
|
||||
<a href="#"><div class="brand">osxphotos 0.54.4 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="#">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.4 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
|
||||
BIN
docs/objects.inv
BIN
docs/objects.inv
Binary file not shown.
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos Tutorial" href="tutorial.html" /><link rel="prev" title="Welcome to OSXPhotos’s documentation!" href="index.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>OSXPhotos - osxphotos 0.54.3 documentation</title>
|
||||
<title>OSXPhotos - osxphotos 0.54.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.4 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.4 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos python API" href="reference.html" /><link rel="prev" title="OSXPhotos Template System" href="template_help.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>OSXPhotos Python Package Overview - osxphotos 0.54.3 documentation</title>
|
||||
<title>OSXPhotos Python Package Overview - osxphotos 0.54.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.4 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.4 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Python Module Index - osxphotos 0.54.3 documentation</title>
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Python Module Index - osxphotos 0.54.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
@@ -122,7 +122,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.4 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -145,7 +145,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.4 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="prev" title="OSXPhotos Python Package Overview" href="package_overview.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>OSXPhotos python API - osxphotos 0.54.3 documentation</title>
|
||||
<title>OSXPhotos python API - osxphotos 0.54.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.4 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.4 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="#" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Search - osxphotos 0.54.3 documentation</title><link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/><title>Search - osxphotos 0.54.4 documentation</title><link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
||||
@@ -121,7 +121,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.4 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -144,7 +144,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.4 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="#" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos Python Package Overview" href="package_overview.html" /><link rel="prev" title="OSXPhotos Command Line Interface (CLI)" href="cli.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>OSXPhotos Template System - osxphotos 0.54.3 documentation</title>
|
||||
<title>OSXPhotos Template System - osxphotos 0.54.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.4 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.4 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
@@ -608,7 +608,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p>{osxphotos_version}</p></td>
|
||||
<td><p>The osxphotos version, e.g. ‘0.54.3’</p></td>
|
||||
<td><p>The osxphotos version, e.g. ‘0.54.4’</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p>{osxphotos_cmd_line}</p></td>
|
||||
<td><p>The full command line used to run osxphotos</p></td>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="OSXPhotos Command Line Interface (CLI)" href="cli.html" /><link rel="prev" title="OSXPhotos" href="overview.html" />
|
||||
|
||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29"/>
|
||||
<title>OSXPhotos Tutorial - osxphotos 0.54.3 documentation</title>
|
||||
<title>OSXPhotos Tutorial - osxphotos 0.54.4 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=d81277517bee4d6b0349d71bb2661d4890b5617c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||
@@ -124,7 +124,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.3 documentation</div></a>
|
||||
<a href="index.html"><div class="brand">osxphotos 0.54.4 documentation</div></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="theme-toggle-container theme-toggle-header">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="sidebar-sticky"><a class="sidebar-brand" href="index.html">
|
||||
|
||||
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.3 documentation</span>
|
||||
<span class="sidebar-brand-text">osxphotos 0.54.4 documentation</span>
|
||||
|
||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
||||
|
||||
@@ -357,7 +357,7 @@ Template Substitutions
|
||||
* - {tab}
|
||||
- :A tab: '\t'
|
||||
* - {osxphotos_version}
|
||||
- The osxphotos version, e.g. '0.54.3'
|
||||
- The osxphotos version, e.g. '0.54.4'
|
||||
* - {osxphotos_cmd_line}
|
||||
- The full command line used to run osxphotos
|
||||
* - {album}
|
||||
|
||||
28
examples/post_function_import.py
Normal file
28
examples/post_function_import.py
Normal file
@@ -0,0 +1,28 @@
|
||||
""" Example function for use with osxphotos import --post-function option """
|
||||
|
||||
import typing as t
|
||||
import photoscript
|
||||
import pathlib
|
||||
|
||||
def post_function(
|
||||
photo: photoscript.Photo, filepath: pathlib.Path, verbose: t.Callable, **kwargs
|
||||
):
|
||||
"""Call this with osxphotos import /file/to/import --post-function post_function.py::post_function
|
||||
This will get called immediately after the photo has been imported into Photos
|
||||
and all metadata been set (e.g. --exiftool, --title, etc.)
|
||||
|
||||
Args:
|
||||
photo: photoscript.Photo instance for the photo that's just been imported
|
||||
filepath: pathlib.Path to the file that was imported (this is the path to the source file, not the path inside the Photos library)
|
||||
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
|
||||
|
||||
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
|
||||
See https://rhettbull.github.io/PhotoScript/ for documentation on photoscript
|
||||
"""
|
||||
|
||||
# add a note to the photo's description
|
||||
verbose("Adding note to description")
|
||||
photo.description = f"{photo.description} (imported with osxphotos)"
|
||||
@@ -1,3 +1,3 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.54.3"
|
||||
__version__ = "0.54.4"
|
||||
|
||||
@@ -26,13 +26,20 @@ import click
|
||||
from photoscript import Photo, PhotosLibrary
|
||||
from rich.console import Console
|
||||
from rich.markdown import Markdown
|
||||
from strpdatetime import strpdatetime
|
||||
|
||||
from osxphotos._constants import _OSXPHOTOS_NONE_SENTINEL
|
||||
from osxphotos._version import __version__
|
||||
from osxphotos.cli.common import get_data_dir
|
||||
from osxphotos.cli.help import HELP_WIDTH
|
||||
from osxphotos.cli.param_types import TemplateString
|
||||
from osxphotos.datetime_utils import datetime_naive_to_local
|
||||
from osxphotos.cli.param_types import FunctionCall, StrpDateTimePattern, TemplateString
|
||||
from osxphotos.datetime_utils import (
|
||||
datetime_has_tz,
|
||||
datetime_naive_to_local,
|
||||
datetime_remove_tz,
|
||||
datetime_tz_to_utc,
|
||||
datetime_utc_to_local,
|
||||
)
|
||||
from osxphotos.exiftool import ExifToolCaching, get_exiftool_path
|
||||
from osxphotos.photoinfo import PhotoInfoNone
|
||||
from osxphotos.photosalbum import PhotosAlbumPhotoScript
|
||||
@@ -42,6 +49,7 @@ from osxphotos.utils import pluralize
|
||||
|
||||
from .click_rich_echo import (
|
||||
rich_click_echo,
|
||||
rich_echo_error,
|
||||
set_rich_console,
|
||||
set_rich_theme,
|
||||
set_rich_timestamp,
|
||||
@@ -89,7 +97,7 @@ class PhotoInfoFromFile:
|
||||
|
||||
@property
|
||||
def date(self):
|
||||
"""Use file creation date and local timezone"""
|
||||
"""Use file creation date and local time zone"""
|
||||
ctime = os.path.getctime(self._path)
|
||||
dt = datetime.datetime.fromtimestamp(ctime)
|
||||
return datetime_naive_to_local(dt)
|
||||
@@ -463,6 +471,33 @@ def set_photo_location(
|
||||
photo.location = location
|
||||
|
||||
|
||||
def set_photo_date_from_filename(
|
||||
photo: Photo, filepath: Path, parse_date: str, verbose: Callable[..., None]
|
||||
):
|
||||
"""Set date of photo from filename"""
|
||||
# TODO: handle timezone (use code from timewarp), for now convert timezone to local timezone
|
||||
try:
|
||||
date = strpdatetime(filepath.name, parse_date)
|
||||
# Photo.date must be timezone naive (assumed to local timezone)
|
||||
if datetime_has_tz(date):
|
||||
local_date = datetime_remove_tz(
|
||||
datetime_utc_to_local(datetime_tz_to_utc(date))
|
||||
)
|
||||
verbose(
|
||||
f"Moving date with timezone [time]{date}[/] to local timezone: [time]{local_date.strftime('%Y-%m-%d %H:%M:%S')}[/]"
|
||||
)
|
||||
date = local_date
|
||||
except ValueError:
|
||||
verbose(
|
||||
f"[warning]Could not parse date from filename [filename]{filepath.name}[/][/]"
|
||||
)
|
||||
return
|
||||
verbose(
|
||||
f"Setting date of photo [filename]{filepath.name}[/] to [time]{date.strftime('%Y-%m-%d %H:%M:%S')}[/]"
|
||||
)
|
||||
photo.date = date
|
||||
|
||||
|
||||
def get_relative_filepath(filepath: Path, relative_to: Optional[str]) -> Path:
|
||||
"""Get relative filepath of file relative to relative_to or return filepath if relative_to is None
|
||||
|
||||
@@ -499,6 +534,7 @@ def check_templates_and_exit(
|
||||
album: Tuple[str],
|
||||
exiftool_path: Optional[str],
|
||||
exiftool: bool,
|
||||
parse_date: Optional[str],
|
||||
):
|
||||
"""Renders templates against each file so user can verify correctness"""
|
||||
for file in files:
|
||||
@@ -539,6 +575,14 @@ def check_templates_and_exit(
|
||||
)
|
||||
rendered_album = rendered_album[0] if rendered_album else "None"
|
||||
echo(f"album: [italic]{al}[/]: {rendered_album}")
|
||||
if parse_date:
|
||||
try:
|
||||
date = strpdatetime(file.name, parse_date)
|
||||
echo(f"date: [italic]{parse_date}[/]: {date}")
|
||||
except ValueError:
|
||||
echo(
|
||||
f"[warning]Could not parse date from filename [filename]{file.name}[/][/]"
|
||||
)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
@@ -1042,6 +1086,70 @@ class ImportCommand(click.Command):
|
||||
but will instead print out the rendered value for each `--title`, `--description`,
|
||||
`--keyword`, and `--album` option. It will also print out the values extracted by
|
||||
the `--exiftool` option.
|
||||
|
||||
## Parsing Dates/Times from Filenames
|
||||
|
||||
The --parse-date option allows you to parse dates/times from the filename of the
|
||||
file being imported. This is useful if you have a large number of files with
|
||||
dates/times embedded in the filename but not in the metadata.
|
||||
|
||||
The argument to `--parse-date` is a pattern string that is used to parse the date/time
|
||||
from the filename. The pattern string is a superset of the python `strftime/strptime`
|
||||
format with the following additions:
|
||||
|
||||
- *: Match any number of characters
|
||||
- ^: Match the beginning of the string
|
||||
- $: Match the end of the string
|
||||
- {n}: Match exactly n characters
|
||||
- {n,}: Match at least n characters
|
||||
- {n,m}: Match at least n characters and at most m characters
|
||||
- In addition to `%%` for a literal `%`, the following format codes are supported:
|
||||
`%^`, `%$`, `%*`, `%|`, `%{`, `%}` for `^`, `$`, `*`, `|`, `{`, `}` respectively
|
||||
- |: join multiple format codes; each code is tried in order until one matches
|
||||
- Unlike the standard library, the leading zero is not optional for
|
||||
%d, %m, %H, %I, %M, %S, %j, %U, %W, and %V
|
||||
- For optional leading zero, use %-d, %-m, %-H, %-I, %-M, %-S, %-j, %-U, %-W, and %-V
|
||||
|
||||
For more information on strptime format codes, see:
|
||||
https://docs.python.org/3/library/datetime.html?highlight=strptime#strftime-and-strptime-format-codes
|
||||
|
||||
**Note**: The time zone of the parsed date/time is assumed to be the local time zone.
|
||||
If the parse pattern includes a time zone, the photo's time will be converted from
|
||||
the specified time zone to the local time zone. osxphotos import does not
|
||||
currently support setting the time zone of imported photos.
|
||||
See also `osxphotos help timewarp` for more information on the timewarp
|
||||
command which can be used to change the time zone of photos after import.
|
||||
|
||||
### Examples
|
||||
|
||||
If you have photos with embedded names in filenames like `IMG_1234_20200322_123456.jpg`
|
||||
and `12345678_20200322.jpg`, you can parse the dates with the following pattern:
|
||||
`--parse-date "IMG_*_%Y%m%d_%H%M%S|*_%Y%m%d.*"`. The first pattern matches the first format
|
||||
and the second pattern matches the second. The `|` character is used to separate the two
|
||||
patterns. The order is important as the first pattern will be tried first then the second
|
||||
and so on. If you have multiple formats in your filenames you will want to order the patterns
|
||||
from most specific to least specific to avoid false matches.
|
||||
|
||||
## Post Function
|
||||
|
||||
You can run a custom python function after each photo is imported using `--post-function`.
|
||||
The format is `osxphotos import /file/to/import --post-function post_function.py::post_function`
|
||||
where `post_function.py` is the name of the python file containing the function and `post_function`
|
||||
is the name of the function. The function will be called with the following arguments:
|
||||
`post_function(photo: photoscript.Photo, filepath: pathlib.Path, verbose: t.Callable, **kwargs)`
|
||||
|
||||
- photo: photoscript.Photo instance for the photo that's just been imported
|
||||
- filepath: pathlib.Path to the file that was imported (this is the path to the source file, not the path inside the Photos library)
|
||||
- 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
|
||||
|
||||
The function will get called immediately after the photo has been imported into Photos
|
||||
and all metadata been set (e.g. --exiftool, --title, etc.)
|
||||
|
||||
You may call more than one function by repeating the `--post-function` option.
|
||||
|
||||
See https://rhettbull.github.io/PhotoScript/
|
||||
for documentation on photoscript and the Photo class that is passed to the function.
|
||||
"""
|
||||
)
|
||||
console = Console()
|
||||
@@ -1113,6 +1221,21 @@ class ImportCommand(click.Command):
|
||||
"Longitude is a number in the range -180.0 to 180.0; "
|
||||
"positive longitudes are east of the Prime Meridian; negative longitudes are west of the Prime Meridian.",
|
||||
)
|
||||
@click.option(
|
||||
"--parse-date",
|
||||
"-P",
|
||||
metavar="DATE_PATTERN",
|
||||
type=StrpDateTimePattern(),
|
||||
help="Parse date from filename using DATE_PATTERN. "
|
||||
"If file does not match DATE_PATTERN, the date will be set by Photos using Photo's default behavior. "
|
||||
"DATE_PATTERN is a strptime-compatible pattern with extensions as pattern described below. "
|
||||
"If DATE_PATTERN matches time zone information, the time will be set to the local time in the timezone "
|
||||
"as the import command does not yet support setting time zone information. "
|
||||
"For example, if your photos are named 'IMG_1234_2022_11_23_12_34_56.jpg' where the date/time is "
|
||||
"'2022-11-23 12:34:56', you could use the pattern '%Y_%m_%d_%H_%M_%S' or "
|
||||
"'IMG_*_%Y_%m_%d_%H_%M_%S' to further narrow the pattern to only match files with 'IMG_xxxx_' in the name."
|
||||
"See also --check-templates.",
|
||||
)
|
||||
@click.option(
|
||||
"--clear-metadata",
|
||||
"-C",
|
||||
@@ -1217,7 +1340,20 @@ class ImportCommand(click.Command):
|
||||
"--check-templates",
|
||||
is_flag=True,
|
||||
help="Don't actually import anything; "
|
||||
"renders template strings so you can verify they are correct.",
|
||||
"renders template strings and date patterns so you can verify they are correct.",
|
||||
)
|
||||
@click.option(
|
||||
"--post-function",
|
||||
metavar="filename.py::function",
|
||||
nargs=1,
|
||||
type=FunctionCall(),
|
||||
multiple=True,
|
||||
help="Run python function after importing file."
|
||||
"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 a reference to the photo object and the path to the file that was imported. "
|
||||
"You can run more than one function by repeating the '--post-function' option with different arguments. "
|
||||
"See Post Function below.",
|
||||
)
|
||||
@THEME_OPTION
|
||||
@click.argument("files", nargs=-1)
|
||||
@@ -1241,6 +1377,8 @@ def import_cli(
|
||||
location,
|
||||
merge_keywords,
|
||||
no_progress,
|
||||
parse_date,
|
||||
post_function,
|
||||
relative_to,
|
||||
report,
|
||||
resume,
|
||||
@@ -1289,6 +1427,7 @@ def import_cli(
|
||||
album,
|
||||
exiftool_path,
|
||||
exiftool,
|
||||
parse_date,
|
||||
)
|
||||
|
||||
# initialize report data
|
||||
@@ -1381,6 +1520,9 @@ def import_cli(
|
||||
if location:
|
||||
set_photo_location(photo, filepath, location, verbose)
|
||||
|
||||
if parse_date:
|
||||
set_photo_date_from_filename(photo, filepath, parse_date, verbose)
|
||||
|
||||
if album:
|
||||
add_photo_to_albums(
|
||||
photo,
|
||||
@@ -1392,6 +1534,17 @@ def import_cli(
|
||||
verbose,
|
||||
)
|
||||
|
||||
if post_function:
|
||||
for function in post_function:
|
||||
# post function is tuple of (function, filename.py::function_name)
|
||||
verbose(f"Calling post-function [bold]{function[1]}")
|
||||
try:
|
||||
function[0](photo, filepath, verbose)
|
||||
except Exception as e:
|
||||
rich_echo_error(
|
||||
f"[error]Error running post-function [italic]{function[1]}[/italic]: {e}"
|
||||
)
|
||||
|
||||
update_report_record(report_data[filepath], photo, filepath)
|
||||
import_db.set(str(filepath), report_data[filepath])
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import re
|
||||
import bitmath
|
||||
import click
|
||||
import pytimeparse2
|
||||
from strpdatetime import strpdatetime
|
||||
|
||||
from osxphotos.export_db_utils import export_db_get_version
|
||||
from osxphotos.photoinfo import PhotoInfoNone
|
||||
@@ -21,6 +22,7 @@ __all__ = [
|
||||
"DateTimeISO8601",
|
||||
"ExportDBType",
|
||||
"FunctionCall",
|
||||
"StrpDateTimePattern",
|
||||
"TemplateString",
|
||||
"TimeISO8601",
|
||||
"TimeOffset",
|
||||
@@ -217,3 +219,24 @@ class UTCOffset(click.ParamType):
|
||||
f"Invalid timezone format: {value}. "
|
||||
"Valid format for timezone offset: '±HH:MM', '±H:MM', or '±HHMM'"
|
||||
)
|
||||
|
||||
|
||||
class StrpDateTimePattern(click.ParamType):
|
||||
"""A pattern to be used with strpdatetime()"""
|
||||
|
||||
name = "STRPDATETIME_PATTERN"
|
||||
|
||||
def convert(self, value, param, ctx):
|
||||
try:
|
||||
strpdatetime("", value)
|
||||
return value
|
||||
except ValueError as e:
|
||||
# ValueError could be due to no match or invalid pattern
|
||||
# only want to fail if invalid pattern
|
||||
if any(
|
||||
s in str(e)
|
||||
for s in ["Invalid format string", "bad directive", "stray %"]
|
||||
):
|
||||
self.fail(f"Invalid strpdatetime format string: {value}. {e}")
|
||||
else:
|
||||
return value
|
||||
|
||||
Binary file not shown.
@@ -25,6 +25,7 @@ requests>=2.27.1,<3.0.0
|
||||
rich>=11.2.0,<13.0.0
|
||||
rich_theme_manager>=0.11.0
|
||||
shortuuid==1.0.9
|
||||
strpdatetime>=0.2.0
|
||||
tenacity>=8.0.1,<9.0.0
|
||||
textx>=3.0.0,<4.0.0
|
||||
toml>=0.10.2,<0.11.0
|
||||
|
||||
1
setup.py
1
setup.py
@@ -100,6 +100,7 @@ setup(
|
||||
"rich>=11.2.0,<13.0.0",
|
||||
"rich_theme_manager>=0.11.0",
|
||||
"shortuuid==1.0.9",
|
||||
"strpdatetime>=0.2.0",
|
||||
"tenacity>=8.0.1,<9.0.0",
|
||||
"textx>=3.0.0,<4.0.0",
|
||||
"toml>=0.10.2,<0.11.0",
|
||||
|
||||
BIN
tests/test-images/IMG_NO_EXIF.jpeg
Normal file
BIN
tests/test-images/IMG_NO_EXIF.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.2 MiB |
@@ -1,15 +1,20 @@
|
||||
""" Test --add-exported-to-album """
|
||||
|
||||
import pytest
|
||||
import os
|
||||
from click.testing import CliRunner
|
||||
|
||||
import photoscript
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
UUID_EXPORT = {"3DD2C897-F19E-4CA6-8C22-B027D5A71907": {"filename": "IMG_4547.jpg"}}
|
||||
UUID_MISSING = {
|
||||
"8E1D7BC9-9321-44F9-8CFB-4083F6B9232A": {"filename": "IMG_2000.JPGssss"}
|
||||
}
|
||||
|
||||
# photos with matching names
|
||||
QUERY_NAME = "AAF035"
|
||||
QUERY_COUNT = 4
|
||||
|
||||
|
||||
@pytest.mark.addalbum
|
||||
def test_export_add_to_album(addalbum_library):
|
||||
@@ -113,3 +118,23 @@ def test_query_add_to_album(addalbum_library):
|
||||
got_uuids = [p.uuid for p in album.photos()]
|
||||
assert sorted(got_uuids) == sorted(list(UUID_EXPORT.keys()))
|
||||
|
||||
|
||||
@pytest.mark.addalbum
|
||||
def test_query_add_to_album_multiple_results(addalbum_library):
|
||||
"""Test osxphotos query --add-to-album with multiple results, see #848"""
|
||||
from osxphotos.cli import query
|
||||
|
||||
runner = CliRunner()
|
||||
cwd = os.getcwd()
|
||||
with runner.isolated_filesystem():
|
||||
QUERY_ALBUM = "OSXPhotos Query"
|
||||
|
||||
result = runner.invoke(
|
||||
query, ["--add-to-album", QUERY_ALBUM, "--name", QUERY_NAME]
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
photoslib = photoscript.PhotosLibrary()
|
||||
album = photoslib.album(QUERY_ALBUM)
|
||||
assert album is not None
|
||||
assert len(album) == QUERY_COUNT
|
||||
|
||||
@@ -9,6 +9,7 @@ import re
|
||||
import shutil
|
||||
import sqlite3
|
||||
import time
|
||||
from datetime import datetime
|
||||
from tempfile import TemporaryDirectory
|
||||
from typing import Dict
|
||||
|
||||
@@ -17,7 +18,9 @@ from click.testing import CliRunner
|
||||
from photoscript import Photo
|
||||
from pytest import MonkeyPatch, approx
|
||||
|
||||
from osxphotos import PhotosDB, QueryOptions
|
||||
from osxphotos.cli.import_cli import import_cli
|
||||
from osxphotos.datetime_utils import datetime_remove_tz
|
||||
from osxphotos.exiftool import get_exiftool_path
|
||||
from tests.conftest import get_os_version
|
||||
|
||||
@@ -26,6 +29,7 @@ TERMINAL_WIDTH = 250
|
||||
TEST_IMAGES_DIR = "tests/test-images"
|
||||
TEST_IMAGE_1 = "tests/test-images/IMG_4179.jpeg"
|
||||
TEST_IMAGE_2 = "tests/test-images/faceinfo/exif1.jpg"
|
||||
TEST_IMAGE_NO_EXIF = "tests/test-images/IMG_NO_EXIF.jpeg"
|
||||
TEST_VIDEO_1 = "tests/test-images/Jellyfish.mov"
|
||||
TEST_VIDEO_2 = "tests/test-images/IMG_0670B_NOGPS.MOV"
|
||||
|
||||
@@ -946,3 +950,81 @@ def test_import_resume(monkeypatch: MonkeyPatch, tmpdir):
|
||||
assert "Skipping" in result.output
|
||||
assert "1 skipped" in result.output
|
||||
assert "imported 1" in result.output
|
||||
|
||||
|
||||
@pytest.mark.test_import
|
||||
def test_import_parse_date(tmp_path: pathlib.Path):
|
||||
"""Test import with --parse-date"""
|
||||
|
||||
# set up test images
|
||||
os.environ["TZ"] = "US/Pacific"
|
||||
cwd = os.getcwd()
|
||||
test_image_source = os.path.join(cwd, TEST_IMAGE_NO_EXIF)
|
||||
|
||||
default_date = datetime(1999, 1, 1, 0, 0, 0)
|
||||
test_data = [
|
||||
["img_1234_2020_11_22_12_34_56.jpg", datetime(2020, 11, 22, 12, 34, 56)],
|
||||
["img_1234_20211122.jpg", datetime(2021, 11, 22, 0, 0, 0)],
|
||||
["19991231_20221122.jpg", datetime(2022, 11, 22, 0, 0, 0)],
|
||||
["test_parse_date.jpg", default_date],
|
||||
]
|
||||
images = []
|
||||
for img in [x[0] for x in test_data]:
|
||||
test_file = tmp_path / img
|
||||
shutil.copy(test_image_source, test_file)
|
||||
images.append(test_file)
|
||||
|
||||
# set file time to default date
|
||||
os.utime(test_file, (default_date.timestamp(), default_date.timestamp()))
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
import_cli,
|
||||
[
|
||||
"--verbose",
|
||||
"--parse-date",
|
||||
"img_*_%Y_%m_%d_%H_%M_%S|img_{4}_%Y%m%d|_%Y%m%d.",
|
||||
*[str(x) for x in images],
|
||||
],
|
||||
terminal_width=TERMINAL_WIDTH,
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
# verify that the date was parsed correctly
|
||||
photosdb = PhotosDB()
|
||||
for test_case in test_data:
|
||||
photo = photosdb.query(QueryOptions(name=[test_case[0]]))[0]
|
||||
assert datetime_remove_tz(photo.date) == test_case[1]
|
||||
|
||||
|
||||
@pytest.mark.test_import
|
||||
def test_import_post_function():
|
||||
"""Test import with --post-function"""
|
||||
|
||||
cwd = os.getcwd()
|
||||
test_image_1 = os.path.join(cwd, TEST_IMAGE_1)
|
||||
|
||||
runner = CliRunner()
|
||||
# pylint: disable=not-context-manager
|
||||
with runner.isolated_filesystem():
|
||||
with open("foo1.py", "w") as f:
|
||||
f.writelines(
|
||||
[
|
||||
"def foo(photo, filepath, verbose, **kwargs):\n",
|
||||
" verbose('FOO BAR')\n",
|
||||
]
|
||||
)
|
||||
|
||||
tempdir = os.getcwd()
|
||||
result = runner.invoke(
|
||||
import_cli,
|
||||
[
|
||||
"import",
|
||||
"--verbose",
|
||||
test_image_1,
|
||||
"--post-function",
|
||||
f"{tempdir}/foo1.py::foo",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "FOO BAR" in result.output
|
||||
|
||||
Reference in New Issue
Block a user