Template system now supports default values
This commit is contained in:
parent
427c4c0bc4
commit
67a9a9e21b
214
README.md
214
README.md
@ -214,19 +214,20 @@ Options:
|
||||
exiftool may be installed from
|
||||
https://exiftool.org/
|
||||
--directory DIRECTORY Optional template for specifying name of
|
||||
output directory. See below for additional
|
||||
details on templating system
|
||||
output directory in the form
|
||||
'{name,DEFAULT}'. See below for additional
|
||||
details on templating system.
|
||||
-h, --help Show this message and exit.
|
||||
|
||||
**Templating System**
|
||||
|
||||
With the --directory option, you may specify a template for the export
|
||||
directory. This directory will be appended to the export path specified in
|
||||
directory. This directory will be appended to the export path specified in
|
||||
the export DEST argument to export. For example, if template is
|
||||
'{created.year}/{created.month}', and export desitnation DEST is
|
||||
'/Users/maria/Pictures/export', the actual export directory for a photo would
|
||||
be '/Users/maria/Pictures/export/2020/March' if the photo was created in
|
||||
March 2020.
|
||||
'/Users/maria/Pictures/export', the actual export directory for a photo would
|
||||
be '/Users/maria/Pictures/export/2020/March' if the photo was created in March
|
||||
2020.
|
||||
|
||||
In the template, valid template substitutions will be replaced by the
|
||||
corresponding value from the table below. Invalid substitutions will result
|
||||
@ -239,54 +240,77 @@ rendered name, escape the curly braces with \, for example, using
|
||||
'{created.year}/\{name\}' for --directory would result in output of
|
||||
2020/{name}/photoname.jpg
|
||||
|
||||
In the current implementation, substitutions which have no value will be
|
||||
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'
|
||||
You may specify an optional default value to use if the substitution does not
|
||||
contain a value (e.g. the value is null) by specifying the default value after
|
||||
a ',' in the template string: for example, if template is
|
||||
'{created.year}/{place.address,'NO_ADDRESS'}' but there was no address
|
||||
associated with the photo, the resulting output would be:
|
||||
'2020/NO_ADDRESS/photoname.jpg'. If specified, the default value may not
|
||||
contain a brace symbol ('{' or '}').
|
||||
|
||||
I plan to extend the templating system to the exported filename so you can specify the filename using a template.
|
||||
If you do not specify a default value and the template substitution has no
|
||||
value, '_' (underscore) will be used as the default value. For example, in the
|
||||
above example, this would result in '2020/_/photoname.jpg' if address was null
|
||||
I plan to eventually extend the templating system to the exported filename so
|
||||
you can specify the filename using a template.
|
||||
|
||||
Substitution Description
|
||||
{name} Filename of the photo
|
||||
{original_name} Photo's original filename when imported to Photos
|
||||
{title} Title of the photo
|
||||
{descr} Description of the photo
|
||||
{created.date} Photo's creation date in ISO format, e.g. '2020-03-22'
|
||||
{created.year} 4-digit year of file creation time
|
||||
{created.yy} 2-digit year of file creation time
|
||||
{created.mm} 2-digit month of the file creation time (zero padded)
|
||||
{created.month} Month name in user's locale of the file creation time
|
||||
{created.mon} Month abbreviation in the user's locale of the file
|
||||
creation time
|
||||
{created.doy} 3-digit day of year (e.g Julian day) of file creation
|
||||
time, starting from 1 (zero padded)
|
||||
{modified.date} Photo's modification date in ISO format, e.g.
|
||||
'2020-03-22'
|
||||
{modified.year} 4-digit year of file modification time
|
||||
{modified.yy} 2-digit year of file modification time
|
||||
{modified.mm} 2-digit month of the file modification time (zero
|
||||
padded)
|
||||
{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;
|
||||
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'
|
||||
{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.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'
|
||||
Substitution Description
|
||||
{name} Filename of the photo
|
||||
{original_name} Photo's original filename when imported to
|
||||
Photos
|
||||
{title} Title of the photo
|
||||
{descr} Description of the photo
|
||||
{created.date} Photo's creation date in ISO format, e.g.
|
||||
'2020-03-22'
|
||||
{created.year} 4-digit year of file creation time
|
||||
{created.yy} 2-digit year of file creation time
|
||||
{created.mm} 2-digit month of the file creation time
|
||||
(zero padded)
|
||||
{created.month} Month name in user's locale of the file
|
||||
creation time
|
||||
{created.mon} Month abbreviation in the user's locale of
|
||||
the file creation time
|
||||
{created.doy} 3-digit day of year (e.g Julian day) of file
|
||||
creation time, starting from 1 (zero padded)
|
||||
{modified.date} Photo's modification date in ISO format,
|
||||
e.g. '2020-03-22'
|
||||
{modified.year} 4-digit year of file modification time
|
||||
{modified.yy} 2-digit year of file modification time
|
||||
{modified.mm} 2-digit month of the file modification time
|
||||
(zero padded)
|
||||
{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, as displayed in Photos
|
||||
{place.name.country} Country name from the photo's reverse
|
||||
geolocation data
|
||||
{place.name.state_province} State or province name from the photo's
|
||||
reverse geolocation data
|
||||
{place.name.city} City or locality name from the photo's
|
||||
reverse geolocation data
|
||||
{place.name.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.address.street} Street part of the postal address, e.g.
|
||||
'2007 18th St NW'
|
||||
{place.address.city} City part of the postal address, e.g.
|
||||
'Washington'
|
||||
{place.address.state_province} State/province part of the postal address,
|
||||
e.g. 'DC'
|
||||
{place.address.postal_code} Postal code part of the postal address, e.g.
|
||||
'20009'
|
||||
{place.address.country} Country name of the postal address, e.g.
|
||||
'United States'
|
||||
{place.address.country_code} ISO country code of the postal address, e.g.
|
||||
'US'
|
||||
```
|
||||
|
||||
Example: export all photos to ~/Desktop/export, including edited versions and live photo movies, group in folders by date created
|
||||
@ -930,14 +954,14 @@ For example: "2038 18th St NW, Washington, DC 20009, United States"
|
||||
|
||||
#### `address`:
|
||||
Returns a `PostalAddress` namedtuple with details of the postal address containing the following fields:
|
||||
- city
|
||||
- country
|
||||
- postal_code
|
||||
- state
|
||||
- street
|
||||
- sub_administrative_area
|
||||
- sub_locality
|
||||
- iso_country_code
|
||||
- `city`
|
||||
- `country`
|
||||
- `postal_code`
|
||||
- `state`
|
||||
- `street`
|
||||
- `sub_administrative_area`
|
||||
- `sub_locality`
|
||||
- `iso_country_code`
|
||||
|
||||
For example:
|
||||
```python
|
||||
@ -947,6 +971,68 @@ PostalAddress(street='3700 Wailea Alanui Dr', sub_locality=None, city='Kihei', s
|
||||
'96753'
|
||||
```
|
||||
|
||||
### Template Functions
|
||||
|
||||
There is a simple template system used by the command line client to specify the output directory using a template. The following are available in `osxphotos.template`.
|
||||
|
||||
#### `render_filepath_template(template, photo, none_str="_")`
|
||||
Render template string for photo. none_str is used if template substitution results in None value and no default specified.
|
||||
- `template`: str in form "{name,DEFAULT}" where name is one of the values in table below. The "," and default value that follows are optional. If specified, "DEFAULT" will be used if "name" is None. This is useful for values which are not always present, for example reverse geolocation data.
|
||||
- `photo`: a [PhotoInfo](#photoinfo) object
|
||||
- `none_str`: optional str to use as substitution when template value is None and no default specified in the template string. default is "_".
|
||||
|
||||
Returns a tuple of (rendered, unmatched) where rendered is the rendered template string with all substitutions made and unmatched is a list of any strings that resembled a template substitution but did not match a known substitution. E.g. strings in the form "{foo}".
|
||||
|
||||
e.g. `render_filepath_template("{created.year}/{foo}", photo)` would return `("2020/{foo}",["{foo}"])`
|
||||
|
||||
| Substitution | Description |
|
||||
|--------------|-------------|
|
||||
|{name}|Filename of the photo|
|
||||
|{original_name}|Photo's original filename when imported to Photos|
|
||||
|{title}|Title of the photo|
|
||||
|{descr}|Description of the photo|
|
||||
|{created.date}|Photo's creation date in ISO format, e.g. '2020-03-22'|
|
||||
|{created.year}|4-digit year of file creation time|
|
||||
|{created.yy}|2-digit year of file creation time|
|
||||
|{created.mm}|2-digit month of the file creation time (zero padded)|
|
||||
|{created.month}|Month name in user's locale of the file creation time|
|
||||
|{created.mon}|Month abbreviation in the user's locale of the file creation time|
|
||||
|{created.doy}|3-digit day of year (e.g Julian day) of file creation time, starting from 1 (zero padded)|
|
||||
|{modified.date}|Photo's modification date in ISO format, e.g. '2020-03-22'|
|
||||
|{modified.year}|4-digit year of file modification time|
|
||||
|{modified.yy}|2-digit year of file modification time|
|
||||
|{modified.mm}|2-digit month of the file modification time (zero padded)|
|
||||
|{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, as displayed in Photos|
|
||||
|{place.name.country}|Country name from the photo's reverse geolocation data|
|
||||
|{place.name.state_province}|State or province name from the photo's reverse geolocation data|
|
||||
|{place.name.city}|City or locality name from the photo's reverse geolocation data|
|
||||
|{place.name.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.address.street}|Street part of the postal address, e.g. '2007 18th St NW'|
|
||||
|{place.address.city}|City part of the postal address, e.g. 'Washington'|
|
||||
|{place.address.state_province}|State/province part of the postal address, e.g. 'DC'|
|
||||
|{place.address.postal_code}|Postal code part of the postal address, e.g. '20009'|
|
||||
|{place.address.country}|Country name of the postal address, e.g. 'United States'|
|
||||
|{place.address.country_code}|ISO country code of the postal address, e.g. 'US'|
|
||||
|
||||
#### `DateTimeFormatter(dt)`
|
||||
Class that provides easy access to formatted datetime values.
|
||||
- `dt`: a datetime.datetime object
|
||||
|
||||
Returnes `DateTimeFormater` class.
|
||||
|
||||
Has the following properties:
|
||||
- `date`: Date in ISO format without timezone, e.g. "2020-03-04"
|
||||
- `year`: 4-digit year
|
||||
- `yy`: 2-digit year
|
||||
- `month`: month name in user's locale
|
||||
- `mon`: month abbreviation in user's locale
|
||||
- `mm`: 2-digit month
|
||||
- `doy`: 3-digit day of year (e.g. Julian day)
|
||||
|
||||
### Utility Functions
|
||||
|
||||
The following functions are located in osxphotos.utils
|
||||
@ -965,15 +1051,15 @@ Returns list of Photos libraries found on the system. **Note**: On MacOS 10.15,
|
||||
|
||||
#### `dd_to_dms_str(lat, lon)`
|
||||
Convert latitude, longitude in degrees to degrees, minutes, seconds as string.
|
||||
lat: latitude in degrees
|
||||
lon: longitude in degrees
|
||||
- `lat`: latitude in degrees
|
||||
- `lon`: longitude in degrees
|
||||
returns: string tuple in format ("51 deg 30' 12.86\\" N", "0 deg 7' 54.50\\" W")
|
||||
This is the same format used by exiftool's json format.
|
||||
|
||||
#### `create_path_by_date(dest, dt)`
|
||||
Creates a path in dest folder in form dest/YYYY/MM/DD/
|
||||
dest: valid path as str
|
||||
dt: datetime.timetuple() object
|
||||
- `dest`: valid path as str
|
||||
- `dt`: datetime.timetuple() object
|
||||
Checks to see if path exists, if it does, do nothing and return path. If path does not exist, creates it and returns path. Useful for exporting photos to a date-based folder structure.
|
||||
|
||||
## Examples
|
||||
|
||||
@ -81,11 +81,11 @@ class ExportCommand(click.Command):
|
||||
formatter.write_text(
|
||||
"With the --directory option, you may specify a template for the "
|
||||
+ "export directory. This directory will be appended to the export path specified "
|
||||
+ " in the export DEST argument to export. For example, if template is "
|
||||
+ "in the export DEST argument to export. For example, if template is "
|
||||
+ "'{created.year}/{created.month}', and export desitnation DEST is "
|
||||
+ "'/Users/maria/Pictures/export', "
|
||||
+ " the actual export directory for a photo would be '/Users/maria/Pictures/export/2020/March' "
|
||||
+ " if the photo was created in March 2020. "
|
||||
+ "the actual export directory for a photo would be '/Users/maria/Pictures/export/2020/March' "
|
||||
+ "if the photo was created in March 2020. "
|
||||
)
|
||||
formatter.write("\n")
|
||||
formatter.write_text(
|
||||
@ -104,16 +104,22 @@ class ExportCommand(click.Command):
|
||||
)
|
||||
formatter.write("\n")
|
||||
formatter.write_text(
|
||||
"In the current implementation, substitutions which have no value "
|
||||
+ "will be replaced by '_', "
|
||||
+ "for example, your template looked like '{created.year}/{place.address}' "
|
||||
"You may specify an optional default value to use if the substitution does not contain a value "
|
||||
+ "(e.g. the value is null) "
|
||||
+ "by specifying the default value after a ',' in the template string: "
|
||||
+ "for example, if template is '{created.year}/{place.address,'NO_ADDRESS'}' "
|
||||
+ "but there was no address associated with the photo, the resulting output would be: "
|
||||
+ "'2020/_/photoname.jpg' "
|
||||
+ "'2020/NO_ADDRESS/photoname.jpg'. "
|
||||
+ "If specified, the default value may not contain a brace symbol ('{' or '}')."
|
||||
)
|
||||
formatter.write("\n")
|
||||
formatter.write_text(
|
||||
"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 "
|
||||
"If you do not specify a default value and the template substitution "
|
||||
+ "has no value, '_' (underscore) will be used as the default value. For example, in the "
|
||||
+ "above example, this would result in '2020/_/photoname.jpg' if address was null"
|
||||
)
|
||||
formatter.write_text(
|
||||
"I plan to eventually extend the templating system "
|
||||
+ "to the exported filename so you can specify the filename using a template."
|
||||
)
|
||||
|
||||
@ -817,8 +823,8 @@ def query(
|
||||
"--directory",
|
||||
metavar="DIRECTORY",
|
||||
default=None,
|
||||
help="Optional template for specifying name of output directory. "
|
||||
"See below for additional details on templating system",
|
||||
help="Optional template for specifying name of output directory in the form '{name,DEFAULT}'. "
|
||||
"See below for additional details on templating system.",
|
||||
)
|
||||
@DB_ARGUMENT
|
||||
@click.argument("dest", nargs=1, type=click.Path(exists=True))
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.24.0"
|
||||
__version__ = "0.24.1"
|
||||
|
||||
@ -25,17 +25,17 @@ TEMPLATE_SUBSTITUTIONS = {
|
||||
"{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, 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.name.country}": "Country name from the photo's reverse geolocation data",
|
||||
"{place.name.state_province}": "State or province name from the photo's reverse geolocation data",
|
||||
"{place.name.city}": "City or locality name from the photo's reverse geolocation data",
|
||||
"{place.name.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_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'",
|
||||
"{place.address.street}": "Street part of the postal address, e.g. '2007 18th St NW'",
|
||||
"{place.address.city}": "City part of the postal address, e.g. 'Washington'",
|
||||
"{place.address.state_province}": "State/province part of the postal address, e.g. 'DC'",
|
||||
"{place.address.postal_code}": "Postal code part of the postal address, e.g. '20009'",
|
||||
"{place.address.country}": "Country name of the postal address, e.g. 'United States'",
|
||||
"{place.address.country_code}": "ISO country code of the postal address, e.g. 'US'",
|
||||
}
|
||||
|
||||
|
||||
@ -119,34 +119,81 @@ def get_template_value(lookup, photo):
|
||||
if lookup == "place.name":
|
||||
return photo.place.name if photo.place else None
|
||||
|
||||
if lookup == "place.names.country":
|
||||
if lookup == "place.name.country":
|
||||
return (
|
||||
photo.place.names.country[0]
|
||||
if photo.place and photo.place.names.country
|
||||
else None
|
||||
)
|
||||
|
||||
if lookup == "place.names.state_province":
|
||||
if lookup == "place.name.state_province":
|
||||
return (
|
||||
photo.place.names.state_province[0]
|
||||
if photo.place and photo.place.names.state_province
|
||||
else None
|
||||
)
|
||||
|
||||
if lookup == "place.names.city":
|
||||
if lookup == "place.name.city":
|
||||
return (
|
||||
photo.place.names.city[0]
|
||||
if photo.place and photo.place.names.city
|
||||
else None
|
||||
)
|
||||
|
||||
if lookup == "place.names.area_of_interest":
|
||||
if lookup == "place.name.area_of_interest":
|
||||
return (
|
||||
photo.place.names.area_of_interest[0]
|
||||
if photo.place and photo.place.names.area_of_interest
|
||||
else None
|
||||
)
|
||||
|
||||
if lookup == "place.address":
|
||||
return (
|
||||
photo.place.address_str if photo.place and photo.place.address_str else None
|
||||
)
|
||||
|
||||
if lookup == "place.address.street":
|
||||
return (
|
||||
photo.place.address.street
|
||||
if photo.place and photo.place.address.street
|
||||
else None
|
||||
)
|
||||
|
||||
if lookup == "place.address.city":
|
||||
return (
|
||||
photo.place.address.city
|
||||
if photo.place and photo.place.address.city
|
||||
else None
|
||||
)
|
||||
|
||||
if lookup == "place.address.state_province":
|
||||
return (
|
||||
photo.place.address.state_province
|
||||
if photo.place and photo.place.address.state_province
|
||||
else None
|
||||
)
|
||||
|
||||
if lookup == "place.address.postal_code":
|
||||
return (
|
||||
photo.place.address.postal_code
|
||||
if photo.place and photo.place.address.postal_code
|
||||
else None
|
||||
)
|
||||
|
||||
if lookup == "place.address.country":
|
||||
return (
|
||||
photo.place.address.country
|
||||
if photo.place and photo.place.address.country
|
||||
else None
|
||||
)
|
||||
|
||||
if lookup == "place.address.country_code":
|
||||
return (
|
||||
photo.place.address.iso_country_code
|
||||
if photo.place and photo.place.address.iso_country_code
|
||||
else None
|
||||
)
|
||||
|
||||
# if here, didn't get a match
|
||||
raise KeyError(f"No rule for processing {lookup}")
|
||||
|
||||
|
||||
@ -109,11 +109,7 @@ def test_PlaceInfo5():
|
||||
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",
|
||||
]
|
||||
assert place.names.city == ["Washington", "Washington", "Washington"]
|
||||
assert place.names.state_province == ["District of Columbia"]
|
||||
assert place.names.country == ["United States"]
|
||||
assert place.country_code == "US"
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
""" Test PlaceInfo """
|
||||
import pytest
|
||||
|
||||
from osxphotos._constants import _UNKNOWN_PERSON
|
||||
|
||||
|
||||
PHOTOS_DB = "./tests/Test-Places-Catalina-10_15_1.photoslibrary/database/photos.db"
|
||||
|
||||
@ -62,23 +60,11 @@ def test_place_place_info_2():
|
||||
assert not photo.place.ishome
|
||||
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.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 (
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
""" 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 = {
|
||||
@ -144,6 +142,7 @@ def test_place_place_info_4():
|
||||
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
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
""" Test PlaceInfo """
|
||||
import pytest
|
||||
|
||||
from osxphotos._constants import _UNKNOWN_PERSON
|
||||
|
||||
PHOTOS_DB = "./tests/Test-10.14.6.photoslibrary/database/photos.db"
|
||||
|
||||
UUID_DICT = {"place_uk": "3Jn73XpSQQCluzRBMWRsMA", "no_place": "15uNd7%8RguTEgNPKHfTWw"}
|
||||
@ -58,7 +56,7 @@ def test_place_str():
|
||||
"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=[], "
|
||||
'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')"
|
||||
)
|
||||
|
||||
120
tests/test_template.py
Normal file
120
tests/test_template.py
Normal file
@ -0,0 +1,120 @@
|
||||
""" Test template.py """
|
||||
import pytest
|
||||
|
||||
PHOTOS_DB = "./tests/Test-Places-Catalina-10_15_1.photoslibrary/database/photos.db"
|
||||
|
||||
UUID_DICT = {"place_dc": "128FB4C6-0B16-4E7D-9108-FB2E90DA1546"}
|
||||
|
||||
|
||||
TEMPLATE_VALUES = {
|
||||
"{name}": "128FB4C6-0B16-4E7D-9108-FB2E90DA1546",
|
||||
"{original_name}": "IMG_1064",
|
||||
"{title}": "Glen Ord",
|
||||
"{descr}": "Jack Rose Dining Saloon",
|
||||
"{created.date}": "2020-02-04",
|
||||
"{created.year}": "2020",
|
||||
"{created.yy}": "20",
|
||||
"{created.mm}": "02",
|
||||
"{created.month}": "February",
|
||||
"{created.mon}": "Feb",
|
||||
"{created.doy}": "035",
|
||||
"{modified.date}": "2020-03-21",
|
||||
"{modified.year}": "2020",
|
||||
"{modified.yy}": "20",
|
||||
"{modified.mm}": "03",
|
||||
"{modified.month}": "March",
|
||||
"{modified.mon}": "Mar",
|
||||
"{modified.doy}": "081",
|
||||
"{place.name}": "Washington, District of Columbia, United States",
|
||||
"{place.name.country}": "United States",
|
||||
"{place.name.state_province}": "District of Columbia",
|
||||
"{place.name.city}": "Washington",
|
||||
"{place.name.area_of_interest}": "_",
|
||||
"{place.address}": "2038 18th St NW, Washington, DC 20009, United States",
|
||||
"{place.address.street}": "2038 18th St NW",
|
||||
"{place.address.city}": "Washington",
|
||||
"{place.address.state_province}": "DC",
|
||||
"{place.address.postal_code}": "20009",
|
||||
"{place.address.country}": "United States",
|
||||
"{place.address.country_code}": "US",
|
||||
}
|
||||
|
||||
|
||||
def test_lookup():
|
||||
""" Test that a lookup is returned for every possible value """
|
||||
import re
|
||||
import osxphotos
|
||||
from osxphotos.template import (
|
||||
get_template_value,
|
||||
render_filepath_template,
|
||||
TEMPLATE_SUBSTITUTIONS,
|
||||
)
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photo = photosdb.photos(uuid=[UUID_DICT["place_dc"]])[0]
|
||||
|
||||
for subst in TEMPLATE_SUBSTITUTIONS:
|
||||
lookup_str = re.match(r"\{([^\\,}]+)\}", subst).group(1)
|
||||
lookup = get_template_value(lookup_str, photo)
|
||||
assert lookup or lookup is None
|
||||
|
||||
|
||||
def test_subst():
|
||||
""" Test that substitutions are correct """
|
||||
import locale
|
||||
import osxphotos
|
||||
from osxphotos.template import render_filepath_template
|
||||
|
||||
locale.setlocale(locale.LC_ALL, "en_US")
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photo = photosdb.photos(uuid=[UUID_DICT["place_dc"]])[0]
|
||||
|
||||
for template in TEMPLATE_VALUES:
|
||||
rendered, _ = render_filepath_template(template, photo)
|
||||
assert rendered == TEMPLATE_VALUES[template]
|
||||
|
||||
|
||||
def test_subst_default_val():
|
||||
""" Test substitution with default value specified """
|
||||
import locale
|
||||
import osxphotos
|
||||
from osxphotos.template import render_filepath_template
|
||||
|
||||
locale.setlocale(locale.LC_ALL, "en_US")
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photo = photosdb.photos(uuid=[UUID_DICT["place_dc"]])[0]
|
||||
|
||||
template = "{place.name.area_of_interest,UNKNOWN}"
|
||||
rendered, _ = render_filepath_template(template, photo)
|
||||
assert rendered == "UNKNOWN"
|
||||
|
||||
|
||||
def test_subst_default_val_2():
|
||||
""" Test substitution with ',' but no default value """
|
||||
import locale
|
||||
import osxphotos
|
||||
from osxphotos.template import render_filepath_template
|
||||
|
||||
locale.setlocale(locale.LC_ALL, "en_US")
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photo = photosdb.photos(uuid=[UUID_DICT["place_dc"]])[0]
|
||||
|
||||
template = "{place.name.area_of_interest,}"
|
||||
rendered, _ = render_filepath_template(template, photo)
|
||||
assert rendered == "_"
|
||||
|
||||
|
||||
def test_subst_unknown_val():
|
||||
""" Test substitution with unknown value specified """
|
||||
import locale
|
||||
import osxphotos
|
||||
from osxphotos.template import render_filepath_template
|
||||
|
||||
locale.setlocale(locale.LC_ALL, "en_US")
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photo = photosdb.photos(uuid=[UUID_DICT["place_dc"]])[0]
|
||||
|
||||
template = "{created.year}/{foo}"
|
||||
rendered, unknown = render_filepath_template(template, photo)
|
||||
assert rendered == "2020/{foo}"
|
||||
assert unknown == ["{foo}"]
|
||||
Loading…
x
Reference in New Issue
Block a user