Compare commits

..

15 Commits

Author SHA1 Message Date
Rhet Turnbull
2041789ff4 Updated README.md [skip ci] 2021-08-15 14:12:15 -07:00
Rhet Turnbull
aec86f93ea Added inspect() to repl, closes #501 2021-08-15 13:50:37 -07:00
Rhet Turnbull
57bfb03e05 Updated CHANGELOG.md [skip ci] 2021-08-02 05:55:19 -07:00
Rhet Turnbull
c2b2476e38 Updated docs for Text Detection [skip ci] 2021-08-02 05:52:48 -07:00
Rhet Turnbull
fa2027d453 Improved caching of detected_text results 2021-08-02 05:10:26 -07:00
Rhet Turnbull
9d980e4917 Updated CHANGELOG.md [skip ci] 2021-07-29 21:27:51 -07:00
Rhet Turnbull
673243c6cd Fix for #500, check for macOS version before loading Vision 2021-07-29 21:16:33 -07:00
Rhet Turnbull
7376223eb8 Updated text_detection to detect macOS version 2021-07-29 07:39:01 -07:00
Rhet Turnbull
ecd0b8e22f Updated detected_text docs to make it clear this only works on Catalina+ 2021-07-29 07:03:04 -07:00
Rhet Turnbull
c4a608b5bd Updated CHANGELOG.md [skip ci] 2021-07-29 07:02:38 -07:00
Rhet Turnbull
4d9e21ea16 Added error logging to PhotoInfo.detected_text 2021-07-29 06:32:07 -07:00
Rhet Turnbull
1ee3e035c4 Updated README.md [skip ci] 2021-07-29 06:25:59 -07:00
Rhet Turnbull
b1c0fb3e82 Added error logging to {detected_text} processing, #499 2021-07-29 06:23:02 -07:00
Rhet Turnbull
de715d2afd Updated CHANGELOG.md [skip ci] 2021-07-28 06:36:10 -07:00
Rhet Turnbull
607cf80dda Removed unneeded test file [skip ci] 2021-07-28 06:27:44 -07:00
13 changed files with 158 additions and 65 deletions

View File

@@ -4,6 +4,36 @@ All notable changes to this project will be documented in this file. Dates are d
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
#### [v0.42.72](https://github.com/RhetTbull/osxphotos/compare/v0.42.71...v0.42.72)
> 2 August 2021
- Improved caching of detected_text results [`fa2027d`](https://github.com/RhetTbull/osxphotos/commit/fa2027d45308738d2335d4b5a72c3ef5c478491a)
#### [v0.42.71](https://github.com/RhetTbull/osxphotos/compare/v0.42.70...v0.42.71)
> 29 July 2021
- Updated text_detection to detect macOS version [`7376223`](https://github.com/RhetTbull/osxphotos/commit/7376223eb87a4919fd54cc685a3f263e83626879)
- Updated detected_text docs to make it clear this only works on Catalina+ [`ecd0b8e`](https://github.com/RhetTbull/osxphotos/commit/ecd0b8e22f8bf1f8d1e98d64834bebf0394dd903)
- Fix for #500, check for macOS version before loading Vision [`673243c`](https://github.com/RhetTbull/osxphotos/commit/673243c6cd1c267b6b741b5429cdb63c062648d1)
#### [v0.42.70](https://github.com/RhetTbull/osxphotos/compare/v0.42.69...v0.42.70)
> 29 July 2021
- Added error logging to {detected_text} processing, #499 [`b1c0fb3`](https://github.com/RhetTbull/osxphotos/commit/b1c0fb3e8284600394ddbfdd7dfa94916a843c81)
- Updated README.md [skip ci] [`1ee3e03`](https://github.com/RhetTbull/osxphotos/commit/1ee3e035c42d687158f7cf73382f0f263516dc37)
- Removed unneeded test file [skip ci] [`607cf80`](https://github.com/RhetTbull/osxphotos/commit/607cf80dda37ad529edd91fe92af3885b04b9a37)
#### [v0.42.69](https://github.com/RhetTbull/osxphotos/compare/v0.42.67...v0.42.69)
> 28 July 2021
- Added {detected_text} template [`c233523`](https://github.com/RhetTbull/osxphotos/commit/c2335236be7a1eecf4f25a9dcb844df4d6372b5c)
- Added PhotoInfo.detected_text() [`123340e`](https://github.com/RhetTbull/osxphotos/commit/123340eadabb0fb07209c4207ccad13a53de3619)
- Updated dependencies [`0c8fbd6`](https://github.com/RhetTbull/osxphotos/commit/0c8fbd69af7a0d696de5224bf3c302e0c240905f)
#### [v0.42.67](https://github.com/RhetTbull/osxphotos/compare/v0.42.66...v0.42.67)
> 24 July 2021

View File

@@ -35,6 +35,7 @@ OSXPhotos provides the ability to interact with and query Apple's Photos.app lib
+ [Raw Photos](#raw-photos)
+ [Template System](#template-system)
+ [ExifTool](#exiftoolExifTool)
+ [Text Detection](#textdetection)
+ [Utility Functions](#utility-functions)
* [Examples](#examples)
* [Related Projects](#related-projects)
@@ -1700,7 +1701,7 @@ Substitution Description
{lf} A line feed: '\n', alias for {newline}
{cr} A carriage return: '\r'
{crlf} a carriage return + line feed: '\r\n'
{osxphotos_version} The osxphotos version, e.g. '0.42.69'
{osxphotos_version} The osxphotos version, e.g. '0.42.73'
{osxphotos_cmd_line} The full command line used to run osxphotos
The following substitutions may result in multiple values. Thus if specified for
@@ -1769,9 +1770,10 @@ Substitution Description
not need to reprocess each photo. You may pass a
confidence threshold value between 0.0 and 1.0 after
a colon as in '{detected_text:0.5}'; The default
confidence threshold is 0.75. Note: this feature is
not the same thing as Live Text in macOS Monterey,
which osxphotos does not yet support.
confidence threshold is 0.75. '{detected_text}' works
only on macOS Catalina (10.15) or later. Note: this
feature is not the same thing as Live Text in macOS
Monterey, which osxphotos does not yet support.
{shell_quote} 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
@@ -2787,7 +2789,8 @@ Some substitutions, notably `album`, `keyword`, and `person` could return multip
See [Template System](#template-system) for additional details.
#### `detected_text(confidence_threshold=TEXT_DETECTION_CONFIDENCE_THRESHOLD)`
#### <a name="detected_text_method">`detected_text(confidence_threshold=TEXT_DETECTION_CONFIDENCE_THRESHOLD)`</a>
Detects text in photo and returns lists of results as (detected text, confidence)
@@ -2797,7 +2800,9 @@ If photo is edited, uses the edited photo, otherwise the original; falls back to
Returns: list of (detected text, confidence) tuples.
Note: This is *not* the same as Live Text in macOS Monterey. When using `detected_text()`, osxphotos will use Apple's [Vision framework](https://developer.apple.com/documentation/vision/recognizing_text_in_images?language=objc) to perform text detection on the image. On my circa 2013 MacBook Pro, this takes about 2 seconds per image. `detected_text()` does memoize the results for a given `confidence_threshold` so repeated calls will not re-process the photo.
Note: This is *not* the same as Live Text in macOS Monterey. When using `detected_text()`, osxphotos will use Apple's [Vision framework](https://developer.apple.com/documentation/vision/recognizing_text_in_images?language=objc) to perform text detection on the image. On my circa 2013 MacBook Pro, this takes about 2 seconds per image. `detected_text()` does memoize the results for a given `confidence_threshold` so repeated calls will not re-process the photo. This works only on macOS Catalina (10.15) or later.
See also [Text Detection](#textdetection).
### ExifInfo
[PhotosInfo.exif_info](#exif-info) returns an `ExifInfo` object with some EXIF data about the photo (Photos 5 only). `ExifInfo` contains the following properties:
@@ -3553,7 +3558,7 @@ The following template field substitutions are availabe for use the templating s
|{lf}|A line feed: '\n', alias for {newline}|
|{cr}|A carriage return: '\r'|
|{crlf}|a carriage return + line feed: '\r\n'|
|{osxphotos_version}|The osxphotos version, e.g. '0.42.69'|
|{osxphotos_version}|The osxphotos version, e.g. '0.42.73'|
|{osxphotos_cmd_line}|The full command line used to run osxphotos|
|{album}|Album(s) photo is contained in|
|{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder|
@@ -3568,7 +3573,7 @@ The following template field substitutions are availabe for use the templating s
|{searchinfo.venue}|Venues associated with a photo, e.g. name of restaurant; (Photos 5+ only, applied automatically by Photos' image categorization algorithms).|
|{searchinfo.venue_type}|Venue types associated with a photo, e.g. 'Restaurant'; (Photos 5+ only, applied automatically by Photos' image categorization algorithms).|
|{photo}|Provides direct access to the PhotoInfo object for the photo. Must be used in format '{photo.property}' where 'property' represents a PhotoInfo property. For example: '{photo.favorite}' is the same as '{favorite}' and '{photo.place.name}' is the same as '{place.name}'. '{photo}' provides access to properties that are not available as separate template fields but it assumes some knowledge of the underlying PhotoInfo class. See https://rhettbull.github.io/osxphotos/ for additional documentation on the PhotoInfo class.|
|{detected_text}|List of text strings found in the image after performing text detection. Using '{detected_text}' will cause osxphotos to perform text detection on your photos using the built-in macOS text detection algorithms which will slow down your export. 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. You may pass a confidence threshold value between 0.0 and 1.0 after a colon as in '{detected_text:0.5}'; The default confidence threshold is 0.75. Note: this feature is not the same thing as Live Text in macOS Monterey, which osxphotos does not yet support.|
|{detected_text}|List of text strings found in the image after performing text detection. Using '{detected_text}' will cause osxphotos to perform text detection on your photos using the built-in macOS text detection algorithms which will slow down your export. 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. You may pass a confidence threshold value between 0.0 and 1.0 after a colon as in '{detected_text:0.5}'; The default confidence threshold is 0.75. '{detected_text}' works only on macOS Catalina (10.15) or later. Note: this feature is not the same thing as Live Text in macOS Monterey, which osxphotos does not yet support.|
|{shell_quote}|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.|
|{function}|Execute a python function from an external file and use return value as template substitution. 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. The function will be passed the PhotoInfo object for the photo. See https://github.com/RhetTbull/osxphotos/blob/master/examples/template_function.py for an example of how to implement a template function.|
<!-- OSXPHOTOS-TEMPLATE-TABLE:END -->
@@ -3633,6 +3638,14 @@ osxphotos.exiftool also provides an `ExifToolCaching` class which caches all met
`ExifTool()` runs `exiftool` as a subprocess using the `-stay_open True` flag to keep the process running in the background. The subprocess will be cleaned up when your main script terminates. `ExifTool()` uses a singleton pattern to ensure that only one instance of `exiftool` is created. Multiple instances of `ExifTool()` will all use the same `exiftool` subprocess.
### <a name="textdetection">Text Detection</a>
The [PhotoInfo.detected_text()](#detected_text_method) and the `{detected_text}` template will perform text detection on the photos in your library. Text detection is a slow process so to avoid unnecessary re-processing of photos, osxphotos will cache the results of the text detection process as an extended attribute on the photo image file. Extended attributes do not modify the actual file. The extended attribute is named `osxphotos.metadata:detected_text` and can be viewed using the built-in [xattr](https://ss64.com/osx/xattr.html) command or my [osxmetadata](https://github.com/RhetTbull/osxmetadata) tool. If you want to remove the cached attribute, you can do so with osxmetadata as follows:
`osxmetadata --clear osxphotos.metadata:detected_text --walk ~/Pictures/Photos\ Library.photoslibrary/`
### Utility Functions
The following functions are located in osxphotos.utils

View File

@@ -1,3 +1,3 @@
""" version info """
__version__ = "0.42.69"
__version__ = "0.42.73"

View File

@@ -4074,6 +4074,10 @@ def _get_selected(photosdb):
@click.pass_context
def repl(ctx, cli_obj, db):
"""Run interactive osxphotos shell"""
from osxphotos import PhotosDB, PhotoInfo, ExifTool
from rich import inspect as _inspect
pretty.install()
print(f"python version: {sys.version}")
print(f"osxphotos version: {osxphotos._version.__version__}")
@@ -4090,6 +4094,10 @@ def repl(ctx, cli_obj, db):
show = _show_photo
get_selected = _get_selected(photosdb)
def inspect(obj):
"""inspect object"""
return _inspect(obj, methods=True)
print(f"Found {len(photos)} photos in {tictoc:0.2f} seconds")
print("The following variables are defined:")
print(f"- photosdb: PhotosDB() instance for {photosdb.library_path}")
@@ -4105,5 +4113,8 @@ def repl(ctx, cli_obj, db):
print(
f"- help(object): print help text including list of methods for object; for example, help(PhotosDB)"
)
print(
f"- inspect(object): print information about an object; for example inspect(photosdb)"
)
print(f"- quit(): exit this interactive shell\n")
code.interact(banner="", local=locals())

View File

@@ -89,11 +89,11 @@ class ExportDB_ABC(ABC):
pass
@abstractmethod
def get_detected_text_for_uuid(self, uuid, confidence):
def get_detected_text_for_uuid(self, uuid):
pass
@abstractmethod
def set_detected_text_for_uuid(self, uuid, text, confidence):
def set_detected_text_for_uuid(self, uuid, json_text):
pass
@abstractmethod
@@ -170,10 +170,10 @@ class ExportDBNoOp(ExportDB_ABC):
def get_previous_uuids(self):
return []
def get_detected_text_for_uuid(self, uuid, confidence):
return []
def get_detected_text_for_uuid(self, uuid):
return None
def set_detected_text_for_uuid(self, uuid, text, confidence):
def set_detected_text_for_uuid(self, uuid, json_text):
pass
def set_data(
@@ -493,7 +493,7 @@ class ExportDB(ExportDB_ABC):
c = conn.cursor()
c.execute(
"INSERT OR REPLACE INTO detected_text(uuid, text_data) VALUES (?, ?);",
(uuid, text_json),
(uuid, text_json,),
)
conn.commit()
except Error as e:

View File

@@ -14,6 +14,7 @@ from datetime import timedelta, timezone
from typing import Optional
import yaml
from osxmetadata import OSXMetaData
from .._constants import (
_MOVIE_TYPE,
@@ -1118,6 +1119,28 @@ class PhotoInfo:
Returns: list of (detected text, confidence) tuples
"""
try:
return self._detected_text_cache[confidence_threshold]
except (AttributeError, KeyError) as e:
if isinstance(e, AttributeError):
self._detected_text_cache = {}
try:
detected_text = self._detected_text()
except Exception as e:
logging.warning(f"Error detecting text in photo {self.uuid}: {e}")
detected_text = []
self._detected_text_cache[confidence_threshold] = [
(text, confidence)
for text, confidence in detected_text
if confidence >= confidence_threshold
]
return self._detected_text_cache[confidence_threshold]
def _detected_text(self):
"""detect text in photo, either from cached extended attribute or by attempting text detection"""
path = (
self.path_edited if self.hasadjustments and self.path_edited else self.path
)
@@ -1125,23 +1148,12 @@ class PhotoInfo:
if not path:
return []
try:
return self._detected_text[(path, confidence_threshold)]
except (AttributeError, KeyError) as e:
if isinstance(e, AttributeError):
self._detected_text = {}
try:
detected_text = detect_text(path)
except Exception as e:
detected_text = []
self._detected_text[(path, confidence_threshold)] = [
(text, confidence)
for text, confidence in detected_text
if confidence >= confidence_threshold
]
return self._detected_text[(path, confidence_threshold)]
md = OSXMetaData(path)
detected_text = md.get_attribute("osxphotos_detected_text")
if detected_text is None:
detected_text = detect_text(path)
md.set_attribute("osxphotos_detected_text", detected_text)
return detected_text
@property
def _longitude(self):

View File

@@ -3,6 +3,7 @@
import datetime
import json
import locale
import logging
import os
import pathlib
import shlex
@@ -205,6 +206,7 @@ TEMPLATE_SUBSTITUTIONS_MULTI_VALUED = {
+ "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. "
+ "You may pass a confidence threshold value between 0.0 and 1.0 after a colon as in '{detected_text:0.5}'; "
+ f"The default confidence threshold is {TEXT_DETECTION_CONFIDENCE_THRESHOLD}. "
+ "'{detected_text}' works only on macOS Catalina (10.15) or later. "
+ "Note: this feature is not the same thing as Live Text in macOS Monterey, which osxphotos does not yet support.",
"{shell_quote}": "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.",
"{function}": "Execute a python function from an external file and use return value as template substitution. "
@@ -1443,22 +1445,8 @@ def _get_detected_text(photo, exportdb, confidence=TEXT_DETECTION_CONFIDENCE_THR
else TEXT_DETECTION_CONFIDENCE_THRESHOLD
)
detected_text = exportdb.get_detected_text_for_uuid(photo.uuid)
if detected_text:
detected_text = json.loads(detected_text)
else:
path = (
photo.path_edited
if photo.hasadjustments and photo.path_edited
else photo.path
)
path = path or photo.path_derivatives[0] if photo.path_derivatives else None
if not path:
detected_text = []
else:
try:
detected_text = detect_text(path)
except Exception as e:
detected_text = []
exportdb.set_detected_text_for_uuid(photo.uuid, json.dumps(detected_text))
# _detected_text caches the text detection results in an extended attribute
# so the first time this gets called is slow but repeated accesses are fast
detected_text = photo._detected_text()
exportdb.set_detected_text_for_uuid(photo.uuid, json.dumps(detected_text))
return [text for text, conf in detected_text if conf >= confidence]

View File

@@ -1,19 +1,33 @@
""" Use Apple's Vision Framework via PyObjC to perform text detection on images """
""" Use Apple's Vision Framework via PyObjC to perform text detection on images (macOS 10.15+ only) """
import logging
from typing import List
import objc
import Quartz
import Vision
from Cocoa import NSURL
from Foundation import NSDictionary
from typing import List
# needed to capture system-level stderr
from wurlitzer import pipes
from .utils import _get_os_version
ver, major, minor = _get_os_version()
if ver == "10" and int(major) < 15:
vision = False
else:
import Vision
vision = True
def detect_text(img_path: str) -> List:
"""process image at img_path with VNRecognizeTextRequest and return list of results"""
if not vision:
logging.warning(f"detect_text not implemented for this version of macOS")
return []
with objc.autorelease_pool():
input_url = NSURL.fileURLWithPath_(img_path)
@@ -38,6 +52,9 @@ def detect_text(img_path: str) -> List:
vision_request.dealloc()
vision_handler.dealloc()
for result in results:
result[0] = str(result[0])
return results

View File

@@ -16,7 +16,7 @@ dataclasses==0.7;python_version<'3.7'
wurlitzer==2.1.0
photoscript==0.1.4
toml==0.10.2
osxmetadata==0.99.26
osxmetadata==0.99.31
textx==2.3.0
rich==10.6.0
bitmath==1.3.3.1

View File

@@ -91,7 +91,7 @@ setup(
"wurlitzer==2.1.0",
"photoscript==0.1.4",
"toml==0.10.2",
"osxmetadata==0.99.26",
"osxmetadata==0.99.31",
"textx==2.3.0",
"rich==10.6.0",
"bitmath==1.3.3.1",

View File

@@ -1,5 +1,7 @@
""" Test ExportDB """
import json
import pytest
EXIF_DATA = """[{"_CreatedBy": "osxphotos, https://github.com/RhetTbull/osxphotos", "EXIF:ImageDescription": "\u2068Elder Park\u2069, \u2068Adelaide\u2069, \u2068Australia\u2069", "XMP:Description": "\u2068Elder Park\u2069, \u2068Adelaide\u2069, \u2068Australia\u2069", "XMP:Title": "Elder Park", "EXIF:GPSLatitude": "34 deg 55' 8.01\" S", "EXIF:GPSLongitude": "138 deg 35' 48.70\" E", "Composite:GPSPosition": "34 deg 55' 8.01\" S, 138 deg 35' 48.70\" E", "EXIF:GPSLatitudeRef": "South", "EXIF:GPSLongitudeRef": "East", "EXIF:DateTimeOriginal": "2017:06:20 17:18:56", "EXIF:OffsetTimeOriginal": "+09:30", "EXIF:ModifyDate": "2020:05:18 14:42:04"}]"""
@@ -12,10 +14,11 @@ DATABASE_VERSION1 = "tests/export_db_version1.db"
def test_export_db():
""" test ExportDB """
"""test ExportDB"""
import os
import tempfile
from osxphotos.export_db import ExportDB, OSXPHOTOS_EXPORTDB_VERSION
from osxphotos.export_db import OSXPHOTOS_EXPORTDB_VERSION, ExportDB
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
dbname = os.path.join(tempdir.name, ".osxphotos_export.db")
@@ -47,6 +50,9 @@ def test_export_db():
assert db.get_sidecar_for_file(filepath) == (SIDECAR_DATA, (13, 14, 15))
assert db.get_previous_uuids() == ["FOO-BAR"]
db.set_detected_text_for_uuid("FOO-BAR", json.dumps([["foo", 0.5]]))
assert json.loads(db.get_detected_text_for_uuid("FOO-BAR")) == [["foo", 0.5]]
# test set_data which sets all at the same time
filepath2 = os.path.join(tempdir.name, "test2.jpg")
db.set_data(
@@ -80,6 +86,7 @@ def test_export_db():
assert db.get_stat_converted_for_file(filepath2) == (7, 8, 9)
assert db.get_stat_edited_for_file(filepath2) == (10, 11, 12)
assert sorted(db.get_previous_uuids()) == (["BAR-FOO", "FOO-BAR"])
assert json.loads(db.get_detected_text_for_uuid("FOO-BAR")) == [["foo", 0.5]]
# update data
db.set_uuid_for_file(filepath, "FUBAR")
@@ -88,10 +95,11 @@ def test_export_db():
def test_export_db_no_op():
""" test ExportDBNoOp """
"""test ExportDBNoOp"""
import os
import tempfile
from osxphotos.export_db import ExportDBNoOp, OSXPHOTOS_EXPORTDB_VERSION
from osxphotos.export_db import OSXPHOTOS_EXPORTDB_VERSION, ExportDBNoOp
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
db = ExportDBNoOp()
@@ -121,6 +129,9 @@ def test_export_db_no_op():
assert db.get_sidecar_for_file(filepath) == (None, (None, None, None))
assert db.get_previous_uuids() == []
db.set_detected_text_for_uuid("FOO-BAR", json.dumps([["foo", 0.5]]))
assert db.get_detected_text_for_uuid("FOO-BAR") is None
# test set_data which sets all at the same time
filepath2 = os.path.join(tempdir.name, "test2.jpg")
db.set_data(
@@ -148,13 +159,14 @@ def test_export_db_no_op():
def test_export_db_in_memory():
""" test ExportDBInMemory """
"""test ExportDBInMemory"""
import os
import tempfile
from osxphotos.export_db import (
OSXPHOTOS_EXPORTDB_VERSION,
ExportDB,
ExportDBInMemory,
OSXPHOTOS_EXPORTDB_VERSION,
)
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
@@ -174,6 +186,7 @@ def test_export_db_in_memory():
db.set_stat_edited_for_file(filepath, (10, 11, 12))
db.set_sidecar_for_file(filepath, SIDECAR_DATA, (13, 14, 15))
assert db.get_previous_uuids() == ["FOO-BAR"]
db.set_detected_text_for_uuid("FOO-BAR", json.dumps([["foo", 0.5]]))
db.close()
@@ -192,6 +205,7 @@ def test_export_db_in_memory():
assert dbram.get_stat_edited_for_file(filepath) == (10, 11, 12)
assert dbram.get_sidecar_for_file(filepath) == (SIDECAR_DATA, (13, 14, 15))
assert dbram.get_previous_uuids() == ["FOO-BAR"]
assert json.loads(dbram.get_detected_text_for_uuid("FOO-BAR")) == [["foo", 0.5]]
# change a value
dbram.set_uuid_for_file(filepath, "FUBAR")
@@ -202,6 +216,7 @@ def test_export_db_in_memory():
dbram.set_stat_converted_for_file(filepath, (1, 2, 3))
dbram.set_stat_edited_for_file(filepath, (4, 5, 6))
dbram.set_sidecar_for_file(filepath, "FUBAR", (20, 21, 22))
dbram.set_detected_text_for_uuid("FUBAR", json.dumps([["bar", 0.5]]))
assert dbram.get_uuid_for_file(filepath_lower) == "FUBAR"
assert dbram.get_info_for_uuid("FUBAR") == INFO_DATA2
@@ -212,6 +227,7 @@ def test_export_db_in_memory():
assert dbram.get_stat_edited_for_file(filepath) == (4, 5, 6)
assert dbram.get_sidecar_for_file(filepath) == ("FUBAR", (20, 21, 22))
assert dbram.get_previous_uuids() == ["FUBAR"]
assert json.loads(dbram.get_detected_text_for_uuid("FUBAR")) == [["bar", 0.5]]
dbram.close()
@@ -228,13 +244,15 @@ def test_export_db_in_memory():
assert db.get_previous_uuids() == ["FOO-BAR"]
assert db.get_info_for_uuid("FUBAR") is None
assert db.get_detected_text_for_uuid("FUBAR") is None
def test_export_db_in_memory_nofile():
""" test ExportDBInMemory with no dbfile """
"""test ExportDBInMemory with no dbfile"""
import os
import tempfile
from osxphotos.export_db import ExportDBInMemory, OSXPHOTOS_EXPORTDB_VERSION
from osxphotos.export_db import OSXPHOTOS_EXPORTDB_VERSION, ExportDBInMemory
tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_")
filepath = os.path.join(tempdir.name, "test.JPG")
@@ -254,6 +272,7 @@ def test_export_db_in_memory_nofile():
dbram.set_stat_converted_for_file(filepath, (1, 2, 3))
dbram.set_stat_edited_for_file(filepath, (4, 5, 6))
dbram.set_sidecar_for_file(filepath, "FUBAR", (20, 21, 22))
dbram.set_detected_text_for_uuid("FUBAR", json.dumps([["bar", 0.5]]))
assert dbram.get_uuid_for_file(filepath_lower) == "FUBAR"
assert dbram.get_info_for_uuid("FUBAR") == INFO_DATA2
@@ -264,5 +283,6 @@ def test_export_db_in_memory_nofile():
assert dbram.get_stat_edited_for_file(filepath) == (4, 5, 6)
assert dbram.get_sidecar_for_file(filepath) == ("FUBAR", (20, 21, 22))
assert dbram.get_previous_uuids() == ["FUBAR"]
assert json.loads(dbram.get_detected_text_for_uuid("FUBAR")) == [["bar", 0.5]]
dbram.close()

View File

@@ -1,4 +1,5 @@
""" Test template.py """
import json
import os
import re
@@ -7,6 +8,7 @@ from photoinfo_mock import PhotoInfoMock
import osxphotos
from osxphotos.exiftool import get_exiftool_path
from osxphotos.export_db import ExportDBInMemory
from osxphotos.phototemplate import (
TEMPLATE_SUBSTITUTIONS,
TEMPLATE_SUBSTITUTIONS_MULTI_VALUED,