Added tests
@ -4,14 +4,16 @@ from pathlib import Path
|
||||
from plistlib import load as plistload
|
||||
from datetime import datetime
|
||||
import tempfile
|
||||
import objc
|
||||
import CoreFoundation
|
||||
from Foundation import *
|
||||
import urllib.parse
|
||||
import sys
|
||||
from shutil import copyfile
|
||||
import pprint
|
||||
import sqlite3
|
||||
|
||||
import objc
|
||||
import CoreFoundation
|
||||
from Foundation import *
|
||||
|
||||
from . import _applescript
|
||||
|
||||
from loguru import logger
|
||||
@ -72,7 +74,7 @@ class PhotosDB:
|
||||
dbfile = os.path.join(library_path, "database/photos.db")
|
||||
logger.debug(dbfile)
|
||||
|
||||
logger.debug("filename = %s" % dbfile)
|
||||
logger.debug(f"filename = {dbfile}")
|
||||
|
||||
# TODO: replace os.path with pathlib
|
||||
# TODO: clean this up -- we'll already know library_path
|
||||
@ -80,12 +82,12 @@ class PhotosDB:
|
||||
(library_path, tmp) = os.path.split(library_path)
|
||||
masters_path = os.path.join(library_path, "Masters")
|
||||
self._masters_path = masters_path
|
||||
logger.debug("library = %s, masters = %s" % (library_path, masters_path))
|
||||
logger.debug(f"library = {library_path}, masters = {masters_path}")
|
||||
|
||||
if not _check_file_exists(dbfile):
|
||||
sys.exit("_dbfile %s does not exist" % (dbfile))
|
||||
sys.exit(f"_dbfile {dbfile} does not exist")
|
||||
|
||||
logger.info("database filename = %s" % dbfile)
|
||||
logger.info(f"database filename = {dbfile}")
|
||||
|
||||
self._dbfile = dbfile
|
||||
self._setup_applescript()
|
||||
@ -234,12 +236,12 @@ class PhotosDB:
|
||||
|
||||
def _open_sql_file(self, file):
|
||||
fname = file
|
||||
logger.debug("Trying to open database %s" % (fname))
|
||||
logger.debug(f"Trying to open database {fname}")
|
||||
try:
|
||||
conn = sqlite3.connect("%s" % (fname))
|
||||
conn = sqlite3.connect(f"{fname}")
|
||||
c = conn.cursor()
|
||||
except sqlite3.Error as e:
|
||||
print("An error occurred: %s %s" % (e.args[0], fname))
|
||||
print(f"An error occurred: {e.args[0]} {fname}")
|
||||
sys.exit(3)
|
||||
logger.debug("SQLite database is open")
|
||||
return (conn, c)
|
||||
@ -277,7 +279,7 @@ class PhotosDB:
|
||||
)
|
||||
for person in c:
|
||||
if person[0] == None:
|
||||
logger.debug("skipping person = None %s" % person[1])
|
||||
logger.debug(f"skipping person = None {person[1]}")
|
||||
continue
|
||||
if not person[1] in self._dbfaces_uuid:
|
||||
self._dbfaces_uuid[person[1]] = []
|
||||
@ -314,7 +316,7 @@ class PhotosDB:
|
||||
self._dbalbums_album[album[0]] = []
|
||||
self._dbalbums_uuid[album[1]].append(album[0])
|
||||
self._dbalbums_album[album[0]].append(album[1])
|
||||
logger.debug("%s %s" % (album[1], album[0]))
|
||||
logger.debug(f"{album[1]} {album[0]}")
|
||||
# set_pbar_status(i)
|
||||
i = i + 1
|
||||
logger.debug("Finished walking through albums")
|
||||
@ -344,7 +346,7 @@ class PhotosDB:
|
||||
self._dbkeywords_keyword[keyword[0]] = []
|
||||
self._dbkeywords_uuid[keyword[1]].append(keyword[0])
|
||||
self._dbkeywords_keyword[keyword[0]].append(keyword[1])
|
||||
logger.debug("%s %s" % (keyword[1], keyword[0]))
|
||||
logger.debug(f"{keyword[1]} {keyword[0]}")
|
||||
# set_pbar_status(i)
|
||||
i = i + 1
|
||||
logger.debug("Finished walking through keywords")
|
||||
@ -357,7 +359,7 @@ class PhotosDB:
|
||||
i = 0
|
||||
for vol in c:
|
||||
self._dbvolumes[vol[0]] = vol[1]
|
||||
logger.debug("%s %s" % (vol[0], vol[1]))
|
||||
logger.debug(f"{vol[0]} {vol[1]}")
|
||||
# set_pbar_status(i)
|
||||
i = i + 1
|
||||
logger.debug("Finished walking through volumes")
|
||||
@ -385,7 +387,7 @@ class PhotosDB:
|
||||
i = i + 1
|
||||
uuid = row[0]
|
||||
if _debug:
|
||||
print("i = %d, uuid = '%s, master = '%s" % (i, uuid, row[2]))
|
||||
print(f"i = {i:d}, uuid = '{uuid}, master = '{row[2]}")
|
||||
self._dbphotos[uuid] = {}
|
||||
self._dbphotos[uuid]["modelID"] = row[1]
|
||||
self._dbphotos[uuid]["masterUuid"] = row[2]
|
||||
@ -490,58 +492,52 @@ class PhotosDB:
|
||||
If called with no args, returns the entire database of photos
|
||||
If called with args, returns photos matching the args (e.g. keywords, persons, etc.)
|
||||
If more than one arg, returns photos matching all the criteria (e.g. keywords AND persons)
|
||||
TODO: Still need to fix AND
|
||||
"""
|
||||
|
||||
def photos(self, keywords=[], uuid=[], persons=[], albums=[]):
|
||||
#TODO: combine photos and photos_sets, I think only one needed
|
||||
# photos = [] # list of photos (PhotoInfo objects) that will be returned
|
||||
photos_sets = [] # list of sets to perform intersection of
|
||||
photos_sets = [] # list of photo sets to perform intersection of
|
||||
if not keywords and not uuid and not persons and not albums:
|
||||
# return all the photos
|
||||
# append keys of all photos as a single set to photos_sets
|
||||
logger.debug("return all photos")
|
||||
photos_sets.append(set(self._dbphotos.keys()))
|
||||
else:
|
||||
if albums:
|
||||
for album in albums:
|
||||
logger.info("album=%s" % album)
|
||||
logger.info(f"album={album}")
|
||||
if album in self._dbalbums_album:
|
||||
logger.info("processing album %s:" % album)
|
||||
logger.info(f"processing album {album}:")
|
||||
photos_sets.append(set(self._dbalbums_album[album]))
|
||||
else:
|
||||
logger.debug("Could not find album '%s' in database" % (album))
|
||||
logger.debug(f"Could not find album '{album}' in database")
|
||||
|
||||
if uuid:
|
||||
for u in uuid:
|
||||
logger.info("uuid=%s" % u)
|
||||
logger.info(f"uuid={u}")
|
||||
if u in self._dbphotos:
|
||||
logger.info("processing uuid %s:" % u)
|
||||
logger.info(f"processing uuid {u}:")
|
||||
photos_sets.append(set([u]))
|
||||
else:
|
||||
logger.debug("Could not find uuid '%s' in database" % (u))
|
||||
logger.debug(f"Could not find uuid '{u}' in database")
|
||||
|
||||
if keywords:
|
||||
for keyword in keywords:
|
||||
logger.info("keyword=%s" % keyword)
|
||||
logger.info(f"keyword={keyword}")
|
||||
if keyword in self._dbkeywords_keyword:
|
||||
logger.info("processing keyword %s:" % keyword)
|
||||
logger.info(f"processing keyword {keyword}:")
|
||||
photos_sets.append(set(self._dbkeywords_keyword[keyword]))
|
||||
logger.debug(f"photos_sets {photos_sets}")
|
||||
else:
|
||||
logger.debug(
|
||||
"Could not find keyword '%s' in database" % (keyword)
|
||||
)
|
||||
logger.debug(f"Could not find keyword '{keyword}' in database")
|
||||
|
||||
if persons:
|
||||
for person in persons:
|
||||
logger.info("person=%s" % person)
|
||||
logger.info(f"person={person}")
|
||||
if person in self._dbfaces_person:
|
||||
logger.info("processing person %s:" % person)
|
||||
logger.info(f"processing person {person}:")
|
||||
photos_sets.append(set(self._dbfaces_person[person]))
|
||||
else:
|
||||
logger.debug(
|
||||
"Could not find person '%s' in database" % (person)
|
||||
)
|
||||
logger.debug(f"Could not find person '{person}' in database")
|
||||
|
||||
photoinfo = []
|
||||
if photos_sets: # found some photos
|
||||
@ -622,6 +618,9 @@ class PhotoInfo:
|
||||
def uuid(self):
|
||||
return self.__uuid
|
||||
|
||||
def ismissing(self):
|
||||
return True if self.__info["isMissing"] == 1 else False
|
||||
|
||||
# compare two PhotoInfo objects for equality
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, self.__class__):
|
||||
|
||||
6
setup.py
@ -27,7 +27,7 @@
|
||||
# SOFTWARE.
|
||||
|
||||
# from distutils.core import setup
|
||||
from setuptools import setup
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
# read the contents of README file
|
||||
from os import path
|
||||
@ -47,7 +47,7 @@ setup(
|
||||
url="https://github.com/RhetTbull/",
|
||||
project_urls={"GitHub": "https://github.com/RhetTbull/osxphotos"},
|
||||
download_url="https://github.com/RhetTbull/osxphotos",
|
||||
packages=["osxphotos"],
|
||||
packages=find_packages(exclude=["tests","examples"]),
|
||||
license="License :: OSI Approved :: MIT License",
|
||||
classifiers=[
|
||||
"Development Status :: 4 - Beta",
|
||||
@ -55,7 +55,7 @@ setup(
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: MacOS :: MacOS X",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
],
|
||||
install_requires=["pyobjc","loguru"],
|
||||
|
||||
21
tests/README.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Tests for osxphotos #
|
||||
|
||||
## Running Tests ##
|
||||
Tests require pytest:
|
||||
`pip install pytest`
|
||||
|
||||
To run the tests, do the following from the main source folder:
|
||||
`python -m pytest tests/`
|
||||
|
||||
Running the tests this way allows the library to be tested without installing it.
|
||||
|
||||
## Attribution ##
|
||||
These tests utilize a test Photos library. The test library is populated with photos from [flickr](https://www.flickr.com). All images used are licensed under Creative Commons 2.0 Attribution [license](https://creativecommons.org/licenses/by/2.0/).
|
||||
|
||||
Images used from:
|
||||
- [Jeff Hitchcock](https://www.flickr.com/photos/arbron/48353451872/)
|
||||
- [Carlos Montesdeoca](https://www.flickr.com/photos/carlosmontesdeocastudio)
|
||||
- [Rydale Clothing](https://www.flickr.com/photos/rydaleclothing)
|
||||
- [Marco Verch](https://www.flickr.com/photos/30478819@N08/48228222317/)
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 541 KiB |
|
After Width: | Height: | Size: 528 KiB |
|
After Width: | Height: | Size: 574 KiB |
|
After Width: | Height: | Size: 500 KiB |
|
After Width: | Height: | Size: 450 KiB |
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>DatabaseMinorVersion</key>
|
||||
<integer>1</integer>
|
||||
<key>DatabaseVersion</key>
|
||||
<integer>112</integer>
|
||||
<key>LastOpenMode</key>
|
||||
<integer>2</integer>
|
||||
<key>LibrarySchemaVersion</key>
|
||||
<integer>3301</integer>
|
||||
<key>MetaSchemaVersion</key>
|
||||
<integer>2</integer>
|
||||
<key>createDate</key>
|
||||
<date>2019-07-26T20:15:17Z</date>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
tests/Test-10.13.6.photoslibrary/database/RKAlbum_name.skindex
Normal file
BIN
tests/Test-10.13.6.photoslibrary/database/RKMemory_title.skindex
Normal file
BIN
tests/Test-10.13.6.photoslibrary/database/metaSchema.db
Normal file
BIN
tests/Test-10.13.6.photoslibrary/database/photos.db
Normal file
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Photos</key>
|
||||
<dict>
|
||||
<key>CollapsedSidebarSectionIdentifiers</key>
|
||||
<array/>
|
||||
<key>ExpandedSidebarItemIdentifiers</key>
|
||||
<array>
|
||||
<string>TopLevelAlbums</string>
|
||||
<string>TopLevelSlideshows</string>
|
||||
</array>
|
||||
<key>IPXWorkspaceControllerZoomLevelsKey</key>
|
||||
<dict>
|
||||
<key>kZoomLevelIdentifierAlbums</key>
|
||||
<integer>7</integer>
|
||||
<key>kZoomLevelIdentifierVersions</key>
|
||||
<integer>7</integer>
|
||||
</dict>
|
||||
<key>lastAddToDestination</key>
|
||||
<dict>
|
||||
<key>key</key>
|
||||
<integer>1</integer>
|
||||
<key>lastKnownDisplayName</key>
|
||||
<string>September 28, 2018</string>
|
||||
<key>type</key>
|
||||
<string>album</string>
|
||||
<key>uuid</key>
|
||||
<string>+Ep8CrNRRhea9eVA618FMg</string>
|
||||
</dict>
|
||||
<key>lastKnownItemCounts</key>
|
||||
<dict>
|
||||
<key>other</key>
|
||||
<integer>0</integer>
|
||||
<key>photos</key>
|
||||
<integer>7</integer>
|
||||
<key>videos</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PhotoAnalysisGraphLastBackgroundGraphRebuildJobDate</key>
|
||||
<date>2019-07-26T20:15:18Z</date>
|
||||
<key>PhotoAnalysisGraphLastBackgroundMemoryGenerationJobDate</key>
|
||||
<date>2019-07-26T20:15:18Z</date>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict/>
|
||||
</plist>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PVClustererBringUpState</key>
|
||||
<integer>50</integer>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IncrementalPersonProcessingStage</key>
|
||||
<integer>0</integer>
|
||||
<key>PersonBuilderLastMinimumFaceGroupSizeForCreatingMergeCandidates</key>
|
||||
<integer>15</integer>
|
||||
<key>PersonBuilderMergeCandidatesEnabled</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 490 KiB |
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PLLanguageAndLocaleKey</key>
|
||||
<string>en-US:en_US</string>
|
||||
<key>PLLastGeoProviderIdKey</key>
|
||||
<string>7618</string>
|
||||
<key>PLLastLocationInfoFormatVer</key>
|
||||
<integer>12</integer>
|
||||
<key>PLLastRevGeoForcedProviderOutOfDateCheckVersionKey</key>
|
||||
<integer>1</integer>
|
||||
<key>PLLastRevGeoVerFileFetchDateKey</key>
|
||||
<date>2019-07-26T20:15:18Z</date>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>LastHistoryRowId</key>
|
||||
<integer>545</integer>
|
||||
<key>LibraryBuildTag</key>
|
||||
<string>BEA5F0E8-BA6B-4462-8F73-3E53BBE4C943</string>
|
||||
<key>LibrarySchemaVersion</key>
|
||||
<integer>3301</integer>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>FileVersion</key>
|
||||
<integer>11</integer>
|
||||
<key>Source</key>
|
||||
<dict>
|
||||
<key>35230</key>
|
||||
<dict>
|
||||
<key>CountryMinVersions</key>
|
||||
<dict>
|
||||
<key>OTHER</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<key>CurrentVersion</key>
|
||||
<integer>1</integer>
|
||||
<key>NoResultErrorIsSuccess</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>57879</key>
|
||||
<dict>
|
||||
<key>CountryMinVersions</key>
|
||||
<dict>
|
||||
<key>OTHER</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<key>CurrentVersion</key>
|
||||
<integer>1</integer>
|
||||
<key>NoResultErrorIsSuccess</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>7618</key>
|
||||
<dict>
|
||||
<key>AddCountyIfNeeded</key>
|
||||
<true/>
|
||||
<key>CountryMinVersions</key>
|
||||
<dict>
|
||||
<key>OTHER</key>
|
||||
<integer>10</integer>
|
||||
</dict>
|
||||
<key>CurrentVersion</key>
|
||||
<integer>10</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 213 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 288 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 272 KiB |
|
After Width: | Height: | Size: 110 KiB |
|
After Width: | Height: | Size: 285 KiB |
|
After Width: | Height: | Size: 141 KiB |
|
After Width: | Height: | Size: 225 KiB |
|
After Width: | Height: | Size: 182 KiB |
|
After Width: | Height: | Size: 485 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 329 KiB |
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>DatabaseMinorVersion</key>
|
||||
<integer>1</integer>
|
||||
<key>DatabaseVersion</key>
|
||||
<integer>112</integer>
|
||||
<key>HistoricalMarker</key>
|
||||
<dict>
|
||||
<key>LastHistoryRowId</key>
|
||||
<integer>551</integer>
|
||||
<key>LibraryBuildTag</key>
|
||||
<string>BEA5F0E8-BA6B-4462-8F73-3E53BBE4C943</string>
|
||||
<key>LibrarySchemaVersion</key>
|
||||
<integer>3301</integer>
|
||||
</dict>
|
||||
<key>LibrarySchemaVersion</key>
|
||||
<integer>3301</integer>
|
||||
<key>MetaSchemaVersion</key>
|
||||
<integer>2</integer>
|
||||
<key>SnapshotComplete</key>
|
||||
<true/>
|
||||
<key>SnapshotCompletedDate</key>
|
||||
<date>2019-07-26T20:15:17Z</date>
|
||||
<key>SnapshotLastValidated</key>
|
||||
<date>2019-07-26T20:15:17Z</date>
|
||||
<key>SnapshotTables</key>
|
||||
<dict/>
|
||||
</dict>
|
||||
</plist>
|
||||
188
tests/test_1.py
Normal file
@ -0,0 +1,188 @@
|
||||
import pytest
|
||||
|
||||
# TODO: put some of this code into a pre-function
|
||||
|
||||
PHOTOS_DB = "./tests/Test-10.13.6.photoslibrary/database/photos.db"
|
||||
KEYWORDS = [
|
||||
"Kids",
|
||||
"wedding",
|
||||
"flowers",
|
||||
"England",
|
||||
"London",
|
||||
"London 2018",
|
||||
"St. James's Park",
|
||||
"UK",
|
||||
"United Kingdom",
|
||||
]
|
||||
PERSONS = ["Katie", "Suzy", "Maria"]
|
||||
ALBUMS = ["Pumpkin Farm"]
|
||||
KEYWORDS_DICT = {
|
||||
"Kids": 4,
|
||||
"wedding": 2,
|
||||
"flowers": 1,
|
||||
"England": 1,
|
||||
"London": 1,
|
||||
"London 2018": 1,
|
||||
"St. James's Park": 1,
|
||||
"UK": 1,
|
||||
"United Kingdom": 1,
|
||||
}
|
||||
PERSONS_DICT = {"Katie": 3, "Suzy": 2, "Maria": 1}
|
||||
ALBUM_DICT = {"Pumpkin Farm": 3}
|
||||
|
||||
|
||||
def test_init():
|
||||
import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
assert isinstance(photosdb, osxphotos.PhotosDB)
|
||||
|
||||
|
||||
def test_persons():
|
||||
import osxphotos
|
||||
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
|
||||
import collections
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
assert "wedding" in photosdb.keywords()
|
||||
assert collections.Counter(KEYWORDS) == collections.Counter(photosdb.keywords())
|
||||
|
||||
|
||||
def test_albums():
|
||||
import osxphotos
|
||||
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)
|
||||
keywords = photosdb.keywords_as_dict()
|
||||
assert keywords["wedding"] == 2
|
||||
assert keywords == KEYWORDS_DICT
|
||||
|
||||
|
||||
def test_persons_as_dict():
|
||||
import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
persons = photosdb.persons_as_dict()
|
||||
assert persons["Maria"] == 1
|
||||
assert persons == PERSONS_DICT
|
||||
|
||||
|
||||
def test_albums_as_dict():
|
||||
import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
albums = photosdb.albums_as_dict()
|
||||
assert albums["Pumpkin Farm"] == 3
|
||||
assert albums == ALBUM_DICT
|
||||
|
||||
|
||||
def test_attributes():
|
||||
import datetime
|
||||
import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photos = photosdb.photos(uuid=["RWmFYiDjSyKjeK8Pfna0Eg"])
|
||||
assert len(photos) == 1
|
||||
p = photos[0]
|
||||
assert p.keywords() == ["Kids"]
|
||||
assert p.filename() == "Pumkins2.jpg"
|
||||
assert p.date() == datetime.datetime(2018, 9, 28, 16, 7, 7)
|
||||
assert p.description() == "Girl holding pumpkin"
|
||||
assert p.name() == "I found one!"
|
||||
assert p.albums() == ["Pumpkin Farm"]
|
||||
assert p.persons() == ["Katie"]
|
||||
assert (
|
||||
p.path()
|
||||
== "./tests/Test-10.13.6.photoslibrary/Masters/2019/07/26/20190726-203227/Pumkins2.jpg"
|
||||
)
|
||||
assert p.ismissing() == False
|
||||
|
||||
|
||||
def test_missing():
|
||||
import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photos = photosdb.photos(uuid=["6iAZJP7ZQ5iXxapoJb3ytA"])
|
||||
assert len(photos) == 1
|
||||
p = photos[0]
|
||||
assert p.path() == None
|
||||
assert p.ismissing() == True
|
||||
|
||||
|
||||
def test_count():
|
||||
import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photos = photosdb.photos()
|
||||
assert len(photos) == 7
|
||||
|
||||
|
||||
def test_keyword_2():
|
||||
import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photos = photosdb.photos(keywords=["wedding"])
|
||||
assert len(photos) == 2
|
||||
|
||||
|
||||
def test_keyword_not_in_album():
|
||||
import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
|
||||
# find all photos with keyword "Kids" not in the album "Pumpkin Farm"
|
||||
photos1 = photosdb.photos(albums=["Pumpkin Farm"])
|
||||
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"
|
||||
|
||||
|
||||
# def main():
|
||||
# photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
# print(photosdb.keywords())
|
||||
# print(photosdb.persons())
|
||||
# print(photosdb.albums())
|
||||
|
||||
# print(photosdb.keywords_as_dict())
|
||||
# print(photosdb.persons_as_dict())
|
||||
# print(photosdb.albums_as_dict())
|
||||
|
||||
# # # find all photos with Keyword = Foo and containing John Smith
|
||||
# # photos = photosdb.photos(keywords=["Foo"],persons=["John Smith"])
|
||||
# #
|
||||
# # # find all photos that include Alice Smith but do not contain the keyword Bar
|
||||
# # photos = [p for p in photosdb.photos(persons=["Alice Smith"])
|
||||
# # if p not in photosdb.photos(keywords=["Bar"]) ]
|
||||
# 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(),
|
||||
# )
|
||||
|
||||
# if __name__ == "__main__":
|
||||
# main()
|
||||