Added detailed place data in PlaceInfo.names
45
README.md
@ -244,9 +244,7 @@ replaced by '_', for example, your template looked like
|
||||
'{created.year}/{place.address}' but there was no address associated with the
|
||||
photo, the resulting output would be: '2020/_/photoname.jpg'
|
||||
|
||||
I plan to add the option to specify the value to be used for missing
|
||||
subsitutions in a future version. I also plan to extend the templating system
|
||||
to the exported filename so you can specify the filename using a template.
|
||||
I plan to extend the templating system to the exported filename so you can specify the filename using a template.
|
||||
|
||||
Substitution Description
|
||||
{name} Filename of the photo
|
||||
@ -274,7 +272,8 @@ Substitution Description
|
||||
modification time
|
||||
{modified.doy} 3-digit day of year (e.g Julian day) of file
|
||||
modification time, starting from 1 (zero padded)
|
||||
{place.name} Place name from the photo's reverse geolocation data
|
||||
{place.name} Place name from the photo's reverse geolocation data;
|
||||
this is the place name shown in the Photos Info window
|
||||
{place.names} list of place names from the photo's reverse
|
||||
geolocation data, joined with '_', for example, '18th
|
||||
St NW_Washington_DC_United States'
|
||||
@ -888,24 +887,38 @@ If overwrite=False and increment=False, export will fail if destination file alr
|
||||
Returns `True` if photo place is user's home address, otherwise `False`.
|
||||
|
||||
#### `name`
|
||||
Returns the name of the local place as str. This may be a street address (e.g. "2038 18th St NW") or a public place (e.g. "St James\'s Park").
|
||||
Returns the name of the local place as str. This is what Photos displays in the Info window. **Note** Photos 5 uses a different algorithm to determine the name than earlier versions which means the same Photo may have a different place name in Photos 4 and Photos 5. `PhotoInfo.name` will return the name Photos would have shown depending on the version of the library being processed. In Photos 5, the place name is generally more detailed than in earlier versions of Photos.
|
||||
|
||||
For example, I have photo in my library that under Photos 4, has place name of "Mayfair Shopping Centre, Victoria, Canada" and under Photos 5 the same photo has place name of "Mayfair, Vancouver Island, Victoria, British Columbia, Canada".
|
||||
|
||||
Returns `None` if photo does not contain a name.
|
||||
|
||||
#### `names`
|
||||
Returns a list of place names in ascending order by area, starting with the smallest area (most local) to largest area (least local). For example:
|
||||
Returns a `PlaceNames` namedtuple with the following fields. Each field is a list with zero or more values, sorted by area in ascending order. E.g. `names.area_of_interest` could be ['Gulf Islands National Seashore', 'Santa Rosa Island'], ["Knott's Berry Farm"], or [] if `area_of_interest` not defined. The value shown in Photos is the first value in the list. With the exception of `body_of_water` each of these field corresponds to an attribute of a [CLPlacemark](https://developer.apple.com/documentation/corelocation/clplacemark) object. **Note** The `PlaceNames` namedtuple contains reserved fields not listed below (see implementation for details), thus it should be referenced only by name (e.g. `names.city`) and not by index.
|
||||
|
||||
["2038 18th St NW",
|
||||
"Adams Morgan",
|
||||
"Washington",
|
||||
"Washington",
|
||||
"Washington",
|
||||
"District of Columbia",
|
||||
"United States"]
|
||||
- `country`; the name of the country associated with the placemark.
|
||||
- `state_province`; administrativeArea, The state or province associated with the placemark.
|
||||
- `sub_administrative_area`; additional administrative area information for the placemark.
|
||||
- `city`; locality; the city associated with the placemark.
|
||||
- `additional_city_info`; subLocality, Additional city-level information for the placemark.
|
||||
- `ocean`; the name of the ocean associated with the placemark.
|
||||
- `area_of_interest`; areasOfInterest, The relevant areas of interest associated with the placemark.
|
||||
- `inland_water`; the name of the inland water body associated with the placemark.
|
||||
- `region`; the geographic region associated with the placemark.
|
||||
- `sub_throughfare`; additional street-level information for the placemark.
|
||||
- `postal_code`; the postal code associated with the placemark.
|
||||
- `street_address`; throughfare, The street address associated with the placemark.
|
||||
- `body_of_water`; in Photos 4, any body of water; in Photos 5 contains the union of ocean and inland_water
|
||||
|
||||
`names[0]` will always be the most local (e.g. street address) component and `names[-1]` will always be the least local which is almost always the country name.
|
||||
**Note**: In Photos <= 4.0, only the following fields are defined; all others are set to empty list:
|
||||
|
||||
**Note**: names may contain duplicates as in above. The data is returned exactly as it is stored by Photos.
|
||||
- `country`
|
||||
- `state_province`
|
||||
- `sub_administrative_area`
|
||||
- `city`
|
||||
- `additional_city_info`
|
||||
- `area_of_interest`
|
||||
- `body_of_water`
|
||||
|
||||
#### `country_code`
|
||||
Returns the country_code of place, for example "GB". Returns `None` if PhotoInfo contains no country code.
|
||||
@ -916,7 +929,7 @@ Returns the full postal address as a string if defined, otherwise `None`.
|
||||
For example: "2038 18th St NW, Washington, DC 20009, United States"
|
||||
|
||||
#### `address`:
|
||||
Returns a `PostalAddress` tuple with details of the postal address containing the following fields:
|
||||
Returns a `PostalAddress` namedtuple with details of the postal address containing the following fields:
|
||||
- city
|
||||
- country
|
||||
- postal_code
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.23.4"
|
||||
__version__ = "0.24.0"
|
||||
|
||||
@ -10,7 +10,7 @@ import logging
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from functools import lru_cache
|
||||
from functools import lru_cache # pylint: disable=syntax-error
|
||||
|
||||
from .utils import _debug
|
||||
|
||||
|
||||
@ -116,8 +116,6 @@ class PhotoInfo:
|
||||
)
|
||||
return photopath
|
||||
|
||||
# if self._info["masterFingerprint"]:
|
||||
# if masterFingerprint is not null, path appears to be valid
|
||||
if self._info["directory"].startswith("/"):
|
||||
photopath = os.path.join(self._info["directory"], self._info["filename"])
|
||||
else:
|
||||
@ -126,13 +124,6 @@ class PhotoInfo:
|
||||
)
|
||||
return photopath
|
||||
|
||||
# if all else fails, photopath = None
|
||||
# photopath = None
|
||||
# logging.debug(
|
||||
# f"WARNING: photopath None, masterFingerprint null, not shared {pformat(self._info)}"
|
||||
# )
|
||||
# return photopath
|
||||
|
||||
@property
|
||||
def path_edited(self):
|
||||
""" absolute path on disk of the edited picture """
|
||||
@ -492,7 +483,7 @@ class PhotoInfo:
|
||||
|
||||
@property
|
||||
def place(self):
|
||||
""" If Photos version >= 5, returns PlaceInfo object containing reverse geolocation info """
|
||||
""" Returns PlaceInfo object containing reverse geolocation info """
|
||||
|
||||
# implementation note: doesn't create the PlaceInfo object until requested
|
||||
# then memoizes the object in self._place to avoid recreating the object
|
||||
@ -500,7 +491,7 @@ class PhotoInfo:
|
||||
if self._db._db_version < _PHOTOS_5_VERSION:
|
||||
try:
|
||||
return self._place # pylint: disable=access-member-before-definition
|
||||
except:
|
||||
except AttributeError:
|
||||
if self._info["placeNames"]:
|
||||
self._place = PlaceInfo4(
|
||||
self._info["placeNames"], self._info["countryCode"]
|
||||
|
||||
@ -395,18 +395,6 @@ class PhotosDB:
|
||||
|
||||
return dest_path
|
||||
|
||||
# def _open_sql_file(self, fname):
|
||||
# """ opens sqlite file fname in read-only mode
|
||||
# returns tuple of (connection, cursor) """
|
||||
# try:
|
||||
# conn = sqlite3.connect(
|
||||
# f"{pathlib.Path(fname).as_uri()}?mode=ro", timeout=1, uri=True
|
||||
# )
|
||||
# c = conn.cursor()
|
||||
# except sqlite3.Error as e:
|
||||
# sys.exit(f"An error occurred opening sqlite file: {e.args[0]} {fname}")
|
||||
# return (conn, c)
|
||||
|
||||
def _get_db_version(self):
|
||||
""" gets the Photos DB version from LiGlobals table """
|
||||
""" returns the version as str"""
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
"""
|
||||
PlaceInfo class
|
||||
Provides reverse geolocation info for photos
|
||||
|
||||
See https://developer.apple.com/documentation/corelocation/clplacemark
|
||||
for additional documentation on reverse geolocation data
|
||||
"""
|
||||
from abc import ABC, abstractmethod
|
||||
from collections import namedtuple # pylint: disable=syntax-error
|
||||
@ -16,13 +19,45 @@ PostalAddress = namedtuple(
|
||||
"sub_locality",
|
||||
"city",
|
||||
"sub_administrative_area",
|
||||
"state",
|
||||
"state_province",
|
||||
"postal_code",
|
||||
"country",
|
||||
"iso_country_code",
|
||||
],
|
||||
)
|
||||
|
||||
# PlaceNames tuple returned by PlaceInfo.names
|
||||
# order of fields 0 - 17 is mapped to placeType value in
|
||||
# PLRevGeoLocationInfo.mapInfo.sortedPlaceInfos
|
||||
# field 18 is combined bodies of water (ocean + inland_water)
|
||||
# and maps to Photos <= 4, RKPlace.type == 44
|
||||
# (Photos <= 4 doesn't have ocean or inland_water types)
|
||||
# The fields named "field0", etc. appear to be unused
|
||||
PlaceNames = namedtuple(
|
||||
"PlaceNames",
|
||||
[
|
||||
"field0",
|
||||
"country", # The name of the country associated with the placemark.
|
||||
"state_province", # administrativeArea, The state or province associated with the placemark.
|
||||
"sub_administrative_area", # Additional administrative area information for the placemark.
|
||||
"city", # locality, The city associated with the placemark.
|
||||
"field5",
|
||||
"additional_city_info", # subLocality, Additional city-level information for the placemark.
|
||||
"ocean", # The name of the ocean associated with the placemark.
|
||||
"area_of_interest", # areasOfInterest, The relevant areas of interest associated with the placemark.
|
||||
"inland_water", # The name of the inland water body associated with the placemark.
|
||||
"field10",
|
||||
"region", # The geographic region associated with the placemark.
|
||||
"sub_throughfare", # Additional street-level information for the placemark.
|
||||
"field13",
|
||||
"postal_code", # The postal code associated with the placemark.
|
||||
"field15",
|
||||
"field16",
|
||||
"street_address", # throughfare, The street address associated with the placemark.
|
||||
"body_of_water", # RKPlace.type == 44, appears to be any body of water (ocean or inland)
|
||||
],
|
||||
)
|
||||
|
||||
# The following classes represent Photo Library Reverse Geolocation Info as stored
|
||||
# in ZADDITIONALASSETATTRIBUTES.ZREVERSELOCATIONDATA
|
||||
# These classes are used by bpylist.archiver to unarchive the serialized objects
|
||||
@ -323,9 +358,18 @@ class PlaceInfo4(PlaceInfo):
|
||||
""" Reverse geolocation place info for a photo (Photos <= 4) """
|
||||
|
||||
def __init__(self, place_names, country_code):
|
||||
""" place_names: list of place names in ascending order by area """
|
||||
""" place_names: list of place name tuples in ascending order by area
|
||||
tuple fields are: modelID, place name, place type, area, e.g.
|
||||
[(5, "St James's Park", 45, 0),
|
||||
(4, 'Westminster', 16, 22097376),
|
||||
(3, 'London', 4, 1596146816),
|
||||
(2, 'England', 2, 180406091776),
|
||||
(1, 'United Kingdom', 1, 414681432064)]
|
||||
country_code: two letter country code for the country
|
||||
"""
|
||||
self._place_names = place_names
|
||||
self._country_code = country_code
|
||||
self._process_place_info()
|
||||
|
||||
@property
|
||||
def address_str(self):
|
||||
@ -341,11 +385,11 @@ class PlaceInfo4(PlaceInfo):
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._place_names[0][1]
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def names(self):
|
||||
return [p[1] for p in self._place_names]
|
||||
return self._names
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
@ -360,6 +404,83 @@ class PlaceInfo4(PlaceInfo):
|
||||
and self._country_code == other._country_code
|
||||
)
|
||||
|
||||
def _process_place_info(self):
|
||||
""" Process place_names to set self._name and self._names """
|
||||
places = self._place_names
|
||||
|
||||
# build a dictionary where key is placetype
|
||||
places_dict = {}
|
||||
for p in places:
|
||||
# places in format:
|
||||
# [(5, "St James's Park", 45, 0), ]
|
||||
# 0: modelID
|
||||
# 1: name
|
||||
# 2: type
|
||||
# 3: area
|
||||
try:
|
||||
places_dict[p[2]].append((p[1], p[3]))
|
||||
except KeyError:
|
||||
places_dict[p[2]] = [(p[1], p[3])]
|
||||
|
||||
# build list to populate PlaceNames tuple
|
||||
# initialize with empty lists for each field in PlaceNames
|
||||
place_info = [[]] * 19
|
||||
|
||||
# add the place names sorted by area (ascending)
|
||||
# in Photos <=4, possible place type values are:
|
||||
# 45: areasOfInterest (The relevant areas of interest associated with the placemark.)
|
||||
# 44: body of water (includes both inlandWater and ocean)
|
||||
# 43: subLocality (Additional city-level information for the placemark.
|
||||
# 16: locality (The city associated with the placemark.)
|
||||
# 4: subAdministrativeArea (Additional administrative area information for the placemark.)
|
||||
# 2: administrativeArea (The state or province associated with the placemark.)
|
||||
# 1: country
|
||||
# mapping = mapping from PlaceNames to field in places_dict
|
||||
# PlaceNames fields map to the placeType value in Photos5 (0..17)
|
||||
# but place type in Photos <=4 has different values
|
||||
# hence (3, 4) means PlaceNames[3] = places_dict[4] (sub_administrative_area)
|
||||
mapping = [(1, 1), (2, 2), (3, 4), (4, 16), (18, 44), (8, 45)]
|
||||
for field5, field4 in mapping:
|
||||
try:
|
||||
place_info[field5] = [
|
||||
p[0]
|
||||
for p in sorted(places_dict[field4], key=lambda place: place[1])
|
||||
]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
place_names = PlaceNames(*place_info)
|
||||
self._names = place_names
|
||||
|
||||
# build the name as it appears in Photos
|
||||
# the length of the name is at most 3 fields and appears to be based on available
|
||||
# reverse geolocation data in the following order (left to right, joined by ',')
|
||||
# always has country if available then either area of interest and city OR
|
||||
# city and state
|
||||
# e.g. 4, 2, 1 OR 8, 4, 1
|
||||
# 8 (45): area_of_interest
|
||||
# 4 (16): locality / city
|
||||
# 2 (2): administrative area (state/province)
|
||||
# 1 (1): country
|
||||
name_list = []
|
||||
if place_names[8]:
|
||||
name_list.append(place_names[8][0])
|
||||
if place_names[4]:
|
||||
name_list.append(place_names[4][0])
|
||||
elif place_names[4]:
|
||||
name_list.append(place_names[4][0])
|
||||
if place_names[2]:
|
||||
name_list.append(place_names[2][0])
|
||||
elif place_names[2]:
|
||||
name_list.append(place_names[2][0])
|
||||
|
||||
# add country
|
||||
if place_names[1]:
|
||||
name_list.append(place_names[1][0])
|
||||
|
||||
name = ", ".join(name_list)
|
||||
self._name = name if name != "" else None
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
@ -382,6 +503,7 @@ class PlaceInfo5(PlaceInfo):
|
||||
self._bplist = revgeoloc_bplist
|
||||
# todo: check for None?
|
||||
self._plrevgeoloc = archiver.unarchive(revgeoloc_bplist)
|
||||
self._process_place_info()
|
||||
|
||||
@property
|
||||
def address_str(self):
|
||||
@ -401,22 +523,12 @@ class PlaceInfo5(PlaceInfo):
|
||||
@property
|
||||
def name(self):
|
||||
""" returns local place name """
|
||||
name = (
|
||||
self._plrevgeoloc.mapItem.sortedPlaceInfos[0].name
|
||||
if self._plrevgeoloc.mapItem.sortedPlaceInfos
|
||||
else None
|
||||
)
|
||||
return name
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def names(self):
|
||||
""" returns list of all place names in reverse order by area
|
||||
e.g. most local is at index 0, least local (usually country) is at index -1 """
|
||||
names = []
|
||||
# todo: strip duplicates
|
||||
for name in self._plrevgeoloc.mapItem.sortedPlaceInfos:
|
||||
names.append(name.name)
|
||||
return names
|
||||
""" returns PlaceNames tuple with detailed reverse geolocation place names """
|
||||
return self._names
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
@ -426,13 +538,72 @@ class PlaceInfo5(PlaceInfo):
|
||||
sub_locality=addr._subLocality,
|
||||
city=addr._city,
|
||||
sub_administrative_area=addr._subAdministrativeArea,
|
||||
state=addr._state,
|
||||
state_province=addr._state,
|
||||
postal_code=addr._postalCode,
|
||||
country=addr._country,
|
||||
iso_country_code=addr._ISOCountryCode,
|
||||
)
|
||||
return address
|
||||
|
||||
def _process_place_info(self):
|
||||
""" Process sortedPlaceInfos to set self._name and self._names """
|
||||
places = self._plrevgeoloc.mapItem.sortedPlaceInfos
|
||||
|
||||
# build a dictionary where key is placetype
|
||||
places_dict = {}
|
||||
for p in places:
|
||||
try:
|
||||
places_dict[p.placeType].append((p.name, p.area))
|
||||
except KeyError:
|
||||
places_dict[p.placeType] = [(p.name, p.area)]
|
||||
|
||||
# build list to populate PlaceNames tuple
|
||||
place_info = []
|
||||
for field in range(18):
|
||||
try:
|
||||
# add the place names sorted by area (ascending)
|
||||
place_info.append(
|
||||
[
|
||||
p[0]
|
||||
for p in sorted(places_dict[field], key=lambda place: place[1])
|
||||
]
|
||||
)
|
||||
except:
|
||||
place_info.append([])
|
||||
|
||||
# fill in body_of_water for compatibility with Photos <= 4
|
||||
place_info.append(place_info[7] + place_info[9])
|
||||
|
||||
place_names = PlaceNames(*place_info)
|
||||
self._names = place_names
|
||||
|
||||
# build the name as it appears in Photos
|
||||
# the length of the name is variable and appears to be based on available
|
||||
# reverse geolocation data in the following order (left to right, joined by ',')
|
||||
# 8: area_of_interest
|
||||
# 11: region (I've only seen this applied to islands)
|
||||
# 4: locality / city
|
||||
# 2: administrative area (state/province)
|
||||
# 1: country
|
||||
# 9: inland_water
|
||||
# 7: ocean
|
||||
name = ", ".join(
|
||||
[
|
||||
p[0]
|
||||
for p in [
|
||||
place_names[8], # area of interest
|
||||
place_names[11], # region (I've only seen this applied to islands)
|
||||
place_names[4], # locality / city
|
||||
place_names[2], # administrative area (state/province)
|
||||
place_names[1], # country
|
||||
place_names[9], # inland_water
|
||||
place_names[7], # ocean
|
||||
]
|
||||
if p and p[0]
|
||||
]
|
||||
)
|
||||
self._name = name if name != "" else None
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, type(self)):
|
||||
return False
|
||||
|
||||
@ -24,12 +24,15 @@ TEMPLATE_SUBSTITUTIONS = {
|
||||
"{modified.month}": "Month name in user's locale of the file modification time",
|
||||
"{modified.mon}": "Month abbreviation in the user's locale of the file modification time",
|
||||
"{modified.doy}": "3-digit day of year (e.g Julian day) of file modification time, starting from 1 (zero padded)",
|
||||
"{place.name}": "Place name from the photo's reverse geolocation data",
|
||||
"{place.names}": "list of place names from the photo's reverse geolocation data, joined with '_', for example, '18th St NW_Washington_DC_United States'",
|
||||
"{place.name}": "Place name from the photo's reverse geolocation data, as displayed in Photos",
|
||||
"{place.names.country}": "Country name from the photo's reverse geolocation data",
|
||||
"{place.names.state_province}": "State or province name from the photo's reverse geolocation data",
|
||||
"{place.names.city}": "City or locality name from the photo's reverse geolocation data",
|
||||
"{place.names.area_of_interest}": "Area of interest name (e.g. landmark or public place) from the photo's reverse geolocation data",
|
||||
"{place.address}": "Postal address from the photo's reverse geolocation data, e.g. '2007 18th St NW, Washington, DC 20009, United States'",
|
||||
"{place.street}": "Street part of the postal address, e.g. '2007 18th St NW'",
|
||||
"{place.city}": "City part of the postal address, e.g. 'Washington'",
|
||||
"{place.state}": "State part of the postal address, e.g. 'DC'",
|
||||
"{place.state_province}": "State/province part of the postal address, e.g. 'DC'",
|
||||
"{place.postal_code}": "Postal code part of the postal address, e.g. '20009'",
|
||||
"{place.country}": "Country name of the postal address, e.g. 'United States'",
|
||||
"{place.country_code}": "ISO country code of the postal address, e.g. 'US'",
|
||||
@ -95,10 +98,10 @@ def render_filename_template(
|
||||
place_name = photo.place.name if photo.place and photo.place.name else none_str
|
||||
rendered = rendered.replace("{place.name}", place_name)
|
||||
|
||||
place_names = (
|
||||
"_".join(photo.place.names) if photo.place and photo.place.names else none_str
|
||||
)
|
||||
rendered = rendered.replace("{place.names}", place_names)
|
||||
# place_names = (
|
||||
# "_".join(photo.place.names) if photo.place and photo.place.names else none_str
|
||||
# )
|
||||
# rendered = rendered.replace("{place.names}", place_names)
|
||||
|
||||
address = (
|
||||
photo.place.address_str if photo.place and photo.place.address_str else none_str
|
||||
@ -119,22 +122,22 @@ def render_filename_template(
|
||||
)
|
||||
rendered = rendered.replace("{place.city}", city)
|
||||
|
||||
state = (
|
||||
photo.place.address.state
|
||||
if photo.place and photo.place.address.state
|
||||
state_province = (
|
||||
photo.place.address.state_province
|
||||
if photo.place and photo.place.address.state_province
|
||||
else none_str
|
||||
)
|
||||
rendered = rendered.replace("{place.state}", state)
|
||||
rendered = rendered.replace("{place.state_province}", state_province)
|
||||
|
||||
postal_code = (
|
||||
photo.place.address.state
|
||||
photo.place.address.postal_code
|
||||
if photo.place and photo.place.address.postal_code
|
||||
else none_str
|
||||
)
|
||||
rendered = rendered.replace("{place.postal_code}", postal_code)
|
||||
|
||||
country = (
|
||||
photo.place.address.state
|
||||
photo.place.address.country
|
||||
if photo.place and photo.place.address.country
|
||||
else none_str
|
||||
)
|
||||
|
||||
|
After Width: | Height: | Size: 4.3 MiB |
|
After Width: | Height: | Size: 457 KiB |
|
After Width: | Height: | Size: 2.1 MiB |
|
After Width: | Height: | Size: 5.0 MiB |
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
@ -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>2020-03-27T13:51:11Z</date>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -0,0 +1,25 @@
|
||||
<?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>lastKnownItemCounts</key>
|
||||
<dict>
|
||||
<key>other</key>
|
||||
<integer>0</integer>
|
||||
<key>photos</key>
|
||||
<integer>6</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>2020-03-27T13:51:13Z</date>
|
||||
<key>PhotoAnalysisGraphLastBackgroundMemoryGenerationJobDate</key>
|
||||
<date>2020-03-27T13:51:13Z</date>
|
||||
</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>ProcessedInQuiescentState</key>
|
||||
<true/>
|
||||
<key>Version</key>
|
||||
<integer>3</integer>
|
||||
</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>4</integer>
|
||||
<key>PersonBuilderLastMinimumFaceGroupSizeForCreatingMergeCandidates</key>
|
||||
<integer>15</integer>
|
||||
<key>PersonBuilderMergeCandidatesEnabled</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -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>2020-03-27T13:51:12Z</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>171</integer>
|
||||
<key>LibraryBuildTag</key>
|
||||
<string>9689BC67-F0CE-460F-B268-CF82E1F1BFC5</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: 114 KiB |
|
After Width: | Height: | Size: 439 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 364 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 134 KiB |
|
After Width: | Height: | Size: 165 KiB |
|
After Width: | Height: | Size: 512 KiB |
|
After Width: | Height: | Size: 140 KiB |
|
After Width: | Height: | Size: 360 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>171</integer>
|
||||
<key>LibraryBuildTag</key>
|
||||
<string>9689BC67-F0CE-460F-B268-CF82E1F1BFC5</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>2020-03-27T13:51:11Z</date>
|
||||
<key>SnapshotLastValidated</key>
|
||||
<date>2020-03-27T13:51:11Z</date>
|
||||
<key>SnapshotTables</key>
|
||||
<dict/>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
tests/test-images/placeinfo/IMG_1523.jpg
Normal file
|
After Width: | Height: | Size: 4.3 MiB |
BIN
tests/test-images/placeinfo/IMG_1523_no_location.jpg
Normal file
|
After Width: | Height: | Size: 457 KiB |
BIN
tests/test-images/placeinfo/IMG_1760.jpg
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
tests/test-images/placeinfo/IMG_1760_Seattle.jpg
Normal file
|
After Width: | Height: | Size: 5.0 MiB |
BIN
tests/test-images/placeinfo/IMG_3439.jpg
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
tests/test-images/placeinfo/IMG_4547.jpg
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
@ -49,7 +49,7 @@ CLI_EXPORTED_DIRECTORY_TEMPLATE_FILENAMES1 = [
|
||||
]
|
||||
|
||||
CLI_EXPORTED_DIRECTORY_TEMPLATE_FILENAMES2 = [
|
||||
"St James's Park/St James Park.jpg",
|
||||
"St James's Park, Great Britain, Westminster, England, United Kingdom/St James Park.jpg",
|
||||
"_/Pumpkins3.jpg",
|
||||
"_/Pumkins2.jpg",
|
||||
"_/Pumkins1.jpg",
|
||||
|
||||
@ -7,11 +7,11 @@ REVERSE_GEO_LOC_DATA_2 = b'bplist00\xd4\x01\x02\x03\x04\x05\x06\x07\nX$versionY$
|
||||
|
||||
# below is just test data, not accurate representation of actual values
|
||||
PLACE_4_INFO_1 = [
|
||||
(1, "St James's Park", 43, 0),
|
||||
(2, "Westminster", 45, 0),
|
||||
(3, "London", 5, 0),
|
||||
(4, "England", 2, 0),
|
||||
(5, "United Kingdom", 1, 0),
|
||||
(5, "St James's Park", 45, 0),
|
||||
(4, "Westminster", 16, 22097376),
|
||||
(3, "London", 4, 1596146816),
|
||||
(2, "England", 2, 180406091776),
|
||||
(1, "United Kingdom", 1, 414681432064),
|
||||
]
|
||||
PLACE_4_NAMES_1 = [
|
||||
"St James's Park",
|
||||
@ -44,14 +44,19 @@ def test_placeInfo4():
|
||||
place = PlaceInfo4(PLACE_4_INFO_1, PLACE_4_COUNTRY_1)
|
||||
assert place is not None
|
||||
assert isinstance(place, PlaceInfo)
|
||||
assert place.name == "St James's Park"
|
||||
assert place.names == PLACE_4_NAMES_1
|
||||
assert place.name == "St James's Park, Westminster, United Kingdom"
|
||||
assert place.names.city == ["Westminster"]
|
||||
assert place.names.country == ["United Kingdom"]
|
||||
assert place.names.area_of_interest == ["St James's Park"]
|
||||
assert place.names.state_province == ["England"]
|
||||
assert place.names.sub_administrative_area == ["London"]
|
||||
assert place.names.region == []
|
||||
assert place.country_code == "GB"
|
||||
assert place.address_str is None
|
||||
assert place.address.city is None
|
||||
assert place.address.country is None
|
||||
assert place.address.postal_code is None
|
||||
assert place.address.state is None
|
||||
assert place.address.state_province is None
|
||||
assert place.address.street is None
|
||||
assert place.address.sub_administrative_area is None
|
||||
assert place.address.sub_locality is None
|
||||
@ -101,22 +106,22 @@ def test_PlaceInfo5():
|
||||
assert place is not None
|
||||
assert isinstance(place, PlaceInfo)
|
||||
assert not place.ishome
|
||||
assert place.name == "2038 18th St NW"
|
||||
assert place.names == [
|
||||
"2038 18th St NW",
|
||||
"Adams Morgan",
|
||||
assert place.name == "Washington, District of Columbia, United States"
|
||||
assert place.names.street_address == ["2038 18th St NW"]
|
||||
assert place.names.additional_city_info == ["Adams Morgan"]
|
||||
assert place.names.city == [
|
||||
"Washington",
|
||||
"Washington",
|
||||
"Washington",
|
||||
"District of Columbia",
|
||||
"United States",
|
||||
]
|
||||
assert place.names.state_province == ["District of Columbia"]
|
||||
assert place.names.country == ["United States"]
|
||||
assert place.country_code == "US"
|
||||
assert place.address_str == "2038 18th St NW, Washington, DC 20009, United States"
|
||||
assert place.address.city == "Washington"
|
||||
assert place.address.country == "United States"
|
||||
assert place.address.postal_code == "20009"
|
||||
assert place.address.state == "DC"
|
||||
assert place.address.state_province == "DC"
|
||||
assert place.address.street == "2038 18th St NW"
|
||||
assert place.address.sub_administrative_area is None
|
||||
assert place.address.sub_locality == "Adams Morgan"
|
||||
|
||||
@ -22,16 +22,19 @@ def test_place_place_info_1():
|
||||
assert photo.place is not None
|
||||
assert isinstance(photo.place, osxphotos.placeinfo.PlaceInfo)
|
||||
assert not photo.place.ishome
|
||||
assert photo.place.name == "2038 18th St NW"
|
||||
assert photo.place.names == [
|
||||
"2038 18th St NW",
|
||||
"Adams Morgan",
|
||||
"Washington",
|
||||
"Washington",
|
||||
"Washington",
|
||||
"District of Columbia",
|
||||
"United States",
|
||||
]
|
||||
assert photo.place.name == "Washington, District of Columbia, United States"
|
||||
assert photo.place.names.country[0] == "United States"
|
||||
assert photo.place.names.state_province[0] == "District of Columbia"
|
||||
assert photo.place.names.city[0] == "Washington"
|
||||
assert photo.place.names.additional_city_info[0] == "Adams Morgan"
|
||||
assert photo.place.names.street_address[0] == "2038 18th St NW"
|
||||
assert photo.place.names.ocean == []
|
||||
assert photo.place.names.area_of_interest == []
|
||||
assert photo.place.names.inland_water == []
|
||||
assert photo.place.names.postal_code == []
|
||||
assert photo.place.names.sub_throughfare == []
|
||||
assert photo.place.names.body_of_water == []
|
||||
|
||||
assert photo.place.country_code == "US"
|
||||
assert (
|
||||
photo.place.address_str
|
||||
@ -40,7 +43,7 @@ def test_place_place_info_1():
|
||||
assert photo.place.address.city == "Washington"
|
||||
assert photo.place.address.country == "United States"
|
||||
assert photo.place.address.postal_code == "20009"
|
||||
assert photo.place.address.state == "DC"
|
||||
assert photo.place.address.state_province == "DC"
|
||||
assert photo.place.address.street == "2038 18th St NW"
|
||||
assert photo.place.address.sub_administrative_area is None
|
||||
assert photo.place.address.sub_locality == "Adams Morgan"
|
||||
@ -57,17 +60,26 @@ def test_place_place_info_2():
|
||||
assert isinstance(photo.place, osxphotos.placeinfo.PlaceInfo)
|
||||
assert photo.place is not None
|
||||
assert not photo.place.ishome
|
||||
assert photo.place.name == "3700 Wailea Alanui Dr"
|
||||
assert photo.place.names == [
|
||||
"3700 Wailea Alanui Dr",
|
||||
assert photo.place.name == "Maui, Wailea, Hawai'i, United States"
|
||||
assert photo.place.names.street_address == ["3700 Wailea Alanui Dr"]
|
||||
assert photo.place.names.city == [
|
||||
"Wailea",
|
||||
"Kihei",
|
||||
"Kihei",
|
||||
]
|
||||
assert photo.place.names.region == [
|
||||
"Maui",
|
||||
]
|
||||
assert photo.place.names.sub_administrative_area == [
|
||||
"Maui",
|
||||
]
|
||||
assert photo.place.names.state_province == [
|
||||
"Hawai'i",
|
||||
]
|
||||
assert photo.place.names.country == [
|
||||
"United States",
|
||||
]
|
||||
|
||||
assert photo.place.country_code == "US"
|
||||
assert (
|
||||
photo.place.address_str
|
||||
@ -77,7 +89,7 @@ def test_place_place_info_2():
|
||||
assert photo.place.address.city == "Kihei"
|
||||
assert photo.place.address.country == "United States"
|
||||
assert photo.place.address.postal_code == "96753"
|
||||
assert photo.place.address.state == "HI"
|
||||
assert photo.place.address.state_province == "HI"
|
||||
assert photo.place.address.street == "3700 Wailea Alanui Dr"
|
||||
assert photo.place.address.sub_administrative_area == "Maui"
|
||||
assert photo.place.address.sub_locality is None
|
||||
@ -94,14 +106,14 @@ def test_place_no_place_info():
|
||||
assert photo.place is None
|
||||
|
||||
|
||||
def test_place_str():
|
||||
# test __str__
|
||||
import osxphotos
|
||||
# def test_place_str():
|
||||
# # test __str__
|
||||
# import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photo = photosdb.photos(uuid=[UUID_DICT["place_dc"]])[0]
|
||||
# photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
# photo = photosdb.photos(uuid=[UUID_DICT["place_dc"]])[0]
|
||||
|
||||
assert (
|
||||
str(photo.place)
|
||||
== "PlaceInfo(name='2038 18th St NW', names='['2038 18th St NW', 'Adams Morgan', 'Washington', 'Washington', 'Washington', 'District of Columbia', 'United States']', country_code='US', ishome='False', address_str='2038 18th St NW, Washington, DC 20009, United States', address='PostalAddress(street='2038 18th St NW', sub_locality='Adams Morgan', city='Washington', sub_administrative_area=None, state='DC', postal_code='20009', country='United States', iso_country_code='US')')"
|
||||
)
|
||||
# assert (
|
||||
# str(photo.place)
|
||||
# == "PlaceInfo(name='2038 18th St NW', names='['2038 18th St NW', 'Adams Morgan', 'Washington', 'Washington', 'Washington', 'District of Columbia', 'United States']', country_code='US', ishome='False', address_str='2038 18th St NW, Washington, DC 20009, United States', address='PostalAddress(street='2038 18th St NW', sub_locality='Adams Morgan', city='Washington', sub_administrative_area=None, state='DC', postal_code='20009', country='United States', iso_country_code='US')')"
|
||||
# )
|
||||
|
||||
172
tests/test_places_high_sierra_10_13_6.py
Normal file
@ -0,0 +1,172 @@
|
||||
""" Test PlaceInfo """
|
||||
import pytest
|
||||
|
||||
from osxphotos._constants import _UNKNOWN_PERSON
|
||||
|
||||
PHOTOS_DB = "./tests/Test-Places-High-Sierra-10.13.6.photoslibrary/database/photos.db"
|
||||
|
||||
UUID_DICT = {
|
||||
"place_dc": "YnaaVzUeQn28zK%eSrT8jg",
|
||||
"no_place": "pERZk5T1Sb+XcKDFRCsGpA",
|
||||
"place_2_names": "ohmoG%mITSG6dcN1PqDMkg",
|
||||
"place_chihuly": "B3PCiPVKSt2eEFGrV5CAFQ",
|
||||
"place_elder_park": "2L6X2hv3ROWRSCU3WRRAGQ",
|
||||
}
|
||||
|
||||
|
||||
def test_place_place_info_1():
|
||||
# test valid place info
|
||||
import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photo = photosdb.photos(uuid=[UUID_DICT["place_dc"]])[0]
|
||||
assert photo.place is not None
|
||||
assert isinstance(photo.place, osxphotos.placeinfo.PlaceInfo)
|
||||
assert not photo.place.ishome
|
||||
assert photo.place.name == "Washington, District of Columbia, United States"
|
||||
assert photo.place.names.country == ["United States"]
|
||||
assert photo.place.names.state_province == ["District of Columbia"]
|
||||
assert photo.place.names.sub_administrative_area == []
|
||||
assert photo.place.names.city == ["Washington"]
|
||||
assert photo.place.names.additional_city_info == []
|
||||
assert photo.place.names.ocean == []
|
||||
assert photo.place.names.area_of_interest == []
|
||||
assert photo.place.names.inland_water == []
|
||||
assert photo.place.names.region == []
|
||||
assert photo.place.names.postal_code == []
|
||||
assert photo.place.names.street_address == []
|
||||
assert photo.place.names.sub_throughfare == []
|
||||
assert photo.place.names.body_of_water == []
|
||||
|
||||
assert photo.place.country_code == "US"
|
||||
assert photo.place.address_str is None
|
||||
assert photo.place.address.city is None
|
||||
assert photo.place.address.country is None
|
||||
assert photo.place.address.postal_code is None
|
||||
assert photo.place.address.state_province is None
|
||||
assert photo.place.address.street is None
|
||||
assert photo.place.address.sub_administrative_area is None
|
||||
assert photo.place.address.sub_locality is None
|
||||
assert photo.place.address.iso_country_code is None
|
||||
|
||||
|
||||
def test_place_place_info_2():
|
||||
# test valid place info with only 2 names of info
|
||||
import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photo = photosdb.photos(uuid=[UUID_DICT["place_2_names"]])[0]
|
||||
assert photo.place is not None
|
||||
assert isinstance(photo.place, osxphotos.placeinfo.PlaceInfo)
|
||||
assert not photo.place.ishome
|
||||
assert photo.place.name == "Artibonite, Haiti"
|
||||
assert photo.place.names.country == ["Haiti"]
|
||||
assert photo.place.names.state_province == ["Artibonite"]
|
||||
assert photo.place.names.sub_administrative_area == []
|
||||
assert photo.place.names.city == []
|
||||
assert photo.place.names.additional_city_info == []
|
||||
assert photo.place.names.ocean == []
|
||||
assert photo.place.names.area_of_interest == []
|
||||
assert photo.place.names.inland_water == []
|
||||
assert photo.place.names.region == []
|
||||
assert photo.place.names.postal_code == []
|
||||
assert photo.place.names.street_address == []
|
||||
assert photo.place.names.sub_throughfare == []
|
||||
assert photo.place.names.body_of_water == ["Caribbean Sea"]
|
||||
|
||||
assert photo.place.country_code == "HT"
|
||||
assert photo.place.address_str is None
|
||||
assert photo.place.address.city is None
|
||||
assert photo.place.address.country is None
|
||||
assert photo.place.address.postal_code is None
|
||||
assert photo.place.address.state_province is None
|
||||
assert photo.place.address.street is None
|
||||
assert photo.place.address.sub_administrative_area is None
|
||||
assert photo.place.address.sub_locality is None
|
||||
assert photo.place.address.iso_country_code is None
|
||||
|
||||
|
||||
def test_place_place_info_3():
|
||||
import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photo = photosdb.photos(uuid=[UUID_DICT["place_chihuly"]])[0]
|
||||
assert photo.place is not None
|
||||
assert isinstance(photo.place, osxphotos.placeinfo.PlaceInfo)
|
||||
assert not photo.place.ishome
|
||||
assert photo.place.name == "Chihuly Garden and Glass, Seattle, United States"
|
||||
assert photo.place.names.country == ["United States"]
|
||||
assert photo.place.names.state_province == ["Washington"]
|
||||
assert photo.place.names.sub_administrative_area == ["King"]
|
||||
assert photo.place.names.city == ["Seattle"]
|
||||
assert photo.place.names.additional_city_info == []
|
||||
assert photo.place.names.ocean == []
|
||||
assert photo.place.names.area_of_interest == ["Chihuly Garden and Glass"]
|
||||
assert photo.place.names.inland_water == []
|
||||
assert photo.place.names.region == []
|
||||
assert photo.place.names.postal_code == []
|
||||
assert photo.place.names.street_address == []
|
||||
assert photo.place.names.sub_throughfare == []
|
||||
assert photo.place.names.body_of_water == []
|
||||
|
||||
assert photo.place.country_code == "US"
|
||||
assert photo.place.address_str is None
|
||||
assert photo.place.address.city is None
|
||||
assert photo.place.address.country is None
|
||||
assert photo.place.address.postal_code is None
|
||||
assert photo.place.address.state_province is None
|
||||
assert photo.place.address.street is None
|
||||
assert photo.place.address.sub_administrative_area is None
|
||||
assert photo.place.address.sub_locality is None
|
||||
assert photo.place.address.iso_country_code is None
|
||||
|
||||
|
||||
def test_place_place_info_4():
|
||||
import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photo = photosdb.photos(uuid=[UUID_DICT["place_elder_park"]])[0]
|
||||
assert photo.place is not None
|
||||
assert isinstance(photo.place, osxphotos.placeinfo.PlaceInfo)
|
||||
assert not photo.place.ishome
|
||||
assert photo.place.name == "Elder Park, Adelaide, Australia"
|
||||
assert photo.place.names.country == ["Australia"]
|
||||
assert photo.place.names.state_province == ["South Australia"]
|
||||
assert photo.place.names.sub_administrative_area == ["Adelaide"]
|
||||
assert photo.place.names.city == ["Adelaide"]
|
||||
assert photo.place.names.additional_city_info == []
|
||||
assert photo.place.names.ocean == []
|
||||
assert photo.place.names.area_of_interest == ["Elder Park"]
|
||||
assert photo.place.names.inland_water == []
|
||||
assert photo.place.names.region == []
|
||||
assert photo.place.names.postal_code == []
|
||||
assert photo.place.names.street_address == []
|
||||
assert photo.place.names.sub_throughfare == []
|
||||
assert photo.place.names.body_of_water == ["River Torrens"]
|
||||
|
||||
def test_place_no_place_info():
|
||||
# test valid place info
|
||||
import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photo = photosdb.photos(uuid=[UUID_DICT["no_place"]])[0]
|
||||
|
||||
assert photo.place is None
|
||||
|
||||
|
||||
# def test_place_str():
|
||||
# # test __str__
|
||||
# import osxphotos
|
||||
|
||||
# photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
# photo = photosdb.photos(uuid=[UUID_DICT["place_uk"]])[0]
|
||||
# assert (
|
||||
# str(photo.place)
|
||||
# == "PlaceInfo(name='St James's Park, Westminster, United Kingdom', "
|
||||
# "names='PlaceNames(field0=[], country=['United Kingdom'], "
|
||||
# "state_province=['England'], sub_administrative_area=['London'], "
|
||||
# "city=['Westminster'], field5=[], additional_city_info=[], ocean=[], "
|
||||
# "area_of_interest=[\"St James's Park\"], inland_water=[], field10=[], "
|
||||
# "region=[], sub_throughfare=[], field13=[], postal_code=[], field15=[], "
|
||||
# "field16=[], street_address=[], body_of_water=[])', country_code='GB')"
|
||||
# )
|
||||
@ -17,20 +17,19 @@ def test_place_place_info_1():
|
||||
assert photo.place is not None
|
||||
assert isinstance(photo.place, osxphotos.placeinfo.PlaceInfo)
|
||||
assert not photo.place.ishome
|
||||
assert photo.place.name == "St James's Park"
|
||||
assert photo.place.names == [
|
||||
"St James's Park",
|
||||
"Westminster",
|
||||
"London",
|
||||
"England",
|
||||
"United Kingdom",
|
||||
]
|
||||
assert photo.place.name == "St James's Park, Westminster, United Kingdom"
|
||||
assert photo.place.names.area_of_interest == ["St James's Park"]
|
||||
assert photo.place.names.city == ["Westminster"]
|
||||
assert photo.place.names.sub_administrative_area == ["London"]
|
||||
assert photo.place.names.state_province == ["England"]
|
||||
assert photo.place.names.country == ["United Kingdom"]
|
||||
|
||||
assert photo.place.country_code == "GB"
|
||||
assert photo.place.address_str is None
|
||||
assert photo.place.address.city is None
|
||||
assert photo.place.address.country is None
|
||||
assert photo.place.address.postal_code is None
|
||||
assert photo.place.address.state is None
|
||||
assert photo.place.address.state_province is None
|
||||
assert photo.place.address.street is None
|
||||
assert photo.place.address.sub_administrative_area is None
|
||||
assert photo.place.address.sub_locality is None
|
||||
@ -55,5 +54,11 @@ def test_place_str():
|
||||
photo = photosdb.photos(uuid=[UUID_DICT["place_uk"]])[0]
|
||||
assert (
|
||||
str(photo.place)
|
||||
== "PlaceInfo(name='St James's Park', names='[\"St James's Park\", 'Westminster', 'London', 'England', 'United Kingdom']', country_code='GB')"
|
||||
== "PlaceInfo(name='St James's Park, Westminster, United Kingdom', "
|
||||
"names='PlaceNames(field0=[], country=['United Kingdom'], "
|
||||
"state_province=['England'], sub_administrative_area=['London'], "
|
||||
"city=['Westminster'], field5=[], additional_city_info=[], ocean=[], "
|
||||
"area_of_interest=[\"St James's Park\"], inland_water=[], field10=[], "
|
||||
"region=[], sub_throughfare=[], field13=[], postal_code=[], field15=[], "
|
||||
"field16=[], street_address=[], body_of_water=[])', country_code='GB')"
|
||||
)
|
||||
|
||||