1973 lines
290 KiB
HTML
1973 lines
290 KiB
HTML
<!doctype html>
|
|
<html class="no-js" lang="en">
|
|
<head><meta charset="utf-8"/>
|
|
<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>osxphotos.phototemplate - osxphotos 0.60.0 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" />
|
|
|
|
|
|
|
|
|
|
<style>
|
|
body {
|
|
--color-code-background: #f8f8f8;
|
|
--color-code-foreground: black;
|
|
|
|
}
|
|
@media not print {
|
|
body[data-theme="dark"] {
|
|
--color-code-background: #202020;
|
|
--color-code-foreground: #d0d0d0;
|
|
|
|
}
|
|
@media (prefers-color-scheme: dark) {
|
|
body:not([data-theme="light"]) {
|
|
--color-code-background: #202020;
|
|
--color-code-foreground: #d0d0d0;
|
|
|
|
}
|
|
}
|
|
}
|
|
</style></head>
|
|
<body>
|
|
|
|
<script>
|
|
document.body.dataset.theme = localStorage.getItem("theme") || "auto";
|
|
</script>
|
|
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
|
<symbol id="svg-toc" viewBox="0 0 24 24">
|
|
<title>Contents</title>
|
|
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 1024 1024">
|
|
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM115.4 518.9L271.7 642c5.8 4.6 14.4.5 14.4-6.9V388.9c0-7.4-8.5-11.5-14.4-6.9L115.4 505.1a8.74 8.74 0 0 0 0 13.8z"/>
|
|
</svg>
|
|
</symbol>
|
|
<symbol id="svg-menu" viewBox="0 0 24 24">
|
|
<title>Menu</title>
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-menu">
|
|
<line x1="3" y1="12" x2="21" y2="12"></line>
|
|
<line x1="3" y1="6" x2="21" y2="6"></line>
|
|
<line x1="3" y1="18" x2="21" y2="18"></line>
|
|
</svg>
|
|
</symbol>
|
|
<symbol id="svg-arrow-right" viewBox="0 0 24 24">
|
|
<title>Expand</title>
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-chevron-right">
|
|
<polyline points="9 18 15 12 9 6"></polyline>
|
|
</svg>
|
|
</symbol>
|
|
<symbol id="svg-sun" viewBox="0 0 24 24">
|
|
<title>Light mode</title>
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather-sun">
|
|
<circle cx="12" cy="12" r="5"></circle>
|
|
<line x1="12" y1="1" x2="12" y2="3"></line>
|
|
<line x1="12" y1="21" x2="12" y2="23"></line>
|
|
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
|
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
|
<line x1="1" y1="12" x2="3" y2="12"></line>
|
|
<line x1="21" y1="12" x2="23" y2="12"></line>
|
|
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
|
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
|
</svg>
|
|
</symbol>
|
|
<symbol id="svg-moon" viewBox="0 0 24 24">
|
|
<title>Dark mode</title>
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-moon">
|
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z" />
|
|
</svg>
|
|
</symbol>
|
|
<symbol id="svg-sun-half" viewBox="0 0 24 24">
|
|
<title>Auto light/dark mode</title>
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-shadow">
|
|
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
|
<circle cx="12" cy="12" r="9" />
|
|
<path d="M13 12h5" />
|
|
<path d="M13 15h4" />
|
|
<path d="M13 18h1" />
|
|
<path d="M13 9h4" />
|
|
<path d="M13 6h1" />
|
|
</svg>
|
|
</symbol>
|
|
</svg>
|
|
|
|
<input type="checkbox" class="sidebar-toggle" name="__navigation" id="__navigation">
|
|
<input type="checkbox" class="sidebar-toggle" name="__toc" id="__toc">
|
|
<label class="overlay sidebar-overlay" for="__navigation">
|
|
<div class="visually-hidden">Hide navigation sidebar</div>
|
|
</label>
|
|
<label class="overlay toc-overlay" for="__toc">
|
|
<div class="visually-hidden">Hide table of contents sidebar</div>
|
|
</label>
|
|
|
|
|
|
|
|
<div class="page">
|
|
<header class="mobile-header">
|
|
<div class="header-left">
|
|
<label class="nav-overlay-icon" for="__navigation">
|
|
<div class="visually-hidden">Toggle site navigation sidebar</div>
|
|
<i class="icon"><svg><use href="#svg-menu"></use></svg></i>
|
|
</label>
|
|
</div>
|
|
<div class="header-center">
|
|
<a href="../../index.html"><div class="brand">osxphotos 0.60.0 documentation</div></a>
|
|
</div>
|
|
<div class="header-right">
|
|
<div class="theme-toggle-container theme-toggle-header">
|
|
<button class="theme-toggle">
|
|
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
|
|
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
|
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
|
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
|
|
</button>
|
|
</div>
|
|
<label class="toc-overlay-icon toc-header-icon no-toc" for="__toc">
|
|
<div class="visually-hidden">Toggle table of contents sidebar</div>
|
|
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
|
|
</label>
|
|
</div>
|
|
</header>
|
|
<aside class="sidebar-drawer">
|
|
<div class="sidebar-container">
|
|
|
|
<div class="sidebar-sticky"><a class="sidebar-brand" href="../../index.html">
|
|
|
|
|
|
<span class="sidebar-brand-text">osxphotos 0.60.0 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">
|
|
<input type="hidden" name="check_keywords" value="yes">
|
|
<input type="hidden" name="area" value="default">
|
|
</form>
|
|
<div id="searchbox"></div><div class="sidebar-scroll"><div class="sidebar-tree">
|
|
<ul>
|
|
<li class="toctree-l1"><a class="reference internal" href="../../overview.html">OSXPhotos</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="../../tutorial.html">OSXPhotos Tutorial</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="../../cli.html">OSXPhotos Command Line Interface (CLI)</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="../../template_help.html">OSXPhotos Template System</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="../../package_overview.html">OSXPhotos Python Package Overview</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="../../reference.html">OSXPhotos Python Reference</a></li>
|
|
</ul>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</aside>
|
|
<div class="main">
|
|
<div class="content">
|
|
<div class="article-container">
|
|
<a href="#" class="back-to-top muted-link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
<path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12z"></path>
|
|
</svg>
|
|
<span>Back to top</span>
|
|
</a>
|
|
<div class="content-icon-container">
|
|
<div class="theme-toggle-container theme-toggle-content">
|
|
<button class="theme-toggle">
|
|
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
|
|
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
|
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
|
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
|
|
</button>
|
|
</div>
|
|
<label class="toc-overlay-icon toc-content-icon no-toc" for="__toc">
|
|
<div class="visually-hidden">Toggle table of contents sidebar</div>
|
|
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
|
|
</label>
|
|
</div>
|
|
<article role="main">
|
|
<h1>Source code for osxphotos.phototemplate</h1><div class="highlight"><pre>
|
|
<span></span><span class="sd">""" Custom template system for osxphotos, implements metadata template language (MTL) """</span>
|
|
|
|
|
|
<span class="kn">import</span> <span class="nn">datetime</span>
|
|
<span class="kn">import</span> <span class="nn">locale</span>
|
|
<span class="kn">import</span> <span class="nn">os</span>
|
|
<span class="kn">import</span> <span class="nn">pathlib</span>
|
|
<span class="kn">import</span> <span class="nn">re</span>
|
|
<span class="kn">import</span> <span class="nn">shlex</span>
|
|
<span class="kn">import</span> <span class="nn">sys</span>
|
|
<span class="kn">from</span> <span class="nn">contextlib</span> <span class="kn">import</span> <span class="n">suppress</span>
|
|
<span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span>
|
|
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">Optional</span><span class="p">,</span> <span class="n">Tuple</span>
|
|
|
|
<span class="kn">from</span> <span class="nn">textx</span> <span class="kn">import</span> <span class="n">TextXSyntaxError</span><span class="p">,</span> <span class="n">metamodel_from_file</span>
|
|
|
|
<span class="kn">import</span> <span class="nn">osxphotos.template_counter</span> <span class="k">as</span> <span class="nn">counter</span>
|
|
|
|
<span class="kn">from</span> <span class="nn">._constants</span> <span class="kn">import</span> <span class="n">_UNKNOWN_PERSON</span><span class="p">,</span> <span class="n">TEXT_DETECTION_CONFIDENCE_THRESHOLD</span>
|
|
<span class="kn">from</span> <span class="nn">._version</span> <span class="kn">import</span> <span class="n">__version__</span>
|
|
<span class="kn">from</span> <span class="nn">.datetime_formatter</span> <span class="kn">import</span> <span class="n">DateTimeFormatter</span>
|
|
<span class="kn">from</span> <span class="nn">.exiftool</span> <span class="kn">import</span> <span class="n">ExifToolCaching</span>
|
|
<span class="kn">from</span> <span class="nn">.path_utils</span> <span class="kn">import</span> <span class="n">sanitize_dirname</span><span class="p">,</span> <span class="n">sanitize_filename</span><span class="p">,</span> <span class="n">sanitize_pathpart</span>
|
|
<span class="kn">from</span> <span class="nn">.utils</span> <span class="kn">import</span> <span class="n">expand_and_validate_filepath</span><span class="p">,</span> <span class="n">load_function</span><span class="p">,</span> <span class="n">uuid_to_shortuuid</span>
|
|
|
|
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="s2">"RenderOptions"</span><span class="p">,</span>
|
|
<span class="s2">"PhotoTemplateParser"</span><span class="p">,</span>
|
|
<span class="s2">"PhotoTemplate"</span><span class="p">,</span>
|
|
<span class="s2">"parse_default_kv"</span><span class="p">,</span>
|
|
<span class="s2">"get_template_help"</span><span class="p">,</span>
|
|
<span class="s2">"format_str_value"</span><span class="p">,</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="c1"># TODO: a lot of values are passed from function to function like path_sep--make these all class properties</span>
|
|
|
|
<span class="c1"># ensure locale set to user's locale</span>
|
|
<span class="n">locale</span><span class="o">.</span><span class="n">setlocale</span><span class="p">(</span><span class="n">locale</span><span class="o">.</span><span class="n">LC_ALL</span><span class="p">,</span> <span class="s2">""</span><span class="p">)</span>
|
|
|
|
<span class="n">MTL_GRAMMAR_MODEL</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="vm">__file__</span><span class="p">)</span><span class="o">.</span><span class="n">parent</span> <span class="o">/</span> <span class="s2">"phototemplate.tx"</span><span class="p">)</span>
|
|
|
|
<span class="sd">"""TextX metamodel for osxphotos template language """</span>
|
|
|
|
<span class="n">PHOTO_VIDEO_TYPE_DEFAULTS</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"photo"</span><span class="p">:</span> <span class="s2">"photo"</span><span class="p">,</span> <span class="s2">"video"</span><span class="p">:</span> <span class="s2">"video"</span><span class="p">}</span>
|
|
|
|
<span class="n">MEDIA_TYPE_DEFAULTS</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="s2">"selfie"</span><span class="p">:</span> <span class="s2">"selfie"</span><span class="p">,</span>
|
|
<span class="s2">"time_lapse"</span><span class="p">:</span> <span class="s2">"time_lapse"</span><span class="p">,</span>
|
|
<span class="s2">"panorama"</span><span class="p">:</span> <span class="s2">"panorama"</span><span class="p">,</span>
|
|
<span class="s2">"slow_mo"</span><span class="p">:</span> <span class="s2">"slow_mo"</span><span class="p">,</span>
|
|
<span class="s2">"screenshot"</span><span class="p">:</span> <span class="s2">"screenshot"</span><span class="p">,</span>
|
|
<span class="s2">"portrait"</span><span class="p">:</span> <span class="s2">"portrait"</span><span class="p">,</span>
|
|
<span class="s2">"live_photo"</span><span class="p">:</span> <span class="s2">"live_photo"</span><span class="p">,</span>
|
|
<span class="s2">"burst"</span><span class="p">:</span> <span class="s2">"burst"</span><span class="p">,</span>
|
|
<span class="s2">"photo"</span><span class="p">:</span> <span class="s2">"photo"</span><span class="p">,</span>
|
|
<span class="s2">"video"</span><span class="p">:</span> <span class="s2">"video"</span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="c1"># Permitted substitutions (each of these returns a single value or None)</span>
|
|
<span class="n">TEMPLATE_SUBSTITUTIONS</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="s2">"</span><span class="si">{name}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Current filename of the photo"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{original_name}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Photo's original filename when imported to Photos"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{title}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Title of the photo"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{descr}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Description of the photo"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{media_type}</span><span class="s2">"</span><span class="p">:</span> <span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"Special media type resolved in this precedence: </span><span class="si">{</span><span class="s1">', '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">t</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">MEDIA_TYPE_DEFAULTS</span><span class="p">)</span><span class="si">}</span><span class="s2">. "</span>
|
|
<span class="s2">"Defaults to 'photo' or 'video' if no special type. "</span>
|
|
<span class="s2">"Customize one or more media types using format: '{media_type,video=vidéo;time_lapse=vidéo_accélérée}'"</span>
|
|
<span class="p">),</span>
|
|
<span class="s2">"</span><span class="si">{photo_or_video}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"'photo' or 'video' depending on what type the image is. To customize, use default value as in '{photo_or_video,photo=fotos;video=videos}'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{hdr}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Photo is HDR?; True/False value, use in format '{hdr?VALUE_IF_TRUE,VALUE_IF_FALSE}'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{edited}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"True if photo has been edited (has adjustments), otherwise False; use in format '{edited?VALUE_IF_TRUE,VALUE_IF_FALSE}'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{edited_version}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"True if template is being rendered for the edited version of a photo, otherwise False. "</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{favorite}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Photo has been marked as favorite?; True/False value, use in format '{favorite?VALUE_IF_TRUE,VALUE_IF_FALSE}'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{created}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Photo's creation date in ISO format, e.g. '2020-03-22'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{created.date}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Photo's creation date in ISO format, e.g. '2020-03-22'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{created.year}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"4-digit year of photo creation time"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{created.yy}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit year of photo creation time"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{created.mm}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit month of the photo creation time (zero padded)"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{created.month}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Month name in user's locale of the photo creation time"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{created.mon}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Month abbreviation in the user's locale of the photo creation time"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{created.dd}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit day of the month (zero padded) of photo creation time"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{created.dow}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Day of week in user's locale of the photo creation time"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{created.doy}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"3-digit day of year (e.g Julian day) of photo creation time, starting from 1 (zero padded)"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{created.hour}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit hour of the photo creation time"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{created.min}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit minute of the photo creation time"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{created.sec}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit second of the photo creation time"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{created.strftime}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Apply strftime template to file creation date/time. Should be used in form "</span>
|
|
<span class="o">+</span> <span class="s2">"{created.strftime,TEMPLATE} where TEMPLATE is a valid strftime template, e.g. "</span>
|
|
<span class="o">+</span> <span class="s2">"{created.strftime,%Y-%U} would result in year-week number of year: '2020-23'. "</span>
|
|
<span class="o">+</span> <span class="s2">"If used with no template will return null value. "</span>
|
|
<span class="o">+</span> <span class="s2">"See https://strftime.org/ for help on strftime templates."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{modified}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Photo's modification date in ISO format, e.g. '2020-03-22'; uses creation date if photo is not modified"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{modified.date}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Photo's modification date in ISO format, e.g. '2020-03-22'; uses creation date if photo is not modified"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{modified.year}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"4-digit year of photo modification time; uses creation date if photo is not modified"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{modified.yy}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit year of photo modification time; uses creation date if photo is not modified"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{modified.mm}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit month of the photo modification time (zero padded); uses creation date if photo is not modified"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{modified.month}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Month name in user's locale of the photo modification time; uses creation date if photo is not modified"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{modified.mon}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Month abbreviation in the user's locale of the photo modification time; uses creation date if photo is not modified"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{modified.dd}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit day of the month (zero padded) of the photo modification time; uses creation date if photo is not modified"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{modified.dow}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Day of week in user's locale of the photo modification time; uses creation date if photo is not modified"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{modified.doy}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"3-digit day of year (e.g Julian day) of photo modification time, starting from 1 (zero padded); uses creation date if photo is not modified"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{modified.hour}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit hour of the photo modification time; uses creation date if photo is not modified"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{modified.min}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit minute of the photo modification time; uses creation date if photo is not modified"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{modified.sec}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit second of the photo modification time; uses creation date if photo is not modified"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{modified.strftime}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Apply strftime template to file modification date/time. Should be used in form "</span>
|
|
<span class="o">+</span> <span class="s2">"{modified.strftime,TEMPLATE} where TEMPLATE is a valid strftime template, e.g. "</span>
|
|
<span class="o">+</span> <span class="s2">"{modified.strftime,%Y-%U} would result in year-week number of year: '2020-23'. "</span>
|
|
<span class="o">+</span> <span class="s2">"If used with no template will return null value. Uses creation date if photo is not modified. "</span>
|
|
<span class="o">+</span> <span class="s2">"See https://strftime.org/ for help on strftime templates."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{today}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Current date in iso format, e.g. '2020-03-22'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{today.date}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Current date in iso format, e.g. '2020-03-22'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{today.year}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"4-digit year of current date"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{today.yy}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit year of current date"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{today.mm}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit month of the current date (zero padded)"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{today.month}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Month name in user's locale of the current date"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{today.mon}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Month abbreviation in the user's locale of the current date"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{today.dd}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit day of the month (zero padded) of current date"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{today.dow}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Day of week in user's locale of the current date"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{today.doy}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"3-digit day of year (e.g Julian day) of current date, starting from 1 (zero padded)"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{today.hour}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit hour of the current date"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{today.min}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit minute of the current date"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{today.sec}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"2-digit second of the current date"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{today.strftime}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Apply strftime template to current date/time. Should be used in form "</span>
|
|
<span class="o">+</span> <span class="s2">"{today.strftime,TEMPLATE} where TEMPLATE is a valid strftime template, e.g. "</span>
|
|
<span class="o">+</span> <span class="s2">"{today.strftime,%Y-%U} would result in year-week number of year: '2020-23'. "</span>
|
|
<span class="o">+</span> <span class="s2">"If used with no template will return null value. "</span>
|
|
<span class="o">+</span> <span class="s2">"See https://strftime.org/ for help on strftime templates."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{place.name}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Place name from the photo's reverse geolocation data, as displayed in Photos"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{place.country_code}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"The ISO country code from the photo's reverse geolocation data"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{place.name.country}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Country name from the photo's reverse geolocation data"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{place.name.state_province}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"State or province name from the photo's reverse geolocation data"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{place.name.city}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"City or locality name from the photo's reverse geolocation data"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{place.name.area_of_interest}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Area of interest name (e.g. landmark or public place) from the photo's reverse geolocation data"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{place.address}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Postal address from the photo's reverse geolocation data, e.g. '2007 18th St NW, Washington, DC 20009, United States'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{place.address.street}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Street part of the postal address, e.g. '2007 18th St NW'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{place.address.city}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"City part of the postal address, e.g. 'Washington'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{place.address.state_province}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"State/province part of the postal address, e.g. 'DC'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{place.address.postal_code}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Postal code part of the postal address, e.g. '20009'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{place.address.country}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Country name of the postal address, e.g. 'United States'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{place.address.country_code}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"ISO country code of the postal address, e.g. 'US'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{searchinfo.season}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Season of the year associated with a photo, e.g. 'Summer'; (Photos 5+ only, applied automatically by Photos' image categorization algorithms)."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{exif.camera_make}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Camera make from original photo's EXIF information as imported by Photos, e.g. 'Apple'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{exif.camera_model}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Camera model from original photo's EXIF information as imported by Photos, e.g. 'iPhone 6s'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{exif.lens_model}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Lens model from original photo's EXIF information as imported by Photos, e.g. 'iPhone 6s back camera 4.15mm f/2.2'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{moment}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"The moment title of the photo"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{uuid}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Photo's internal universally unique identifier (UUID) for the photo, a 36-character string unique to the photo, e.g. '128FB4C6-0B16-4E7D-9108-FB2E90DA1546'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{shortuuid}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"A shorter representation of photo's internal universally unique identifier (UUID) for the photo, "</span>
|
|
<span class="o">+</span> <span class="s2">"a 22-character string unique to the photo, e.g. 'JYsxugP9UjetmCbBCHXcmu'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{id}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"A unique number for the photo based on its primary key in the Photos database. "</span>
|
|
<span class="o">+</span> <span class="s2">"A sequential integer, e.g. 1, 2, 3...etc. Each asset associated with a photo (e.g. an image and Live Photo preview) will share the same id. "</span>
|
|
<span class="o">+</span> <span class="s2">"May be formatted using a python string format code. "</span>
|
|
<span class="o">+</span> <span class="s2">"For example, to format as a 5-digit integer and pad with zeros, use '</span><span class="si">{id:05d}</span><span class="s2">' which results in "</span>
|
|
<span class="o">+</span> <span class="s2">"00001, 00002, 00003...etc. "</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{counter}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"A sequential counter, starting at 0, that increments each time it is evaluated."</span>
|
|
<span class="o">+</span> <span class="s2">"To start counting at a value other than 0, append append '(starting_value)' to the field name."</span>
|
|
<span class="o">+</span> <span class="s2">"For example, to start counting at 1 instead of 0: '{counter(1)}'."</span>
|
|
<span class="o">+</span> <span class="s2">"May be formatted using a python string format code."</span>
|
|
<span class="o">+</span> <span class="s2">"For example, to format as a 5-digit integer and pad with zeros, use '{counter:05d(1)}'"</span>
|
|
<span class="o">+</span> <span class="s2">"which results in 00001, 00002, 00003...etc."</span>
|
|
<span class="o">+</span> <span class="s2">"You may also specify a stop value which causes the counter to reset to the starting value"</span>
|
|
<span class="o">+</span> <span class="s2">"when the stop value is reached and a step size which causes the counter to increment by"</span>
|
|
<span class="o">+</span> <span class="s2">"the specified value instead of 1. Use the format '{counter(start,stop,step)}' where start,"</span>
|
|
<span class="o">+</span> <span class="s2">"stop, and step are integers. For example, to count from 1 to 10 by 2, use '{counter(1,11,2)}'."</span>
|
|
<span class="o">+</span> <span class="s2">"Note that the counter stops counting when the stop value is reached and does not return the"</span>
|
|
<span class="o">+</span> <span class="s2">"stop value. Start, stop, and step are optional and may be omitted. For example, to count"</span>
|
|
<span class="o">+</span> <span class="s2">"from 0 by 2s, use '{counter(,,2)}'."</span>
|
|
<span class="o">+</span> <span class="s2">"You may create an arbitrary number of counters by appending a unique name to the field name"</span>
|
|
<span class="o">+</span> <span class="s2">"preceded by a period: '</span><span class="si">{counter.a}</span><span class="s2">', '</span><span class="si">{counter.b}</span><span class="s2">', etc. Each counter will have its own state"</span>
|
|
<span class="o">+</span> <span class="s2">"and will start at 0 and increment by 1 unless otherwise specified."</span>
|
|
<span class="o">+</span> <span class="s2">" Note: </span><span class="si">{counter}</span><span class="s2"> is not suitable for use with 'export' and '--update' "</span>
|
|
<span class="o">+</span> <span class="s2">"as the counter associated with a photo may change between export sessions. See also </span><span class="si">{id}</span><span class="s2">."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{album_seq}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"An integer, starting at 0, indicating the photo's index (sequence) in the containing album. "</span>
|
|
<span class="o">+</span> <span class="s2">"Only valid when used in a '--filename' template and only when '</span><span class="si">{album}</span><span class="s2">' or '</span><span class="si">{folder_album}</span><span class="s2">' is used in the '--directory' template. "</span>
|
|
<span class="o">+</span> <span class="s1">'For example </span><span class="se">\'</span><span class="s1">--directory "</span><span class="si">{folder_album}</span><span class="s1">" --filename "</span><span class="si">{album_seq}</span><span class="s1">_</span><span class="si">{original_name}</span><span class="s1">"</span><span class="se">\'</span><span class="s1">. '</span>
|
|
<span class="o">+</span> <span class="s2">"To start counting at a value other than 0, append append '(starting_value)' to the field name. "</span>
|
|
<span class="o">+</span> <span class="s2">"For example, to start counting at 1 instead of 0: '{album_seq(1)}'. "</span>
|
|
<span class="o">+</span> <span class="s2">"May be formatted using a python string format code. "</span>
|
|
<span class="o">+</span> <span class="s2">"For example, to format as a 5-digit integer and pad with zeros, use '</span><span class="si">{album_seq:05d}</span><span class="s2">' which results in "</span>
|
|
<span class="o">+</span> <span class="s2">"00000, 00001, 00002...etc. "</span>
|
|
<span class="o">+</span> <span class="s2">"To format while also using a starting value: '{album_seq:05d(1)}' which results in 0001, 00002...etc."</span>
|
|
<span class="o">+</span> <span class="s2">"This may result in incorrect sequences if you have duplicate albums with the same name; see also '</span><span class="si">{folder_album_seq}</span><span class="s2">'."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{folder_album_seq}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"An integer, starting at 0, indicating the photo's index (sequence) in the containing album and folder path. "</span>
|
|
<span class="o">+</span> <span class="s2">"Only valid when used in a '--filename' template and only when '</span><span class="si">{folder_album}</span><span class="s2">' is used in the '--directory' template. "</span>
|
|
<span class="o">+</span> <span class="s1">'For example </span><span class="se">\'</span><span class="s1">--directory "</span><span class="si">{folder_album}</span><span class="s1">" --filename "</span><span class="si">{folder_album_seq}</span><span class="s1">_</span><span class="si">{original_name}</span><span class="s1">"</span><span class="se">\'</span><span class="s1">. '</span>
|
|
<span class="o">+</span> <span class="s2">"To start counting at a value other than 0, append '(starting_value)' to the field name. "</span>
|
|
<span class="o">+</span> <span class="s2">"For example, to start counting at 1 instead of 0: '{folder_album_seq(1)}' "</span>
|
|
<span class="o">+</span> <span class="s2">"May be formatted using a python string format code. "</span>
|
|
<span class="o">+</span> <span class="s2">"For example, to format as a 5-digit integer and pad with zeros, use '</span><span class="si">{folder_album_seq:05d}</span><span class="s2">' which results in "</span>
|
|
<span class="o">+</span> <span class="s2">"00000, 00001, 00002...etc. "</span>
|
|
<span class="o">+</span> <span class="s2">"To format while also using a starting value: '{folder_album_seq:05d(1)}' which results in 0001, 00002...etc."</span>
|
|
<span class="o">+</span> <span class="s2">"This may result in incorrect sequences if you have duplicate albums with the same name in the same folder; see also '</span><span class="si">{album_seq}</span><span class="s2">'. "</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{comma}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"A comma: ','"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{semicolon}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"A semicolon: ';'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{questionmark}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"A question mark: '?'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{pipe}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"A vertical pipe: '|'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{openbrace}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"An open brace: '{'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{closebrace}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"A close brace: '}'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{openparens}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"An open parentheses: '('"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{closeparens}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"A close parentheses: ')'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{openbracket}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"An open bracket: '['"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{closebracket}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"A close bracket: ']'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{newline}</span><span class="s2">"</span><span class="p">:</span> <span class="sa">r</span><span class="s2">"A newline: '\n'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{lf}</span><span class="s2">"</span><span class="p">:</span> <span class="sa">r</span><span class="s2">"A line feed: '\n', alias for </span><span class="si">{newline}</span><span class="s2">"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{cr}</span><span class="s2">"</span><span class="p">:</span> <span class="sa">r</span><span class="s2">"A carriage return: '\r'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{crlf}</span><span class="s2">"</span><span class="p">:</span> <span class="sa">r</span><span class="s2">"A carriage return + line feed: '\r\n'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{tab}</span><span class="s2">"</span><span class="p">:</span> <span class="sa">r</span><span class="s2">":A tab: '\t'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{osxphotos_version}</span><span class="s2">"</span><span class="p">:</span> <span class="sa">f</span><span class="s2">"The osxphotos version, e.g. '</span><span class="si">{</span><span class="n">__version__</span><span class="si">}</span><span class="s2">'"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{osxphotos_cmd_line}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"The full command line used to run osxphotos"</span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="n">TEMPLATE_SUBSTITUTIONS_PATHLIB</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="s2">"</span><span class="si">{export_dir}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"The full path to the export directory"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{filepath}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"The full path to the exported file"</span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="c1"># Permitted multi-value substitutions (each of these returns None or 1 or more values)</span>
|
|
<span class="n">TEMPLATE_SUBSTITUTIONS_MULTI_VALUED</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="s2">"</span><span class="si">{album}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Album(s) photo is contained in"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{folder_album}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{project}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Project(s) photo is contained in (such as greeting cards, calendars, slideshows)"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{album_project}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Album(s) and project(s) photo is contained in; treats projects as regular albums"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{folder_album_project}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Folder path + album (includes projects as albums) photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{keyword}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Keyword(s) assigned to photo"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{person}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Person(s) / face(s) in a photo"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{label}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Image categorization label associated with a photo (Photos 5+ only). "</span>
|
|
<span class="s2">"Labels are added automatically by Photos using machine learning algorithms to categorize images. "</span>
|
|
<span class="s2">"These are not the same as </span><span class="si">{keyword}</span><span class="s2"> which refers to the user-defined keywords/tags applied in Photos."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{label_normalized}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"All lower case version of 'label' (Photos 5+ only)"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{comment}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Comment(s) on shared Photos; format is 'Person name: comment text' (Photos 5+ only)"</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{exiftool}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Format: '{exiftool:GROUP:TAGNAME}'; use exiftool (https://exiftool.org) to extract metadata, in form GROUP:TAGNAME, from image. "</span>
|
|
<span class="s2">"E.g. '{exiftool:EXIF:Make}' to get camera make, or {exiftool:IPTC:Keywords} to extract keywords. "</span>
|
|
<span class="s2">"See https://exiftool.org/TagNames/ for list of valid tag names. You must specify group (e.g. EXIF, IPTC, etc) "</span>
|
|
<span class="s2">"as used in `exiftool -G`. exiftool must be installed in the path to use this template."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{searchinfo.holiday}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Holiday names associated with a photo, e.g. 'Christmas Day'; (Photos 5+ only, applied automatically by Photos' image categorization algorithms)."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{searchinfo.activity}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Activities associated with a photo, e.g. 'Sporting Event'; (Photos 5+ only, applied automatically by Photos' image categorization algorithms)."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{searchinfo.venue}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Venues associated with a photo, e.g. name of restaurant; (Photos 5+ only, applied automatically by Photos' image categorization algorithms)."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{searchinfo.venue_type}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Venue types associated with a photo, e.g. 'Restaurant'; (Photos 5+ only, applied automatically by Photos' image categorization algorithms)."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{photo}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Provides direct access to the PhotoInfo object for the photo. "</span>
|
|
<span class="o">+</span> <span class="s2">"Must be used in format '</span><span class="si">{photo.property}</span><span class="s2">' where 'property' represents a PhotoInfo property. "</span>
|
|
<span class="o">+</span> <span class="s2">"For example: '</span><span class="si">{photo.favorite}</span><span class="s2">' is the same as '</span><span class="si">{favorite}</span><span class="s2">' and '</span><span class="si">{photo.place.name}</span><span class="s2">' is the same as '</span><span class="si">{place.name}</span><span class="s2">'. "</span>
|
|
<span class="o">+</span> <span class="s2">"'</span><span class="si">{photo}</span><span class="s2">' provides access to properties that are not available as separate template fields but it assumes some knowledge of "</span>
|
|
<span class="o">+</span> <span class="s2">"the underlying PhotoInfo class. See https://rhettbull.github.io/osxphotos/ for additional documentation on the PhotoInfo class."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{detected_text}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"List of text strings found in the image after performing text detection. "</span>
|
|
<span class="o">+</span> <span class="s2">"Using '</span><span class="si">{detected_text}</span><span class="s2">' will cause osxphotos to perform text detection on your photos using the built-in macOS text detection algorithms which will slow down your export. "</span>
|
|
<span class="o">+</span> <span class="s2">"The results for each photo will be cached in the export database so that future exports with '--update' do not need to reprocess each photo. "</span>
|
|
<span class="o">+</span> <span class="s2">"You may pass a confidence threshold value between 0.0 and 1.0 after a colon as in '</span><span class="si">{detected_text:0.5}</span><span class="s2">'; "</span>
|
|
<span class="o">+</span> <span class="sa">f</span><span class="s2">"The default confidence threshold is </span><span class="si">{</span><span class="n">TEXT_DETECTION_CONFIDENCE_THRESHOLD</span><span class="si">}</span><span class="s2">. "</span>
|
|
<span class="o">+</span> <span class="s2">"'</span><span class="si">{detected_text}</span><span class="s2">' works only on macOS Catalina (10.15) or later. "</span>
|
|
<span class="o">+</span> <span class="s2">"Note: this feature is not the same thing as Live Text in macOS Monterey, which osxphotos does not yet support."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{shell_quote}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Use in form '{shell_quote,TEMPLATE}'; quotes the rendered TEMPLATE value(s) for safe usage in the shell, e.g. My file.jpeg => 'My file.jpeg'; only adds quotes if needed."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{strip}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Use in form '{strip,TEMPLATE}'; strips whitespace from begining and end of rendered TEMPLATE value(s)."</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{format}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Use in form, '{format:TYPE:FORMAT,TEMPLATE}'; converts TEMPLATE value to TYPE then formats the value "</span>
|
|
<span class="o">+</span> <span class="s2">"using Python string formatting codes specified by FORMAT; TYPE is one of: 'int', 'float', or 'str'. "</span>
|
|
<span class="s2">"For example, '{format:float:.1f,{exiftool:EXIF:FocalLength}}' will format focal length to 1 decimal place (e.g. '100.0'). "</span><span class="p">,</span>
|
|
<span class="s2">"</span><span class="si">{function}</span><span class="s2">"</span><span class="p">:</span> <span class="s2">"Execute a python function from an external file and use return value as template substitution. "</span>
|
|
<span class="o">+</span> <span class="s2">"Use in format: {function:file.py::function_name} where 'file.py' is the name of the python file and 'function_name' is the name of the function to call. "</span>
|
|
<span class="o">+</span> <span class="s2">"The function will be passed the PhotoInfo object for the photo. "</span>
|
|
<span class="o">+</span> <span class="s2">"See https://github.com/RhetTbull/osxphotos/blob/master/examples/template_function.py for an example of how to implement a template function."</span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="n">FILTER_VALUES</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="s2">"lower"</span><span class="p">:</span> <span class="s2">"Convert value to lower case, e.g. 'Value' => 'value'."</span><span class="p">,</span>
|
|
<span class="s2">"upper"</span><span class="p">:</span> <span class="s2">"Convert value to upper case, e.g. 'Value' => 'VALUE'."</span><span class="p">,</span>
|
|
<span class="s2">"strip"</span><span class="p">:</span> <span class="s2">"Strip whitespace from beginning/end of value, e.g. ' Value ' => 'Value'."</span><span class="p">,</span>
|
|
<span class="s2">"titlecase"</span><span class="p">:</span> <span class="s2">"Convert value to title case, e.g. 'my value' => 'My Value'."</span><span class="p">,</span>
|
|
<span class="s2">"capitalize"</span><span class="p">:</span> <span class="s2">"Capitalize first word of value and convert other words to lower case, e.g. 'MY VALUE' => 'My value'."</span><span class="p">,</span>
|
|
<span class="s2">"braces"</span><span class="p">:</span> <span class="s2">"Enclose value in curly braces, e.g. 'value => '</span><span class="si">{value}</span><span class="s2">'."</span><span class="p">,</span>
|
|
<span class="s2">"parens"</span><span class="p">:</span> <span class="s2">"Enclose value in parentheses, e.g. 'value' => '(value')"</span><span class="p">,</span>
|
|
<span class="s2">"brackets"</span><span class="p">:</span> <span class="s2">"Enclose value in brackets, e.g. 'value' => '[value]'"</span><span class="p">,</span>
|
|
<span class="s2">"shell_quote"</span><span class="p">:</span> <span class="s2">"Quotes the value for safe usage in the shell, e.g. My file.jpeg => 'My file.jpeg'; only adds quotes if needed."</span><span class="p">,</span>
|
|
<span class="s2">"function"</span><span class="p">:</span> <span class="s2">"Run custom python function to filter value; use in format 'function:/path/to/file.py::function_name'. See example at https://github.com/RhetTbull/osxphotos/blob/master/examples/template_filter.py"</span><span class="p">,</span>
|
|
<span class="s2">"split(x)"</span><span class="p">:</span> <span class="s2">"Split value into a list of values using x as delimiter, e.g. 'value1;value2' => ['value1', 'value2'] if used with split(;)."</span><span class="p">,</span>
|
|
<span class="s2">"autosplit"</span><span class="p">:</span> <span class="s2">"Automatically split delimited string into separate values; will split strings delimited by comma, semicolon, or space, e.g. 'value1,value2' => ['value1', 'value2']."</span><span class="p">,</span>
|
|
<span class="s2">"chop(x)"</span><span class="p">:</span> <span class="s2">"Remove x characters off the end of value, e.g. chop(1): 'Value' => 'Valu'; when applied to a list, chops characters from each list value, e.g. chop(1): ['travel', 'beach']=> ['trave', 'beac']."</span><span class="p">,</span>
|
|
<span class="s2">"chomp(x)"</span><span class="p">:</span> <span class="s2">"Remove x characters from the beginning of value, e.g. chomp(1): ['Value'] => ['alue']; when applied to a list, removes characters from each list value, e.g. chomp(1): ['travel', 'beach']=> ['ravel', 'each']."</span><span class="p">,</span>
|
|
<span class="s2">"sort"</span><span class="p">:</span> <span class="s2">"Sort list of values, e.g. ['c', 'b', 'a'] => ['a', 'b', 'c']."</span><span class="p">,</span>
|
|
<span class="s2">"rsort"</span><span class="p">:</span> <span class="s2">"Sort list of values in reverse order, e.g. ['a', 'b', 'c'] => ['c', 'b', 'a']."</span><span class="p">,</span>
|
|
<span class="s2">"reverse"</span><span class="p">:</span> <span class="s2">"Reverse order of values, e.g. ['a', 'b', 'c'] => ['c', 'b', 'a']."</span><span class="p">,</span>
|
|
<span class="s2">"uniq"</span><span class="p">:</span> <span class="s2">"Remove duplicate values, e.g. ['a', 'b', 'c', 'b', 'a'] => ['a', 'b', 'c']."</span><span class="p">,</span>
|
|
<span class="s2">"join(x)"</span><span class="p">:</span> <span class="s2">"Join list of values with delimiter x, e.g. join(,): ['a', 'b', 'c'] => 'a,b,c'; "</span>
|
|
<span class="o">+</span> <span class="s2">"the DELIM option functions similar to join(x) but with DELIM, the join happens before being passed to any filters."</span>
|
|
<span class="o">+</span> <span class="s2">"May optionally be used without an argument, that is 'join()' which joins values together with no delimiter. "</span>
|
|
<span class="o">+</span> <span class="s2">"e.g. join(): ['a', 'b', 'c'] => 'abc'."</span><span class="p">,</span>
|
|
<span class="s2">"append(x)"</span><span class="p">:</span> <span class="s2">"Append x to list of values, e.g. append(d): ['a', 'b', 'c'] => ['a', 'b', 'c', 'd']."</span><span class="p">,</span>
|
|
<span class="s2">"prepend(x)"</span><span class="p">:</span> <span class="s2">"Prepend x to list of values, e.g. prepend(d): ['a', 'b', 'c'] => ['d', 'a', 'b', 'c']."</span><span class="p">,</span>
|
|
<span class="s2">"appends(x)"</span><span class="p">:</span> <span class="s2">"Append s[tring] Append x to each value of list of values, e.g. appends(d): ['a', 'b', 'c'] => ['ad', 'bd', 'cd']."</span><span class="p">,</span>
|
|
<span class="s2">"prepends(x)"</span><span class="p">:</span> <span class="s2">"Prepend s[tring] x to each value of list of values, e.g. prepends(d): ['a', 'b', 'c'] => ['da', 'db', 'dc']."</span><span class="p">,</span>
|
|
<span class="s2">"remove(x)"</span><span class="p">:</span> <span class="s2">"Remove x from list of values, e.g. remove(b): ['a', 'b', 'c'] => ['a', 'c']."</span><span class="p">,</span>
|
|
<span class="s2">"slice(start:stop:step)"</span><span class="p">:</span> <span class="s2">"Slice list using same semantics as Python's list slicing, "</span>
|
|
<span class="o">+</span> <span class="s2">"e.g. slice(1:3): ['a', 'b', 'c', 'd'] => ['b', 'c']; slice(1:4:2): ['a', 'b', 'c', 'd'] => ['b', 'd']; "</span>
|
|
<span class="o">+</span> <span class="s2">"slice(1:): ['a', 'b', 'c', 'd'] => ['b', 'c', 'd']; slice(:-1): ['a', 'b', 'c', 'd'] => ['a', 'b', 'c']; "</span>
|
|
<span class="o">+</span> <span class="s2">"slice(::-1): ['a', 'b', 'c', 'd'] => ['d', 'c', 'b', 'a']. See also sslice()."</span><span class="p">,</span>
|
|
<span class="s2">"sslice(start:stop:step)"</span><span class="p">:</span> <span class="s2">"[s(tring) slice] Slice values in a list using same semantics as Python's string slicing, "</span>
|
|
<span class="o">+</span> <span class="s2">"e.g. sslice(1:3):'abcd => 'bc'; sslice(1:4:2): 'abcd' => 'bd', etc. See also slice()."</span><span class="p">,</span>
|
|
<span class="s2">"filter(x)"</span><span class="p">:</span> <span class="s2">"Filter list of values using predicate x; for example, `{folder_album|filter(contains Events)}` returns only folders/albums containing the word 'Events' in their path."</span><span class="p">,</span>
|
|
<span class="s2">"int"</span><span class="p">:</span> <span class="s2">"Convert values in list to integer, e.g. 1.0 => 1. If value cannot be converted to integer, remove value from list. "</span>
|
|
<span class="o">+</span> <span class="s2">"['1.1', 'x'] => ['1']. See also float."</span><span class="p">,</span>
|
|
<span class="s2">"float"</span><span class="p">:</span> <span class="s2">"Convert values in list to floating point number, e.g. 1 => 1.0. If value cannot be converted to float, remove value from list. "</span>
|
|
<span class="o">+</span> <span class="s2">"['1', 'x'] => ['1.0']. See also int."</span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="c1"># Just the substitutions without the braces</span>
|
|
<span class="n">SINGLE_VALUE_SUBSTITUTIONS</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"{"</span><span class="p">,</span> <span class="s2">""</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"}"</span><span class="p">,</span> <span class="s2">""</span><span class="p">)</span> <span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">TEMPLATE_SUBSTITUTIONS</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="n">PATHLIB_SUBSTITUTIONS</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"{"</span><span class="p">,</span> <span class="s2">""</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"}"</span><span class="p">,</span> <span class="s2">""</span><span class="p">)</span> <span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">TEMPLATE_SUBSTITUTIONS_PATHLIB</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="n">MULTI_VALUE_SUBSTITUTIONS</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="n">field</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"{"</span><span class="p">,</span> <span class="s2">""</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"}"</span><span class="p">,</span> <span class="s2">""</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">TEMPLATE_SUBSTITUTIONS_MULTI_VALUED</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="n">FIELD_NAMES</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="n">SINGLE_VALUE_SUBSTITUTIONS</span> <span class="o">+</span> <span class="n">MULTI_VALUE_SUBSTITUTIONS</span> <span class="o">+</span> <span class="n">PATHLIB_SUBSTITUTIONS</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="c1"># default values for string manipulation template options</span>
|
|
<span class="n">INPLACE_DEFAULT</span> <span class="o">=</span> <span class="s2">","</span>
|
|
<span class="n">PATH_SEP_DEFAULT</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">sep</span>
|
|
|
|
<span class="c1"># globals for tracking {seq} substitutions</span>
|
|
<span class="n">_global_seq_count</span> <span class="o">=</span> <span class="mi">0</span>
|
|
|
|
<span class="n">PUNCTUATION</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="s2">"comma"</span><span class="p">:</span> <span class="s2">","</span><span class="p">,</span>
|
|
<span class="s2">"semicolon"</span><span class="p">:</span> <span class="s2">";"</span><span class="p">,</span>
|
|
<span class="s2">"pipe"</span><span class="p">:</span> <span class="s2">"|"</span><span class="p">,</span>
|
|
<span class="s2">"openbrace"</span><span class="p">:</span> <span class="s2">"{"</span><span class="p">,</span>
|
|
<span class="s2">"closebrace"</span><span class="p">:</span> <span class="s2">"}"</span><span class="p">,</span>
|
|
<span class="s2">"openparens"</span><span class="p">:</span> <span class="s2">"("</span><span class="p">,</span>
|
|
<span class="s2">"closeparens"</span><span class="p">:</span> <span class="s2">")"</span><span class="p">,</span>
|
|
<span class="s2">"openbracket"</span><span class="p">:</span> <span class="s2">"["</span><span class="p">,</span>
|
|
<span class="s2">"closebracket"</span><span class="p">:</span> <span class="s2">"]"</span><span class="p">,</span>
|
|
<span class="s2">"questionmark"</span><span class="p">:</span> <span class="s2">"?"</span><span class="p">,</span>
|
|
<span class="s2">"newline"</span><span class="p">:</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span>
|
|
<span class="s2">"lf"</span><span class="p">:</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span>
|
|
<span class="s2">"cr"</span><span class="p">:</span> <span class="s2">"</span><span class="se">\r</span><span class="s2">"</span><span class="p">,</span>
|
|
<span class="s2">"crlf"</span><span class="p">:</span> <span class="s2">"</span><span class="se">\r\n</span><span class="s2">"</span><span class="p">,</span>
|
|
<span class="s2">"tab"</span><span class="p">:</span> <span class="s2">"</span><span class="se">\t</span><span class="s2">"</span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
|
|
|
|
<span class="nd">@dataclass</span>
|
|
<span class="k">class</span> <span class="nc">RenderOptions</span><span class="p">:</span>
|
|
<span class="sd">"""Options for PhotoTemplate.render</span>
|
|
|
|
<span class="sd"> template: str template</span>
|
|
<span class="sd"> none_str: str to use default for None values, default is '_'</span>
|
|
<span class="sd"> path_sep: optional string to use as path separator, default is os.path.sep</span>
|
|
<span class="sd"> expand_inplace: expand multi-valued substitutions in-place as a single string</span>
|
|
<span class="sd"> instead of returning individual strings</span>
|
|
<span class="sd"> inplace_sep: optional string to use as separator between multi-valued keywords</span>
|
|
<span class="sd"> with expand_inplace; default is ','</span>
|
|
<span class="sd"> filename: if True, template output will be sanitized to produce valid file name</span>
|
|
<span class="sd"> dirname: if True, template output will be sanitized to produce valid directory name</span>
|
|
<span class="sd"> strip: if True, strips leading/trailing whitespace from rendered templates</span>
|
|
<span class="sd"> edited_version: set to True if you want {edited_version} to resolve to True (e.g. exporting edited version of photo)</span>
|
|
<span class="sd"> export_dir: set to the export directory if you want to evalute {export_dir} template</span>
|
|
<span class="sd"> dest_path: set to the destination path of the photo (for use by {function} template), only valid with --filename</span>
|
|
<span class="sd"> filepath: set to value for filepath of the exported photo if you want to evaluate {filepath} template</span>
|
|
<span class="sd"> quote: quote path templates for execution in the shell</span>
|
|
<span class="sd"> caller: which command is calling the template (e.g. 'export')</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">none_str</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s2">"_"</span>
|
|
<span class="n">path_sep</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="n">PATH_SEP_DEFAULT</span>
|
|
<span class="n">expand_inplace</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">inplace_sep</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="n">INPLACE_DEFAULT</span>
|
|
<span class="n">filename</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">dirname</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">strip</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">edited_version</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">export_dir</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">dest_path</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">filepath</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">quote</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">caller</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s2">"export"</span>
|
|
|
|
|
|
<span class="k">class</span> <span class="nc">PhotoTemplateParser</span><span class="p">:</span>
|
|
<span class="sd">"""Parser for PhotoTemplate"""</span>
|
|
|
|
<span class="c1"># implemented as Singleton</span>
|
|
|
|
<span class="k">def</span> <span class="fm">__new__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="sd">"""create new object or return instance of already created singleton"""</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="s2">"instance"</span><span class="p">)</span> <span class="ow">or</span> <span class="ow">not</span> <span class="bp">cls</span><span class="o">.</span><span class="n">instance</span><span class="p">:</span>
|
|
<span class="bp">cls</span><span class="o">.</span><span class="n">instance</span> <span class="o">=</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__new__</span><span class="p">(</span><span class="bp">cls</span><span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="bp">cls</span><span class="o">.</span><span class="n">instance</span>
|
|
|
|
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="sd">"""return existing singleton or create a new one"""</span>
|
|
|
|
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"metamodel"</span><span class="p">):</span>
|
|
<span class="k">return</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">metamodel</span> <span class="o">=</span> <span class="n">metamodel_from_file</span><span class="p">(</span><span class="n">MTL_GRAMMAR_MODEL</span><span class="p">,</span> <span class="n">skipws</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">template_statement</span><span class="p">):</span>
|
|
<span class="sd">"""Parse a template_statement string"""</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">metamodel</span><span class="o">.</span><span class="n">model_from_str</span><span class="p">(</span><span class="n">template_statement</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">fields</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">template_statement</span><span class="p">):</span>
|
|
<span class="sd">"""Return list of fields found in a template statement; does not verify that fields are valid"""</span>
|
|
<span class="n">model</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">template_statement</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="p">[</span><span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">field</span> <span class="k">for</span> <span class="n">ts</span> <span class="ow">in</span> <span class="n">model</span><span class="o">.</span><span class="n">template_strings</span> <span class="k">if</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="p">]</span>
|
|
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate">[docs]</a><span class="k">class</span> <span class="nc">PhotoTemplate</span><span class="p">:</span>
|
|
<span class="sd">"""PhotoTemplate class to render a template string from a PhotoInfo object"""</span>
|
|
|
|
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">photo</span><span class="p">,</span> <span class="n">exiftool_path</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="sd">"""Inits PhotoTemplate class with photo</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> photo: a PhotoInfo instance.</span>
|
|
<span class="sd"> exiftool_path: optional path to exiftool for use with {exiftool:} template; if not provided, will look for exiftool in $PATH</span>
|
|
<span class="sd"> """</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">photo</span> <span class="o">=</span> <span class="n">photo</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">exiftool_path</span> <span class="o">=</span> <span class="n">exiftool_path</span>
|
|
|
|
<span class="c1"># holds value of current date/time for {today.x} fields</span>
|
|
<span class="c1"># gets initialized in get_template_value</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">today</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="c1"># get parser singleton</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">parser</span> <span class="o">=</span> <span class="n">PhotoTemplateParser</span><span class="p">()</span>
|
|
|
|
<span class="c1"># initialize render options</span>
|
|
<span class="c1"># this will be done in render() but for testing, some of the lookup functions are called directly</span>
|
|
<span class="n">options</span> <span class="o">=</span> <span class="n">RenderOptions</span><span class="p">()</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="o">=</span> <span class="n">options</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">path_sep</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">path_sep</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">inplace_sep</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">inplace_sep</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">edited_version</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">edited_version</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">none_str</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">none_str</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">expand_inplace</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">expand_inplace</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">filename</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">filename</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">dirname</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">dirname</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">strip</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">strip</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">export_dir</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">export_dir</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">filepath</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">filepath</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">quote</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">quote</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">dest_path</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">dest_path</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">variables</span> <span class="o">=</span> <span class="p">{}</span>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.render"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.render">[docs]</a> <span class="k">def</span> <span class="nf">render</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">template</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
|
|
<span class="n">options</span><span class="p">:</span> <span class="n">RenderOptions</span><span class="p">,</span>
|
|
<span class="p">):</span>
|
|
<span class="sd">"""Render a filename or directory template</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> template: str template</span>
|
|
<span class="sd"> options: a RenderOptions instance</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> ([rendered_strings], [unmatched]): tuple of list of rendered strings and list of unmatched template values</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">template</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="nb">str</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"template must be type str, not </span><span class="si">{</span><span class="nb">type</span><span class="p">(</span><span class="n">template</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="o">=</span> <span class="n">options</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">path_sep</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">path_sep</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">inplace_sep</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">inplace_sep</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">edited_version</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">edited_version</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">none_str</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">none_str</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">expand_inplace</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">expand_inplace</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">filename</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">filename</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">dirname</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">dirname</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">strip</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">strip</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">export_dir</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">export_dir</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">dest_path</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">dest_path</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">filepath</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">filepath</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">quote</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">quote</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">dest_path</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">dest_path</span>
|
|
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">model</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">parser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">template</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">TextXSyntaxError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"SyntaxError: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">model</span><span class="p">:</span>
|
|
<span class="c1"># empty string</span>
|
|
<span class="k">return</span> <span class="p">[],</span> <span class="p">[]</span>
|
|
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_render_statement</span><span class="p">(</span><span class="n">model</span><span class="p">)</span></div>
|
|
|
|
<span class="k">def</span> <span class="nf">_render_statement</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">statement</span><span class="p">,</span>
|
|
<span class="n">field_arg</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="p">):</span>
|
|
<span class="n">results</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">unmatched</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">ts</span> <span class="ow">in</span> <span class="n">statement</span><span class="o">.</span><span class="n">template_strings</span><span class="p">:</span>
|
|
<span class="n">results</span><span class="p">,</span> <span class="n">unmatched</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_render_template_string</span><span class="p">(</span>
|
|
<span class="n">ts</span><span class="p">,</span> <span class="n">results</span><span class="o">=</span><span class="n">results</span><span class="p">,</span> <span class="n">unmatched</span><span class="o">=</span><span class="n">unmatched</span><span class="p">,</span> <span class="n">field_arg</span><span class="o">=</span><span class="n">field_arg</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="n">rendered_strings</span> <span class="o">=</span> <span class="n">results</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">filename</span><span class="p">:</span>
|
|
<span class="n">rendered_strings</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="n">sanitize_filename</span><span class="p">(</span><span class="n">rendered_str</span><span class="p">)</span> <span class="k">for</span> <span class="n">rendered_str</span> <span class="ow">in</span> <span class="n">rendered_strings</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">strip</span><span class="p">:</span>
|
|
<span class="n">rendered_strings</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="n">rendered_str</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">for</span> <span class="n">rendered_str</span> <span class="ow">in</span> <span class="n">rendered_strings</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="k">return</span> <span class="n">rendered_strings</span><span class="p">,</span> <span class="n">unmatched</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_render_template_string</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">ts</span><span class="p">,</span>
|
|
<span class="n">field_arg</span><span class="p">,</span>
|
|
<span class="n">results</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">unmatched</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="p">):</span>
|
|
<span class="sd">"""Render a TemplateString object"""</span>
|
|
|
|
<span class="n">results</span> <span class="o">=</span> <span class="n">results</span> <span class="ow">or</span> <span class="p">[</span><span class="s2">""</span><span class="p">]</span>
|
|
<span class="n">unmatched</span> <span class="o">=</span> <span class="n">unmatched</span> <span class="ow">or</span> <span class="p">[]</span>
|
|
|
|
<span class="k">if</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="p">:</span>
|
|
<span class="c1"># have a template field to process</span>
|
|
<span class="n">field</span> <span class="o">=</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">field</span>
|
|
<span class="n">subfield</span> <span class="o">=</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">subfield</span>
|
|
|
|
<span class="c1"># process filters</span>
|
|
<span class="n">filters</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">if</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">filter</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">filters</span> <span class="o">=</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">filter</span><span class="o">.</span><span class="n">value</span>
|
|
|
|
<span class="c1"># process field arguments</span>
|
|
<span class="k">if</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">fieldarg</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">field_arg</span> <span class="o">=</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">fieldarg</span><span class="o">.</span><span class="n">value</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">field_arg</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="c1"># process delim</span>
|
|
<span class="k">if</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">delim</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># if value is None, means format was {+field}</span>
|
|
<span class="n">delim</span> <span class="o">=</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">delim</span><span class="o">.</span><span class="n">value</span> <span class="ow">or</span> <span class="s2">""</span>
|
|
<span class="n">delim</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">expand_variables_to_str</span><span class="p">(</span><span class="n">delim</span><span class="p">,</span> <span class="s2">"delim"</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">delim</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="k">if</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">bool</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">is_bool</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="k">if</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">bool</span><span class="o">.</span><span class="n">value</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">bool_val</span><span class="p">,</span> <span class="n">u</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_render_statement</span><span class="p">(</span>
|
|
<span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">bool</span><span class="o">.</span><span class="n">value</span><span class="p">,</span>
|
|
<span class="n">field_arg</span><span class="o">=</span><span class="n">field_arg</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="n">unmatched</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">u</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># blank bool value</span>
|
|
<span class="n">bool_val</span> <span class="o">=</span> <span class="p">[</span><span class="s2">""</span><span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">is_bool</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">bool_val</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="c1"># process default</span>
|
|
<span class="k">if</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">default</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># default is also a TemplateString</span>
|
|
<span class="k">if</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">default</span><span class="o">.</span><span class="n">value</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">default</span><span class="p">,</span> <span class="n">u</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_render_statement</span><span class="p">(</span>
|
|
<span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">default</span><span class="o">.</span><span class="n">value</span><span class="p">,</span>
|
|
<span class="n">field_arg</span><span class="o">=</span><span class="n">field_arg</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="n">unmatched</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">u</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># blank default value</span>
|
|
<span class="n">default</span> <span class="o">=</span> <span class="p">[</span><span class="s2">""</span><span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">default</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
<span class="c1"># process conditional</span>
|
|
<span class="k">if</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">conditional</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">operator</span> <span class="o">=</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">conditional</span><span class="o">.</span><span class="n">operator</span>
|
|
<span class="n">negation</span> <span class="o">=</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">conditional</span><span class="o">.</span><span class="n">negation</span>
|
|
<span class="k">if</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">conditional</span><span class="o">.</span><span class="n">value</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># conditional value is also a TemplateString</span>
|
|
<span class="n">conditional_value</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">cv</span> <span class="ow">in</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">conditional</span><span class="o">.</span><span class="n">value</span><span class="p">:</span>
|
|
<span class="n">value</span><span class="p">,</span> <span class="n">u</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_render_statement</span><span class="p">(</span><span class="n">cv</span><span class="p">)</span>
|
|
<span class="n">conditional_value</span> <span class="o">+=</span> <span class="n">value</span>
|
|
<span class="n">unmatched</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">u</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># this shouldn't happen</span>
|
|
<span class="n">conditional_value</span> <span class="o">=</span> <span class="p">[</span><span class="s2">""</span><span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">operator</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">negation</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">conditional_value</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"%"</span><span class="p">):</span>
|
|
<span class="c1"># variable in form {%var}</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">variables</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">field</span><span class="p">[</span><span class="mi">1</span><span class="p">:],</span> <span class="kc">None</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">vals</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Variable '</span><span class="si">{</span><span class="n">field</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span><span class="si">}</span><span class="s2">' is not defined."</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"var"</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">subfield</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">default</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span>
|
|
<span class="s2">"var must have a subfield and value in form {var:subfield,value}"</span>
|
|
<span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">variables</span><span class="p">[</span><span class="n">subfield</span><span class="p">]</span> <span class="o">=</span> <span class="n">default</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">vals</span><span class="p">,</span> <span class="n">u</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_field_values</span><span class="p">(</span><span class="n">field</span><span class="p">,</span> <span class="n">subfield</span><span class="p">,</span> <span class="n">field_arg</span><span class="p">,</span> <span class="n">default</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">u</span><span class="p">:</span>
|
|
<span class="n">unmatched</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">u</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="p">[],</span> <span class="n">unmatched</span>
|
|
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="p">[</span><span class="n">val</span> <span class="k">for</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">vals</span> <span class="k">if</span> <span class="n">val</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">]</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">expand_inplace</span> <span class="ow">or</span> <span class="n">delim</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">sep</span> <span class="o">=</span> <span class="n">delim</span> <span class="k">if</span> <span class="n">delim</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">inplace_sep</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="p">[</span><span class="n">sep</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="n">vals</span><span class="p">))]</span> <span class="k">if</span> <span class="n">vals</span> <span class="k">else</span> <span class="p">[]</span>
|
|
|
|
<span class="k">for</span> <span class="n">filter_</span> <span class="ow">in</span> <span class="n">filters</span><span class="p">:</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_filter_values</span><span class="p">(</span><span class="n">filter_</span><span class="p">,</span> <span class="n">vals</span><span class="p">)</span>
|
|
|
|
<span class="c1"># process find/replace</span>
|
|
<span class="k">if</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">findreplace</span><span class="p">:</span>
|
|
<span class="n">new_vals</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">vals</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">pair</span> <span class="ow">in</span> <span class="n">ts</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">findreplace</span><span class="o">.</span><span class="n">pairs</span><span class="p">:</span>
|
|
<span class="n">find</span> <span class="o">=</span> <span class="n">pair</span><span class="o">.</span><span class="n">find</span> <span class="ow">or</span> <span class="s2">""</span>
|
|
<span class="n">find</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">expand_variables_to_str</span><span class="p">(</span><span class="n">find</span><span class="p">,</span> <span class="s2">"find/replace"</span><span class="p">)</span>
|
|
<span class="n">repl</span> <span class="o">=</span> <span class="n">pair</span><span class="o">.</span><span class="n">replace</span> <span class="ow">or</span> <span class="s2">""</span>
|
|
<span class="n">repl</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">expand_variables_to_str</span><span class="p">(</span><span class="n">repl</span><span class="p">,</span> <span class="s2">"find/replace"</span><span class="p">)</span>
|
|
<span class="n">val</span> <span class="o">=</span> <span class="n">val</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">find</span><span class="p">,</span> <span class="n">repl</span><span class="p">)</span>
|
|
<span class="n">new_vals</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">val</span><span class="p">)</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="n">new_vals</span>
|
|
|
|
<span class="k">if</span> <span class="n">operator</span><span class="p">:</span>
|
|
<span class="c1"># have a conditional operator</span>
|
|
|
|
<span class="k">def</span> <span class="nf">string_test</span><span class="p">(</span><span class="n">test_function</span><span class="p">):</span>
|
|
<span class="sd">"""Perform string comparison using test_function; closure to capture conditional_value, vals, negation"""</span>
|
|
<span class="n">match</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">conditional_value</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">vals</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">test_function</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">c</span><span class="p">):</span>
|
|
<span class="n">match</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="k">break</span>
|
|
<span class="k">if</span> <span class="n">match</span><span class="p">:</span>
|
|
<span class="k">break</span>
|
|
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="p">[</span><span class="s2">"True"</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">match</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">negation</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="n">negation</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">match</span><span class="p">)</span>
|
|
<span class="k">else</span> <span class="p">[]</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">comparison_test</span><span class="p">(</span><span class="n">test_function</span><span class="p">):</span>
|
|
<span class="sd">"""Perform numerical comparisons using test_function; closure to capture conditional_val, vals, negation"""</span>
|
|
<span class="c1"># returns True if any of the values match the condition</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">conditional_value</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"comparison operators may only be used with a single conditional value: </span><span class="si">{</span><span class="n">conditional_value</span><span class="si">}</span><span class="s2">"</span>
|
|
<span class="p">)</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">match</span> <span class="o">=</span> <span class="nb">any</span><span class="p">(</span>
|
|
<span class="nb">bool</span><span class="p">(</span><span class="n">test_function</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">v</span><span class="p">),</span> <span class="nb">float</span><span class="p">(</span><span class="n">conditional_value</span><span class="p">[</span><span class="mi">0</span><span class="p">])))</span>
|
|
<span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">vals</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="p">[</span><span class="s2">"True"</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">match</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">negation</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="n">negation</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">match</span><span class="p">)</span>
|
|
<span class="k">else</span> <span class="p">[]</span>
|
|
<span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">ValueError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"comparison operators may only be used with values that can be converted to numbers: </span><span class="si">{</span><span class="n">vals</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">conditional_value</span><span class="si">}</span><span class="s2">"</span>
|
|
<span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
|
|
|
<span class="k">if</span> <span class="n">operator</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"contains"</span><span class="p">,</span> <span class="s2">"matches"</span><span class="p">,</span> <span class="s2">"startswith"</span><span class="p">,</span> <span class="s2">"endswith"</span><span class="p">]:</span>
|
|
<span class="c1"># process any "or" values separated by "|"</span>
|
|
<span class="n">temp_values</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">conditional_value</span><span class="p">:</span>
|
|
<span class="n">temp_values</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"|"</span><span class="p">))</span>
|
|
<span class="n">conditional_value</span> <span class="o">=</span> <span class="n">temp_values</span>
|
|
|
|
<span class="k">if</span> <span class="n">operator</span> <span class="o">==</span> <span class="s2">"contains"</span><span class="p">:</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="n">string_test</span><span class="p">(</span><span class="k">lambda</span> <span class="n">v</span><span class="p">,</span> <span class="n">c</span><span class="p">:</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">v</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">operator</span> <span class="o">==</span> <span class="s2">"matches"</span><span class="p">:</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="n">string_test</span><span class="p">(</span><span class="k">lambda</span> <span class="n">v</span><span class="p">,</span> <span class="n">c</span><span class="p">:</span> <span class="n">v</span> <span class="o">==</span> <span class="n">c</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">operator</span> <span class="o">==</span> <span class="s2">"startswith"</span><span class="p">:</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="n">string_test</span><span class="p">(</span><span class="k">lambda</span> <span class="n">v</span><span class="p">,</span> <span class="n">c</span><span class="p">:</span> <span class="n">v</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">c</span><span class="p">))</span>
|
|
<span class="k">elif</span> <span class="n">operator</span> <span class="o">==</span> <span class="s2">"endswith"</span><span class="p">:</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="n">string_test</span><span class="p">(</span><span class="k">lambda</span> <span class="n">v</span><span class="p">,</span> <span class="n">c</span><span class="p">:</span> <span class="n">v</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="n">c</span><span class="p">))</span>
|
|
<span class="k">elif</span> <span class="n">operator</span> <span class="o">==</span> <span class="s2">"=="</span><span class="p">:</span>
|
|
<span class="n">match</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">vals</span><span class="p">)</span> <span class="o">==</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">conditional_value</span><span class="p">)</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="p">[</span><span class="s2">"True"</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">match</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">negation</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="n">negation</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">match</span><span class="p">)</span>
|
|
<span class="k">else</span> <span class="p">[]</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">operator</span> <span class="o">==</span> <span class="s2">"!="</span><span class="p">:</span>
|
|
<span class="n">match</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">vals</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">conditional_value</span><span class="p">)</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="p">[</span><span class="s2">"True"</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">match</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">negation</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="n">negation</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">match</span><span class="p">)</span>
|
|
<span class="k">else</span> <span class="p">[]</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">operator</span> <span class="o">==</span> <span class="s2">"<"</span><span class="p">:</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="n">comparison_test</span><span class="p">(</span><span class="k">lambda</span> <span class="n">v</span><span class="p">,</span> <span class="n">c</span><span class="p">:</span> <span class="n">v</span> <span class="o"><</span> <span class="n">c</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">operator</span> <span class="o">==</span> <span class="s2">"<="</span><span class="p">:</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="n">comparison_test</span><span class="p">(</span><span class="k">lambda</span> <span class="n">v</span><span class="p">,</span> <span class="n">c</span><span class="p">:</span> <span class="n">v</span> <span class="o"><=</span> <span class="n">c</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">operator</span> <span class="o">==</span> <span class="s2">">"</span><span class="p">:</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="n">comparison_test</span><span class="p">(</span><span class="k">lambda</span> <span class="n">v</span><span class="p">,</span> <span class="n">c</span><span class="p">:</span> <span class="n">v</span> <span class="o">></span> <span class="n">c</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">operator</span> <span class="o">==</span> <span class="s2">">="</span><span class="p">:</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="n">comparison_test</span><span class="p">(</span><span class="k">lambda</span> <span class="n">v</span><span class="p">,</span> <span class="n">c</span><span class="p">:</span> <span class="n">v</span> <span class="o">>=</span> <span class="n">c</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">is_bool</span><span class="p">:</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="n">default</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">vals</span> <span class="k">else</span> <span class="n">bool_val</span>
|
|
<span class="k">elif</span> <span class="ow">not</span> <span class="n">vals</span> <span class="ow">and</span> <span class="n">field</span> <span class="o">!=</span> <span class="s2">"var"</span><span class="p">:</span>
|
|
<span class="c1"># don't assign default value if the template was variable assignment</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="n">default</span> <span class="ow">or</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">none_str</span><span class="p">]</span>
|
|
|
|
<span class="n">pre</span> <span class="o">=</span> <span class="n">ts</span><span class="o">.</span><span class="n">pre</span> <span class="ow">or</span> <span class="s2">""</span>
|
|
<span class="n">post</span> <span class="o">=</span> <span class="n">ts</span><span class="o">.</span><span class="n">post</span> <span class="ow">or</span> <span class="s2">""</span>
|
|
|
|
<span class="n">rendered</span> <span class="o">=</span> <span class="p">[</span><span class="n">pre</span> <span class="o">+</span> <span class="n">val</span> <span class="o">+</span> <span class="n">post</span> <span class="k">for</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">vals</span><span class="p">]</span>
|
|
<span class="n">results_new</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">ren</span> <span class="ow">in</span> <span class="n">rendered</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">res</span> <span class="ow">in</span> <span class="n">results</span><span class="p">:</span>
|
|
<span class="n">res_new</span> <span class="o">=</span> <span class="n">res</span> <span class="o">+</span> <span class="n">ren</span>
|
|
<span class="n">results_new</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">res_new</span><span class="p">)</span>
|
|
<span class="n">results</span> <span class="o">=</span> <span class="n">results_new</span>
|
|
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># no template</span>
|
|
<span class="n">pre</span> <span class="o">=</span> <span class="n">ts</span><span class="o">.</span><span class="n">pre</span> <span class="ow">or</span> <span class="s2">""</span>
|
|
<span class="n">post</span> <span class="o">=</span> <span class="n">ts</span><span class="o">.</span><span class="n">post</span> <span class="ow">or</span> <span class="s2">""</span>
|
|
<span class="n">results</span> <span class="o">=</span> <span class="p">[</span><span class="n">r</span> <span class="o">+</span> <span class="n">pre</span> <span class="o">+</span> <span class="n">post</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">results</span><span class="p">]</span>
|
|
|
|
<span class="k">return</span> <span class="n">results</span><span class="p">,</span> <span class="n">unmatched</span>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.expand_variables_to_str"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.expand_variables_to_str">[docs]</a> <span class="k">def</span> <span class="nf">expand_variables_to_str</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Expand variables in value and return a str of the expanded value.</span>
|
|
<span class="sd"> Enforce that the expanded value is a single value, raises ValueError if not.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> value: the value to expand</span>
|
|
<span class="sd"> name: the name of the value being expanded (used in error messages)</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">expanded</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">expand_variables</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">expanded</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2"> must have a single value, not </span><span class="si">{</span><span class="n">expanded</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">expanded</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></div>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.expand_variables"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.expand_variables">[docs]</a> <span class="k">def</span> <span class="nf">expand_variables</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
|
|
<span class="sd">"""Expand variables in value"""</span>
|
|
<span class="c1"># replace any variables with their values</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">value</span><span class="p">]</span>
|
|
<span class="n">new_values</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="c1"># allow %% to escape %, match variables in form %var</span>
|
|
<span class="n">variable_match</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s2">"(?:</span><span class="si">%%</span><span class="s2">)*(%[\w]+)?"</span><span class="p">)</span>
|
|
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
|
|
<span class="n">match</span> <span class="o">=</span> <span class="n">variable_match</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">match</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]:</span>
|
|
<span class="k">break</span>
|
|
<span class="n">var</span> <span class="o">=</span> <span class="n">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
|
<span class="n">var_name</span> <span class="o">=</span> <span class="n">var</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>
|
|
<span class="k">if</span> <span class="n">var_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">variables</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Variable '</span><span class="si">{</span><span class="n">var_name</span><span class="si">}</span><span class="s2">' is not defined."</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">var_val</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">variables</span><span class="p">[</span><span class="n">var_name</span><span class="p">]:</span>
|
|
<span class="n">new_values</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">f</span><span class="s2">"(%%)*</span><span class="si">{</span><span class="n">var</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="sa">r</span><span class="s2">"\g<1>"</span> <span class="o">+</span> <span class="n">var_val</span><span class="p">,</span> <span class="n">val</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">new_values</span> <span class="o">==</span> <span class="n">values</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">new_values</span><span class="p">:</span>
|
|
<span class="k">break</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="n">new_values</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
|
|
<span class="n">new_values</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
<span class="c1"># replace %% with %</span>
|
|
<span class="c1"># any %% left in the string will be replaced with %</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">value</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"</span><span class="si">%%</span><span class="s2">"</span><span class="p">,</span> <span class="s2">"%"</span><span class="p">)</span> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
|
|
<span class="k">return</span> <span class="n">values</span></div>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.get_field_values"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.get_field_values">[docs]</a> <span class="k">def</span> <span class="nf">get_field_values</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">field</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
|
|
<span class="n">subfield</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span>
|
|
<span class="n">field_arg</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span>
|
|
<span class="n">default</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Tuple</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]]:</span>
|
|
<span class="sd">"""Get the values for a field"""</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">unmatched</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">if</span> <span class="p">(</span>
|
|
<span class="n">field</span> <span class="ow">in</span> <span class="n">SINGLE_VALUE_SUBSTITUTIONS</span>
|
|
<span class="ow">or</span> <span class="n">field</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"."</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="n">SINGLE_VALUE_SUBSTITUTIONS</span>
|
|
<span class="p">):</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_template_value</span><span class="p">(</span>
|
|
<span class="n">field</span><span class="p">,</span>
|
|
<span class="n">default</span><span class="o">=</span><span class="n">default</span><span class="p">,</span>
|
|
<span class="n">subfield</span><span class="o">=</span><span class="n">subfield</span><span class="p">,</span>
|
|
<span class="n">field_arg</span><span class="o">=</span><span class="n">field_arg</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"exiftool"</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">subfield</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
|
<span class="s2">"SyntaxError: GROUP:NAME subfield must not be null with {exiftool:GROUP:NAME}'"</span>
|
|
<span class="p">)</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_template_value_exiftool</span><span class="p">(</span>
|
|
<span class="n">subfield</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"function"</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">subfield</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
|
<span class="s2">"SyntaxError: filename and function must not be null with {function::filename.py:function_name}"</span>
|
|
<span class="p">)</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_template_value_function</span><span class="p">(</span>
|
|
<span class="n">subfield</span><span class="p">,</span> <span class="n">field_arg</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">caller</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">MULTI_VALUE_SUBSTITUTIONS</span> <span class="ow">or</span> <span class="n">field</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"photo"</span><span class="p">):</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_template_value_multi</span><span class="p">(</span>
|
|
<span class="n">field</span><span class="p">,</span> <span class="n">subfield</span><span class="p">,</span> <span class="n">path_sep</span><span class="o">=</span><span class="n">field_arg</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="n">default</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"."</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="n">PATHLIB_SUBSTITUTIONS</span><span class="p">:</span>
|
|
<span class="n">vals</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_template_value_pathlib</span><span class="p">(</span><span class="n">field</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">unmatched</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">field</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="p">[],</span> <span class="n">unmatched</span>
|
|
<span class="k">return</span> <span class="n">vals</span><span class="p">,</span> <span class="n">unmatched</span></div>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.get_template_value"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.get_template_value">[docs]</a> <span class="k">def</span> <span class="nf">get_template_value</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">field</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
|
|
<span class="n">default</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span>
|
|
<span class="n">subfield</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span>
|
|
<span class="n">field_arg</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span>
|
|
<span class="p">):</span>
|
|
<span class="sd">"""lookup value for template field (single-value template substitutions)</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> field: template field to find value for.</span>
|
|
<span class="sd"> default: the default value provided by the user</span>
|
|
<span class="sd"> bool_val: True value if expression is boolean</span>
|
|
<span class="sd"> delim: delimiter for expand in place</span>
|
|
<span class="sd"> path_sep: path separator for fields that are path-like</span>
|
|
<span class="sd"> subfield: subfield (value after : in field)</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> The matching template value (which may be None).</span>
|
|
|
|
<span class="sd"> Raises:</span>
|
|
<span class="sd"> ValueError if no rule exists for field.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="c1"># initialize today with current date/time if needed</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">today</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">today</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span>
|
|
|
|
<span class="n">value</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="c1"># wouldn't a switch/case statement be nice...</span>
|
|
<span class="c1"># handle the fields that don't require a PhotoInfo object first</span>
|
|
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"today"</span><span class="p">):</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">format_date_field</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">today</span><span class="p">,</span> <span class="n">field</span><span class="p">,</span> <span class="n">default</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">PUNCTUATION</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">PUNCTUATION</span><span class="p">[</span><span class="n">field</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"osxphotos_version"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">__version__</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"osxphotos_cmd_line"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="s2">" "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># if no uuid, don't have a PhotoInfo object (could be PhotoInfoNone)</span>
|
|
<span class="c1"># so don't try to handle any of the photo fields</span>
|
|
<span class="k">return</span> <span class="p">[]</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"name"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span><span class="o">.</span><span class="n">stem</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"original_name"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">original_filename</span><span class="p">)</span><span class="o">.</span><span class="n">stem</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"title"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">title</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"descr"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">description</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"media_type"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_media_type</span><span class="p">(</span><span class="n">default</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"photo_or_video"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_photo_video_type</span><span class="p">(</span><span class="n">default</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"hdr"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="s2">"hdr"</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">hdr</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"edited"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="s2">"edited"</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">hasadjustments</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"edited_version"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="s2">"edited_version"</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">edited_version</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"favorite"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="s2">"favorite"</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">favorite</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="n">field</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"created"</span><span class="p">):</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">format_date_field</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">date</span><span class="p">,</span> <span class="n">field</span><span class="p">,</span> <span class="n">default</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"modified"</span><span class="p">):</span>
|
|
<span class="c1"># if no modified date, use photo.date</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">format_date_field</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">date_modified</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">date</span><span class="p">,</span> <span class="n">field</span><span class="p">,</span> <span class="n">default</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"place"</span><span class="p">):</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">get_place_value</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="p">,</span> <span class="n">field</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"searchinfo.season"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">search_info</span><span class="o">.</span><span class="n">season</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">search_info</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"exif.camera_make"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">exif_info</span><span class="o">.</span><span class="n">camera_make</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">exif_info</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"exif.camera_model"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">exif_info</span><span class="o">.</span><span class="n">camera_model</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">exif_info</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"exif.lens_model"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">exif_info</span><span class="o">.</span><span class="n">lens_model</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">exif_info</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"moment"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">moment_info</span><span class="o">.</span><span class="n">title</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">moment_info</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"uuid"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"shortuuid"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">uuid_to_shortuuid</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span><span class="p">)</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"id"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">format_str_value</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">_info</span><span class="p">[</span><span class="s2">"pk"</span><span class="p">],</span> <span class="n">subfield</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"album_seq"</span><span class="p">)</span> <span class="ow">or</span> <span class="n">field</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"folder_album_seq"</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">dest_path</span> <span class="o">:=</span> <span class="bp">self</span><span class="o">.</span><span class="n">dest_path</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"album_seq"</span><span class="p">):</span>
|
|
<span class="n">album</span> <span class="o">=</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="n">dest_path</span><span class="p">)</span><span class="o">.</span><span class="n">name</span>
|
|
<span class="n">album_info</span> <span class="o">=</span> <span class="n">_get_album_by_name</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="p">,</span> <span class="n">album</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">album_info</span> <span class="o">=</span> <span class="n">_get_album_by_path</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="p">,</span> <span class="n">dest_path</span><span class="p">)</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">album_info</span><span class="o">.</span><span class="n">photo_index</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="p">)</span> <span class="k">if</span> <span class="n">album_info</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">if</span> <span class="n">value</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">start_id</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">field_arg</span><span class="p">)</span> <span class="k">if</span> <span class="n">field_arg</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">else</span> <span class="mi">0</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">+</span> <span class="n">start_id</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">format_str_value</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">subfield</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"counter"</span><span class="p">):</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">counter</span><span class="o">.</span><span class="n">get_counter_value</span><span class="p">(</span><span class="n">field</span><span class="p">,</span> <span class="n">subfield</span><span class="p">,</span> <span class="n">field_arg</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># if here, didn't get a match</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unhandled template value: </span><span class="si">{</span><span class="n">field</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
|
|
<span class="c1"># sanitize filename or directory name if needed</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">filename</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">sanitize_pathpart</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">dirname</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">sanitize_dirname</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
|
|
|
<span class="c1"># ensure no empty strings in value (see #512)</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="kc">None</span> <span class="k">if</span> <span class="n">value</span> <span class="o">==</span> <span class="s2">""</span> <span class="k">else</span> <span class="n">value</span>
|
|
|
|
<span class="k">return</span> <span class="p">[</span><span class="n">value</span><span class="p">]</span></div>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.get_template_value_pathlib"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.get_template_value_pathlib">[docs]</a> <span class="k">def</span> <span class="nf">get_template_value_pathlib</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">):</span>
|
|
<span class="sd">"""lookup value for template pathlib template fields</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> field: template field to find value for.</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> The matching template value (which may be None).</span>
|
|
|
|
<span class="sd"> Raises:</span>
|
|
<span class="sd"> ValueError if no rule exists for field.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">field_stem</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"."</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="n">field_stem</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">PATHLIB_SUBSTITUTIONS</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"SyntaxError: Unknown field: </span><span class="si">{</span><span class="n">field</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
|
|
<span class="n">field_value</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">field_value</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field_stem</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">AttributeError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unknown path-like field: </span><span class="si">{</span><span class="n">field_stem</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
|
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">_get_pathlib_value</span><span class="p">(</span><span class="n">field</span><span class="p">,</span> <span class="n">field_value</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">quote</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">filename</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">sanitize_pathpart</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">dirname</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">sanitize_dirname</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="p">[</span><span class="n">value</span><span class="p">]</span></div>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.get_filter_values"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.get_filter_values">[docs]</a> <span class="k">def</span> <span class="nf">get_filter_values</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filter_</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">values</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
|
|
<span class="sd">"""Return filtered values"""</span>
|
|
|
|
<span class="c1"># extract args, if any</span>
|
|
<span class="k">if</span> <span class="n">re</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="sa">r</span><span class="s2">"\(.*\)"</span><span class="p">,</span> <span class="n">filter_</span><span class="p">):</span>
|
|
<span class="n">filter_</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span> <span class="n">filter_</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"("</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="s2">")"</span><span class="p">)</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">expand_variables_to_str</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="s2">"Filter arguments"</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="c1"># check that filter name (without subfields or arguments) is valid</span>
|
|
<span class="n">valid_filters</span> <span class="o">=</span> <span class="p">[</span><span class="n">f</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"("</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">FILTER_VALUES</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="n">filter_</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">":"</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">valid_filters</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unknown filter: </span><span class="si">{</span><span class="n">filter_</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">filter_</span> <span class="ow">in</span> <span class="p">[</span>
|
|
<span class="s2">"append"</span><span class="p">,</span>
|
|
<span class="s2">"appends"</span><span class="p">,</span>
|
|
<span class="s2">"chomp"</span><span class="p">,</span>
|
|
<span class="s2">"chop"</span><span class="p">,</span>
|
|
<span class="s2">"filter"</span><span class="p">,</span>
|
|
<span class="s2">"prepend"</span><span class="p">,</span>
|
|
<span class="s2">"prepends"</span><span class="p">,</span>
|
|
<span class="s2">"remove"</span><span class="p">,</span>
|
|
<span class="s2">"slice"</span><span class="p">,</span>
|
|
<span class="s2">"split"</span><span class="p">,</span>
|
|
<span class="s2">"sslice"</span><span class="p">,</span>
|
|
<span class="p">]</span> <span class="ow">and</span> <span class="p">(</span><span class="n">args</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="ow">not</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">)):</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">filter_</span><span class="si">}</span><span class="s2"> requires arguments"</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"lower"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"upper"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"strip"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"capitalize"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span><span class="o">.</span><span class="n">capitalize</span><span class="p">()</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"titlecase"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"braces"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"{"</span> <span class="o">+</span> <span class="n">v</span> <span class="o">+</span> <span class="s2">"}"</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"parens"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="sa">f</span><span class="s2">"(</span><span class="si">{</span><span class="n">v</span><span class="si">}</span><span class="s2">)"</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"brackets"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="sa">f</span><span class="s2">"[</span><span class="si">{</span><span class="n">v</span><span class="si">}</span><span class="s2">]"</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"shell_quote"</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">shlex</span><span class="o">.</span><span class="n">quote</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"split"</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">delim</span> <span class="o">:=</span> <span class="n">args</span><span class="p">:</span>
|
|
<span class="n">new_values</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
|
|
<span class="n">new_values</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">v</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">delim</span><span class="p">))</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">new_values</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">values</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"chop"</span><span class="p">:</span>
|
|
<span class="c1"># chop off characters from the end</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">chop</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">ValueError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Invalid value for chop: </span><span class="si">{</span><span class="n">args</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span><span class="p">[:</span><span class="o">-</span><span class="n">chop</span><span class="p">]</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span> <span class="k">if</span> <span class="n">chop</span> <span class="k">else</span> <span class="n">values</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"chomp"</span><span class="p">:</span>
|
|
<span class="c1"># chop off characters from the beginning</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">chomp</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">ValueError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Invalid value for chomp: </span><span class="si">{</span><span class="n">args</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span><span class="p">[</span><span class="n">chomp</span><span class="p">:]</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span> <span class="k">if</span> <span class="n">chomp</span> <span class="k">else</span> <span class="n">values</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"autosplit"</span><span class="p">:</span>
|
|
<span class="c1"># try to split keyword strings automatically</span>
|
|
<span class="n">temp_values</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">","</span><span class="p">,</span> <span class="s2">" "</span><span class="p">)</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="n">temp_values</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">";"</span><span class="p">,</span> <span class="s2">" "</span><span class="p">)</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">temp_values</span><span class="p">]</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">temp_values</span><span class="p">:</span>
|
|
<span class="n">value</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">val</span><span class="o">.</span><span class="n">split</span><span class="p">())</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"sort"</span><span class="p">:</span>
|
|
<span class="c1"># sort list of values</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"rsort"</span><span class="p">:</span>
|
|
<span class="c1"># reverse sort list of values</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"reverse"</span><span class="p">:</span>
|
|
<span class="c1"># reverse list of values</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">values</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"uniq"</span><span class="p">:</span>
|
|
<span class="c1"># remove duplicate values from list</span>
|
|
<span class="n">temp_values</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">v</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">temp_values</span><span class="p">:</span>
|
|
<span class="n">temp_values</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">temp_values</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"join"</span><span class="p">:</span>
|
|
<span class="c1"># join list of values with delimiter</span>
|
|
<span class="n">delim</span> <span class="o">=</span> <span class="n">args</span> <span class="ow">or</span> <span class="s2">""</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">delim</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">values</span><span class="p">)]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"append"</span><span class="p">:</span>
|
|
<span class="c1"># append value to list</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">values</span> <span class="o">+</span> <span class="p">[</span><span class="n">args</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"prepend"</span><span class="p">:</span>
|
|
<span class="c1"># prepend value to list</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">args</span><span class="p">]</span> <span class="o">+</span> <span class="n">values</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"appends"</span><span class="p">:</span>
|
|
<span class="c1"># append value to each item in list</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">v</span><span class="si">}{</span><span class="n">args</span><span class="si">}</span><span class="s2">"</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"prepends"</span><span class="p">:</span>
|
|
<span class="c1"># prepend value to each item in list</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">args</span><span class="si">}{</span><span class="n">v</span><span class="si">}</span><span class="s2">"</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"remove"</span><span class="p">:</span>
|
|
<span class="c1"># remove value from list</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span> <span class="k">if</span> <span class="n">v</span> <span class="o">!=</span> <span class="n">args</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"slice"</span><span class="p">:</span>
|
|
<span class="c1"># slice list of values</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">values</span><span class="p">[</span><span class="n">create_slice</span><span class="p">(</span><span class="n">args</span><span class="p">)]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"sslice"</span><span class="p">:</span>
|
|
<span class="c1"># slice each value in a list</span>
|
|
<span class="n">slice_</span> <span class="o">=</span> <span class="n">create_slice</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span><span class="p">[</span><span class="n">slice_</span><span class="p">]</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"filter"</span><span class="p">:</span>
|
|
<span class="c1"># filter values based on a predicate</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">filter_predicate</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">args</span><span class="p">)]</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"int"</span><span class="p">:</span>
|
|
<span class="c1"># convert value to integer</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">values_to_int</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span> <span class="o">==</span> <span class="s2">"float"</span><span class="p">:</span>
|
|
<span class="c1"># convert value to float</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">values_to_float</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">filter_</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"function:"</span><span class="p">):</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_template_value_filter_function</span><span class="p">(</span><span class="n">filter_</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">values</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">return</span> <span class="n">value</span></div>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.filter_predicate"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.filter_predicate">[docs]</a> <span class="k">def</span> <span class="nf">filter_predicate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">args</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">bool</span><span class="p">:</span>
|
|
<span class="sd">"""Return True if value passes predicate"""</span>
|
|
|
|
<span class="c1"># extract function name and arguments</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">args</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="s2">"Filter predicate requires arguments"</span><span class="p">)</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"not"</span><span class="p">:</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>
|
|
<span class="k">return</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">filter_predicate</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="s2">" "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">args</span><span class="p">))</span>
|
|
|
|
<span class="n">predicate</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="n">conditional_value</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"|"</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">comparison_test</span><span class="p">(</span><span class="n">test_function</span><span class="p">):</span>
|
|
<span class="sd">"""Perform numerical comparisons using test_function"""</span>
|
|
<span class="c1"># returns True if any of the values match the condition</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="nb">any</span><span class="p">(</span>
|
|
<span class="nb">bool</span><span class="p">(</span><span class="n">test_function</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">value</span><span class="p">),</span> <span class="nb">float</span><span class="p">(</span><span class="n">c</span><span class="p">)))</span>
|
|
<span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">conditional_value</span>
|
|
<span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">ValueError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"comparison operators may only be used with values that can be converted to numbers: </span><span class="si">{</span><span class="n">value</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">conditional_value</span><span class="si">}</span><span class="s2">"</span>
|
|
<span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
|
|
|
<span class="n">predicate_is_true</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="k">if</span> <span class="n">predicate</span> <span class="o">==</span> <span class="s2">"contains"</span><span class="p">:</span>
|
|
<span class="n">predicate_is_true</span> <span class="o">=</span> <span class="nb">any</span><span class="p">(</span><span class="n">c</span> <span class="ow">in</span> <span class="n">value</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">conditional_value</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">predicate</span> <span class="o">==</span> <span class="s2">"endswith"</span><span class="p">:</span>
|
|
<span class="n">predicate_is_true</span> <span class="o">=</span> <span class="nb">any</span><span class="p">(</span><span class="n">value</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">conditional_value</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">predicate</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"matches"</span><span class="p">,</span> <span class="s2">"=="</span><span class="p">]:</span>
|
|
<span class="n">predicate_is_true</span> <span class="o">=</span> <span class="nb">any</span><span class="p">(</span><span class="n">value</span> <span class="o">==</span> <span class="n">c</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">conditional_value</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">predicate</span> <span class="o">==</span> <span class="s2">"startswith"</span><span class="p">:</span>
|
|
<span class="n">predicate_is_true</span> <span class="o">=</span> <span class="nb">any</span><span class="p">(</span><span class="n">value</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">conditional_value</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">predicate</span> <span class="o">==</span> <span class="s2">"!="</span><span class="p">:</span>
|
|
<span class="n">predicate_is_true</span> <span class="o">=</span> <span class="nb">any</span><span class="p">(</span><span class="n">value</span> <span class="o">!=</span> <span class="n">c</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">conditional_value</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">predicate</span> <span class="o">==</span> <span class="s2">"<"</span><span class="p">:</span>
|
|
<span class="n">predicate_is_true</span> <span class="o">=</span> <span class="n">comparison_test</span><span class="p">(</span><span class="k">lambda</span> <span class="n">v</span><span class="p">,</span> <span class="n">c</span><span class="p">:</span> <span class="n">v</span> <span class="o"><</span> <span class="n">c</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">predicate</span> <span class="o">==</span> <span class="s2">"<="</span><span class="p">:</span>
|
|
<span class="n">predicate_is_true</span> <span class="o">=</span> <span class="n">comparison_test</span><span class="p">(</span><span class="k">lambda</span> <span class="n">v</span><span class="p">,</span> <span class="n">c</span><span class="p">:</span> <span class="n">v</span> <span class="o"><=</span> <span class="n">c</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">predicate</span> <span class="o">==</span> <span class="s2">">"</span><span class="p">:</span>
|
|
<span class="n">predicate_is_true</span> <span class="o">=</span> <span class="n">comparison_test</span><span class="p">(</span><span class="k">lambda</span> <span class="n">v</span><span class="p">,</span> <span class="n">c</span><span class="p">:</span> <span class="n">v</span> <span class="o">></span> <span class="n">c</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">predicate</span> <span class="o">==</span> <span class="s2">">="</span><span class="p">:</span>
|
|
<span class="n">predicate_is_true</span> <span class="o">=</span> <span class="n">comparison_test</span><span class="p">(</span><span class="k">lambda</span> <span class="n">v</span><span class="p">,</span> <span class="n">c</span><span class="p">:</span> <span class="n">v</span> <span class="o">>=</span> <span class="n">c</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Invalid predicate: </span><span class="si">{</span><span class="n">predicate</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="n">predicate_is_true</span></div>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.get_template_value_multi"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.get_template_value_multi">[docs]</a> <span class="k">def</span> <span class="nf">get_template_value_multi</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">,</span> <span class="n">subfield</span><span class="p">,</span> <span class="n">path_sep</span><span class="p">,</span> <span class="n">default</span><span class="p">):</span>
|
|
<span class="sd">"""lookup value for template field (multi-value template substitutions)</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> field: template field to find value for.</span>
|
|
<span class="sd"> subfield: the template subfield value</span>
|
|
<span class="sd"> path_sep: path separator to use for folder_album field</span>
|
|
<span class="sd"> default: value of default field</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> List of the matching template values or [].</span>
|
|
|
|
<span class="sd"> Raises:</span>
|
|
<span class="sd"> ValueError if no rule exists for field.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="sd">""" return list of values for a multi-valued template field """</span>
|
|
|
|
<span class="n">path_sep</span> <span class="o">=</span> <span class="n">path_sep</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">path_sep</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">[]</span>
|
|
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">if</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"album"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">burst_albums</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">burst</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">albums</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"project"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span><span class="o">.</span><span class="n">title</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">project_info</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"album_project"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">burst_albums</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">burst</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">albums</span>
|
|
<span class="n">values</span> <span class="o">+=</span> <span class="p">[</span><span class="n">p</span><span class="o">.</span><span class="n">title</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">project_info</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"keyword"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">keywords</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"person"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">persons</span>
|
|
<span class="c1"># remove any _UNKNOWN_PERSON values</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">val</span> <span class="k">for</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">values</span> <span class="k">if</span> <span class="n">val</span> <span class="o">!=</span> <span class="n">_UNKNOWN_PERSON</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"label"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">labels</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"label_normalized"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">labels_normalized</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"folder_album"</span><span class="p">,</span> <span class="s2">"folder_album_project"</span><span class="p">]:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="c1"># photos must be in an album to be in a folder</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">burst</span><span class="p">:</span>
|
|
<span class="n">album_info</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">burst_album_info</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">album_info</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">album_info</span>
|
|
<span class="k">if</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"folder_album_project"</span><span class="p">:</span>
|
|
<span class="n">album_info</span> <span class="o">+=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">project_info</span>
|
|
<span class="k">for</span> <span class="n">album</span> <span class="ow">in</span> <span class="n">album_info</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">album</span><span class="o">.</span><span class="n">folder_names</span><span class="p">:</span>
|
|
<span class="c1"># album in folder</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">dirname</span><span class="p">:</span>
|
|
<span class="c1"># being used as a filepath so sanitize each part</span>
|
|
<span class="n">folder</span> <span class="o">=</span> <span class="n">path_sep</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
|
|
<span class="n">sanitize_dirname</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">album</span><span class="o">.</span><span class="n">folder_names</span>
|
|
<span class="p">)</span>
|
|
<span class="n">folder</span> <span class="o">+=</span> <span class="n">path_sep</span> <span class="o">+</span> <span class="n">sanitize_dirname</span><span class="p">(</span><span class="n">album</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">folder</span> <span class="o">=</span> <span class="n">path_sep</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">album</span><span class="o">.</span><span class="n">folder_names</span><span class="p">)</span>
|
|
<span class="n">folder</span> <span class="o">+=</span> <span class="n">path_sep</span> <span class="o">+</span> <span class="n">album</span><span class="o">.</span><span class="n">title</span>
|
|
<span class="n">values</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">folder</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">dirname</span><span class="p">:</span>
|
|
<span class="n">values</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">sanitize_dirname</span><span class="p">(</span><span class="n">album</span><span class="o">.</span><span class="n">title</span><span class="p">))</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">values</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">album</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"comment"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">comment</span><span class="o">.</span><span class="n">user</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">comment</span><span class="o">.</span><span class="n">text</span><span class="si">}</span><span class="s2">"</span> <span class="k">for</span> <span class="n">comment</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">comments</span>
|
|
<span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"searchinfo.holiday"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">search_info</span><span class="o">.</span><span class="n">holidays</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">search_info</span> <span class="k">else</span> <span class="p">[]</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"searchinfo.activity"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">search_info</span><span class="o">.</span><span class="n">activities</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">search_info</span> <span class="k">else</span> <span class="p">[]</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"searchinfo.venue"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">search_info</span><span class="o">.</span><span class="n">venues</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">search_info</span> <span class="k">else</span> <span class="p">[]</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"searchinfo.venue_type"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">search_info</span><span class="o">.</span><span class="n">venue_types</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">search_info</span> <span class="k">else</span> <span class="p">[]</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"shell_quote"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">shlex</span><span class="o">.</span><span class="n">quote</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">default</span> <span class="k">if</span> <span class="n">v</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"strip"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">v</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">default</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"format"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_format_values</span><span class="p">(</span><span class="n">field</span><span class="p">,</span> <span class="n">subfield</span><span class="p">,</span> <span class="n">default</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"photo"</span><span class="p">):</span>
|
|
<span class="c1"># provide access to PhotoInfo object</span>
|
|
<span class="n">properties</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"."</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">properties</span><span class="p">)</span> <span class="o"><=</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
|
<span class="s2">"Missing property in </span><span class="si">{photo}</span><span class="s2"> template. Use in form </span><span class="si">{photo.property}</span><span class="s2">."</span>
|
|
<span class="p">)</span>
|
|
<span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span>
|
|
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">properties</span><span class="p">)):</span>
|
|
<span class="n">property_</span> <span class="o">=</span> <span class="n">properties</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">obj</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">property_</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">obj</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">break</span>
|
|
<span class="k">except</span> <span class="ne">AttributeError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
|
<span class="s2">"Invalid property for </span><span class="si">{photo}</span><span class="s2"> template: "</span> <span class="o">+</span> <span class="sa">f</span><span class="s2">"'</span><span class="si">{</span><span class="n">property_</span><span class="si">}</span><span class="s2">'"</span>
|
|
<span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
|
|
|
<span class="k">if</span> <span class="n">obj</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="nb">bool</span><span class="p">):</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">property_</span><span class="p">]</span> <span class="k">if</span> <span class="n">obj</span> <span class="k">else</span> <span class="p">[]</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="nb">int</span><span class="p">,</span> <span class="nb">float</span><span class="p">)):</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">obj</span><span class="p">)]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">field</span> <span class="o">==</span> <span class="s2">"detected_text"</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="n">_get_detected_text</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="p">,</span> <span class="n">confidence</span><span class="o">=</span><span class="n">subfield</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unhandled template value: </span><span class="si">{</span><span class="n">field</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
|
|
<span class="c1"># sanitize directory names if needed, folder_album handled differently above</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">filename</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">sanitize_pathpart</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">dirname</span> <span class="ow">and</span> <span class="n">field</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"folder_album"</span><span class="p">,</span> <span class="s2">"folder_album_project"</span><span class="p">]:</span>
|
|
<span class="c1"># skip folder_album because it would have been handled above</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">sanitize_dirname</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
|
|
<span class="c1"># If no values, insert None so code below will substitute none_str for None</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="n">values</span> <span class="ow">or</span> <span class="p">[]</span>
|
|
<span class="k">return</span> <span class="n">values</span></div>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.get_format_values"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.get_format_values">[docs]</a> <span class="k">def</span> <span class="nf">get_format_values</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span> <span class="n">field</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">subfield</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">default</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Optional</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]]]:</span>
|
|
<span class="sd">"""Return values for {format} templates"""</span>
|
|
|
|
<span class="k">if</span> <span class="n">field</span> <span class="o">!=</span> <span class="s2">"format"</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unhandled template value in get_format_values: </span><span class="si">{</span><span class="n">field</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">subfield</span> <span class="ow">or</span> <span class="s2">":"</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">subfield</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="s2">"</span><span class="si">{format}</span><span class="s2"> requires subfield in form TYPE:FORMAT"</span><span class="p">)</span>
|
|
<span class="n">type_</span><span class="p">,</span> <span class="n">format_str</span> <span class="o">=</span> <span class="n">subfield</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">":"</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">type_</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">"int"</span><span class="p">,</span> <span class="s2">"float"</span><span class="p">,</span> <span class="s2">"str"</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"'</span><span class="si">{</span><span class="n">type_</span><span class="si">}</span><span class="s2">' is not a valid type for </span><span class="si">{</span><span class="nb">format</span><span class="si">}</span><span class="s2">: must be one of 'int', 'float', 'str'"</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">type_</span> <span class="o">==</span> <span class="s2">"int"</span><span class="p">:</span>
|
|
<span class="c1"># convert to float then int to avoid error when converting a string float to int</span>
|
|
<span class="n">default_</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">v</span><span class="p">))</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">default</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">type_</span> <span class="o">==</span> <span class="s2">"float"</span><span class="p">:</span>
|
|
<span class="n">default_</span> <span class="o">=</span> <span class="p">[</span><span class="nb">float</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">default</span><span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">default_</span> <span class="o">=</span> <span class="n">default</span>
|
|
<span class="n">format_str</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">expand_variables_to_str</span><span class="p">(</span><span class="n">format_str</span><span class="p">,</span> <span class="s2">"format string"</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="p">[</span><span class="n">format_str_value</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">format_str</span><span class="p">)</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">default_</span><span class="p">]</span></div>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.get_template_value_exiftool"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.get_template_value_exiftool">[docs]</a> <span class="k">def</span> <span class="nf">get_template_value_exiftool</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">subfield</span><span class="p">,</span>
|
|
<span class="p">):</span>
|
|
<span class="sd">"""Get template value for format "{exiftool:EXIF:Model}" """</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">[]</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">path</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">[]</span>
|
|
|
|
<span class="n">exif</span> <span class="o">=</span> <span class="n">ExifToolCaching</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">path</span><span class="p">,</span> <span class="n">exiftool</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">exiftool_path</span><span class="p">)</span>
|
|
<span class="n">exifdict</span> <span class="o">=</span> <span class="n">exif</span><span class="o">.</span><span class="n">asdict</span><span class="p">(</span><span class="n">normalized</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
|
<span class="n">subfield</span> <span class="o">=</span> <span class="n">subfield</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="n">subfield</span> <span class="ow">in</span> <span class="n">exifdict</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="n">exifdict</span><span class="p">[</span><span class="n">subfield</span><span class="p">]</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="n">values</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="nb">list</span><span class="p">)</span> <span class="k">else</span> <span class="p">[</span><span class="n">values</span><span class="p">]</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
|
|
<span class="c1"># sanitize directory names if needed</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">filename</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">sanitize_pathpart</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">dirname</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">sanitize_dirname</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
<span class="k">return</span> <span class="n">values</span></div>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.get_template_value_function"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.get_template_value_function">[docs]</a> <span class="k">def</span> <span class="nf">get_template_value_function</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">subfield</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
|
|
<span class="n">field_arg</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span>
|
|
<span class="n">caller</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
|
|
<span class="p">):</span>
|
|
<span class="sd">"""Get template value from external function</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> subfield: the filename and function name in for filename.py::function</span>
|
|
<span class="sd"> field_arg: the argument to pass to the function</span>
|
|
<span class="sd"> caller: the calling source of the template ('export' or 'import')</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">if</span> <span class="s2">"::"</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">subfield</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"SyntaxError: could not parse function name from '</span><span class="si">{</span><span class="n">subfield</span><span class="si">}</span><span class="s2">'"</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="n">filename</span><span class="p">,</span> <span class="n">funcname</span> <span class="o">=</span> <span class="n">subfield</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"::"</span><span class="p">)</span>
|
|
|
|
<span class="n">filename_validated</span> <span class="o">=</span> <span class="n">expand_and_validate_filepath</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">filename_validated</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"'</span><span class="si">{</span><span class="n">filename</span><span class="si">}</span><span class="s2">' does not appear to be a file"</span><span class="p">)</span>
|
|
|
|
<span class="n">template_func</span> <span class="o">=</span> <span class="n">load_function</span><span class="p">(</span><span class="n">filename_validated</span><span class="p">,</span> <span class="n">funcname</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># must be a PhotoInfoNone instance</span>
|
|
<span class="c1"># if no uuid, then template is being validated but not actually run</span>
|
|
<span class="c1"># so don't run the function</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">elif</span> <span class="n">caller</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"export"</span><span class="p">,</span> <span class="s2">"query"</span><span class="p">]:</span>
|
|
<span class="c1"># function signature is:</span>
|
|
<span class="c1"># def example(photo: PhotoInfo, options: ExportOptions, args: Optional[str] = None, **kwargs) -> Union[List, str]:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="n">template_func</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="p">,</span> <span class="n">options</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="n">field_arg</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">caller</span> <span class="o">==</span> <span class="s2">"import"</span><span class="p">:</span>
|
|
<span class="c1"># function signature is:</span>
|
|
<span class="c1"># def example(filepath: pathlib.Path, args: Optional[str] = None, **kwargs) -> Union[List, str]:</span>
|
|
<span class="c1"># the PhotoInfoFromFile class used by import sets `path` to the path of the file being imported</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="n">template_func</span><span class="p">(</span><span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">path</span><span class="p">),</span> <span class="n">args</span><span class="o">=</span><span class="n">field_arg</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unhandled caller: </span><span class="si">{</span><span class="n">caller</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="nb">list</span><span class="p">)):</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"Invalid return type for function </span><span class="si">{</span><span class="n">funcname</span><span class="si">}</span><span class="s2">: expected str or list"</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">values</span><span class="p">)</span> <span class="o">==</span> <span class="nb">str</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">values</span><span class="p">]</span>
|
|
|
|
<span class="c1"># sanitize directory names if needed</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">filename</span><span class="p">:</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">sanitize_pathpart</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">dirname</span><span class="p">:</span>
|
|
<span class="c1"># sanitize but don't replace any "/" as user function may want to create sub directories</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">sanitize_dirname</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">replacement</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">values</span><span class="p">]</span>
|
|
|
|
<span class="k">return</span> <span class="n">values</span></div>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.get_template_value_filter_function"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.get_template_value_filter_function">[docs]</a> <span class="k">def</span> <span class="nf">get_template_value_filter_function</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filter_</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
|
|
<span class="sd">"""Filter template value from external function"""</span>
|
|
<span class="c1"># TODO: add args to filter function call? Would change signature of function</span>
|
|
|
|
<span class="n">filter_</span> <span class="o">=</span> <span class="n">filter_</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"function:"</span><span class="p">,</span> <span class="s2">""</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="s2">"::"</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">filter_</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"SyntaxError: could not parse function name from '</span><span class="si">{</span><span class="n">filter_</span><span class="si">}</span><span class="s2">'"</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="n">filename</span><span class="p">,</span> <span class="n">funcname</span> <span class="o">=</span> <span class="n">filter_</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"::"</span><span class="p">)</span>
|
|
|
|
<span class="n">filename_validated</span> <span class="o">=</span> <span class="n">expand_and_validate_filepath</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">filename_validated</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"'</span><span class="si">{</span><span class="n">filename</span><span class="si">}</span><span class="s2">' does not appear to be a file"</span><span class="p">)</span>
|
|
|
|
<span class="n">template_func</span> <span class="o">=</span> <span class="n">load_function</span><span class="p">(</span><span class="n">filename_validated</span><span class="p">,</span> <span class="n">funcname</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="p">(</span><span class="nb">list</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">)):</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">values</span><span class="p">]</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">uuid</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># if uuid is None, it's a PhotoInfoNone instance and template is being validated</span>
|
|
<span class="c1"># so don't run the function</span>
|
|
<span class="n">values</span> <span class="o">=</span> <span class="n">template_func</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="nb">list</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"Invalid return type for function </span><span class="si">{</span><span class="n">funcname</span><span class="si">}</span><span class="s2">: expected list"</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="n">values</span></div>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.get_photo_video_type"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.get_photo_video_type">[docs]</a> <span class="k">def</span> <span class="nf">get_photo_video_type</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default</span><span class="p">):</span>
|
|
<span class="sd">"""return media type, e.g. photo or video"""</span>
|
|
<span class="n">default_dict</span> <span class="o">=</span> <span class="n">parse_default_kv</span><span class="p">(</span><span class="n">default</span><span class="p">,</span> <span class="n">PHOTO_VIDEO_TYPE_DEFAULTS</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">default_dict</span><span class="p">[</span><span class="s2">"photo"</span><span class="p">]</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="o">.</span><span class="n">isphoto</span> <span class="k">else</span> <span class="n">default_dict</span><span class="p">[</span><span class="s2">"video"</span><span class="p">]</span></div>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.get_media_type"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.get_media_type">[docs]</a> <span class="k">def</span> <span class="nf">get_media_type</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default</span><span class="p">):</span>
|
|
<span class="sd">"""return special media type, e.g. slow_mo, panorama, etc., defaults to photo or video if no special type"""</span>
|
|
<span class="n">default_dict</span> <span class="o">=</span> <span class="n">parse_default_kv</span><span class="p">(</span><span class="n">default</span><span class="p">,</span> <span class="n">MEDIA_TYPE_DEFAULTS</span><span class="p">)</span>
|
|
<span class="n">p</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">photo</span>
|
|
<span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">selfie</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">default_dict</span><span class="p">[</span><span class="s2">"selfie"</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">p</span><span class="o">.</span><span class="n">time_lapse</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">default_dict</span><span class="p">[</span><span class="s2">"time_lapse"</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">p</span><span class="o">.</span><span class="n">panorama</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">default_dict</span><span class="p">[</span><span class="s2">"panorama"</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">p</span><span class="o">.</span><span class="n">slow_mo</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">default_dict</span><span class="p">[</span><span class="s2">"slow_mo"</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">p</span><span class="o">.</span><span class="n">screenshot</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">default_dict</span><span class="p">[</span><span class="s2">"screenshot"</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">p</span><span class="o">.</span><span class="n">portrait</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">default_dict</span><span class="p">[</span><span class="s2">"portrait"</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">p</span><span class="o">.</span><span class="n">live_photo</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">default_dict</span><span class="p">[</span><span class="s2">"live_photo"</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">p</span><span class="o">.</span><span class="n">burst</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">default_dict</span><span class="p">[</span><span class="s2">"burst"</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="n">p</span><span class="o">.</span><span class="n">ismovie</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">default_dict</span><span class="p">[</span><span class="s2">"video"</span><span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">default_dict</span><span class="p">[</span><span class="s2">"photo"</span><span class="p">]</span></div>
|
|
|
|
<div class="viewcode-block" id="PhotoTemplate.get_photo_bool_attribute"><a class="viewcode-back" href="../../reference.html#osxphotos.PhotoTemplate.get_photo_bool_attribute">[docs]</a> <span class="k">def</span> <span class="nf">get_photo_bool_attribute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">attr</span><span class="p">,</span> <span class="n">default</span><span class="p">,</span> <span class="n">bool_val</span><span class="p">):</span>
|
|
<span class="sd">"""Return the boolean value for a photo attribute"""</span>
|
|
<span class="k">return</span> <span class="n">bool_val</span> <span class="k">if</span> <span class="p">(</span><span class="n">val</span> <span class="o">:=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">photo</span><span class="p">,</span> <span class="n">attr</span><span class="p">))</span> <span class="k">else</span> <span class="n">default</span></div></div>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">parse_default_kv</span><span class="p">(</span><span class="n">default</span><span class="p">,</span> <span class="n">default_dict</span><span class="p">):</span>
|
|
<span class="sd">"""parse a string in form key1=value1;key2=value2,... as used for some template fields</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> default: str, in form 'photo=foto;video=vidéo'</span>
|
|
<span class="sd"> default_dict: dict, in form {"photo": "fotos", "video": "vidéos"} with default values</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> dict in form {"photo": "fotos", "video": "vidéos"}</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">default_dict_</span> <span class="o">=</span> <span class="n">default_dict</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="n">default</span><span class="p">:</span>
|
|
<span class="n">defaults</span> <span class="o">=</span> <span class="n">default</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">";"</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">kv</span> <span class="ow">in</span> <span class="n">defaults</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">kv</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"="</span><span class="p">)</span>
|
|
<span class="n">k</span> <span class="o">=</span> <span class="n">k</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
|
|
<span class="n">v</span> <span class="o">=</span> <span class="n">v</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
|
|
<span class="n">default_dict_</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="n">v</span>
|
|
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
<span class="k">return</span> <span class="n">default_dict_</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">get_template_help</span><span class="p">():</span>
|
|
<span class="sd">"""Return help for template system as markdown string"""</span>
|
|
<span class="c1"># TODO: would be better to use importlib.abc.ResourceReader but I can't find a single example of how to do this</span>
|
|
<span class="n">help_file</span> <span class="o">=</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="vm">__file__</span><span class="p">)</span><span class="o">.</span><span class="n">parent</span> <span class="o">/</span> <span class="s2">"phototemplate.md"</span>
|
|
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">help_file</span><span class="p">,</span> <span class="s2">"r"</span><span class="p">)</span> <span class="k">as</span> <span class="n">fd</span><span class="p">:</span>
|
|
<span class="n">md</span> <span class="o">=</span> <span class="n">fd</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
|
|
<span class="k">return</span> <span class="n">md</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">get_template_field_table</span><span class="p">():</span>
|
|
<span class="sd">"""Return markdown table of template field substitutions"""</span>
|
|
<span class="n">template_table</span> <span class="o">=</span> <span class="s2">"| Field | Description |"</span> <span class="o">+</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">|--------------|-------------|"</span>
|
|
<span class="k">for</span> <span class="n">subst</span><span class="p">,</span> <span class="n">descr</span> <span class="ow">in</span> <span class="p">[</span>
|
|
<span class="o">*</span><span class="n">TEMPLATE_SUBSTITUTIONS</span><span class="o">.</span><span class="n">items</span><span class="p">(),</span>
|
|
<span class="o">*</span><span class="n">TEMPLATE_SUBSTITUTIONS_MULTI_VALUED</span><span class="o">.</span><span class="n">items</span><span class="p">(),</span>
|
|
<span class="p">]:</span>
|
|
<span class="c1"># replace '|' with '\|' to avoid markdown parsing issues (e.g. in {pipe} description)</span>
|
|
<span class="n">descr</span> <span class="o">=</span> <span class="n">descr</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"'|'"</span><span class="p">,</span> <span class="sa">r</span><span class="s2">"'\|'"</span><span class="p">)</span>
|
|
<span class="n">template_table</span> <span class="o">+=</span> <span class="sa">f</span><span class="s2">"</span><span class="se">\n</span><span class="s2">|</span><span class="si">{</span><span class="n">subst</span><span class="si">}</span><span class="s2">|</span><span class="si">{</span><span class="n">descr</span><span class="si">}</span><span class="s2">|"</span>
|
|
<span class="k">return</span> <span class="n">template_table</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">_get_pathlib_value</span><span class="p">(</span><span class="n">field</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span> <span class="n">quote</span><span class="p">):</span>
|
|
<span class="sd">"""Get the value for a pathlib.Path type template</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> field: the path field, e.g. "filename.stem"</span>
|
|
<span class="sd"> value: the value for the path component</span>
|
|
<span class="sd"> quote: bool; if true, quotes the returned path for safe execution in the shell</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">parts</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"."</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">parts</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">shlex</span><span class="o">.</span><span class="n">quote</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">value</span><span class="p">))</span> <span class="k">if</span> <span class="n">quote</span> <span class="k">else</span> <span class="nb">str</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
|
|
|
<span class="n">path</span> <span class="o">=</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">attribute</span> <span class="ow">in</span> <span class="n">parts</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">val</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">attribute</span><span class="p">)</span>
|
|
<span class="n">path</span> <span class="o">=</span> <span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="n">val</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">AttributeError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Illegal value for filepath template: </span><span class="si">{</span><span class="n">attribute</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
|
|
|
<span class="n">val_str</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">val</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">quote</span><span class="p">:</span>
|
|
<span class="n">val_str</span> <span class="o">=</span> <span class="n">shlex</span><span class="o">.</span><span class="n">quote</span><span class="p">(</span><span class="n">val_str</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">val_str</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">format_str_value</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">format_str</span><span class="p">):</span>
|
|
<span class="sd">"""Format value based on format code in field in format id:02d"""</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">format_str</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
|
<span class="n">format_str</span> <span class="o">=</span> <span class="s2">"{0:"</span> <span class="o">+</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">format_str</span><span class="si">}</span><span class="s2">"</span> <span class="o">+</span> <span class="s2">"}"</span>
|
|
<span class="k">return</span> <span class="n">format_str</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">_get_album_by_name</span><span class="p">(</span><span class="n">photo</span><span class="p">,</span> <span class="n">album</span><span class="p">):</span>
|
|
<span class="sd">"""Finds first album named album that photo is in and returns the AlbumInfo object, otherwise returns None"""</span>
|
|
<span class="k">return</span> <span class="nb">next</span><span class="p">(</span>
|
|
<span class="p">(</span><span class="n">album_info</span> <span class="k">for</span> <span class="n">album_info</span> <span class="ow">in</span> <span class="n">photo</span><span class="o">.</span><span class="n">album_info</span> <span class="k">if</span> <span class="n">album_info</span><span class="o">.</span><span class="n">title</span> <span class="o">==</span> <span class="n">album</span><span class="p">),</span>
|
|
<span class="kc">None</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">_get_album_by_path</span><span class="p">(</span><span class="n">photo</span><span class="p">,</span> <span class="n">folder_album_path</span><span class="p">):</span>
|
|
<span class="sd">"""finds the first album whose folder_album path matches and folder_album_path and returns the AlbumInfo object, otherwise, returns None"""</span>
|
|
<span class="k">for</span> <span class="n">album_info</span> <span class="ow">in</span> <span class="n">photo</span><span class="o">.</span><span class="n">album_info</span><span class="p">:</span>
|
|
<span class="c1"># following code is how {folder_album} builds the folder path</span>
|
|
<span class="n">folder</span> <span class="o">=</span> <span class="s2">"/"</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">sanitize_dirname</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">album_info</span><span class="o">.</span><span class="n">folder_names</span><span class="p">)</span>
|
|
<span class="n">folder</span> <span class="o">+=</span> <span class="sa">f</span><span class="s2">"/</span><span class="si">{</span><span class="n">sanitize_dirname</span><span class="p">(</span><span class="n">album_info</span><span class="o">.</span><span class="n">title</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
|
|
<span class="k">if</span> <span class="n">folder_album_path</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="n">folder</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">album_info</span>
|
|
<span class="k">return</span> <span class="kc">None</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">_get_detected_text</span><span class="p">(</span><span class="n">photo</span><span class="p">,</span> <span class="n">confidence</span><span class="o">=</span><span class="n">TEXT_DETECTION_CONFIDENCE_THRESHOLD</span><span class="p">):</span>
|
|
<span class="sd">"""Returns the detected text for a photo</span>
|
|
<span class="sd"> {detected_text} uses this instead of PhotoInfo.detected_text() to cache the text for all confidence values</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">photo</span><span class="o">.</span><span class="n">isphoto</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">[]</span>
|
|
|
|
<span class="n">confidence</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="nb">float</span><span class="p">(</span><span class="n">confidence</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">confidence</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="k">else</span> <span class="n">TEXT_DETECTION_CONFIDENCE_THRESHOLD</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="c1"># _detected_text caches the text detection results in an extended attribute</span>
|
|
<span class="c1"># so the first time this gets called is slow but repeated accesses are fast</span>
|
|
<span class="n">detected_text</span> <span class="o">=</span> <span class="n">photo</span><span class="o">.</span><span class="n">_detected_text</span><span class="p">()</span>
|
|
<span class="k">return</span> <span class="p">[</span><span class="n">text</span> <span class="k">for</span> <span class="n">text</span><span class="p">,</span> <span class="n">conf</span> <span class="ow">in</span> <span class="n">detected_text</span> <span class="k">if</span> <span class="n">conf</span> <span class="o">>=</span> <span class="n">confidence</span><span class="p">]</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">create_slice</span><span class="p">(</span><span class="n">args</span><span class="p">):</span>
|
|
<span class="sd">"""Create a slice object from a string of args in form "start:end:step" """</span>
|
|
<span class="n">slice_args</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">":"</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">slice_args</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">start</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">slice_args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">or</span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="n">end</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">step</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">slice_args</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
|
|
<span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">=</span> <span class="n">slice_args</span>
|
|
<span class="n">start</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">start</span><span class="p">)</span> <span class="k">if</span> <span class="n">start</span> <span class="o">!=</span> <span class="s2">""</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="n">end</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">end</span><span class="p">)</span> <span class="k">if</span> <span class="n">end</span> <span class="o">!=</span> <span class="s2">""</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="n">step</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">slice_args</span><span class="p">)</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
|
|
<span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">,</span> <span class="n">step</span> <span class="o">=</span> <span class="n">slice_args</span>
|
|
<span class="n">start</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">start</span><span class="p">)</span> <span class="k">if</span> <span class="n">start</span> <span class="o">!=</span> <span class="s2">""</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="n">end</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">end</span><span class="p">)</span> <span class="k">if</span> <span class="n">end</span> <span class="o">!=</span> <span class="s2">""</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="n">step</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">step</span><span class="p">)</span> <span class="k">if</span> <span class="n">step</span> <span class="o">!=</span> <span class="s2">""</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">SyntaxError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Invalid slice: </span><span class="si">{</span><span class="n">args</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="nb">slice</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">,</span> <span class="n">step</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">values_to_int</span><span class="p">(</span><span class="n">values</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
|
|
<span class="sd">"""Convert a list of strings to str representation of ints, if possible, otherwise strip values from list"""</span>
|
|
<span class="n">int_values</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
|
|
<span class="k">with</span> <span class="n">suppress</span><span class="p">(</span><span class="ne">ValueError</span><span class="p">):</span>
|
|
<span class="n">int_values</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">v</span><span class="p">))))</span>
|
|
<span class="k">return</span> <span class="n">int_values</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">values_to_float</span><span class="p">(</span><span class="n">values</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
|
|
<span class="sd">"""Convert a list of strings to str representation of float, if possible, otherwise strip values from list"""</span>
|
|
<span class="n">float_values</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
|
|
<span class="k">with</span> <span class="n">suppress</span><span class="p">(</span><span class="ne">ValueError</span><span class="p">):</span>
|
|
<span class="n">float_values</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">v</span><span class="p">)))</span>
|
|
<span class="k">return</span> <span class="n">float_values</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">format_date_field</span><span class="p">(</span><span class="n">dt</span><span class="p">:</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="p">,</span> <span class="n">field</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">args</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
|
<span class="sd">"""Format a date template field in format 'created', 'create.year' etc.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> dt: datetime object</span>
|
|
<span class="sd"> field: the field to format, e.g. 'created.year', 'today.strftime'</span>
|
|
<span class="sd"> args: the argument to the field, e.g. '%Y' for strftime</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">fields</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"."</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">fields</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="c1"># no subfield, just return the formatted date str</span>
|
|
<span class="k">return</span> <span class="n">dt</span><span class="o">.</span><span class="n">date</span><span class="p">()</span><span class="o">.</span><span class="n">isoformat</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">fields</span><span class="p">)</span> <span class="o">></span> <span class="mi">2</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unhandled template value: </span><span class="si">{</span><span class="n">field</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
<span class="n">subfield</span> <span class="o">=</span> <span class="n">fields</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="n">subfield</span> <span class="o">==</span> <span class="s2">"strftime"</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">args</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="kc">None</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">dt</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
|
<span class="k">except</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Invalid strftime template: '</span><span class="si">{</span><span class="n">args</span><span class="si">}</span><span class="s2">'"</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">DateTimeFormatter</span><span class="p">(</span><span class="n">dt</span><span class="p">),</span> <span class="n">subfield</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">AttributeError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unhandled template value: </span><span class="si">{</span><span class="n">field</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="kn">from</span> <span class="nn">e</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">get_place_value</span><span class="p">(</span><span class="n">photo</span><span class="p">:</span> <span class="s2">"PhotoInfo"</span><span class="p">,</span> <span class="n">field</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span> <span class="c1"># noqa: F821</span>
|
|
<span class="sd">"""Get the value of a 'place' field by attribute</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> photo: the PhotoInfo object</span>
|
|
<span class="sd"> field: the field to get, e.g. 'place.name'</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">photo</span><span class="o">.</span><span class="n">place</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="kc">None</span>
|
|
|
|
<span class="n">fields</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"."</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">fields</span><span class="p">)</span> <span class="o"><</span> <span class="mi">2</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Invalid place field: </span><span class="si">{</span><span class="n">field</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
<span class="n">subfields</span> <span class="o">=</span> <span class="n">fields</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>
|
|
<span class="k">if</span> <span class="n">subfields</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">"name"</span><span class="p">,</span> <span class="s2">"country_code"</span><span class="p">]</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">subfields</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">photo</span><span class="o">.</span><span class="n">place</span><span class="p">,</span> <span class="n">subfields</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="ow">or</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="n">subfields</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"name"</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">subfields</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">subfields</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"country"</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">photo</span><span class="o">.</span><span class="n">place</span><span class="o">.</span><span class="n">names</span><span class="o">.</span><span class="n">country</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">photo</span><span class="o">.</span><span class="n">place</span><span class="o">.</span><span class="n">names</span><span class="o">.</span><span class="n">country</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="n">subfields</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"state_province"</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="n">photo</span><span class="o">.</span><span class="n">place</span><span class="o">.</span><span class="n">names</span><span class="o">.</span><span class="n">state_province</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="n">photo</span><span class="o">.</span><span class="n">place</span><span class="o">.</span><span class="n">names</span><span class="o">.</span><span class="n">state_province</span>
|
|
<span class="k">else</span> <span class="kc">None</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">subfields</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"city"</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">photo</span><span class="o">.</span><span class="n">place</span><span class="o">.</span><span class="n">names</span><span class="o">.</span><span class="n">city</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">photo</span><span class="o">.</span><span class="n">place</span><span class="o">.</span><span class="n">names</span><span class="o">.</span><span class="n">city</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="n">subfields</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"area_of_interest"</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="n">photo</span><span class="o">.</span><span class="n">place</span><span class="o">.</span><span class="n">names</span><span class="o">.</span><span class="n">area_of_interest</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="n">photo</span><span class="o">.</span><span class="n">place</span><span class="o">.</span><span class="n">names</span><span class="o">.</span><span class="n">area_of_interest</span>
|
|
<span class="k">else</span> <span class="kc">None</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">subfields</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"address"</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">subfields</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">photo</span><span class="o">.</span><span class="n">place</span><span class="o">.</span><span class="n">address_str</span>
|
|
<span class="k">elif</span> <span class="n">subfields</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">in</span> <span class="p">[</span>
|
|
<span class="s2">"street"</span><span class="p">,</span>
|
|
<span class="s2">"city"</span><span class="p">,</span>
|
|
<span class="s2">"state_province"</span><span class="p">,</span>
|
|
<span class="s2">"postal_code"</span><span class="p">,</span>
|
|
<span class="s2">"country"</span><span class="p">,</span>
|
|
<span class="p">]:</span>
|
|
<span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">photo</span><span class="o">.</span><span class="n">place</span><span class="o">.</span><span class="n">address</span><span class="p">,</span> <span class="n">subfields</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="ow">or</span> <span class="kc">None</span>
|
|
<span class="k">elif</span> <span class="n">subfields</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"country_code"</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">photo</span><span class="o">.</span><span class="n">place</span><span class="o">.</span><span class="n">address</span><span class="o">.</span><span class="n">iso_country_code</span> <span class="ow">or</span> <span class="kc">None</span>
|
|
<span class="c1"># did not find a match</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Unhandled template value: </span><span class="si">{</span><span class="n">field</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
</pre></div>
|
|
</article>
|
|
</div>
|
|
<footer>
|
|
|
|
<div class="related-pages">
|
|
|
|
|
|
</div>
|
|
<div class="bottom-of-page">
|
|
<div class="left-details">
|
|
<div class="copyright">
|
|
Copyright © 2021, Rhet Turnbull
|
|
</div>
|
|
Made with <a href="https://www.sphinx-doc.org/">Sphinx</a> and <a class="muted-link" href="https://pradyunsg.me">@pradyunsg</a>'s
|
|
|
|
<a href="https://github.com/pradyunsg/furo">Furo</a>
|
|
|
|
</div>
|
|
<div class="right-details">
|
|
<div class="icons">
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</footer>
|
|
</div>
|
|
<aside class="toc-drawer no-toc">
|
|
|
|
|
|
|
|
</aside>
|
|
</div>
|
|
</div><script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
|
|
<script src="../../_static/jquery.js"></script>
|
|
<script src="../../_static/underscore.js"></script>
|
|
<script src="../../_static/_sphinx_javascript_frameworks_compat.js"></script>
|
|
<script src="../../_static/doctools.js"></script>
|
|
<script src="../../_static/sphinx_highlight.js"></script>
|
|
<script src="../../_static/scripts/furo.js"></script>
|
|
<script src="../../_static/clipboard.min.js"></script>
|
|
<script src="../../_static/copybutton.js"></script>
|
|
</body>
|
|
</html> |