Added location (latitude/longitude), closes issue #2

This commit is contained in:
Rhet Turnbull
2019-11-27 07:27:49 -08:00
parent 67127ef370
commit 44321da243
5 changed files with 79 additions and 12 deletions

View File

@@ -342,6 +342,9 @@ Returns `True` if the picture has been marked as a favorite, otherwise `False`
#### `hidden()`
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()`
Returns a JSON representation of all photo info
@@ -386,7 +389,7 @@ The sqlite3 database used by Photos uses write ahead logging that is updated asy
- [Click](https://pypi.org/project/click/)
## Acknowledgements
This code was inspired by photo-export by Patrick Fältström see: (https://github.com/patrikhson/photo-export) Copyright (c) 2015 Patrik Fältström paf@frobbit.se
This project was inspired by photo-export by Patrick Fältström see: (https://github.com/patrikhson/photo-export) Copyright (c) 2015 Patrik Fältström paf@frobbit.se
To interact with the Photos app, I use [py-applescript]( https://github.com/rdhyee/py-applescript) by "Raymond Yee / rdhyee". Rather than import this module, I included the entire module
(which is published as public domain code) in a private module to prevent ambiguity with

View File

@@ -378,7 +378,7 @@ class PhotosDB:
""" process the Photos database to extract info """
""" works on Photos version <= 4.0 """
#TODO: Update strings to remove + (not needed)
# TODO: Update strings to remove + (not needed)
# Epoch is Jan 1, 2001
td = (datetime(2001, 1, 1, 0, 0) - datetime(1970, 1, 1, 0, 0)).total_seconds()
@@ -491,7 +491,7 @@ class PhotosDB:
+ "RKVersion.hasAdjustments, RKVersion.hasKeywords, RKVersion.imageTimeZoneOffsetSeconds, "
+ "RKMaster.volumeId, RKMaster.imagePath, RKVersion.extendedDescription, RKVersion.name, "
+ "RKMaster.isMissing, RKMaster.originalFileName, RKVersion.isFavorite, RKVersion.isHidden, "
+ "RKVersion.longitude, RKVersion.latitude "
+ "RKVersion.latitude, RKVersion.longitude "
+ "from RKVersion, RKMaster where RKVersion.isInTrash = 0 and RKVersion.type = 2 and "
+ "RKVersion.masterUuid = RKMaster.uuid and RKVersion.filename not like '%.pdf'"
)
@@ -529,9 +529,8 @@ class PhotosDB:
self._dbphotos[uuid]["originalFilename"] = row[15]
self._dbphotos[uuid]["favorite"] = row[16]
self._dbphotos[uuid]["hidden"] = row[17]
self._dbphotos[uuid]["longitude"] = row[18]
self._dbphotos[uuid]["latitude"] = row[19]
self._dbphotos[uuid]["latitude"] = row[18]
self._dbphotos[uuid]["longitude"] = row[19]
conn.close()
@@ -735,7 +734,9 @@ class PhotosDB:
"ZGENERICASSET.ZHIDDEN, "
"ZGENERICASSET.ZFAVORITE, "
"ZGENERICASSET.ZDIRECTORY, "
"ZGENERICASSET.ZFILENAME "
"ZGENERICASSET.ZFILENAME, "
"ZGENERICASSET.ZLATITUDE, "
"ZGENERICASSET.ZLONGITUDE "
"FROM ZGENERICASSET "
"JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = ZGENERICASSET.Z_PK "
"WHERE ZGENERICASSET.ZTRASHEDSTATE = 0 AND ZGENERICASSET.ZKIND = 0 "
@@ -761,7 +762,9 @@ class PhotosDB:
# 9 "ZGENERICASSET.ZHIDDEN, "
# 10 "ZGENERICASSET.ZFAVORITE, "
# 11 "ZGENERICASSET.ZDIRECTORY, "
# 12 "ZGENERICASSET.ZFILENAME "
# 12 "ZGENERICASSET.ZFILENAME, "
# 13 "ZGENERICASSET.ZLATITUDE, "
# 14 "ZGENERICASSET.ZLONGITUDE "
i = 0
for row in c:
@@ -799,6 +802,15 @@ class PhotosDB:
self._dbphotos[uuid]["filename"] = row[12]
self._dbphotos[uuid]["directory"] = row[11]
# set latitude and longitude
# if both latitude and longitude = -180.0, then they are NULL
if row[13] == -180.0 and row[14] == -180.0:
self._dbphotos[uuid]["latitude"] = None
self._dbphotos[uuid]["longitude"] = None
else:
self._dbphotos[uuid]["latitude"] = row[13]
self._dbphotos[uuid]["longitude"] = row[14]
# these will get filled in later
# init to avoid key errors
self._dbphotos[uuid]["extendedDescription"] = None # fill this in later
@@ -1087,14 +1099,18 @@ class PhotoInfo:
""" True if picture is hidden """
return True if self.__info["hidden"] == 1 else False
def longitude(self):
def location(self):
""" returns (latitude, longitude) as float in degrees or None """
return (self._latitude(), self._longitude())
def _longitude(self):
""" Returns longitude, in degrees """
return self.__info["longitude"]
def latitude(self):
def _latitude(self):
""" Returns latitude, in degrees """
return self.__info["latitude"]
def __repr__(self):
return f"osxphotos.PhotoInfo(db={self.__db}, uuid='{self.__uuid}', info={self.__info})"

View File

@@ -38,7 +38,7 @@ with open(path.join(this_directory, "README.md"), encoding="utf-8") as f:
setup(
name="osxphotos",
version="0.14.4",
version="0.14.5",
description="Manipulate (read-only) Apple's Photos app library on Mac OS X",
long_description=long_description,
long_description_content_type="text/markdown",

View File

@@ -181,6 +181,30 @@ def test_not_hidden():
p = photos[0]
assert p.hidden() == False
def test_location_1():
# test photo with lat/lon info
import osxphotos
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=["DC99FBDD-7A52-4100-A5BB-344131646C30"])
assert len(photos) == 1
p = photos[0]
lat, lon = p.location()
assert lat == pytest.approx(51.50357167)
assert lon == pytest.approx(-0.1318055)
def test_location_2():
# test photo with no location info
import osxphotos
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=["6191423D-8DB8-4D4C-92BE-9BBBA308AAC4"])
assert len(photos) == 1
p = photos[0]
lat, lon = p.location()
assert lat is None
assert lon is None
def test_count():
import osxphotos

View File

@@ -181,6 +181,30 @@ def test_not_hidden():
assert p.hidden() == False
def test_location_1():
#test photo with lat/lon info
import osxphotos
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=["3Jn73XpSQQCluzRBMWRsMA"])
assert len(photos) == 1
p = photos[0]
lat, lon = p.location()
assert lat == pytest.approx(51.50357167)
assert lon == pytest.approx(-0.1318055)
def test_location_2():
# test photo with no location info
import osxphotos
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
photos = photosdb.photos(uuid=["YZFCPY24TUySvpu7owiqxA"])
assert len(photos) == 1
p = photos[0]
lat, lon = p.location()
assert lat is None
assert lon is None
def test_count():
import osxphotos