Skip to content

Commit

Permalink
Bug fix for Finder comments extended attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
RhetTbull committed Dec 31, 2020
1 parent a20cfa1 commit 477c64e
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 63 deletions.
2 changes: 1 addition & 1 deletion osxmetadata/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -762,8 +762,8 @@ def process_single_file(
md.set_attribute(attr1, md.get_attribute(attr2))

if get:
data = {}
if json_:
data = {}
data["_version"] = __version__
data["_filepath"] = fpath.resolve().as_posix()
data["_filename"] = fpath.name
Expand Down
2 changes: 1 addition & 1 deletion osxmetadata/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.99.12"
__version__ = "0.99.13"
2 changes: 1 addition & 1 deletion osxmetadata/attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import logging
from collections import namedtuple # pylint: disable=syntax-error

from .classes import _AttributeList, _AttributeTagsList, _AttributeFinderInfo
from .classes import _AttributeFinderInfo, _AttributeList, _AttributeTagsList
from .constants import *
from .datetime_utils import (
datetime_has_tz,
Expand Down
46 changes: 0 additions & 46 deletions osxmetadata/findercomments.py

This file was deleted.

62 changes: 55 additions & 7 deletions osxmetadata/osxmetadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import datetime
import json
import logging
import os.path
import pathlib
import plistlib
import sys
Expand All @@ -14,6 +15,7 @@

import xattr

from . import _applescript
from ._version import __version__
from .attributes import ATTRIBUTES, Attribute, validate_attribute_value
from .classes import _AttributeList, _AttributeTagsList
Expand Down Expand Up @@ -45,7 +47,6 @@
datetime_utc_to_local,
)
from .debug import _debug, _get_logger, _set_debug
from .findercomments import clear_finder_comment, set_finder_comment
from .findertags import Tag, get_tag_color_name, set_finderinfo_color

__all__ = [
Expand All @@ -71,6 +72,27 @@
# TODO: check what happens if OSXMetaData.__init__ called with invalid file--should result in error but saw one case where it didn't
# TODO: cleartags does not always clear colors--this is a new behavior, did Mac OS change something in implementation of colors?

# AppleScript for manipulating Finder comments
_scpt_set_finder_comment = _applescript.AppleScript(
"""
on run {path, fc}
set thePath to path
set theComment to fc
tell application "Finder" to set comment of (POSIX file thePath as alias) to theComment
end run
"""
)

_scpt_clear_finder_comment = _applescript.AppleScript(
"""
on run {path}
set thePath to path
set theComment to missing value
tell application "Finder" to set comment of (POSIX file thePath as alias) to theComment
end run
"""
)


class OSXMetaData:
"""Create an OSXMetaData object to access file metadata"""
Expand Down Expand Up @@ -305,7 +327,7 @@ def set_attribute(self, attribute_name, value):
if attribute.name in _FINDER_COMMENT_NAMES:
# Finder Comment needs special handling
# code following will also set the attribute for Finder Comment
set_finder_comment(self._posix_name, value)
self.set_finder_comment(self._posix_name, value)
elif attribute.class_ in [_AttributeList, _AttributeTagsList]:
getattr(self, attribute.name).set_value(value)
else:
Expand Down Expand Up @@ -378,10 +400,7 @@ def append_attribute(self, attribute_name, value, update=False):
try:
if attribute.name in _FINDER_COMMENT_NAMES:
# Finder Comment needs special handling
# code following will also set the attribute for Finder Comment
set_finder_comment(self._posix_name, new_value)
plist = plistlib.dumps(new_value, fmt=FMT_BINARY)
self._attrs.set(attribute.constant, plist)
self.set_finder_comment(self._posix_name, new_value)
elif attribute.class_ in [_AttributeList, _AttributeTagsList]:
# if tags, set_value will normalize
getattr(self, attribute.name).set_value(new_value)
Expand Down Expand Up @@ -441,7 +460,7 @@ def clear_attribute(self, attribute_name):
if attribute.name in _FINDER_COMMENT_NAMES:
# Finder Comment needs special handling
# code following will also clear the attribute for Finder Comment
clear_finder_comment(self._posix_name)
self.clear_finder_comment(self._posix_name)

if attribute.name in ["finderinfo", "tags"]:
# don't clear the entire FinderInfo attribute, just delete the color
Expand Down Expand Up @@ -472,6 +491,35 @@ def list_metadata(self):
]
return mdlist

def set_finder_comment(self, path, comment):
""" set finder comment for object path (file or directory)
path: path to file or directory in posix format
comment: comment string
"""
if not os.path.exists(path):
raise FileNotFoundError(f"Could not find {path}")

if comment:
_scpt_set_finder_comment.run(path, comment)
plist = plistlib.dumps(comment, fmt=FMT_BINARY)
self._attrs.set(ATTRIBUTES["findercomment"].constant, plist)
else:
self.clear_finder_comment(path)

def clear_finder_comment(self, path):
""" clear finder comment for object path (file or directory)
path: path to file or directory in posix format
"""
if not os.path.exists(path):
raise FileNotFoundError(f"Could not find {path}")

_scpt_clear_finder_comment.run(path)
try:
self._attrs.remove(ATTRIBUTES["findercomment"].constant)
except (IOError, OSError):
# exception raised if attribute not found and attempt to remove it
pass

def __getattr__(self, name):
""" if attribute name is in ATTRIBUTE dict, return the value
otherwise raise KeyError """
Expand Down
12 changes: 6 additions & 6 deletions tests/test_findercomment.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ def test_finder_comments(temp_file):
fc += ", foo"
assert meta.findercomment == fc

# set finder comment to "" results in null string but not deleted
# set finder comment to "" deletes it as this mirrors Finder and mdls
meta.findercomment = ""
assert meta.findercomment == ""
assert meta.findercomment is None

meta.findercomment = "foo"
assert meta.findercomment == "foo"
Expand Down Expand Up @@ -68,16 +68,16 @@ def test_finder_comments_2(temp_file):
fc += ", foo"
assert meta.findercomment == fc

# set finder comment to "" results in null string but not deleted
# set finder comment to "" deletes it as this mirrors mdls and Finder
meta.set_attribute(attribute, "")
assert meta.get_attribute(attribute) == ""
assert meta.get_attribute(attribute) is None

meta.set_attribute(attribute, "foo")
assert meta.get_attribute(attribute) == "foo"

# set finder comment to None deletes it
meta.set_attribute(attribute, "")
assert meta.get_attribute(attribute) == ""
meta.set_attribute(attribute, None)
assert meta.get_attribute(attribute) is None

meta.clear_attribute(attribute)
assert meta.get_attribute(attribute) is None
Expand Down
2 changes: 1 addition & 1 deletion tests/test_osxmetadata.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#!/usr/bin/env python

import platform
from tempfile import NamedTemporaryFile, TemporaryDirectory

import pytest
import platform


@pytest.fixture(params=["file", "dir"])
Expand Down

0 comments on commit 477c64e

Please sign in to comment.