Refactored PhotoInfo to use properties instead of methods--major update

This commit is contained in:
Rhet Turnbull
2019-12-21 09:38:54 -08:00
parent 2dc7bccfb7
commit 1ddd90cbdc
13 changed files with 282 additions and 263 deletions

View File

@@ -30,7 +30,7 @@
- [`original_filename()`](#original_filename)
- [`date()`](#date)
- [`description()`](#description)
- [`name()`](#name)
- [`title()`](#title)
- [`keywords()`](#keywords)
- [`albums()`](#albums)
- [`persons()`](#persons)
@@ -42,7 +42,7 @@
- [`favorite()`](#favorite)
- [`hidden()`](#hidden)
- [`location()`](#location)
- [`to_json()`](#to_json)
- [`json()`](#json)
- [`export(dest, *filename, edited=False, overwrite=False, increment=True)`](#exportdest-filename-editedfalse-overwritefalse-incrementtrue)
+ [Utility Functions](#utility-functions)
- [```get_system_library_path()```](#get_system_library_path)
@@ -121,11 +121,11 @@ Options:
--person TEXT Search for person(s).
--album TEXT Search for album(s).
--uuid TEXT Search for UUID(s).
--name TEXT Search for TEXT in name of photo.
--no-name Search for photos with no name.
--title TEXT Search for TEXT in title of photo.
--no-title Search for photos with no title.
--description TEXT Search for TEXT in description of photo.
--no-description Search for photos with no description.
-i, --ignore-case Case insensitive search for name or description. Does
-i, --ignore-case Case insensitive search for title or description. Does
not apply to keyword, person, or album.
--edited Search for photos that have been edited.
--external-edit Search for photos edited in external editor.
@@ -167,15 +167,15 @@ def main():
for p in photos:
print(
p.uuid,
p.filename(),
p.original_filename(),
p.date(),
p.description(),
p.name(),
p.keywords(),
p.albums(),
p.persons(),
p.path(),
p.filename,
p.original_filename,
p.date,
p.description,
p.title,
p.keywords,
p.albums,
p.persons,
p.path,
)
if __name__ == "__main__":
@@ -191,6 +191,7 @@ import os.path
import osxphotos
def main():
photosdb = osxphotos.PhotosDB()
photos = photosdb.photos()
@@ -198,14 +199,15 @@ def main():
export_path = os.path.expanduser("~/Desktop/export")
for p in photos:
if not p.ismissing():
if p.hasadjustments():
if not p.ismissing:
if p.hasadjustments:
exported = p.export(export_path, edited=True)
else:
exported = p.export(export_path)
print(f"Exported {p.filename()} to {exported}")
print(f"Exported {p.filename} to {exported}")
else:
print(f"Skipping missing photo: {p.filename()}")
print(f"Skipping missing photo: {p.filename}")
if __name__ == "__main__":
main()
@@ -438,8 +440,8 @@ Returns the date of the photo as a datetime.datetime object
#### `description()`
Returns the description of the photo
#### `name()`
Returns the name (or the title as Photos calls it) of the photo
#### `title()`
Returns the title of the photo
#### `keywords()`
Returns a list of keywords (e.g. tags) applied to the photo
@@ -474,7 +476,7 @@ Returns `True` if the picture has been marked as hidden, otherwise `False`
#### `location()`
Returns latitude and longitude as a tuple of floats (latitude, longitude). If location is not set, latitude and longitude are returned as `None`
#### `to_json()`
#### `json()`
Returns a JSON representation of all photo info
#### `export(dest, *filename, edited=False, overwrite=False, increment=True)`

View File

@@ -29,17 +29,17 @@ def main():
photos = photosdb.photos()
for p in photos:
print(
p.uuid(),
p.filename(),
p.date(),
p.description(),
p.name(),
p.keywords(),
p.albums(),
p.persons(),
p.path(),
p.ismissing(),
p.hasadjustments(),
p.uuid,
p.filename,
p.date,
p.description,
p.title,
p.keywords,
p.albums,
p.persons,
p.path,
p.ismissing,
p.hasadjustments,
)

View File

@@ -6,6 +6,7 @@ import os.path
import osxphotos
def main():
photosdb = osxphotos.PhotosDB()
photos = photosdb.photos()
@@ -13,14 +14,15 @@ def main():
export_path = os.path.expanduser("~/Desktop/export")
for p in photos:
if not p.ismissing():
if p.hasadjustments():
if not p.ismissing:
if p.hasadjustments:
exported = p.export(export_path, edited=True)
else:
exported = p.export(export_path)
print(f"Exported {p.filename()} to {exported}")
print(f"Exported {p.filename} to {exported}")
else:
print(f"Skipping missing photo: {p.filename()}")
print(f"Skipping missing photo: {p.filename}")
if __name__ == "__main__":
main()
main()

View File

@@ -9,7 +9,7 @@ import osxphotos
from ._version import __version__
# TODO: add "--any" to search any field (e.g. keyword, description, name contains "wedding") (add case insensitive option)
# TODO: add "--any" to search any field (e.g. keyword, description, title contains "wedding") (add case insensitive option)
class CLI_Obj:
@@ -169,9 +169,9 @@ def list_libraries(cli_obj):
@click.option("--album", default=None, multiple=True, help="Search for album(s).")
@click.option("--uuid", default=None, multiple=True, help="Search for UUID(s).")
@click.option(
"--name", default=None, multiple=True, help="Search for TEXT in name of photo."
"--title", default=None, multiple=True, help="Search for TEXT in title of photo."
)
@click.option("--no-name", is_flag=True, help="Search for photos with no name.")
@click.option("--no-title", is_flag=True, help="Search for photos with no title.")
@click.option(
"--description",
default=None,
@@ -185,7 +185,7 @@ def list_libraries(cli_obj):
"-i",
"--ignore-case",
is_flag=True,
help="Case insensitive search for name or description. Does not apply to keyword, person, or album.",
help="Case insensitive search for title or description. Does not apply to keyword, person, or album.",
)
@click.option("--edited", is_flag=True, help="Search for photos that have been edited.")
@click.option(
@@ -219,8 +219,8 @@ def query(
person,
album,
uuid,
name,
no_name,
title,
no_title,
description,
no_description,
ignore_case,
@@ -246,8 +246,8 @@ def query(
person,
album,
uuid,
name,
no_name,
title,
no_title,
description,
no_description,
edited,
@@ -274,8 +274,8 @@ def query(
# can't search for both missing and notmissing
click.echo(cli.commands["query"].get_help(ctx))
return
elif name and no_name:
# can't search for both name and no_name
elif title and no_title:
# can't search for both title and no_title
click.echo(cli.commands["query"].get_help(ctx))
return
elif description and no_description:
@@ -288,19 +288,19 @@ def query(
keywords=keyword, persons=person, albums=album, uuid=uuid
)
if name:
# search name field for text
# if more than one, find photos with all name values in in name
if title:
# search title field for text
# if more than one, find photos with all title values in title
if ignore_case:
# case-insensitive
for n in name:
n = n.lower()
photos = [p for p in photos if p.name() and n in p.name().lower()]
for t in title:
t = t.lower()
photos = [p for p in photos if p.title and t in p.title.lower()]
else:
for n in name:
photos = [p for p in photos if p.name() and n in p.name()]
elif no_name:
photos = [p for p in photos if not p.name()]
for t in title:
photos = [p for p in photos if p.title and t in p.title]
elif no_title:
photos = [p for p in photos if not p.title]
if description:
# search description field for text
@@ -361,7 +361,7 @@ def print_photo_info(photos, json=False):
if json:
dump = []
for p in photos:
dump.append(p.to_json())
dump.append(p.json())
click.echo(f"[{', '.join(dump)}]")
else:
# dump as CSV
@@ -377,7 +377,7 @@ def print_photo_info(photos, json=False):
"original_filename",
"date",
"description",
"name",
"title",
"keywords",
"albums",
"persons",
@@ -395,24 +395,24 @@ def print_photo_info(photos, json=False):
for p in photos:
dump.append(
[
p.uuid(),
p.filename(),
p.original_filename(),
str(p.date()),
p.description(),
p.name(),
", ".join(p.keywords()),
", ".join(p.albums()),
", ".join(p.persons()),
p.path(),
p.ismissing(),
p.hasadjustments(),
p.external_edit(),
p.favorite(),
p.hidden(),
p._latitude(),
p._longitude(),
p.path_edited(),
p.uuid,
p.filename,
p.original_filename,
str(p.date),
p.description,
p.title,
", ".join(p.keywords),
", ".join(p.albums),
", ".join(p.persons),
p.path,
p.ismissing,
p.hasadjustments,
p.external_edit,
p.favorite,
p.hidden,
p._latitude,
p._longitude,
p.path_edited,
]
)
for row in dump:

View File

@@ -1,3 +1,3 @@
""" version info """
__version__ = "0.16.02"
__version__ = "0.17.00"

View File

@@ -30,15 +30,18 @@ class PhotoInfo:
self._info = info
self._db = db
@property
def filename(self):
""" filename of the picture """
return self._info["filename"]
@property
def original_filename(self):
""" original filename of the picture """
""" Photos 5 mangles filenames upon import """
return self._info["originalFilename"]
@property
def date(self):
""" image creation date as timezone aware datetime object """
imagedate = self._info["imageDate"]
@@ -48,10 +51,12 @@ class PhotoInfo:
imagedate_utc = imagedate.astimezone(tz=tz)
return imagedate_utc
@property
def tzoffset(self):
""" timezone offset from UTC in seconds """
return self._info["imageTimeZoneOffsetSeconds"]
@property
def path(self):
""" absolute path on disk of the original picture """
photopath = ""
@@ -93,6 +98,7 @@ class PhotoInfo:
return photopath
@property
def path_edited(self):
""" absolute path on disk of the edited picture """
""" None if photo has not been edited """
@@ -165,14 +171,17 @@ class PhotoInfo:
return photopath
@property
def description(self):
""" long / extended description of picture """
return self._info["extendedDescription"]
@property
def persons(self):
""" list of persons in picture """
return self._info["persons"]
@property
def albums(self):
""" list of albums picture is contained in """
albums = []
@@ -180,24 +189,23 @@ class PhotoInfo:
albums.append(self._db._dbalbum_details[album]["title"])
return albums
@property
def keywords(self):
""" list of keywords for picture """
return self._info["keywords"]
def name(self):
""" (deprecated) name / title of picture """
# TODO: add warning on deprecation
return self._info["name"]
@property
def title(self):
""" name / title of picture """
# TODO: Update documentation and tests to use title
return self._info["name"]
@property
def uuid(self):
""" UUID of picture """
return self._uuid
@property
def ismissing(self):
""" returns true if photo is missing from disk (which means it's not been downloaded from iCloud)
NOTE: the photos.db database uses an asynchrounous write-ahead log so changes in Photos
@@ -210,10 +218,12 @@ class PhotoInfo:
"""
return True if self._info["isMissing"] == 1 else False
@property
def hasadjustments(self):
""" True if picture has adjustments / edits """
return True if self._info["hasAdjustments"] == 1 else False
@property
def external_edit(self):
""" Returns True if picture was edited outside of Photos using external editor """
return (
@@ -222,17 +232,20 @@ class PhotoInfo:
else False
)
@property
def favorite(self):
""" True if picture is marked as favorite """
return True if self._info["favorite"] == 1 else False
@property
def hidden(self):
""" True if picture is hidden """
return True if self._info["hidden"] == 1 else False
@property
def location(self):
""" returns (latitude, longitude) as float in degrees or None """
return (self._latitude(), self._longitude())
return (self._latitude, self._longitude)
def export(
self,
@@ -278,43 +291,43 @@ class PhotoInfo:
# need to use file extension from edited file as Photos saves a jpeg once edited
if edited:
# verify we have a valid path_edited and use that to get filename
if not self.path_edited():
if not self.path_edited:
raise FileNotFoundError(
f"edited=True but path_edited is none; hasadjustments: {self.hasadjustments()}"
f"edited=True but path_edited is none; hasadjustments: {self.hasadjustments}"
)
edited_name = Path(self.path_edited()).name
edited_name = Path(self.path_edited).name
edited_suffix = Path(edited_name).suffix
filename = Path(self.filename()).stem + "_edited" + edited_suffix
filename = Path(self.filename).stem + "_edited" + edited_suffix
else:
filename = self.filename()
filename = self.filename
# get path to source file and verify it's not None and is valid file
# TODO: how to handle ismissing or not hasadjustments and edited=True cases?
if edited:
if not self.hasadjustments():
if not self.hasadjustments:
logging.warning(
"Attempting to export edited photo but hasadjustments=False"
)
if self.path_edited() is not None:
src = self.path_edited()
if self.path_edited is not None:
src = self.path_edited
else:
raise FileNotFoundError(
f"edited=True but path_edited is none; hasadjustments: {self.hasadjustments()}"
f"edited=True but path_edited is none; hasadjustments: {self.hasadjustments}"
)
else:
if self.ismissing():
if self.ismissing:
logging.warning(
f"Attempting to export photo with ismissing=True: path = {self.path()}"
f"Attempting to export photo with ismissing=True: path = {self.path}"
)
if self.path() is None:
if self.path is None:
logging.warning(
f"Attempting to export photo but path is None: ismissing = {self.ismissing()}"
f"Attempting to export photo but path is None: ismissing = {self.ismissing}"
)
raise FileNotFoundError("Cannot export photo if path is None")
else:
src = self.path()
src = self.path
if not os.path.isfile(src):
raise FileNotFoundError(f"{src} does not appear to exist")
@@ -368,25 +381,25 @@ class PhotoInfo:
def _exiftool_json_sidecar(self):
""" return json string of EXIF details in exiftool sidecar format """
exif = {}
exif["FileName"] = self.filename()
exif["FileName"] = self.filename
if self.description():
exif["ImageDescription"] = self.description()
exif["Description"] = self.description()
if self.description:
exif["ImageDescription"] = self.description
exif["Description"] = self.description
if self.title():
exif["Title"] = self.title()
if self.title:
exif["Title"] = self.title
if self.keywords():
exif["TagsList"] = exif["Keywords"] = self.keywords()
if self.keywords:
exif["TagsList"] = exif["Keywords"] = self.keywords
if self.persons():
exif["PersonInImage"] = self.persons()
if self.persons:
exif["PersonInImage"] = self.persons
# if self.favorite():
# exif["Rating"] = 5
(lat, lon) = self.location()
(lat, lon) = self.location
if lat is not None and lon is not None:
lat_str, lon_str = dd_to_dms_str(lat, lon)
exif["GPSLatitude"] = lat_str
@@ -398,7 +411,7 @@ class PhotoInfo:
exif["GPSLongitudeRef"] = lon_ref
# process date/time and timezone offset
date = self.date()
date = self.date
# exiftool expects format to "2015:01:18 12:00:00"
datetimeoriginal = date.strftime("%Y:%m:%d %H:%M:%S")
offsettime = date.strftime("%z")
@@ -425,10 +438,12 @@ class PhotoInfo:
f.write(json_str)
f.close()
@property
def _longitude(self):
""" Returns longitude, in degrees """
return self._info["longitude"]
@property
def _latitude(self):
""" Returns latitude, in degrees """
return self._info["latitude"]
@@ -439,49 +454,49 @@ class PhotoInfo:
def __str__(self):
info = {
"uuid": self.uuid(),
"filename": self.filename(),
"original_filename": self.original_filename(),
"date": str(self.date()),
"description": self.description(),
"name": self.name(),
"keywords": self.keywords(),
"albums": self.albums(),
"persons": self.persons(),
"path": self.path(),
"ismissing": self.ismissing(),
"hasadjustments": self.hasadjustments(),
"external_edit": self.external_edit(),
"favorite": self.favorite(),
"hidden": self.hidden(),
"latitude": self._latitude(),
"longitude": self._longitude(),
"path_edited": self.path_edited(),
"uuid": self.uuid,
"filename": self.filename,
"original_filename": self.original_filename,
"date": str(self.date),
"description": self.description,
"name": self.name,
"keywords": self.keywords,
"albums": self.albums,
"persons": self.persons,
"path": self.path,
"ismissing": self.ismissing,
"hasadjustments": self.hasadjustments,
"external_edit": self.external_edit,
"favorite": self.favorite,
"hidden": self.hidden,
"latitude": self._latitude,
"longitude": self._longitude,
"path_edited": self.path_edited,
}
return yaml.dump(info, sort_keys=False)
def to_json(self):
def json(self):
""" return JSON representation """
# TODO: Add additional details here
pic = {
"uuid": self.uuid(),
"filename": self.filename(),
"original_filename": self.original_filename(),
"date": str(self.date()),
"description": self.description(),
"name": self.name(),
"keywords": self.keywords(),
"albums": self.albums(),
"persons": self.persons(),
"path": self.path(),
"ismissing": self.ismissing(),
"hasadjustments": self.hasadjustments(),
"external_edit": self.external_edit(),
"favorite": self.favorite(),
"hidden": self.hidden(),
"latitude": self._latitude(),
"longitude": self._longitude(),
"path_edited": self.path_edited(),
"uuid": self.uuid,
"filename": self.filename,
"original_filename": self.original_filename,
"date": str(self.date),
"description": self.description,
"title": self.title,
"keywords": self.keywords,
"albums": self.albums,
"persons": self.persons,
"path": self.path,
"ismissing": self.ismissing,
"hasadjustments": self.hasadjustments,
"external_edit": self.external_edit,
"favorite": self.favorite,
"hidden": self.hidden,
"latitude": self._latitude,
"longitude": self._longitude,
"path_edited": self.path_edited,
}
return json.dumps(pic)

View File

@@ -116,20 +116,20 @@ def test_attributes():
photos = photosdb.photos(uuid=["sE5LlfekS8ykEE7o0cuMVA"])
assert len(photos) == 1
p = photos[0]
assert p.keywords() == ["Kids"]
assert p.original_filename() == "Pumkins2.jpg"
assert p.filename() == "Pumkins2.jpg"
assert p.date() == datetime.datetime(
assert p.keywords == ["Kids"]
assert p.original_filename == "Pumkins2.jpg"
assert p.filename == "Pumkins2.jpg"
assert p.date == datetime.datetime(
2018, 9, 28, 16, 7, 7, 0, datetime.timezone(datetime.timedelta(seconds=-14400))
)
assert p.description() == "Girl holding pumpkin"
assert p.name() == "I found one!"
assert p.albums() == ["Pumpkin Farm"]
assert p.persons() == ["Katie"]
assert p.path().endswith(
assert p.description == "Girl holding pumpkin"
assert p.title == "I found one!"
assert p.albums == ["Pumpkin Farm"]
assert p.persons == ["Katie"]
assert p.path.endswith(
"/tests/Test-10.12.6.photoslibrary/Masters/2019/08/24/20190824-030824/Pumkins2.jpg"
)
assert p.ismissing() == False
assert p.ismissing == False
def test_missing():
@@ -139,8 +139,8 @@ def test_missing():
photos = photosdb.photos(uuid=["Pj99JmYjQkeezdY2OFuSaw"])
assert len(photos) == 1
p = photos[0]
assert p.path() == None
assert p.ismissing() == True
assert p.path == None
assert p.ismissing == True
def test_count():
@@ -169,4 +169,4 @@ def test_keyword_not_in_album():
photos2 = photosdb.photos(keywords=["Kids"])
photos3 = [p for p in photos2 if p not in photos1]
assert len(photos3) == 1
assert photos3[0].uuid() == "Pj99JmYjQkeezdY2OFuSaw"
assert photos3[0].uuid == "Pj99JmYjQkeezdY2OFuSaw"

View File

@@ -193,20 +193,20 @@ def test_attributes():
photos = photosdb.photos(uuid=["D79B8D77-BFFC-460B-9312-034F2877D35B"])
assert len(photos) == 1
p = photos[0]
assert p.keywords() == ["Kids"]
assert p.original_filename() == "Pumkins2.jpg"
assert p.filename() == "D79B8D77-BFFC-460B-9312-034F2877D35B.jpeg"
assert p.date() == datetime.datetime(
assert p.keywords == ["Kids"]
assert p.original_filename == "Pumkins2.jpg"
assert p.filename == "D79B8D77-BFFC-460B-9312-034F2877D35B.jpeg"
assert p.date == datetime.datetime(
2018, 9, 28, 16, 7, 7, 0, datetime.timezone(datetime.timedelta(seconds=-14400))
)
assert p.description() == "Girl holding pumpkin"
assert p.name() == "I found one!"
assert p.albums() == ["Pumpkin Farm", "Test Album"]
assert p.persons() == ["Katie"]
assert p.path().endswith(
assert p.description == "Girl holding pumpkin"
assert p.title == "I found one!"
assert p.albums == ["Pumpkin Farm", "Test Album"]
assert p.persons == ["Katie"]
assert p.path.endswith(
"tests/Test-10.15.1.photoslibrary/originals/D/D79B8D77-BFFC-460B-9312-034F2877D35B.jpeg"
)
assert p.ismissing() == False
assert p.ismissing == False
def test_missing():
@@ -216,8 +216,8 @@ def test_missing():
photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
assert len(photos) == 1
p = photos[0]
assert p.path() == None
assert p.ismissing() == True
assert p.path == None
assert p.ismissing == True
def test_favorite():
@@ -227,7 +227,7 @@ def test_favorite():
photos = photosdb.photos(uuid=[UUID_DICT["favorite"]])
assert len(photos) == 1
p = photos[0]
assert p.favorite() == True
assert p.favorite == True
def test_not_favorite():
@@ -237,7 +237,7 @@ def test_not_favorite():
photos = photosdb.photos(uuid=[UUID_DICT["not_favorite"]])
assert len(photos) == 1
p = photos[0]
assert p.favorite() == False
assert p.favorite == False
def test_hidden():
@@ -247,7 +247,7 @@ def test_hidden():
photos = photosdb.photos(uuid=[UUID_DICT["hidden"]])
assert len(photos) == 1
p = photos[0]
assert p.hidden() == True
assert p.hidden == True
def test_not_hidden():
@@ -257,7 +257,7 @@ def test_not_hidden():
photos = photosdb.photos(uuid=[UUID_DICT["not_hidden"]])
assert len(photos) == 1
p = photos[0]
assert p.hidden() == False
assert p.hidden == False
def test_location_1():
@@ -268,7 +268,7 @@ def test_location_1():
photos = photosdb.photos(uuid=[UUID_DICT["location"]])
assert len(photos) == 1
p = photos[0]
lat, lon = p.location()
lat, lon = p.location
assert lat == pytest.approx(51.50357167)
assert lon == pytest.approx(-0.1318055)
@@ -281,7 +281,7 @@ def test_location_2():
photos = photosdb.photos(uuid=[UUID_DICT["no_location"]])
assert len(photos) == 1
p = photos[0]
lat, lon = p.location()
lat, lon = p.location
assert lat is None
assert lon is None
@@ -294,7 +294,7 @@ def test_hasadjustments1():
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
assert len(photos) == 1
p = photos[0]
assert p.hasadjustments() == True
assert p.hasadjustments == True
def test_hasadjustments2():
@@ -305,7 +305,7 @@ def test_hasadjustments2():
photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]])
assert len(photos) == 1
p = photos[0]
assert p.hasadjustments() == False
assert p.hasadjustments == False
def test_external_edit1():
@@ -317,7 +317,7 @@ def test_external_edit1():
assert len(photos) == 1
p = photos[0]
assert p.external_edit() == True
assert p.external_edit == True
def test_external_edit2():
@@ -329,7 +329,7 @@ def test_external_edit2():
assert len(photos) == 1
p = photos[0]
assert p.external_edit() == False
assert p.external_edit == False
def test_path_edited1():
@@ -340,7 +340,7 @@ def test_path_edited1():
photos = photosdb.photos(uuid=["E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51"])
assert len(photos) == 1
p = photos[0]
path = p.path_edited()
path = p.path_edited
assert path.endswith(
"resources/renders/E/E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51_1_201_a.jpeg"
)
@@ -354,7 +354,7 @@ def test_path_edited2():
photos = photosdb.photos(uuid=["6191423D-8DB8-4D4C-92BE-9BBBA308AAC4"])
assert len(photos) == 1
p = photos[0]
path = p.path_edited()
path = p.path_edited
assert path is None
@@ -384,7 +384,7 @@ def test_keyword_not_in_album():
photos2 = photosdb.photos(keywords=["Kids"])
photos3 = [p for p in photos2 if p not in photos1]
assert len(photos3) == 1
assert photos3[0].uuid() == "A1DD1F98-2ECD-431F-9AC9-5AFEFE2D3A5C"
assert photos3[0].uuid == "A1DD1F98-2ECD-431F-9AC9-5AFEFE2D3A5C"
def test_get_db_path():
@@ -416,7 +416,7 @@ def test_export_1():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)
@@ -465,7 +465,7 @@ def test_export_3():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename()
filename = photos[0].filename
filename2 = pathlib.Path(filename)
filename2 = f"{filename2.stem} (1){filename2.suffix}"
expected_dest = os.path.join(dest, filename)
@@ -526,7 +526,7 @@ def test_export_5():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)
@@ -583,7 +583,7 @@ def test_export_7():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)
@@ -609,7 +609,7 @@ def test_export_8():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
with pytest.raises(Exception) as e:
@@ -630,7 +630,7 @@ def test_export_9():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
with pytest.raises(Exception) as e:
@@ -698,9 +698,9 @@ def test_export_12():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
edited_name = pathlib.Path(photos[0].path_edited()).name
edited_name = pathlib.Path(photos[0].path_edited).name
edited_suffix = pathlib.Path(edited_name).suffix
filename = pathlib.Path(photos[0].filename()).stem + "_edited" + edited_suffix
filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, edited=True)
@@ -730,7 +730,7 @@ def test_export_13():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
with pytest.raises(Exception) as e:

View File

@@ -72,7 +72,7 @@ def test_export_1():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)
@@ -121,7 +121,7 @@ def test_export_3():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename()
filename = photos[0].filename
filename2 = pathlib.Path(filename)
filename2 = f"{filename2.stem} (1){filename2.suffix}"
expected_dest = os.path.join(dest, filename)
@@ -182,7 +182,7 @@ def test_export_5():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)
@@ -239,7 +239,7 @@ def test_export_7():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)
@@ -265,7 +265,7 @@ def test_export_8():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
with pytest.raises(Exception) as e:
@@ -286,7 +286,7 @@ def test_export_9():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
with pytest.raises(Exception) as e:
@@ -354,9 +354,9 @@ def test_export_12():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
edited_name = pathlib.Path(photos[0].path_edited()).name
edited_name = pathlib.Path(photos[0].path_edited).name
edited_suffix = pathlib.Path(edited_name).suffix
filename = pathlib.Path(photos[0].filename()).stem + "_edited" + edited_suffix
filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, edited=True)
@@ -386,7 +386,7 @@ def test_export_13():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
with pytest.raises(Exception) as e:

View File

@@ -58,7 +58,7 @@ def test_export_1():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)
@@ -107,7 +107,7 @@ def test_export_3():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename()
filename = photos[0].filename
filename2 = pathlib.Path(filename)
filename2 = f"{filename2.stem} (1){filename2.suffix}"
expected_dest = os.path.join(dest, filename)
@@ -168,7 +168,7 @@ def test_export_5():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)
@@ -225,7 +225,7 @@ def test_export_7():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest)
@@ -251,7 +251,7 @@ def test_export_8():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["missing"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
with pytest.raises(Exception) as e:
@@ -272,7 +272,7 @@ def test_export_9():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
with pytest.raises(Exception) as e:
@@ -340,9 +340,9 @@ def test_export_12():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
edited_name = pathlib.Path(photos[0].path_edited()).name
edited_name = pathlib.Path(photos[0].path_edited).name
edited_suffix = pathlib.Path(edited_name).suffix
filename = pathlib.Path(photos[0].filename()).stem + "_edited" + edited_suffix
filename = pathlib.Path(photos[0].filename).stem + "_edited" + edited_suffix
expected_dest = os.path.join(dest, filename)
got_dest = photos[0].export(dest, edited=True)
@@ -372,7 +372,7 @@ def test_export_13():
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=[UUID_DICT["export"]])
filename = photos[0].filename()
filename = photos[0].filename
expected_dest = os.path.join(dest, filename)
with pytest.raises(Exception) as e:

View File

@@ -115,20 +115,20 @@ def test_attributes():
photos = photosdb.photos(uuid=["RWmFYiDjSyKjeK8Pfna0Eg"])
assert len(photos) == 1
p = photos[0]
assert p.keywords() == ["Kids"]
assert p.original_filename() == "Pumkins2.jpg"
assert p.filename() == "Pumkins2.jpg"
assert p.date() == datetime.datetime(
assert p.keywords == ["Kids"]
assert p.original_filename == "Pumkins2.jpg"
assert p.filename == "Pumkins2.jpg"
assert p.date == datetime.datetime(
2018, 9, 28, 16, 7, 7, 0, datetime.timezone(datetime.timedelta(seconds=-14400))
)
assert p.description() == "Girl holding pumpkin"
assert p.name() == "I found one!"
assert p.albums() == ["Pumpkin Farm"]
assert p.persons() == ["Katie"]
assert p.path().endswith(
assert p.description == "Girl holding pumpkin"
assert p.title == "I found one!"
assert p.albums == ["Pumpkin Farm"]
assert p.persons == ["Katie"]
assert p.path.endswith(
"/tests/Test-10.13.6.photoslibrary/Masters/2019/07/26/20190726-203227/Pumkins2.jpg"
)
assert p.ismissing() == False
assert p.ismissing == False
def test_missing():
@@ -138,8 +138,8 @@ def test_missing():
photos = photosdb.photos(uuid=["6iAZJP7ZQ5iXxapoJb3ytA"])
assert len(photos) == 1
p = photos[0]
assert p.path() == None
assert p.ismissing() == True
assert p.path == None
assert p.ismissing == True
def test_count():
@@ -168,4 +168,4 @@ def test_keyword_not_in_album():
photos2 = photosdb.photos(keywords=["Kids"])
photos3 = [p for p in photos2 if p not in photos1]
assert len(photos3) == 1
assert photos3[0].uuid() == "6iAZJP7ZQ5iXxapoJb3ytA"
assert photos3[0].uuid == "6iAZJP7ZQ5iXxapoJb3ytA"

View File

@@ -115,20 +115,20 @@ def test_attributes():
photos = photosdb.photos(uuid=["15uNd7%8RguTEgNPKHfTWw"])
assert len(photos) == 1
p = photos[0]
assert p.keywords() == ["Kids"]
assert p.original_filename() == "Pumkins2.jpg"
assert p.filename() == "Pumkins2.jpg"
assert p.date() == datetime.datetime(
assert p.keywords == ["Kids"]
assert p.original_filename == "Pumkins2.jpg"
assert p.filename == "Pumkins2.jpg"
assert p.date == datetime.datetime(
2018, 9, 28, 16, 7, 7, 0, datetime.timezone(datetime.timedelta(seconds=-14400))
)
assert p.description() == "Girl holding pumpkin"
assert p.name() == "I found one!"
assert p.albums() == ["Pumpkin Farm"]
assert p.persons() == ["Katie"]
assert p.path().endswith(
assert p.description == "Girl holding pumpkin"
assert p.title == "I found one!"
assert p.albums == ["Pumpkin Farm"]
assert p.persons == ["Katie"]
assert p.path.endswith(
"/tests/Test-10.14.5.photoslibrary/Masters/2019/07/27/20190727-131650/Pumkins2.jpg"
)
assert p.ismissing() == False
assert p.ismissing == False
def test_missing():
@@ -138,8 +138,8 @@ def test_missing():
photos = photosdb.photos(uuid=["od0fmC7NQx+ayVr+%i06XA"])
assert len(photos) == 1
p = photos[0]
assert p.path() == None
assert p.ismissing() == True
assert p.path == None
assert p.ismissing == True
def test_count():
@@ -168,4 +168,4 @@ def test_keyword_not_in_album():
photos2 = photosdb.photos(keywords=["Kids"])
photos3 = [p for p in photos2 if p not in photos1]
assert len(photos3) == 1
assert photos3[0].uuid() == "od0fmC7NQx+ayVr+%i06XA"
assert photos3[0].uuid == "od0fmC7NQx+ayVr+%i06XA"

View File

@@ -118,20 +118,20 @@ def test_attributes():
photos = photosdb.photos(uuid=["15uNd7%8RguTEgNPKHfTWw"])
assert len(photos) == 1
p = photos[0]
assert p.keywords() == ["Kids"]
assert p.original_filename() == "Pumkins2.jpg"
assert p.filename() == "Pumkins2.jpg"
assert p.date() == datetime.datetime(
assert p.keywords == ["Kids"]
assert p.original_filename == "Pumkins2.jpg"
assert p.filename == "Pumkins2.jpg"
assert p.date == datetime.datetime(
2018, 9, 28, 16, 7, 7, 0, datetime.timezone(datetime.timedelta(seconds=-14400))
)
assert p.description() == "Girl holding pumpkin"
assert p.name() == "I found one!"
assert p.albums() == ["Pumpkin Farm", "Test Album (1)"]
assert p.persons() == ["Katie"]
assert p.path().endswith(
assert p.description == "Girl holding pumpkin"
assert p.title == "I found one!"
assert p.albums == ["Pumpkin Farm", "Test Album (1)"]
assert p.persons == ["Katie"]
assert p.path.endswith(
"/tests/Test-10.14.6.photoslibrary/Masters/2019/07/27/20190727-131650/Pumkins2.jpg"
)
assert p.ismissing() == False
assert p.ismissing == False
def test_missing():
@@ -141,8 +141,8 @@ def test_missing():
photos = photosdb.photos(uuid=["od0fmC7NQx+ayVr+%i06XA"])
assert len(photos) == 1
p = photos[0]
assert p.path() == None
assert p.ismissing() == True
assert p.path == None
assert p.ismissing == True
def test_favorite():
@@ -152,7 +152,7 @@ def test_favorite():
photos = photosdb.photos(uuid=["6bxcNnzRQKGnK4uPrCJ9UQ"])
assert len(photos) == 1
p = photos[0]
assert p.favorite() == True
assert p.favorite == True
def test_not_favorite():
@@ -162,7 +162,7 @@ def test_not_favorite():
photos = photosdb.photos(uuid=["od0fmC7NQx+ayVr+%i06XA"])
assert len(photos) == 1
p = photos[0]
assert p.favorite() == False
assert p.favorite == False
def test_hidden():
@@ -172,7 +172,7 @@ def test_hidden():
photos = photosdb.photos(uuid=["od0fmC7NQx+ayVr+%i06XA"])
assert len(photos) == 1
p = photos[0]
assert p.hidden() == True
assert p.hidden == True
def test_not_hidden():
@@ -182,7 +182,7 @@ def test_not_hidden():
photos = photosdb.photos(uuid=["6bxcNnzRQKGnK4uPrCJ9UQ"])
assert len(photos) == 1
p = photos[0]
assert p.hidden() == False
assert p.hidden == False
def test_location_1():
@@ -193,7 +193,7 @@ def test_location_1():
photos = photosdb.photos(uuid=["3Jn73XpSQQCluzRBMWRsMA"])
assert len(photos) == 1
p = photos[0]
lat, lon = p.location()
lat, lon = p.location
assert lat == pytest.approx(51.50357167)
assert lon == pytest.approx(-0.1318055)
@@ -206,7 +206,7 @@ def test_location_2():
photos = photosdb.photos(uuid=["YZFCPY24TUySvpu7owiqxA"])
assert len(photos) == 1
p = photos[0]
lat, lon = p.location()
lat, lon = p.location
assert lat is None
assert lon is None
@@ -219,7 +219,7 @@ def test_hasadjustments1():
photos = photosdb.photos(uuid=["6bxcNnzRQKGnK4uPrCJ9UQ"])
assert len(photos) == 1
p = photos[0]
assert p.hasadjustments() == True
assert p.hasadjustments == True
def test_hasadjustments2():
@@ -230,7 +230,7 @@ def test_hasadjustments2():
photos = photosdb.photos(uuid=["15uNd7%8RguTEgNPKHfTWw"])
assert len(photos) == 1
p = photos[0]
assert p.hasadjustments() == False
assert p.hasadjustments == False
def test_external_edit1():
@@ -242,7 +242,7 @@ def test_external_edit1():
assert len(photos) == 1
p = photos[0]
assert p.external_edit() == True
assert p.external_edit == True
def test_external_edit2():
@@ -254,7 +254,7 @@ def test_external_edit2():
assert len(photos) == 1
p = photos[0]
assert p.external_edit() == False
assert p.external_edit == False
def test_path_edited1():
@@ -265,7 +265,7 @@ def test_path_edited1():
photos = photosdb.photos(uuid=["6bxcNnzRQKGnK4uPrCJ9UQ"])
assert len(photos) == 1
p = photos[0]
path = p.path_edited()
path = p.path_edited
assert path.endswith("resources/media/version/00/00/fullsizeoutput_9.jpeg")
@@ -277,7 +277,7 @@ def test_path_edited2():
photos = photosdb.photos(uuid=["15uNd7%8RguTEgNPKHfTWw"])
assert len(photos) == 1
p = photos[0]
path = p.path_edited()
path = p.path_edited
assert path is None
@@ -307,7 +307,7 @@ def test_keyword_not_in_album():
photos2 = photosdb.photos(keywords=["Kids"])
photos3 = [p for p in photos2 if p not in photos1]
assert len(photos3) == 1
assert photos3[0].uuid() == "od0fmC7NQx+ayVr+%i06XA"
assert photos3[0].uuid == "od0fmC7NQx+ayVr+%i06XA"
def test_get_db_path():