Fixed sidecar collisions, closes #210
This commit is contained in:
@@ -1,3 +1,3 @@
|
|||||||
""" version info """
|
""" version info """
|
||||||
|
|
||||||
__version__ = "0.33.7"
|
__version__ = "0.33.8"
|
||||||
|
|||||||
@@ -688,7 +688,7 @@ def export2(
|
|||||||
|
|
||||||
if sidecar_json:
|
if sidecar_json:
|
||||||
logging.debug("writing exiftool_json_sidecar")
|
logging.debug("writing exiftool_json_sidecar")
|
||||||
sidecar_filename = dest.parent / pathlib.Path(f"{dest.stem}.json")
|
sidecar_filename = dest.parent / pathlib.Path(f"{dest.stem}{dest.suffix}.json")
|
||||||
sidecar_str = self._exiftool_json_sidecar(
|
sidecar_str = self._exiftool_json_sidecar(
|
||||||
use_albums_as_keywords=use_albums_as_keywords,
|
use_albums_as_keywords=use_albums_as_keywords,
|
||||||
use_persons_as_keywords=use_persons_as_keywords,
|
use_persons_as_keywords=use_persons_as_keywords,
|
||||||
@@ -704,12 +704,13 @@ def export2(
|
|||||||
|
|
||||||
if sidecar_xmp:
|
if sidecar_xmp:
|
||||||
logging.debug("writing xmp_sidecar")
|
logging.debug("writing xmp_sidecar")
|
||||||
sidecar_filename = dest.parent / pathlib.Path(f"{dest.stem}.xmp")
|
sidecar_filename = dest.parent / pathlib.Path(f"{dest.stem}{dest.suffix}.xmp")
|
||||||
sidecar_str = self._xmp_sidecar(
|
sidecar_str = self._xmp_sidecar(
|
||||||
use_albums_as_keywords=use_albums_as_keywords,
|
use_albums_as_keywords=use_albums_as_keywords,
|
||||||
use_persons_as_keywords=use_persons_as_keywords,
|
use_persons_as_keywords=use_persons_as_keywords,
|
||||||
keyword_template=keyword_template,
|
keyword_template=keyword_template,
|
||||||
description_template=description_template,
|
description_template=description_template,
|
||||||
|
extension=dest.suffix[1:] if dest.suffix else None,
|
||||||
)
|
)
|
||||||
if not dry_run:
|
if not dry_run:
|
||||||
try:
|
try:
|
||||||
@@ -1120,6 +1121,7 @@ def _xmp_sidecar(
|
|||||||
use_persons_as_keywords=False,
|
use_persons_as_keywords=False,
|
||||||
keyword_template=None,
|
keyword_template=None,
|
||||||
description_template=None,
|
description_template=None,
|
||||||
|
extension=None
|
||||||
):
|
):
|
||||||
""" returns string for XMP sidecar
|
""" returns string for XMP sidecar
|
||||||
use_albums_as_keywords: treat album names as keywords
|
use_albums_as_keywords: treat album names as keywords
|
||||||
@@ -1129,10 +1131,9 @@ def _xmp_sidecar(
|
|||||||
|
|
||||||
xmp_template = Template(filename=os.path.join(_TEMPLATE_DIR, _XMP_TEMPLATE_NAME))
|
xmp_template = Template(filename=os.path.join(_TEMPLATE_DIR, _XMP_TEMPLATE_NAME))
|
||||||
|
|
||||||
if self.path is not None:
|
if extension is None:
|
||||||
extension = pathlib.Path(self.path).suffix[1:].upper()
|
extension = pathlib.Path(self.original_filename)
|
||||||
else:
|
extension = extension.suffix[1:] if extension.suffix else None
|
||||||
extension = None
|
|
||||||
|
|
||||||
if description_template is not None:
|
if description_template is not None:
|
||||||
description = self.render_template(
|
description = self.render_template(
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ CLI_EXPORT_BY_DATE_NEED_TOUCH_UUID = [
|
|||||||
CLI_EXPORT_BY_DATE_NEED_TOUCH_TIMES = [1538165227, 1539436692]
|
CLI_EXPORT_BY_DATE_NEED_TOUCH_TIMES = [1538165227, 1539436692]
|
||||||
CLI_EXPORT_BY_DATE = ["2018/09/28/Pumpkins3.jpg", "2018/09/28/Pumkins1.jpg"]
|
CLI_EXPORT_BY_DATE = ["2018/09/28/Pumpkins3.jpg", "2018/09/28/Pumkins1.jpg"]
|
||||||
|
|
||||||
CLI_EXPORT_SIDECAR_FILENAMES = ["Pumkins2.jpg", "Pumkins2.json", "Pumkins2.xmp"]
|
CLI_EXPORT_SIDECAR_FILENAMES = ["Pumkins2.jpg", "Pumkins2.jpg.json", "Pumkins2.jpg.xmp"]
|
||||||
|
|
||||||
CLI_EXPORT_LIVE = [
|
CLI_EXPORT_LIVE = [
|
||||||
"51F2BEF7-431A-4D31-8AC1-3284A57826AE.jpeg",
|
"51F2BEF7-431A-4D31-8AC1-3284A57826AE.jpeg",
|
||||||
@@ -224,7 +224,7 @@ CLI_UUID_DICT_15_5 = {
|
|||||||
"template": "F12384F6-CD17-4151-ACBA-AE0E3688539E",
|
"template": "F12384F6-CD17-4151-ACBA-AE0E3688539E",
|
||||||
}
|
}
|
||||||
|
|
||||||
CLI_TEMPLATE_SIDECAR_FILENAME = "Pumkins1.json"
|
CLI_TEMPLATE_SIDECAR_FILENAME = "Pumkins1.jpg.json"
|
||||||
|
|
||||||
CLI_UUID_DICT_14_6 = {"intrash": "3tljdX43R8+k6peNHVrJNQ"}
|
CLI_UUID_DICT_14_6 = {"intrash": "3tljdX43R8+k6peNHVrJNQ"}
|
||||||
|
|
||||||
@@ -2256,7 +2256,7 @@ def test_export_sidecar_keyword_template():
|
|||||||
"EXIF:ModifyDate": "2020:04:11 12:34:16"}]"""
|
"EXIF:ModifyDate": "2020:04:11 12:34:16"}]"""
|
||||||
)[0]
|
)[0]
|
||||||
|
|
||||||
json_file = open("Pumkins2.json", "r")
|
json_file = open("Pumkins2.jpg.json", "r")
|
||||||
json_got = json.load(json_file)[0]
|
json_got = json.load(json_file)[0]
|
||||||
json_file.close()
|
json_file.close()
|
||||||
|
|
||||||
|
|||||||
@@ -63,9 +63,10 @@ UUID_DICT = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# used with UUID_DICT["xmp"]
|
# used with UUID_DICT["xmp"]
|
||||||
XMP_FILENAME = "Pumkins1.xmp"
|
XMP_FILENAME = "Pumkins1.jpg.xmp"
|
||||||
XMP_JPG_FILENAME = "Pumkins1.jpg"
|
XMP_JPG_FILENAME = "Pumkins1.jpg"
|
||||||
|
|
||||||
|
|
||||||
def test_export_1():
|
def test_export_1():
|
||||||
# test basic export
|
# test basic export
|
||||||
# get an unedited image and export it using default filename
|
# get an unedited image and export it using default filename
|
||||||
@@ -581,7 +582,8 @@ def test_xmp_sidecar_is_valid(tmp_path):
|
|||||||
assert xmp_file.is_file()
|
assert xmp_file.is_file()
|
||||||
exiftool = ExifTool(str(xmp_file))
|
exiftool = ExifTool(str(xmp_file))
|
||||||
output = exiftool.run_commands("-validate", "-warning")
|
output = exiftool.run_commands("-validate", "-warning")
|
||||||
assert output == b'[ExifTool] Validate : 0 0 0'
|
assert output == b"[ExifTool] Validate : 0 0 0"
|
||||||
|
|
||||||
|
|
||||||
def test_xmp_sidecar():
|
def test_xmp_sidecar():
|
||||||
import osxphotos
|
import osxphotos
|
||||||
@@ -596,7 +598,73 @@ def test_xmp_sidecar():
|
|||||||
<rdf:Description rdf:about=""
|
<rdf:Description rdf:about=""
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
||||||
<photoshop:SidecarForExtension>JPEG</photoshop:SidecarForExtension>
|
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
|
||||||
|
<dc:description>Girls with pumpkins</dc:description>
|
||||||
|
<dc:title>Can we carry this?</dc:title>
|
||||||
|
<!-- keywords and persons listed in <dc:subject> as Photos does -->
|
||||||
|
<dc:subject>
|
||||||
|
<rdf:Seq>
|
||||||
|
<rdf:li>Kids</rdf:li>
|
||||||
|
<rdf:li>Suzy</rdf:li>
|
||||||
|
<rdf:li>Katie</rdf:li>
|
||||||
|
</rdf:Seq>
|
||||||
|
</dc:subject>
|
||||||
|
<photoshop:DateCreated>2018-09-28T15:35:49.063000-04:00</photoshop:DateCreated>
|
||||||
|
</rdf:Description>
|
||||||
|
<rdf:Description rdf:about=""
|
||||||
|
xmlns:Iptc4xmpExt='http://iptc.org/std/Iptc4xmpExt/2008-02-29/'>
|
||||||
|
<Iptc4xmpExt:PersonInImage>
|
||||||
|
<rdf:Bag>
|
||||||
|
<rdf:li>Suzy</rdf:li>
|
||||||
|
<rdf:li>Katie</rdf:li>
|
||||||
|
</rdf:Bag>
|
||||||
|
</Iptc4xmpExt:PersonInImage>
|
||||||
|
</rdf:Description>
|
||||||
|
<rdf:Description rdf:about=""
|
||||||
|
xmlns:digiKam='http://www.digikam.org/ns/1.0/'>
|
||||||
|
<digiKam:TagsList>
|
||||||
|
<rdf:Seq>
|
||||||
|
<rdf:li>Kids</rdf:li>
|
||||||
|
</rdf:Seq>
|
||||||
|
</digiKam:TagsList>
|
||||||
|
</rdf:Description>
|
||||||
|
<rdf:Description rdf:about=""
|
||||||
|
xmlns:xmp='http://ns.adobe.com/xap/1.0/'>
|
||||||
|
<xmp:CreateDate>2018-09-28T15:35:49</xmp:CreateDate>
|
||||||
|
<xmp:ModifyDate>2018-09-28T15:35:49</xmp:ModifyDate>
|
||||||
|
</rdf:Description>
|
||||||
|
<rdf:Description rdf:about=""
|
||||||
|
xmlns:exif='http://ns.adobe.com/exif/1.0/'>
|
||||||
|
</rdf:Description>
|
||||||
|
</rdf:RDF>
|
||||||
|
</x:xmpmeta>"""
|
||||||
|
|
||||||
|
xmp_expected_lines = [line.strip() for line in xmp_expected.split("\n")]
|
||||||
|
|
||||||
|
xmp_got = photos[0]._xmp_sidecar(extension="jpg")
|
||||||
|
xmp_got_lines = [line.strip() for line in xmp_got.split("\n")]
|
||||||
|
|
||||||
|
for line_expected, line_got in zip(
|
||||||
|
sorted(xmp_expected_lines), sorted(xmp_got_lines)
|
||||||
|
):
|
||||||
|
assert line_expected == line_got
|
||||||
|
|
||||||
|
|
||||||
|
def test_xmp_sidecar_extension():
|
||||||
|
""" test XMP sidecar when no extension is passed """
|
||||||
|
import osxphotos
|
||||||
|
|
||||||
|
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||||
|
photos = photosdb.photos(uuid=[UUID_DICT["xmp"]])
|
||||||
|
|
||||||
|
xmp_expected = """<!-- Created with osxphotos https://github.com/RhetTbull/osxphotos -->
|
||||||
|
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
|
||||||
|
<!-- mirrors Photos 5 "Export IPTC as XMP" option -->
|
||||||
|
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||||
|
<rdf:Description rdf:about=""
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
||||||
|
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
|
||||||
<dc:description>Girls with pumpkins</dc:description>
|
<dc:description>Girls with pumpkins</dc:description>
|
||||||
<dc:title>Can we carry this?</dc:title>
|
<dc:title>Can we carry this?</dc:title>
|
||||||
<!-- keywords and persons listed in <dc:subject> as Photos does -->
|
<!-- keywords and persons listed in <dc:subject> as Photos does -->
|
||||||
@@ -661,7 +729,7 @@ def test_xmp_sidecar_use_persons_keyword():
|
|||||||
<rdf:Description rdf:about=""
|
<rdf:Description rdf:about=""
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
||||||
<photoshop:SidecarForExtension>JPEG</photoshop:SidecarForExtension>
|
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
|
||||||
<dc:description>Girls with pumpkins</dc:description>
|
<dc:description>Girls with pumpkins</dc:description>
|
||||||
<dc:title>Can we carry this?</dc:title>
|
<dc:title>Can we carry this?</dc:title>
|
||||||
<!-- keywords and persons listed in <dc:subject> as Photos does -->
|
<!-- keywords and persons listed in <dc:subject> as Photos does -->
|
||||||
@@ -706,7 +774,7 @@ def test_xmp_sidecar_use_persons_keyword():
|
|||||||
|
|
||||||
xmp_expected_lines = [line.strip() for line in xmp_expected.split("\n")]
|
xmp_expected_lines = [line.strip() for line in xmp_expected.split("\n")]
|
||||||
|
|
||||||
xmp_got = photos[0]._xmp_sidecar(use_persons_as_keywords=True)
|
xmp_got = photos[0]._xmp_sidecar(use_persons_as_keywords=True, extension="jpg")
|
||||||
xmp_got_lines = [line.strip() for line in xmp_got.split("\n")]
|
xmp_got_lines = [line.strip() for line in xmp_got.split("\n")]
|
||||||
|
|
||||||
for line_expected, line_got in zip(
|
for line_expected, line_got in zip(
|
||||||
@@ -728,7 +796,7 @@ def test_xmp_sidecar_use_albums_keyword():
|
|||||||
<rdf:Description rdf:about=""
|
<rdf:Description rdf:about=""
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
||||||
<photoshop:SidecarForExtension>JPEG</photoshop:SidecarForExtension>
|
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
|
||||||
<dc:description>Girls with pumpkins</dc:description>
|
<dc:description>Girls with pumpkins</dc:description>
|
||||||
<dc:title>Can we carry this?</dc:title>
|
<dc:title>Can we carry this?</dc:title>
|
||||||
<!-- keywords and persons listed in <dc:subject> as Photos does -->
|
<!-- keywords and persons listed in <dc:subject> as Photos does -->
|
||||||
@@ -773,7 +841,7 @@ def test_xmp_sidecar_use_albums_keyword():
|
|||||||
|
|
||||||
xmp_expected_lines = [line.strip() for line in xmp_expected.split("\n")]
|
xmp_expected_lines = [line.strip() for line in xmp_expected.split("\n")]
|
||||||
|
|
||||||
xmp_got = photos[0]._xmp_sidecar(use_albums_as_keywords=True)
|
xmp_got = photos[0]._xmp_sidecar(use_albums_as_keywords=True, extension="jpg")
|
||||||
xmp_got_lines = [line.strip() for line in xmp_got.split("\n")]
|
xmp_got_lines = [line.strip() for line in xmp_got.split("\n")]
|
||||||
|
|
||||||
for line_expected, line_got in zip(
|
for line_expected, line_got in zip(
|
||||||
@@ -796,7 +864,7 @@ def test_xmp_sidecar_gps():
|
|||||||
<rdf:Description rdf:about=""
|
<rdf:Description rdf:about=""
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
||||||
<photoshop:SidecarForExtension>JPEG</photoshop:SidecarForExtension>
|
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
|
||||||
<dc:description></dc:description>
|
<dc:description></dc:description>
|
||||||
<dc:title>St. James's Park</dc:title>
|
<dc:title>St. James's Park</dc:title>
|
||||||
<!-- keywords and persons listed in <dc:subject> as Photos does -->
|
<!-- keywords and persons listed in <dc:subject> as Photos does -->
|
||||||
@@ -845,7 +913,7 @@ def test_xmp_sidecar_gps():
|
|||||||
|
|
||||||
xmp_expected_lines = [line.strip() for line in xmp_expected.split("\n")]
|
xmp_expected_lines = [line.strip() for line in xmp_expected.split("\n")]
|
||||||
|
|
||||||
xmp_got = photos[0]._xmp_sidecar()
|
xmp_got = photos[0]._xmp_sidecar(extension="jpg")
|
||||||
xmp_got_lines = [line.strip() for line in xmp_got.split("\n")]
|
xmp_got_lines = [line.strip() for line in xmp_got.split("\n")]
|
||||||
|
|
||||||
for line_expected, line_got in zip(
|
for line_expected, line_got in zip(
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ def test_xmp_sidecar_keyword_template():
|
|||||||
<rdf:Description rdf:about=""
|
<rdf:Description rdf:about=""
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
||||||
<photoshop:SidecarForExtension>JPEG</photoshop:SidecarForExtension>
|
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
|
||||||
<dc:description>Girls with pumpkins</dc:description>
|
<dc:description>Girls with pumpkins</dc:description>
|
||||||
<dc:title>Can we carry this?</dc:title>
|
<dc:title>Can we carry this?</dc:title>
|
||||||
<!-- keywords and persons listed in <dc:subject> as Photos does -->
|
<!-- keywords and persons listed in <dc:subject> as Photos does -->
|
||||||
@@ -213,7 +213,7 @@ def test_xmp_sidecar_keyword_template():
|
|||||||
xmp_expected_lines = [line.strip() for line in xmp_expected.split("\n")]
|
xmp_expected_lines = [line.strip() for line in xmp_expected.split("\n")]
|
||||||
|
|
||||||
xmp_got = photos[0]._xmp_sidecar(
|
xmp_got = photos[0]._xmp_sidecar(
|
||||||
keyword_template=["{created.year}", "{folder_album}"]
|
keyword_template=["{created.year}", "{folder_album}"], extension="jpg"
|
||||||
)
|
)
|
||||||
xmp_got_lines = [line.strip() for line in xmp_got.split("\n")]
|
xmp_got_lines = [line.strip() for line in xmp_got.split("\n")]
|
||||||
|
|
||||||
|
|||||||
@@ -418,7 +418,7 @@ def test_xmp_sidecar():
|
|||||||
<rdf:Description rdf:about=""
|
<rdf:Description rdf:about=""
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
||||||
<photoshop:SidecarForExtension>JPG</photoshop:SidecarForExtension>
|
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
|
||||||
<dc:description>Girls with pumpkins</dc:description>
|
<dc:description>Girls with pumpkins</dc:description>
|
||||||
<dc:title>Can we carry this?</dc:title>
|
<dc:title>Can we carry this?</dc:title>
|
||||||
<!-- keywords and persons listed in <dc:subject> as Photos does -->
|
<!-- keywords and persons listed in <dc:subject> as Photos does -->
|
||||||
@@ -461,7 +461,7 @@ def test_xmp_sidecar():
|
|||||||
|
|
||||||
xmp_expected_lines = [line.strip() for line in xmp_expected.split("\n")]
|
xmp_expected_lines = [line.strip() for line in xmp_expected.split("\n")]
|
||||||
|
|
||||||
xmp_got = photos[0]._xmp_sidecar()
|
xmp_got = photos[0]._xmp_sidecar(extension="jpg")
|
||||||
xmp_got_lines = [line.strip() for line in xmp_got.split("\n")]
|
xmp_got_lines = [line.strip() for line in xmp_got.split("\n")]
|
||||||
|
|
||||||
for line_expected, line_got in zip(xmp_expected_lines, xmp_got_lines):
|
for line_expected, line_got in zip(xmp_expected_lines, xmp_got_lines):
|
||||||
@@ -481,7 +481,7 @@ def test_xmp_sidecar_keyword_template():
|
|||||||
<rdf:Description rdf:about=""
|
<rdf:Description rdf:about=""
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/">
|
||||||
<photoshop:SidecarForExtension>JPG</photoshop:SidecarForExtension>
|
<photoshop:SidecarForExtension>jpg</photoshop:SidecarForExtension>
|
||||||
<dc:description>Girls with pumpkins</dc:description>
|
<dc:description>Girls with pumpkins</dc:description>
|
||||||
<dc:title>Can we carry this?</dc:title>
|
<dc:title>Can we carry this?</dc:title>
|
||||||
<!-- keywords and persons listed in <dc:subject> as Photos does -->
|
<!-- keywords and persons listed in <dc:subject> as Photos does -->
|
||||||
@@ -528,7 +528,7 @@ def test_xmp_sidecar_keyword_template():
|
|||||||
xmp_expected_lines = [line.strip() for line in xmp_expected.split("\n")]
|
xmp_expected_lines = [line.strip() for line in xmp_expected.split("\n")]
|
||||||
|
|
||||||
xmp_got = photos[0]._xmp_sidecar(
|
xmp_got = photos[0]._xmp_sidecar(
|
||||||
keyword_template=["{folder_album}", "{created.year}"]
|
keyword_template=["{folder_album}", "{created.year}"], extension="jpg"
|
||||||
)
|
)
|
||||||
xmp_got_lines = [line.strip() for line in xmp_got.split("\n")]
|
xmp_got_lines = [line.strip() for line in xmp_got.split("\n")]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user