diff --git a/README.md b/README.md index af52be64..d07fe7fb 100644 --- a/README.md +++ b/README.md @@ -446,6 +446,13 @@ Options: do not include an extension in the FILENAME template. See below for additional details on templating system. + --strip Optionally strip leading and trailing + whitespace from any rendered templates. For + example, if --filename template is "{title,} + {original_name}" and image has no title, + resulting file would have a leading space + but if used with --strip, this will be + removed. --edited-suffix SUFFIX Optional suffix template for naming edited photos. Default name for edited photos is in form 'photoname_edited.ext'. For example, @@ -885,6 +892,19 @@ Substitution Description e.g. 'Summer'; (Photos 5+ only, applied automatically by Photos' image categorization algorithms). +{exif.camera_make} Camera make from original photo's EXIF + inormation as imported by Photos, e.g. + 'Apple' +{exif.camera_model} Camera model from original photo's EXIF + inormation as imported by Photos, e.g. + 'iPhone 6s' +{exif.lens_model} Lens model from original photo's EXIF + inormation as imported by Photos, e.g. + 'iPhone 6s back camera 4.15mm f/2.2' +{uuid} Photo's internal universally unique + identifier (UUID) for the photo, a + 36-character string unique to the photo, + e.g. '128FB4C6-0B16-4E7D-9108-FB2E90DA1546' The following substitutions may result in multiple values. Thus if specified for --directory these could result in multiple copies of a photo being being @@ -1778,7 +1798,7 @@ If overwrite=False and increment=False, export will fail if destination file alr #### `render_template()` -`render_template(template_str, none_str = "_", path_sep = None, expand_inplace = False, inplace_sep = None, filename=False, dirname=False)` +`render_template(template_str, none_str = "_", path_sep = None, expand_inplace = False, inplace_sep = None, filename=False, dirname=False, strip=False)` Render template string for photo. none_str is used if template substitution results in None value and no default specified. @@ -1789,6 +1809,7 @@ Render template string for photo. none_str is used if template substitution res - `inplace_sep`: optional string to use as separator between multi-valued keywords with expand_inplace; default is ',' - `filename`: if True, template output will be sanitized to produce valid file name - `dirname`: if True, template output will be sanitized to produce valid directory name +- `strip`: if True, leading/trailign whitespace will be stripped from rendered template strings Returns a tuple of (rendered, unmatched) where rendered is a list of rendered strings 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. if template contained "{foo}", unmatched would be ["foo"]. @@ -2401,6 +2422,10 @@ The following template field substitutions are availabe for use with `PhotoInfo. |{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'| |{searchinfo.season}|Season of the year associated with a photo, e.g. 'Summer'; (Photos 5+ only, applied automatically by Photos' image categorization algorithms).| +|{exif.camera_make}|Camera make from original photo's EXIF inormation as imported by Photos, e.g. 'Apple'| +|{exif.camera_model}|Camera model from original photo's EXIF inormation as imported by Photos, e.g. 'iPhone 6s'| +|{exif.lens_model}|Lens model from original photo's EXIF inormation as imported by Photos, e.g. 'iPhone 6s back camera 4.15mm f/2.2'| +|{uuid}|Photo's internal universally unique identifier (UUID) for the photo, a 36-character string unique to the photo, e.g. '128FB4C6-0B16-4E7D-9108-FB2E90DA1546'| |{album}|Album(s) photo is contained in| |{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder| |{keyword}|Keyword(s) assigned to photo| diff --git a/osxphotos/__main__.py b/osxphotos/__main__.py index 37ff47d3..2fe9fb44 100644 --- a/osxphotos/__main__.py +++ b/osxphotos/__main__.py @@ -1586,6 +1586,14 @@ def query( "File extension will be added automatically--do not include an extension in the FILENAME template. " "See below for additional details on templating system.", ) +@click.option( + "--strip", + is_flag=True, + help="Optionally strip leading and trailing whitespace from any rendered templates. " + 'For example, if --filename template is "{title,} {original_name}" and image has no ' + "title, resulting file would have a leading space but if used with --strip, this will " + "be removed.", +) @click.option( "--edited-suffix", metavar="SUFFIX", @@ -1749,6 +1757,7 @@ def export( has_raw, directory, filename_template, + strip, edited_suffix, original_suffix, place, @@ -1887,6 +1896,7 @@ def export( has_raw = cfg.has_raw directory = cfg.directory filename_template = cfg.filename_template + strip = cfg.strip edited_suffix = cfg.edited_suffix original_suffix = cfg.original_suffix place = cfg.place @@ -2252,6 +2262,7 @@ def export( ignore_date_modified=ignore_date_modified, use_photokit=use_photokit, exiftool_option=exiftool_option, + strip=strip, ) results += export_results @@ -2276,13 +2287,14 @@ def export( person_keyword=person_keyword, exiftool_merge_keywords=exiftool_merge_keywords, finder_tag_template=finder_tag_template, + strip=strip, ) results.xattr_written.extend(tags_written) results.xattr_skipped.extend(tags_skipped) if xattr_template: xattr_written, xattr_skipped = write_extended_attributes( - p, photo_files, xattr_template + p, photo_files, xattr_template, strip=strip ) results.xattr_written.extend(xattr_written) results.xattr_skipped.extend(xattr_skipped) @@ -2822,6 +2834,7 @@ def export_photo( ignore_date_modified=False, use_photokit=False, exiftool_option=None, + strip=False, ): """Helper function for export that does the actual export @@ -2912,12 +2925,14 @@ def export_photo( if photo.hasadjustments and photo.path_edited is None: missing_edited = True - filenames = get_filenames_from_template(photo, filename_template, original_name) + filenames = get_filenames_from_template( + photo, filename_template, original_name, strip=strip + ) for filename in filenames: if original_suffix: try: rendered_suffix, unmatched = photo.render_template( - original_suffix, filename=True + original_suffix, filename=True, strip=strip ) except ValueError: raise click.BadOptionUsage( @@ -2950,7 +2965,7 @@ def export_photo( ) dest_paths = get_dirnames_from_template( - photo, directory, export_by_date, dest, dry_run + photo, directory, export_by_date, dest, dry_run, strip=strip ) sidecar = [s.lower() for s in sidecar] @@ -3062,7 +3077,7 @@ def export_photo( if edited_suffix: try: rendered_suffix, unmatched = photo.render_template( - edited_suffix, filename=True + edited_suffix, filename=True, strip=strip ) except ValueError: raise click.BadOptionUsage( @@ -3167,7 +3182,7 @@ def export_photo( return results -def get_filenames_from_template(photo, filename_template, original_name): +def get_filenames_from_template(photo, filename_template, original_name, strip=False): """get list of export filenames for a photo Args: @@ -3185,7 +3200,7 @@ def get_filenames_from_template(photo, filename_template, original_name): photo_ext = pathlib.Path(photo.original_filename).suffix try: filenames, unmatched = photo.render_template( - filename_template, path_sep="_", filename=True + filename_template, path_sep="_", filename=True, strip=strip ) except ValueError: raise click.BadOptionUsage( @@ -3208,7 +3223,9 @@ def get_filenames_from_template(photo, filename_template, original_name): return filenames -def get_dirnames_from_template(photo, directory, export_by_date, dest, dry_run): +def get_dirnames_from_template( + photo, directory, export_by_date, dest, dry_run, strip=False +): """get list of directories to export a photo into, creates directories if they don't exist Args: @@ -3236,7 +3253,9 @@ def get_dirnames_from_template(photo, directory, export_by_date, dest, dry_run): elif directory: # got a directory template, render it and check results are valid try: - dirnames, unmatched = photo.render_template(directory, dirname=True) + dirnames, unmatched = photo.render_template( + directory, dirname=True, strip=strip + ) except ValueError: raise click.BadOptionUsage("directory", f"Invalid template '{directory}'") if not dirnames or unmatched: @@ -3498,6 +3517,7 @@ def write_finder_tags( person_keyword=None, exiftool_merge_keywords=None, finder_tag_template=None, + strip=False, ): """Write Finder tags (extended attributes) to files; only writes attributes if attributes on file differ from what would be written @@ -3537,7 +3557,10 @@ def write_finder_tags( for template_str in finder_tag_template: try: rendered, unmatched = photo.render_template( - template_str, none_str=_OSXPHOTOS_NONE_SENTINEL, path_sep="/" + template_str, + none_str=_OSXPHOTOS_NONE_SENTINEL, + path_sep="/", + strip=strip, ) except ValueError: raise click.BadOptionUsage( @@ -3575,7 +3598,7 @@ def write_finder_tags( return (written, skipped) -def write_extended_attributes(photo, files, xattr_template): +def write_extended_attributes(photo, files, xattr_template, strip=False): """ Writes extended attributes to exported files Args: @@ -3590,7 +3613,10 @@ def write_extended_attributes(photo, files, xattr_template): for xattr, template_str in xattr_template: try: rendered, unmatched = photo.render_template( - template_str, none_str=_OSXPHOTOS_NONE_SENTINEL, path_sep="/" + template_str, + none_str=_OSXPHOTOS_NONE_SENTINEL, + path_sep="/", + strip=strip, ) except ValueError: raise click.BadOptionUsage( diff --git a/osxphotos/_version.py b/osxphotos/_version.py index 0a48d76f..0384f60d 100644 --- a/osxphotos/_version.py +++ b/osxphotos/_version.py @@ -1,5 +1,5 @@ """ version info """ -__version__ = "0.39.4" +__version__ = "0.39.5" diff --git a/osxphotos/photoinfo/photoinfo.py b/osxphotos/photoinfo/photoinfo.py index 952fae90..28878afb 100644 --- a/osxphotos/photoinfo/photoinfo.py +++ b/osxphotos/photoinfo/photoinfo.py @@ -832,6 +832,7 @@ class PhotoInfo: inplace_sep=None, filename=False, dirname=False, + strip=False, ): """Renders a template string for PhotoInfo instance using PhotoTemplate @@ -846,6 +847,7 @@ class PhotoInfo: with expand_inplace; default is ',' filename: if True, template output will be sanitized to produce valid file name dirname: if True, template output will be sanitized to produce valid directory name + strip: if True, strips leading/trailing white space from resulting template Returns: ([rendered_strings], [unmatched]): tuple of list of rendered strings and list of unmatched template values @@ -859,6 +861,7 @@ class PhotoInfo: inplace_sep=inplace_sep, filename=filename, dirname=dirname, + strip=strip, ) @property diff --git a/osxphotos/phototemplate.py b/osxphotos/phototemplate.py index 6edd98bd..a2a87855 100644 --- a/osxphotos/phototemplate.py +++ b/osxphotos/phototemplate.py @@ -118,6 +118,10 @@ TEMPLATE_SUBSTITUTIONS = { "{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'", "{searchinfo.season}": "Season of the year associated with a photo, e.g. 'Summer'; (Photos 5+ only, applied automatically by Photos' image categorization algorithms).", + "{exif.camera_make}": "Camera make from original photo's EXIF inormation as imported by Photos, e.g. 'Apple'", + "{exif.camera_model}": "Camera model from original photo's EXIF inormation as imported by Photos, e.g. 'iPhone 6s'", + "{exif.lens_model}": "Lens model from original photo's EXIF inormation as imported by Photos, e.g. 'iPhone 6s back camera 4.15mm f/2.2'", + "{uuid}": "Photo's internal universally unique identifier (UUID) for the photo, a 36-character string unique to the photo, e.g. '128FB4C6-0B16-4E7D-9108-FB2E90DA1546'", } # Permitted multi-value substitutions (each of these returns None or 1 or more values) @@ -251,6 +255,7 @@ class PhotoTemplate: inplace_sep=None, filename=False, dirname=False, + strip=False, ): """ Render a filename or directory template @@ -264,6 +269,7 @@ class PhotoTemplate: with expand_inplace; default is ',' filename: if True, template output will be sanitized to produce valid file name dirname: if True, template output will be sanitized to produce valid directory name + strip: if True, strips leading/trailing whitespace from rendered templates Returns: ([rendered_strings], [unmatched]): tuple of list of rendered strings and list of unmatched template values @@ -364,6 +370,11 @@ class PhotoTemplate: sanitize_filename(rendered_str) for rendered_str in rendered_strings ] + if strip: + rendered_strings = [ + rendered_str.strip() for rendered_str in rendered_strings + ] + return rendered_strings, unmatched def _render_multi_valued_templates( @@ -890,6 +901,14 @@ class PhotoTemplate: ) elif field == "searchinfo.season": value = self.photo.search_info.season if self.photo.search_info else None + elif field == "exif.camera_make": + value = self.photo.exif_info.camera_make if self.photo.exif_info else None + elif field == "exif.camera_model": + value = self.photo.exif_info.camera_model if self.photo.exif_info else None + elif field == "exif.lens_model": + value = self.photo.exif_info.lens_model if self.photo.exif_info else None + elif field == "uuid": + value = self.photo.uuid else: # if here, didn't get a match raise ValueError(f"Unhandled template value: {field}") diff --git a/tests/search_info_test_data_10_15_7.json b/tests/search_info_test_data_10_15_7.json index ac1a61f6..bcf0f070 100644 --- a/tests/search_info_test_data_10_15_7.json +++ b/tests/search_info_test_data_10_15_7.json @@ -1 +1 @@ -{"UUID_SEARCH_INFO": {"C8EAF50A-D891-4E0C-8086-C417E1284153": {"labels": ["Butter", "Food"], "place_names": ["Durham Bulls Athletic Park"], "streets": ["Blackwell St"], "neighborhoods": ["American Tobacco District", "Downtown Durham"], "city": "Durham", "locality_names": ["Durham"], "state": "North Carolina", "state_abbreviation": "NC", "country": "United States", "bodies_of_water": [], "month": "October", "year": "2018", "holidays": [], "activities": ["Dinner", "Travel", "Entertainment", "Dining", "Trip"], "season": "Fall", "venues": ["Copa", "Pie Pusher's", "Luna Rotisserie and Empanadas", "The Pinhook"], "venue_types": ["Nightlife", "Cocktail Bar", "Pizza", "Restaurant", "Bar", "Tapas & Small Plates", "Food", "Empanadas", "Arts & Entertainment", "Chicken Wings", "Latin American", "Cuban", "Music Venue"], "media_types": []}, "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": {"labels": ["Sunset Sunrise", "Desert", "Sky", "Outdoor", "Land"], "place_names": ["Royal Palms State Beach"], "streets": [], "neighborhoods": ["San Pedro"], "city": "Los Angeles", "locality_names": [], "state": "California", "state_abbreviation": "", "country": "United States", "bodies_of_water": ["Catalina Channel"], "month": "November", "year": "2017", "holidays": [], "activities": ["Beach Activity", "Activity"], "season": "Fall", "venues": [], "venue_types": [], "media_types": ["Live Photos"]}, "2C151013-5BBA-4D00-B70F-1C9420418B86": {"labels": ["Forest", "Land", "Water Body", "Furniture", "Bench", "Water", "People", "Plant", "Outdoor", "Vegetation"], "place_names": [], "streets": [], "neighborhoods": [], "city": "", "locality_names": [], "state": "", "state_abbreviation": "", "country": "", "bodies_of_water": [], "month": "December", "year": "2014", "holidays": ["Christmas Day"], "activities": ["Celebration", "Holiday"], "season": "Winter", "venues": [], "venue_types": [], "media_types": []}}, "UUID_SEARCH_INFO_NORMALIZED": {"C8EAF50A-D891-4E0C-8086-C417E1284153": {"labels": ["butter", "food"], "place_names": ["durham bulls athletic park"], "streets": ["blackwell st"], "neighborhoods": ["american tobacco district", "downtown durham"], "city": "durham", "locality_names": ["durham"], "state": "north carolina", "state_abbreviation": "nc", "country": "united states", "bodies_of_water": [], "month": "october", "year": "2018", "holidays": [], "activities": ["dinner", "travel", "entertainment", "dining", "trip"], "season": "fall", "venues": ["copa", "pie pusher's", "luna rotisserie and empanadas", "the pinhook"], "venue_types": ["nightlife", "cocktail bar", "pizza", "restaurant", "bar", "tapas & small plates", "food", "empanadas", "arts & entertainment", "chicken wings", "latin american", "cuban", "music venue"], "media_types": []}, "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": {"labels": ["sunset sunrise", "desert", "sky", "outdoor", "land"], "place_names": ["royal palms state beach"], "streets": [], "neighborhoods": ["san pedro"], "city": "los angeles", "locality_names": [], "state": "california", "state_abbreviation": "", "country": "united states", "bodies_of_water": ["catalina channel"], "month": "november", "year": "2017", "holidays": [], "activities": ["beach activity", "activity"], "season": "fall", "venues": [], "venue_types": [], "media_types": ["live photos"]}, "2C151013-5BBA-4D00-B70F-1C9420418B86": {"labels": ["forest", "land", "water body", "furniture", "bench", "water", "people", "plant", "outdoor", "vegetation"], "place_names": [], "streets": [], "neighborhoods": [], "city": "", "locality_names": [], "state": "", "state_abbreviation": "", "country": "", "bodies_of_water": [], "month": "december", "year": "2014", "holidays": ["christmas day"], "activities": ["celebration", "holiday"], "season": "winter", "venues": [], "venue_types": [], "media_types": []}}, "UUID_SEARCH_INFO_ALL": {"C8EAF50A-D891-4E0C-8086-C417E1284153": ["Butter", "Food", "Durham Bulls Athletic Park", "Blackwell St", "American Tobacco District", "Downtown Durham", "Durham", "Dinner", "Travel", "Entertainment", "Dining", "Trip", "Copa", "Pie Pusher's", "Luna Rotisserie and Empanadas", "The Pinhook", "Nightlife", "Cocktail Bar", "Pizza", "Restaurant", "Bar", "Tapas & Small Plates", "Food", "Empanadas", "Arts & Entertainment", "Chicken Wings", "Latin American", "Cuban", "Music Venue", "Durham", "North Carolina", "NC", "United States", "October", "2018", "Fall"], "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": ["Sunset Sunrise", "Desert", "Sky", "Outdoor", "Land", "Royal Palms State Beach", "San Pedro", "Catalina Channel", "Beach Activity", "Activity", "Live Photos", "Los Angeles", "California", "United States", "November", "2017", "Fall"], "2C151013-5BBA-4D00-B70F-1C9420418B86": ["Forest", "Land", "Water Body", "Furniture", "Bench", "Water", "People", "Plant", "Outdoor", "Vegetation", "Christmas Day", "Celebration", "Holiday", "December", "2014", "Winter"]}, "UUID_SEARCH_INFO_ALL_NORMALIZED": {"C8EAF50A-D891-4E0C-8086-C417E1284153": ["butter", "food", "durham bulls athletic park", "blackwell st", "american tobacco district", "downtown durham", "durham", "dinner", "travel", "entertainment", "dining", "trip", "copa", "pie pusher's", "luna rotisserie and empanadas", "the pinhook", "nightlife", "cocktail bar", "pizza", "restaurant", "bar", "tapas & small plates", "food", "empanadas", "arts & entertainment", "chicken wings", "latin american", "cuban", "music venue", "durham", "north carolina", "nc", "united states", "october", "2018", "fall"], "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": ["sunset sunrise", "desert", "sky", "outdoor", "land", "royal palms state beach", "san pedro", "catalina channel", "beach activity", "activity", "live photos", "los angeles", "california", "united states", "november", "2017", "fall"], "2C151013-5BBA-4D00-B70F-1C9420418B86": ["forest", "land", "water body", "furniture", "bench", "water", "people", "plant", "outdoor", "vegetation", "christmas day", "celebration", "holiday", "december", "2014", "winter"]}} +{"UUID_SEARCH_INFO": {"C8EAF50A-D891-4E0C-8086-C417E1284153": {"labels": ["Butter", "Food"], "place_names": ["Durham Bulls Athletic Park"], "streets": ["Blackwell St"], "neighborhoods": ["American Tobacco District", "Downtown Durham"], "city": "Durham", "locality_names": ["Durham"], "state": "North Carolina", "state_abbreviation": "NC", "country": "United States", "bodies_of_water": [], "month": "October", "year": "2018", "holidays": [], "activities": ["Entertainment", "Travel", "Dining", "Dinner", "Trip"], "season": "Fall", "venues": ["Pie Pusher's", "The Pinhook", "Luna Rotisserie and Empanadas", "Copa"], "venue_types": ["Nightlife", "Cocktail Bar", "Pizza", "Restaurant", "Bar", "Tapas & Small Plates", "Food", "Empanadas", "Chicken Wings", "Arts & Entertainment", "Latin American", "Cuban", "Music Venue"], "media_types": []}, "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": {"labels": ["Desert", "Sky", "Sunset Sunrise", "Outdoor", "Land"], "place_names": ["Royal Palms State Beach"], "streets": [], "neighborhoods": ["San Pedro"], "city": "Los Angeles", "locality_names": [], "state": "California", "state_abbreviation": "", "country": "United States", "bodies_of_water": ["Catalina Channel"], "month": "November", "year": "2017", "holidays": [], "activities": ["Beach Activity", "Activity"], "season": "Fall", "venues": [], "venue_types": [], "media_types": ["Live Photos"]}, "2C151013-5BBA-4D00-B70F-1C9420418B86": {"labels": ["Forest", "Vegetation", "Bench", "Land", "Furniture", "Water", "Water Body", "Outdoor", "People"], "place_names": [], "streets": [], "neighborhoods": [], "city": "", "locality_names": [], "state": "", "state_abbreviation": "", "country": "", "bodies_of_water": [], "month": "December", "year": "2014", "holidays": ["Christmas Day"], "activities": ["Celebration", "Holiday"], "season": "Winter", "venues": [], "venue_types": [], "media_types": []}}, "UUID_SEARCH_INFO_NORMALIZED": {"C8EAF50A-D891-4E0C-8086-C417E1284153": {"labels": ["butter", "food"], "place_names": ["durham bulls athletic park"], "streets": ["blackwell st"], "neighborhoods": ["american tobacco district", "downtown durham"], "city": "durham", "locality_names": ["durham"], "state": "north carolina", "state_abbreviation": "nc", "country": "united states", "bodies_of_water": [], "month": "october", "year": "2018", "holidays": [], "activities": ["entertainment", "travel", "dining", "dinner", "trip"], "season": "fall", "venues": ["pie pusher's", "the pinhook", "luna rotisserie and empanadas", "copa"], "venue_types": ["nightlife", "cocktail bar", "pizza", "restaurant", "bar", "tapas & small plates", "food", "empanadas", "chicken wings", "arts & entertainment", "latin american", "cuban", "music venue"], "media_types": []}, "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": {"labels": ["desert", "sky", "sunset sunrise", "outdoor", "land"], "place_names": ["royal palms state beach"], "streets": [], "neighborhoods": ["san pedro"], "city": "los angeles", "locality_names": [], "state": "california", "state_abbreviation": "", "country": "united states", "bodies_of_water": ["catalina channel"], "month": "november", "year": "2017", "holidays": [], "activities": ["beach activity", "activity"], "season": "fall", "venues": [], "venue_types": [], "media_types": ["live photos"]}, "2C151013-5BBA-4D00-B70F-1C9420418B86": {"labels": ["forest", "vegetation", "bench", "land", "furniture", "water", "water body", "outdoor", "people"], "place_names": [], "streets": [], "neighborhoods": [], "city": "", "locality_names": [], "state": "", "state_abbreviation": "", "country": "", "bodies_of_water": [], "month": "december", "year": "2014", "holidays": ["christmas day"], "activities": ["celebration", "holiday"], "season": "winter", "venues": [], "venue_types": [], "media_types": []}}, "UUID_SEARCH_INFO_ALL": {"C8EAF50A-D891-4E0C-8086-C417E1284153": ["Butter", "Food", "Durham Bulls Athletic Park", "Blackwell St", "American Tobacco District", "Downtown Durham", "Durham", "Entertainment", "Travel", "Dining", "Dinner", "Trip", "Pie Pusher's", "The Pinhook", "Luna Rotisserie and Empanadas", "Copa", "Nightlife", "Cocktail Bar", "Pizza", "Restaurant", "Bar", "Tapas & Small Plates", "Food", "Empanadas", "Chicken Wings", "Arts & Entertainment", "Latin American", "Cuban", "Music Venue", "Durham", "North Carolina", "NC", "United States", "October", "2018", "Fall"], "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": ["Desert", "Sky", "Sunset Sunrise", "Outdoor", "Land", "Royal Palms State Beach", "San Pedro", "Catalina Channel", "Beach Activity", "Activity", "Live Photos", "Los Angeles", "California", "United States", "November", "2017", "Fall"], "2C151013-5BBA-4D00-B70F-1C9420418B86": ["Forest", "Vegetation", "Bench", "Land", "Furniture", "Water", "Water Body", "Outdoor", "People", "Christmas Day", "Celebration", "Holiday", "December", "2014", "Winter"]}, "UUID_SEARCH_INFO_ALL_NORMALIZED": {"C8EAF50A-D891-4E0C-8086-C417E1284153": ["butter", "food", "durham bulls athletic park", "blackwell st", "american tobacco district", "downtown durham", "durham", "entertainment", "travel", "dining", "dinner", "trip", "pie pusher's", "the pinhook", "luna rotisserie and empanadas", "copa", "nightlife", "cocktail bar", "pizza", "restaurant", "bar", "tapas & small plates", "food", "empanadas", "chicken wings", "arts & entertainment", "latin american", "cuban", "music venue", "durham", "north carolina", "nc", "united states", "october", "2018", "fall"], "71DFB4C3-E868-4BE4-906E-D96BD8692D7E": ["desert", "sky", "sunset sunrise", "outdoor", "land", "royal palms state beach", "san pedro", "catalina channel", "beach activity", "activity", "live photos", "los angeles", "california", "united states", "november", "2017", "fall"], "2C151013-5BBA-4D00-B70F-1C9420418B86": ["forest", "vegetation", "bench", "land", "furniture", "water", "water body", "outdoor", "people", "christmas day", "celebration", "holiday", "december", "2014", "winter"]}} diff --git a/tests/test_cli.py b/tests/test_cli.py index bb9453c1..0f6ea834 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -2880,7 +2880,6 @@ def test_export_filename_template_1(): ], ) assert result.exit_code == 0 - workdir = os.getcwd() files = glob.glob("*.*") assert sorted(files) == sorted(CLI_EXPORTED_FILENAME_TEMPLATE_FILENAMES1) @@ -2915,6 +2914,37 @@ def test_export_filename_template_2(): assert sorted(files) == sorted(CLI_EXPORTED_FILENAME_TEMPLATE_FILENAMES2) +def test_export_filename_template_strip(): + """ export photos using filename template with --strip """ + import glob + import locale + import os + import os.path + import osxphotos + from osxphotos.__main__ import export + + locale.setlocale(locale.LC_ALL, "en_US") + + runner = CliRunner() + cwd = os.getcwd() + # pylint: disable=not-context-manager + with runner.isolated_filesystem(): + result = runner.invoke( + export, + [ + os.path.join(cwd, CLI_PHOTOS_DB), + ".", + "-V", + "--filename", + "{searchinfo.venue,} {created.year}-{original_name}", + "--strip", + ], + ) + assert result.exit_code == 0 + files = glob.glob("*.*") + assert sorted(files) == sorted(CLI_EXPORTED_FILENAME_TEMPLATE_FILENAMES1) + + def test_export_filename_template_pathsep_in_name_1(): """ export photos using filename template with folder_album and "/" in album name """ import locale diff --git a/tests/test_template.py b/tests/test_template.py index e9c46250..660c321d 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -136,6 +136,10 @@ TEMPLATE_VALUES = { "{place.address.postal_code}": "20009", "{place.address.country}": "United States", "{place.address.country_code}": "US", + "{uuid}": "128FB4C6-0B16-4E7D-9108-FB2E90DA1546", + "{exif.camera_make}": "Apple", + "{exif.camera_model}": "iPhone 6s", + "{exif.lens_model}": "iPhone 6s back camera 4.15mm f/2.2", }