diff --git a/README.md b/README.md index 70708301..d74d8c27 100644 --- a/README.md +++ b/README.md @@ -269,6 +269,9 @@ Options: --no-comment Search for photos with no comments. --has-likes Search for photos that have likes. --no-likes Search for photos with no likes. + --is-reference Search for photos that were imported as + referenced files (not copied into Photos + library). --missing Export only photos missing from the Photos library; must be used with --download-missing. --deleted Include photos from the 'Recently Deleted' @@ -1601,6 +1604,9 @@ Returns list of [LikeInfo](#likeinfo) objects for likes on shared photos or empt **Note**: *Only valid on Photos 5 / MacOS 10.15+; on Photos <= 4, returns empty list. +#### `isreference` +Returns `True` if the original image file is a referenced file (imported without copying to the Photos library) otherwise returns `False`. + #### `isphoto` Returns True if type is photo/still image, otherwise False diff --git a/osxphotos/__main__.py b/osxphotos/__main__.py index 7aaf94f7..13deaae3 100644 --- a/osxphotos/__main__.py +++ b/osxphotos/__main__.py @@ -674,6 +674,11 @@ def query_options(f): o("--no-comment", is_flag=True, help="Search for photos with no comments."), o("--has-likes", is_flag=True, help="Search for photos that have likes."), o("--no-likes", is_flag=True, help="Search for photos with no likes."), + o( + "--is-reference", + is_flag=True, + help="Search for photos that were imported as referenced files (not copied into Photos library).", + ), ] for o in options[::-1]: f = o(f) @@ -1166,6 +1171,7 @@ def export( exportdb, load_config, save_config, + is_reference, ): """Export photos from the Photos database. Export path DEST is required. @@ -1590,6 +1596,7 @@ def export( no_comment=no_comment, has_likes=has_likes, no_likes=no_likes, + is_reference=is_reference, ) if photos: @@ -1865,6 +1872,7 @@ def query( no_comment, has_likes, no_likes, + is_reference, ): """Query the Photos database using 1 or more search options; if more than one option is provided, they are treated as "AND" @@ -1887,6 +1895,7 @@ def query( from_date, to_date, label, + is_reference, ] exclusive = [ (favorite, not_favorite), @@ -2002,6 +2011,7 @@ def query( no_comment=no_comment, has_likes=has_likes, no_likes=no_likes, + is_reference=is_reference, ) # below needed for to make CliRunner work for testing @@ -2172,6 +2182,7 @@ def _query( no_comment=False, has_likes=False, no_likes=False, + is_reference=False, ): """Run a query against PhotosDB to extract the photos based on user supply criteria used by query and export commands @@ -2316,9 +2327,9 @@ def _query( photos = [p for p in photos if not p.hidden] if missing: - photos = [p for p in photos if p.ismissing] + photos = [p for p in photos if not p.path] elif not_missing: - photos = [p for p in photos if not p.ismissing] + photos = [p for p in photos if p.path] if shared: photos = [p for p in photos if p.shared] @@ -2401,6 +2412,9 @@ def _query( elif no_likes: photos = [p for p in photos if not p.likes] + if is_reference: + photos = [p for p in photos if p.isreference] + return photos @@ -3760,5 +3774,6 @@ SOFTWARE. click.echo(f"Source code available at: {OSXPHOTOS_URL}") click.echo(license) + if __name__ == "__main__": cli() # pylint: disable=no-value-for-parameter diff --git a/osxphotos/photoinfo/photoinfo.py b/osxphotos/photoinfo/photoinfo.py index a65a0cf8..54a000a6 100644 --- a/osxphotos/photoinfo/photoinfo.py +++ b/osxphotos/photoinfo/photoinfo.py @@ -138,6 +138,7 @@ class PhotoInfo: except AttributeError: self._path = None photopath = None + # TODO: should path try to return path even if ismissing? if self._info["isMissing"] == 1: return photopath # path would be meaningless until downloaded @@ -643,6 +644,11 @@ class PhotoInfo: else: return True if self._info["cloudAssetGUID"] is not None else False + @property + def isreference(self): + """ Returns True if photo is a reference (not copied to the Photos library), otherwise False """ + return self._info["isreference"] + @property def burst(self): """ Returns True if photo is part of a Burst photo set, otherwise False """ @@ -1033,6 +1039,7 @@ class PhotoInfo: "path_live_photo": self.path_live_photo, "iscloudasset": self.iscloudasset, "incloud": self.incloud, + "isreference": self.isreference, "date_modified": self.date_modified, "portrait": self.portrait, "screenshot": self.screenshot, diff --git a/osxphotos/photosdb/photosdb.py b/osxphotos/photosdb/photosdb.py index f2f3ac4b..719b2ec7 100644 --- a/osxphotos/photosdb/photosdb.py +++ b/osxphotos/photosdb/photosdb.py @@ -889,7 +889,8 @@ class PhotosDB: RKMaster.fileSize, RKVersion.subType, RKVersion.inTrashDate, - RKVersion.showInLibrary + RKVersion.showInLibrary, + RKMaster.fileIsReference FROM RKVersion, RKMaster WHERE RKVersion.masterUuid = RKMaster.uuid""" ) @@ -919,8 +920,9 @@ class PhotosDB: RKMaster.originalFileSize, RKVersion.subType, RKVersion.inTrashDate, - RKVersion.showInLibrary - FROM RKVersion, RKMaster + RKVersion.showInLibrary, + RKMaster.fileIsReference + FROM RKVersion, RKMaster WHERE RKVersion.masterUuid = RKMaster.uuid""" ) @@ -968,6 +970,7 @@ class PhotosDB: # 40 RKVersion.subType # 41 RKVersion.inTrashDate # 42 RKVersion.showInLibrary -- is item visible in library (e.g. non-selected burst images are not visible) + # 43 RKMaster.fileIsReference -- file is reference (imported without copying to Photos library) for row in c: uuid = row[0] @@ -1164,6 +1167,10 @@ class PhotosDB: self._dbphotos[uuid]["visibility_state"] = row[42] self._dbphotos[uuid]["visible"] = row[42] == 1 + # file is reference (not copied into Photos library) + self._dbphotos[uuid]["isreference"] = row[43] == 1 + self._dbphotos[uuid]["saved_asset_type"] = None # Photos 5+ + # import session not yet handled for Photos 4 self._dbphotos[uuid]["import_session"] = None self._dbphotos[uuid]["import_uuid"] = None @@ -1859,7 +1866,8 @@ class PhotosDB: {depth_state}, {asset_table}.ZADJUSTMENTTIMESTAMP, {asset_table}.ZVISIBILITYSTATE, - {asset_table}.ZTRASHEDDATE + {asset_table}.ZTRASHEDDATE, + {asset_table}.ZSAVEDASSETTYPE FROM {asset_table} JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = {asset_table}.Z_PK ORDER BY {asset_table}.ZUUID """ @@ -1906,6 +1914,7 @@ class PhotosDB: # 37 ZGENERICASSET.ZADJUSTMENTTIMESTAMP -- when was photo edited? # 38 ZGENERICASSET.ZVISIBILITYSTATE -- 0 if visible, 2 if not (e.g. a burst image) # 39 ZGENERICASSET.ZTRASHEDDATE -- date item placed in the trash or null if not in trash + # 40 ZGENERICASSET.ZSAVEDASSETTYPE -- how item imported for row in c: uuid = row[0] @@ -2085,6 +2094,14 @@ class PhotosDB: info["visibility_state"] = row[38] info["visible"] = row[38] == 0 + # ZSAVEDASSETTYPE Values: + # 3: imported by copying to Photos library + # 4: shared iCloud photo + # 6: imported by iCloud (e.g. from iPhone) + # 10: referenced file (not copied to Photos library) + info["saved_asset_type"] = row[40] + info["isreference"] = row[40] == 10 + # initialize import session info which will be filled in later # not every photo has an import session so initialize all records now info["import_session"] = None diff --git a/tests/search_info_test_data_10_15_7.json b/tests/search_info_test_data_10_15_7.json index 6e6b58dc..6648d2a5 100644 --- a/tests/search_info_test_data_10_15_7.json +++ b/tests/search_info_test_data_10_15_7.json @@ -1 +1 @@ -{"UUID_SEARCH_INFO": {"C8EAF50A-D891-4E0C-8086-C417E1284153": {"labels": ["Food", "Butter"], "place_names": ["Durham Bulls Athletic Park"], "streets": ["Blackwell St"], "neighborhoods": ["American Tobacco District", "Downtown Durham"], "city": "Durham", "locality_names": ["Durham"], "state": "North Carolina", "state_abbreviation": "NC", "country": "United States", "bodies_of_water": [], "month": "October", "year": "2018", "holidays": [], "activities": ["Dinner", "Travel", "Entertainment", "Dining", "Trip"], "season": "Fall", "venues": ["Copa", "Pie Pusher's", "The Pinhook", "Luna Rotisserie and Empanadas"], "venue_types": ["Cocktail Bar", "Nightlife", "Pizza", "Restaurant", "Bar", "Tapas & Small Plates", "Food", "Empanadas", "Chicken Wings", "Arts & Entertainment", "Latin American", "Cuban", "Music Venue"], "media_types": []}, "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": {"labels": ["Desert", "Land", "Sky", "Sunset Sunrise", "Outdoor"], "place_names": ["Royal Palms State Beach"], "streets": [], "neighborhoods": ["San Pedro"], "city": "Los Angeles", "locality_names": [], "state": "California", "state_abbreviation": "", "country": "United States", "bodies_of_water": ["Catalina Channel"], "month": "November", "year": "2017", "holidays": [], "activities": ["Beach Activity", "Activity"], "season": "Fall", "venues": [], "venue_types": [], "media_types": ["Live Photos"]}, "2C151013-5BBA-4D00-B70F-1C9420418B86": {"labels": ["People", "Forest", "Land", "Furniture", "Bench", "Plant", "Outdoor", "Vegetation", "Water", "Water Body"], "place_names": [], "streets": [], "neighborhoods": [], "city": "", "locality_names": [], "state": "", "state_abbreviation": "", "country": "", "bodies_of_water": [], "month": "December", "year": "2014", "holidays": ["Christmas Day"], "activities": ["Celebration", "Holiday"], "season": "Winter", "venues": [], "venue_types": [], "media_types": []}}, "UUID_SEARCH_INFO_NORMALIZED": {"C8EAF50A-D891-4E0C-8086-C417E1284153": {"labels": ["food", "butter"], "place_names": ["durham bulls athletic park"], "streets": ["blackwell st"], "neighborhoods": ["american tobacco district", "downtown durham"], "city": "durham", "locality_names": ["durham"], "state": "north carolina", "state_abbreviation": "nc", "country": "united states", "bodies_of_water": [], "month": "october", "year": "2018", "holidays": [], "activities": ["dinner", "travel", "entertainment", "dining", "trip"], "season": "fall", "venues": ["copa", "pie pusher's", "the pinhook", "luna rotisserie and empanadas"], "venue_types": ["cocktail bar", "nightlife", "pizza", "restaurant", "bar", "tapas & small plates", "food", "empanadas", "chicken wings", "arts & entertainment", "latin american", "cuban", "music venue"], "media_types": []}, "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": {"labels": ["desert", "land", "sky", "sunset sunrise", "outdoor"], "place_names": ["royal palms state beach"], "streets": [], "neighborhoods": ["san pedro"], "city": "los angeles", "locality_names": [], "state": "california", "state_abbreviation": "", "country": "united states", "bodies_of_water": ["catalina channel"], "month": "november", "year": "2017", "holidays": [], "activities": ["beach activity", "activity"], "season": "fall", "venues": [], "venue_types": [], "media_types": ["live photos"]}, "2C151013-5BBA-4D00-B70F-1C9420418B86": {"labels": ["people", "forest", "land", "furniture", "bench", "plant", "outdoor", "vegetation", "water", "water body"], "place_names": [], "streets": [], "neighborhoods": [], "city": "", "locality_names": [], "state": "", "state_abbreviation": "", "country": "", "bodies_of_water": [], "month": "december", "year": "2014", "holidays": ["christmas day"], "activities": ["celebration", "holiday"], "season": "winter", "venues": [], "venue_types": [], "media_types": []}}, "UUID_SEARCH_INFO_ALL": {"C8EAF50A-D891-4E0C-8086-C417E1284153": ["Food", "Butter", "Durham Bulls Athletic Park", "Blackwell St", "American Tobacco District", "Downtown Durham", "Durham", "Dinner", "Travel", "Entertainment", "Dining", "Trip", "Copa", "Pie Pusher's", "The Pinhook", "Luna Rotisserie and Empanadas", "Cocktail Bar", "Nightlife", "Pizza", "Restaurant", "Bar", "Tapas & Small Plates", "Food", "Empanadas", "Chicken Wings", "Arts & Entertainment", "Latin American", "Cuban", "Music Venue", "Durham", "North Carolina", "NC", "United States", "October", "2018", "Fall"], "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": ["Desert", "Land", "Sky", "Sunset Sunrise", "Outdoor", "Royal Palms State Beach", "San Pedro", "Catalina Channel", "Beach Activity", "Activity", "Live Photos", "Los Angeles", "California", "United States", "November", "2017", "Fall"], "2C151013-5BBA-4D00-B70F-1C9420418B86": ["People", "Forest", "Land", "Furniture", "Bench", "Plant", "Outdoor", "Vegetation", "Water", "Water Body", "Christmas Day", "Celebration", "Holiday", "December", "2014", "Winter"]}, "UUID_SEARCH_INFO_ALL_NORMALIZED": {"C8EAF50A-D891-4E0C-8086-C417E1284153": ["food", "butter", "durham bulls athletic park", "blackwell st", "american tobacco district", "downtown durham", "durham", "dinner", "travel", "entertainment", "dining", "trip", "copa", "pie pusher's", "the pinhook", "luna rotisserie and empanadas", "cocktail bar", "nightlife", "pizza", "restaurant", "bar", "tapas & small plates", "food", "empanadas", "chicken wings", "arts & entertainment", "latin american", "cuban", "music venue", "durham", "north carolina", "nc", "united states", "october", "2018", "fall"], "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": ["desert", "land", "sky", "sunset sunrise", "outdoor", "royal palms state beach", "san pedro", "catalina channel", "beach activity", "activity", "live photos", "los angeles", "california", "united states", "november", "2017", "fall"], "2C151013-5BBA-4D00-B70F-1C9420418B86": ["people", "forest", "land", "furniture", "bench", "plant", "outdoor", "vegetation", "water", "water body", "christmas day", "celebration", "holiday", "december", "2014", "winter"]}} +{"UUID_SEARCH_INFO": {"C8EAF50A-D891-4E0C-8086-C417E1284153": {"labels": ["Butter", "Food"], "place_names": ["Durham Bulls Athletic Park"], "streets": ["Blackwell St"], "neighborhoods": ["American Tobacco District", "Downtown Durham"], "city": "Durham", "locality_names": ["Durham"], "state": "North Carolina", "state_abbreviation": "NC", "country": "United States", "bodies_of_water": [], "month": "October", "year": "2018", "holidays": [], "activities": ["Dinner", "Travel", "Entertainment", "Dining", "Trip"], "season": "Fall", "venues": ["Copa", "Pie Pusher's", "The Pinhook", "Luna Rotisserie and Empanadas"], "venue_types": ["Cocktail Bar", "Nightlife", "Pizza", "Restaurant", "Bar", "Tapas & Small Plates", "Food", "Empanadas", "Chicken Wings", "Arts & Entertainment", "Latin American", "Cuban", "Music Venue"], "media_types": []}, "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": {"labels": ["Sky", "Sunset Sunrise", "Outdoor", "Land", "Desert"], "place_names": ["Royal Palms State Beach"], "streets": [], "neighborhoods": ["San Pedro"], "city": "Los Angeles", "locality_names": [], "state": "California", "state_abbreviation": "", "country": "United States", "bodies_of_water": ["Catalina Channel"], "month": "November", "year": "2017", "holidays": [], "activities": ["Beach Activity", "Activity"], "season": "Fall", "venues": [], "venue_types": [], "media_types": ["Live Photos"]}, "2C151013-5BBA-4D00-B70F-1C9420418B86": {"labels": ["Bench", "People", "Land", "Vegetation", "Forest", "Outdoor", "Furniture", "Water", "Water Body"], "place_names": [], "streets": [], "neighborhoods": [], "city": "", "locality_names": [], "state": "", "state_abbreviation": "", "country": "", "bodies_of_water": [], "month": "December", "year": "2014", "holidays": ["Christmas Day"], "activities": ["Celebration", "Holiday"], "season": "Winter", "venues": [], "venue_types": [], "media_types": []}}, "UUID_SEARCH_INFO_NORMALIZED": {"C8EAF50A-D891-4E0C-8086-C417E1284153": {"labels": ["butter", "food"], "place_names": ["durham bulls athletic park"], "streets": ["blackwell st"], "neighborhoods": ["american tobacco district", "downtown durham"], "city": "durham", "locality_names": ["durham"], "state": "north carolina", "state_abbreviation": "nc", "country": "united states", "bodies_of_water": [], "month": "october", "year": "2018", "holidays": [], "activities": ["dinner", "travel", "entertainment", "dining", "trip"], "season": "fall", "venues": ["copa", "pie pusher's", "the pinhook", "luna rotisserie and empanadas"], "venue_types": ["cocktail bar", "nightlife", "pizza", "restaurant", "bar", "tapas & small plates", "food", "empanadas", "chicken wings", "arts & entertainment", "latin american", "cuban", "music venue"], "media_types": []}, "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": {"labels": ["sky", "sunset sunrise", "outdoor", "land", "desert"], "place_names": ["royal palms state beach"], "streets": [], "neighborhoods": ["san pedro"], "city": "los angeles", "locality_names": [], "state": "california", "state_abbreviation": "", "country": "united states", "bodies_of_water": ["catalina channel"], "month": "november", "year": "2017", "holidays": [], "activities": ["beach activity", "activity"], "season": "fall", "venues": [], "venue_types": [], "media_types": ["live photos"]}, "2C151013-5BBA-4D00-B70F-1C9420418B86": {"labels": ["bench", "people", "land", "vegetation", "forest", "outdoor", "furniture", "water", "water body"], "place_names": [], "streets": [], "neighborhoods": [], "city": "", "locality_names": [], "state": "", "state_abbreviation": "", "country": "", "bodies_of_water": [], "month": "december", "year": "2014", "holidays": ["christmas day"], "activities": ["celebration", "holiday"], "season": "winter", "venues": [], "venue_types": [], "media_types": []}}, "UUID_SEARCH_INFO_ALL": {"C8EAF50A-D891-4E0C-8086-C417E1284153": ["Butter", "Food", "Durham Bulls Athletic Park", "Blackwell St", "American Tobacco District", "Downtown Durham", "Durham", "Dinner", "Travel", "Entertainment", "Dining", "Trip", "Copa", "Pie Pusher's", "The Pinhook", "Luna Rotisserie and Empanadas", "Cocktail Bar", "Nightlife", "Pizza", "Restaurant", "Bar", "Tapas & Small Plates", "Food", "Empanadas", "Chicken Wings", "Arts & Entertainment", "Latin American", "Cuban", "Music Venue", "Durham", "North Carolina", "NC", "United States", "October", "2018", "Fall"], "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": ["Sky", "Sunset Sunrise", "Outdoor", "Land", "Desert", "Royal Palms State Beach", "San Pedro", "Catalina Channel", "Beach Activity", "Activity", "Live Photos", "Los Angeles", "California", "United States", "November", "2017", "Fall"], "2C151013-5BBA-4D00-B70F-1C9420418B86": ["Bench", "People", "Land", "Vegetation", "Forest", "Outdoor", "Furniture", "Water", "Water Body", "Christmas Day", "Celebration", "Holiday", "December", "2014", "Winter"]}, "UUID_SEARCH_INFO_ALL_NORMALIZED": {"C8EAF50A-D891-4E0C-8086-C417E1284153": ["butter", "food", "durham bulls athletic park", "blackwell st", "american tobacco district", "downtown durham", "durham", "dinner", "travel", "entertainment", "dining", "trip", "copa", "pie pusher's", "the pinhook", "luna rotisserie and empanadas", "cocktail bar", "nightlife", "pizza", "restaurant", "bar", "tapas & small plates", "food", "empanadas", "chicken wings", "arts & entertainment", "latin american", "cuban", "music venue", "durham", "north carolina", "nc", "united states", "october", "2018", "fall"], "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": ["sky", "sunset sunrise", "outdoor", "land", "desert", "royal palms state beach", "san pedro", "catalina channel", "beach activity", "activity", "live photos", "los angeles", "california", "united states", "november", "2017", "fall"], "2C151013-5BBA-4D00-B70F-1C9420418B86": ["bench", "people", "land", "vegetation", "forest", "outdoor", "furniture", "water", "water body", "christmas day", "celebration", "holiday", "december", "2014", "winter"]}} diff --git a/tests/test_bigsur_10_16_0_1.py b/tests/test_bigsur_10_16_0_1.py index a3a5dc65..42df52ae 100644 --- a/tests/test_bigsur_10_16_0_1.py +++ b/tests/test_bigsur_10_16_0_1.py @@ -1,9 +1,9 @@ -import pytest - from collections import namedtuple -from osxphotos._constants import _UNKNOWN_PERSON +import pytest +import osxphotos +from osxphotos._constants import _UNKNOWN_PERSON PHOTOS_DB = "tests/Test-10.16.0.1.photoslibrary/database/photos.db" PHOTOS_DB_PATH = "/Test-10.16.0.1.photoslibrary/database/photos.db" @@ -169,6 +169,15 @@ PATH_HEIC_EDITED = ( "resources/renders/7/7783E8E6-9CAC-40F3-BE22-81FB7051C266_1_201_a.heic" ) +# file is reference (not copied to library) +UUID_IS_REFERENCE = "A1DD1F98-2ECD-431F-9AC9-5AFEFE2D3A5C" +UUID_NOT_REFERENCE = "E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51" + + +@pytest.fixture(scope="module") +def photosdb(): + return osxphotos.PhotosDB(dbfile=PHOTOS_DB) + def test_init1(): # test named argument @@ -230,80 +239,56 @@ def test_init5(mocker): assert osxphotos.PhotosDB() -def test_db_len(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_db_len(photosdb): # assert photosdb.db_version in osxphotos._TESTED_DB_VERSIONS assert len(photosdb) == PHOTOS_DB_LEN -def test_db_version(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_db_version(photosdb): # assert photosdb.db_version in osxphotos._TESTED_DB_VERSIONS assert photosdb.db_version == "6000" -def test_persons(): - import osxphotos +def test_persons(photosdb): import collections - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) assert "Katie" in photosdb.persons assert collections.Counter(PERSONS) == collections.Counter(photosdb.persons) -def test_keywords(): - import osxphotos +def test_keywords(photosdb): import collections - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) assert "wedding" in photosdb.keywords assert collections.Counter(KEYWORDS) == collections.Counter(photosdb.keywords) -def test_album_names(): - import osxphotos +def test_album_names(photosdb): import collections - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) assert "Pumpkin Farm" in photosdb.albums assert collections.Counter(ALBUMS) == collections.Counter(photosdb.albums) -def test_keywords_dict(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_keywords_dict(photosdb): keywords = photosdb.keywords_as_dict assert keywords["wedding"] == 3 assert keywords == KEYWORDS_DICT -def test_persons_as_dict(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_persons_as_dict(photosdb): persons = photosdb.persons_as_dict assert persons["Maria"] == 2 assert persons == PERSONS_DICT -def test_albums_as_dict(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_albums_as_dict(photosdb): albums = photosdb.albums_as_dict assert albums["Pumpkin Farm"] == 3 assert albums == ALBUM_DICT -def test_album_sort_order(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_album_sort_order(photosdb): album = [a for a in photosdb.album_info if a.title == "Pumpkin Farm"][0] photos = album.photos @@ -311,20 +296,15 @@ def test_album_sort_order(): assert uuids == ALBUM_SORT_ORDER -def test_album_empty_album(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_album_empty_album(photosdb): album = [a for a in photosdb.album_info if a.title == "EmptyAlbum"][0] photos = album.photos assert photos == [] -def test_attributes(): +def test_attributes(photosdb): import datetime - import osxphotos - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=["D79B8D77-BFFC-460B-9312-034F2877D35B"]) assert len(photos) == 1 p = photos[0] @@ -344,12 +324,10 @@ def test_attributes(): assert p.ismissing == False -def test_attributes_2(): +def test_attributes_2(photosdb): """ Test attributes including height, width, etc """ import datetime - import osxphotos - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]]) assert len(photos) == 1 p = photos[0] @@ -384,10 +362,7 @@ def test_attributes_2(): assert p.original_filesize == 460483 -def test_missing(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_missing(photosdb): photos = photosdb.photos(uuid=[UUID_DICT["missing"]]) assert len(photos) == 1 p = photos[0] @@ -395,51 +370,36 @@ def test_missing(): assert p.ismissing == True -def test_favorite(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_favorite(photosdb): photos = photosdb.photos(uuid=[UUID_DICT["favorite"]]) assert len(photos) == 1 p = photos[0] assert p.favorite == True -def test_not_favorite(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_not_favorite(photosdb): photos = photosdb.photos(uuid=[UUID_DICT["not_favorite"]]) assert len(photos) == 1 p = photos[0] assert p.favorite == False -def test_hidden(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_hidden(photosdb): photos = photosdb.photos(uuid=[UUID_DICT["hidden"]]) assert len(photos) == 1 p = photos[0] assert p.hidden == True -def test_not_hidden(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_not_hidden(photosdb): photos = photosdb.photos(uuid=[UUID_DICT["not_hidden"]]) assert len(photos) == 1 p = photos[0] assert p.hidden == False -def test_location_1(): +def test_location_1(photosdb): # test photo with lat/lon info - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["location"]]) assert len(photos) == 1 p = photos[0] @@ -448,11 +408,8 @@ def test_location_1(): assert lon == pytest.approx(-0.1318055) -def test_location_2(): +def test_location_2(photosdb): # test photo with no location info - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["no_location"]]) assert len(photos) == 1 p = photos[0] @@ -461,33 +418,24 @@ def test_location_2(): assert lon is None -def test_hasadjustments1(): +def test_hasadjustments1(photosdb): # test hasadjustments == True - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]]) assert len(photos) == 1 p = photos[0] assert p.hasadjustments == True -def test_hasadjustments2(): +def test_hasadjustments2(photosdb): # test hasadjustments == False - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]]) assert len(photos) == 1 p = photos[0] assert p.hasadjustments == False -def test_external_edit1(): +def test_external_edit1(photosdb): # test image has been edited in external editor - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["external_edit"]]) assert len(photos) == 1 p = photos[0] @@ -495,11 +443,8 @@ def test_external_edit1(): assert p.external_edit == True -def test_external_edit2(): +def test_external_edit2(photosdb): # test image has not been edited in external editor - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["no_external_edit"]]) assert len(photos) == 1 p = photos[0] @@ -507,12 +452,10 @@ def test_external_edit2(): assert p.external_edit == False -def test_path_edited_jpeg(): +def test_path_edited_jpeg(photosdb): # test a valid edited path import os.path - import osxphotos - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=["E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51"]) assert len(photos) == 1 p = photos[0] @@ -523,22 +466,17 @@ def test_path_edited_jpeg(): assert os.path.exists(path) -def test_path_edited_heic(): +def test_path_edited_heic(photosdb): # test a valid edited path for .heic image import pathlib - import osxphotos - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photo = photosdb.get_photo(UUID_HEIC_EDITED) assert photo.path_edited.endswith(PATH_HEIC_EDITED) assert pathlib.Path(photo.path_edited).is_file() -def test_path_edited2(): +def test_path_edited2(photosdb): # test an invalid edited path - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]]) assert len(photos) == 1 p = photos[0] @@ -546,115 +484,79 @@ def test_path_edited2(): assert path is None -def test_count(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_count(photosdb): photos = photosdb.photos() assert len(photos) == PHOTOS_NOT_IN_TRASH_LEN -def test_photos_intrash_1(): +def test_photos_intrash_1(photosdb): """ test PhotosDB.photos(intrash=True) """ - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(intrash=True) assert len(photos) == PHOTOS_IN_TRASH_LEN -def test_photos_intrash_2(): +def test_photos_intrash_2(photosdb): """ test PhotosDB.photos(intrash=True) """ - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(intrash=True) for p in photos: assert p.intrash -def test_photos_intrash_3(): +def test_photos_intrash_3(photosdb): """ test PhotosDB.photos(intrash=False) """ - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(intrash=False) for p in photos: assert not p.intrash -def test_photoinfo_intrash_1(): +def test_photoinfo_intrash_1(photosdb): """ Test PhotoInfo.intrash """ - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) p = photosdb.photos(uuid=[UUID_DICT["intrash"]], intrash=True)[0] assert p.intrash -def test_photoinfo_intrash_2(): +def test_photoinfo_intrash_2(photosdb): """ Test PhotoInfo.intrash and intrash=default""" - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) p = photosdb.photos(uuid=[UUID_DICT["intrash"]]) assert not p -def test_photoinfo_intrash_3(): +def test_photoinfo_intrash_3(photosdb): """ Test PhotoInfo.intrash and photo has keyword and person """ - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) p = photosdb.photos(uuid=[UUID_DICT["intrash_person_keywords"]], intrash=True)[0] assert p.intrash assert "Maria" in p.persons assert "wedding" in p.keywords -def test_photoinfo_intrash_4(): +def test_photoinfo_intrash_4(photosdb): """ Test PhotoInfo.intrash and photo has keyword and person """ - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) p = photosdb.photos(persons=["Maria"], intrash=True)[0] assert p.intrash assert "Maria" in p.persons assert "wedding" in p.keywords -def test_photoinfo_intrash_5(): +def test_photoinfo_intrash_5(photosdb): """ Test PhotoInfo.intrash and photo has keyword and person """ - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) p = photosdb.photos(keywords=["wedding"], intrash=True)[0] assert p.intrash assert "Maria" in p.persons assert "wedding" in p.keywords -def test_photoinfo_not_intrash(): +def test_photoinfo_not_intrash(photosdb): """ Test PhotoInfo.intrash """ - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) p = photosdb.photos(uuid=[UUID_DICT["not_intrash"]])[0] assert not p.intrash -def test_keyword_2(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_keyword_2(photosdb): photos = photosdb.photos(keywords=["wedding"]) assert len(photos) == 2 # won't show the one in the trash -def test_keyword_not_in_album(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_keyword_not_in_album(photosdb): # find all photos with keyword "Kids" not in the album "Pumpkin Farm" photos1 = photosdb.photos(albums=["Pumpkin Farm"]) @@ -664,47 +566,33 @@ def test_keyword_not_in_album(): assert photos3[0].uuid == "A1DD1F98-2ECD-431F-9AC9-5AFEFE2D3A5C" -def test_album_folder_name(): +def test_album_folder_name(photosdb): """Test query with album name same as a folder name """ - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(albums=["Pumpkin Farm"]) assert sorted(p.uuid for p in photos) == sorted(UUID_PUMPKIN_FARM) -def test_multi_person(): - import osxphotos - - photosdb = osxphotos.PhotosDB(PHOTOS_DB) +def test_multi_person(photosdb): photos = photosdb.photos(persons=["Katie", "Suzy"]) assert len(photos) == 3 -def test_get_db_path(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_get_db_path(photosdb): db_path = photosdb.db_path assert db_path.endswith(PHOTOS_DB_PATH) -def test_get_library_path(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_get_library_path(photosdb): lib_path = photosdb.library_path assert lib_path.endswith(PHOTOS_LIBRARY_PATH) -def test_get_db_connection(): +def test_get_db_connection(photosdb): """ Test PhotosDB.get_db_connection """ - import osxphotos import sqlite3 - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) conn, cursor = photosdb.get_db_connection() assert isinstance(conn, sqlite3.Connection) @@ -717,18 +605,15 @@ def test_get_db_connection(): conn.close() -def test_export_1(): +def test_export_1(photosdb): # test basic export # get an unedited image and export it using default filename import os import os.path import tempfile - import osxphotos - tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_") dest = tempdir.name - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["export"]]) filename = photos[0].filename @@ -739,18 +624,15 @@ def test_export_1(): assert os.path.isfile(got_dest) -def test_export_2(): +def test_export_2(photosdb): # test export with user provided filename import os import os.path import tempfile import time - import osxphotos - tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_") dest = tempdir.name - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["export"]]) timestamp = time.time() @@ -762,18 +644,15 @@ def test_export_2(): assert os.path.isfile(got_dest) -def test_export_3(): +def test_export_3(photosdb): # test file already exists and test increment=True (default) import os import os.path import pathlib import tempfile - import osxphotos - tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_") dest = tempdir.name - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["export"]]) filename = photos[0].filename @@ -788,7 +667,7 @@ def test_export_3(): assert os.path.isfile(got_dest_2) -def test_export_4(): +def test_export_4(photosdb): # test user supplied file already exists and test increment=True (default) import os import os.path @@ -796,11 +675,8 @@ def test_export_4(): import tempfile import time - import osxphotos - tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_") dest = tempdir.name - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["export"]]) timestamp = time.time() @@ -815,18 +691,15 @@ def test_export_4(): assert os.path.isfile(got_dest_2) -def test_export_5(): +def test_export_5(photosdb): # test file already exists and test increment=True (default) # and overwrite = True import os import os.path import tempfile - import osxphotos - tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_") dest = tempdir.name - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["export"]]) filename = photos[0].filename @@ -840,7 +713,7 @@ def test_export_5(): assert os.path.isfile(got_dest_2) -def test_export_6(): +def test_export_6(photosdb): # test user supplied file already exists and test increment=True (default) # and overwrite = True import os @@ -849,11 +722,8 @@ def test_export_6(): import tempfile import time - import osxphotos - tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_") dest = tempdir.name - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["export"]]) timestamp = time.time() @@ -868,18 +738,15 @@ def test_export_6(): assert os.path.isfile(got_dest_2) -def test_export_7(): +def test_export_7(photosdb): # test file already exists and test increment=False (not default), overwrite=False (default) # should raise exception import os import os.path import tempfile - import osxphotos - tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_") dest = tempdir.name - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["export"]]) filename = photos[0].filename @@ -891,18 +758,15 @@ def test_export_7(): assert e.type == type(FileExistsError()) -def test_export_8(): +def test_export_8(photosdb): # try to export missing file # should raise exception import os import os.path import tempfile - import osxphotos - tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_") dest = tempdir.name - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["missing"]]) filename = photos[0].filename @@ -912,16 +776,13 @@ def test_export_8(): assert e.type == type(FileNotFoundError()) -def test_export_9(): +def test_export_9(photosdb): # try to export edited file that's not edited # should raise exception import os import os.path import tempfile - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_") dest = tempdir.name photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]]) @@ -933,7 +794,7 @@ def test_export_9(): assert e.type == ValueError -def test_export_10(): +def test_export_10(photosdb): # try to export edited file that's not edited and name provided # should raise exception import os @@ -941,9 +802,6 @@ def test_export_10(): import tempfile import time - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_") dest = tempdir.name photos = photosdb.photos(uuid=[UUID_DICT["no_adjustments"]]) @@ -956,18 +814,15 @@ def test_export_10(): assert e.type == ValueError -def test_export_11(): +def test_export_11(photosdb): # export edited file with name provided import os import os.path import tempfile import time - import osxphotos - tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_") dest = tempdir.name - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]]) timestamp = time.time() @@ -978,18 +833,15 @@ def test_export_11(): assert got_dest == expected_dest -def test_export_12(): +def test_export_12(photosdb): # export edited file with default name import os import os.path import pathlib import tempfile - import osxphotos - tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_") dest = tempdir.name - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]]) edited_name = pathlib.Path(photos[0].path_edited).name @@ -1001,15 +853,13 @@ def test_export_12(): assert got_dest == expected_dest -def test_export_13(): +def test_export_13(photosdb): # export to invalid destination # should raise exception import os import os.path import tempfile - import osxphotos - tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_") dest = tempdir.name @@ -1019,7 +869,6 @@ def test_export_13(): dest = os.path.join(dest, str(i)) i += 1 - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["export"]]) filename = photos[0].filename @@ -1029,18 +878,15 @@ def test_export_13(): assert e.type == type(FileNotFoundError()) -def test_export_14(caplog): +def test_export_14(caplog, photosdb): # test export with user provided filename with different (but valid) extension than source import os import os.path import tempfile import time - import osxphotos - tempdir = tempfile.TemporaryDirectory(prefix="osxphotos_") dest = tempdir.name - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["export_tif"]]) timestamp = time.time() @@ -1054,24 +900,22 @@ def test_export_14(caplog): assert "Invalid destination suffix" not in caplog.text -def test_eq(): +def test_eq(photosdb): """ Test equality of two PhotoInfo objects """ import osxphotos - photosdb1 = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb2 = osxphotos.PhotosDB(dbfile=PHOTOS_DB) - photos1 = photosdb1.photos(uuid=[UUID_DICT["export"]]) + photos1 = photosdb.photos(uuid=[UUID_DICT["export"]]) photos2 = photosdb2.photos(uuid=[UUID_DICT["export"]]) assert photos1[0] == photos2[0] -def test_eq_2(): +def test_eq_2(photosdb): """ Test equality of two PhotoInfo objects when one has memoized property """ import osxphotos - photosdb1 = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb2 = osxphotos.PhotosDB(dbfile=PHOTOS_DB) - photos1 = photosdb1.photos(uuid=[UUID_DICT["in_album"]]) + photos1 = photosdb.photos(uuid=[UUID_DICT["in_album"]]) photos2 = photosdb2.photos(uuid=[UUID_DICT["in_album"]]) # memoize a value @@ -1081,18 +925,13 @@ def test_eq_2(): assert photos1[0] == photos2[0] -def test_not_eq(): - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) +def test_not_eq(photosdb): photos1 = photosdb.photos(uuid=[UUID_DICT["export"]]) photos2 = photosdb.photos(uuid=[UUID_DICT["missing"]]) assert photos1[0] != photos2[0] def test_photosdb_repr(): - import osxphotos - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photosdb2 = eval(repr(photosdb)) @@ -1102,11 +941,9 @@ def test_photosdb_repr(): } -def test_photosinfo_repr(): - import osxphotos +def test_photosinfo_repr(photosdb): import datetime - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) photos = photosdb.photos(uuid=[UUID_DICT["favorite"]]) photo = photos[0] photo2 = eval(repr(photo)) @@ -1116,8 +953,7 @@ def test_photosinfo_repr(): } -def test_from_to_date(): - import osxphotos +def test_from_to_date(photosdb): import datetime as dt import os import time @@ -1125,8 +961,6 @@ def test_from_to_date(): os.environ["TZ"] = "US/Pacific" time.tzset() - photosdb = osxphotos.PhotosDB(PHOTOS_DB) - photos = photosdb.photos(from_date=dt.datetime(2018, 10, 28)) assert len(photos) == 7 @@ -1139,12 +973,10 @@ def test_from_to_date(): assert len(photos) == 4 -def test_date_invalid(): +def test_date_invalid(photosdb): """ Test date is invalid """ from datetime import datetime, timedelta, timezone - import osxphotos - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) # UUID_DICT["date_invalid"] has an invalid date that's # been manually adjusted in the database photos = photosdb.photos(uuid=[UUID_DICT["date_invalid"]]) @@ -1155,12 +987,10 @@ def test_date_invalid(): assert p.date == datetime(1970, 1, 1).astimezone(tz=tz) -def test_date_modified_invalid(): +def test_date_modified_invalid(photosdb): """ Test date modified is invalid """ from datetime import datetime, timedelta, timezone - import osxphotos - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) # UUID_DICT["date_invalid"] has an invalid modified date that's # been manually adjusted in the database photos = photosdb.photos(uuid=[UUID_DICT["date_invalid"]]) @@ -1169,11 +999,8 @@ def test_date_modified_invalid(): assert p.date_modified is None -def test_uti(): +def test_uti(photosdb): """ test uti """ - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) for uuid, uti in UTI_DICT.items(): photo = photosdb.get_photo(uuid) @@ -1181,11 +1008,8 @@ def test_uti(): assert photo.uti_original == UTI_ORIGINAL_DICT[uuid] -def test_raw(): +def test_raw(photosdb): """ Test various raw properties """ - import osxphotos - - photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB) for uuid, rawinfo in RAW_DICT.items(): photo = photosdb.get_photo(uuid) @@ -1195,3 +1019,12 @@ def test_raw(): assert photo.uti == rawinfo.uti assert photo.uti_original == rawinfo.uti_original assert photo.uti_raw == rawinfo.uti_raw + + +def test_is_reference(photosdb): + """ test isreference """ + + photo = photosdb.get_photo(UUID_IS_REFERENCE) + assert photo.isreference + photo = photosdb.get_photo(UUID_NOT_REFERENCE) + assert not photo.isreference diff --git a/tests/test_catalina_10_15_7.py b/tests/test_catalina_10_15_7.py index ab76b3ee..708d248f 100644 --- a/tests/test_catalina_10_15_7.py +++ b/tests/test_catalina_10_15_7.py @@ -198,6 +198,9 @@ ORIGINAL_FILENAME_DICT = { "original_filename": "Pumkins2.jpg", } +UUID_IS_REFERENCE = "A1DD1F98-2ECD-431F-9AC9-5AFEFE2D3A5C" +UUID_NOT_REFERENCE = "F12384F6-CD17-4151-ACBA-AE0E3688539E" + @pytest.fixture(scope="module") def photosdb(): @@ -1185,3 +1188,11 @@ def test_visible_burst(photosdb_local): assert photo.burst assert len(photo.burst_photos) == 4 + +def test_is_reference(photosdb): + """ test isreference """ + + photo = photosdb.get_photo(UUID_IS_REFERENCE) + assert photo.isreference + photo = photosdb.get_photo(UUID_NOT_REFERENCE) + assert not photo.isreference diff --git a/tests/test_cli.py b/tests/test_cli.py index 01d3f2a8..0a60fd42 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -573,6 +573,11 @@ UUID_JPEGS_DICT = { UUID_HEIC = {"7783E8E6-9CAC-40F3-BE22-81FB7051C266": "IMG_3092"} +UUID_IS_REFERENCE = [ + "8E1D7BC9-9321-44F9-8CFB-4083F6B9232A", + "A1DD1F98-2ECD-431F-9AC9-5AFEFE2D3A5C", +] + def modify_file(filename): """ appends data to a file to modify it """ @@ -857,6 +862,26 @@ def test_query_no_likes(): assert uuid not in UUID_HAS_LIKES +def test_query_is_reference(): + """ Test query with --is-reference """ + import json + import os + import os.path + from osxphotos.__main__ import query + + runner = CliRunner() + cwd = os.getcwd() + result = runner.invoke( + query, ["--json", "--db", os.path.join(cwd, PHOTOS_DB_15_7), "--is-reference"] + ) + assert result.exit_code == 0 + + # build list of uuids we got from the output JSON + json_got = json.loads(result.output) + uuid_got = [photo["uuid"] for photo in json_got] + assert sorted(uuid_got) == sorted(UUID_IS_REFERENCE) + + def test_export(): import glob import os @@ -1587,7 +1612,7 @@ def test_export_convert_to_jpeg(): files = glob.glob("*") assert sorted(files) == sorted(CLI_EXPORT_FILENAMES_CONVERT_TO_JPEG) large_file = pathlib.Path(CLI_EXPORT_CONVERT_TO_JPEG_LARGE_FILE) - assert large_file.stat().st_size > 7000000 + assert large_file.stat().st_size > 7000000 @pytest.mark.skipif( diff --git a/tests/test_export_catalina_10_15_7.py b/tests/test_export_catalina_10_15_7.py index c7edf618..0e9a1d44 100644 --- a/tests/test_export_catalina_10_15_7.py +++ b/tests/test_export_catalina_10_15_7.py @@ -623,3 +623,4 @@ def test_xmp_sidecar_keyword_template(photosdb): keyword_template=["{created.year}", "{folder_album}"], extension="jpg" ) assert xmp_got == xmp_expected + diff --git a/tests/test_mojave_10_14_6.py b/tests/test_mojave_10_14_6.py index 65bde365..17fcdc9a 100644 --- a/tests/test_mojave_10_14_6.py +++ b/tests/test_mojave_10_14_6.py @@ -100,6 +100,8 @@ PHOTOS_DB_LEN = 13 PHOTOS_NOT_IN_TRASH_LEN = 12 PHOTOS_IN_TRASH_LEN = 1 +UUID_NOT_REFERENCE = "6bxcNnzRQKGnK4uPrCJ9UQ" +UUID_IS_REFERENCE = "od0fmC7NQx+ayVr+%i06XA" RawInfo = namedtuple( "RawInfo", @@ -595,7 +597,7 @@ def test_raw(photosdb): photo = photosdb.get_photo(UUID_DICT["raw"]) # assert photo.israw assert not photo.has_raw - assert photo.uti_raw == None + assert photo.uti_raw is None assert photo.uti == "com.adobe.raw-image" assert photo.path_raw is None @@ -626,3 +628,12 @@ def test_raw(): assert photo.uti == rawinfo.uti assert photo.uti_original == rawinfo.uti_original assert photo.uti_raw == rawinfo.uti_raw + + +def test_is_reference(photosdb): + """ test isreference """ + + photo = photosdb.get_photo(UUID_IS_REFERENCE) + assert photo.isreference + photo = photosdb.get_photo(UUID_NOT_REFERENCE) + assert not photo.isreference