Skip to content

Commit

Permalink
Ran black on all code
Browse files Browse the repository at this point in the history
  • Loading branch information
RhetTbull committed Dec 29, 2018
1 parent 0fe9e00 commit 1b1384d
Show file tree
Hide file tree
Showing 7 changed files with 1,784 additions and 1,721 deletions.
176 changes: 96 additions & 80 deletions osxmetadata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,55 +12,65 @@
import datetime
from . import _applescript

#this was inspired by osx-tags by "Ben S / scooby" and is published under
#the same MIT license. See: https://github.com/scooby/osx-tags
# this was inspired by osx-tags by "Ben S / scooby" and is published under
# the same MIT license. See: https://github.com/scooby/osx-tags

#TODO: What to do about colors
#TODO: Add ability to remove key instead of just clear contents
# TODO: What to do about colors
# TODO: Add ability to remove key instead of just clear contents

#what to import
__all__ = ['OSXMetaData']
# what to import
__all__ = ["OSXMetaData"]

# color labels
_COLORNAMES = {
'None' : 0,
'Gray' : 1,
'Green': 2,
'Purple': 3,
'Blue': 4,
'Yellow': 5,
'Red': 6,
'Orange' : 7}

_COLORIDS = {
0 : 'None',
1 : 'Gray',
2 : 'Green',
3 : 'Purple',
4 : 'Blue',
5 : 'Yellow',
6 : 'Red',
7 : 'Orange'}

_VALID_COLORIDS = '01234567'
_MAX_FINDERCOMMENT = 750 #determined through trial & error with Finder
_MAX_WHEREFROM = 1024 #just picked something....todo: need to figure out what max length is

_TAGS = 'com.apple.metadata:_kMDItemUserTags'
_FINDER_COMMENT = 'com.apple.metadata:kMDItemFinderComment'
_WHERE_FROM = 'com.apple.metadata:kMDItemWhereFroms'
_DOWNLOAD_DATE = 'com.apple.metadata:kMDItemDownloadedDate'
_COLORNAMES = {
"None": 0,
"Gray": 1,
"Green": 2,
"Purple": 3,
"Blue": 4,
"Yellow": 5,
"Red": 6,
"Orange": 7,
}

_COLORIDS = {
0: "None",
1: "Gray",
2: "Green",
3: "Purple",
4: "Blue",
5: "Yellow",
6: "Red",
7: "Orange",
}

_VALID_COLORIDS = "01234567"
_MAX_FINDERCOMMENT = 750 # determined through trial & error with Finder
_MAX_WHEREFROM = (
1024
) # just picked something....todo: need to figure out what max length is

_TAGS = "com.apple.metadata:_kMDItemUserTags"
_FINDER_COMMENT = "com.apple.metadata:kMDItemFinderComment"
_WHERE_FROM = "com.apple.metadata:kMDItemWhereFroms"
_DOWNLOAD_DATE = "com.apple.metadata:kMDItemDownloadedDate"


class _NullsInString(Exception):
"""Nulls in string."""
#class _NullsInString


# class _NullsInString


def _onError(e):
sys.stderr.write(str(e) + "\n")
#_onError

class _Tags:

# _onError


class _Tags:
def __init__(self, xa: xattr):
self.__attrs = xa
self.__load_tags()
Expand All @@ -69,10 +79,12 @@ def __tag_split(self, tag):
"""
Extracts the color information from a Finder tag.
"""
parts = tag.rsplit('\n', 1)
parts = tag.rsplit("\n", 1)
if len(parts) == 1:
return parts[0], 0
elif len(parts[1]) != 1 or parts[1] not in _VALID_COLORIDS: # Not a color number
elif (
len(parts[1]) != 1 or parts[1] not in _VALID_COLORIDS
): # Not a color number
return tag, 0
else:
return parts[0], int(parts[1])
Expand All @@ -81,19 +93,19 @@ def __load_tags(self):
self.__tags = {}
try:
self.__tagvalues = self.__attrs[_TAGS]
#load the binary plist value
# load the binary plist value
self.__tagvalues = loads(self.__tagvalues)
for x in self.__tagvalues:
(tag, color) = self.__tag_split(x)
self.__tags[tag] = color
#self.__tags = [self.__tag_strip_color(x) for x in self.__tagvalues]
(tag, color) = self.__tag_split(x)
self.__tags[tag] = color
# self.__tags = [self.__tag_strip_color(x) for x in self.__tagvalues]
except KeyError:
self.__tags = None
if self.__tags:
self.__tag_set = set(self.__tags.keys())
else:
self.__tag_set = set([])

def __iter__(self):
self.__load_tags()
self.__tag_list = list(self.__tag_set)
Expand All @@ -119,21 +131,21 @@ def __repr__(self):

def __str__(self):
self.__load_tags()
return ', '.join(self.__tag_set)
return ", ".join(self.__tag_set)

def add(self, tag):
if not isinstance(tag, str):
raise TypeError("Tags must be strings")
self.__load_tags()
tags = set(map(self.__tag_normalize,self.__tag_set))
tags = set(map(self.__tag_normalize, self.__tag_set))
tags.add(self.__tag_normalize(tag))
self.__write_tags(*tags)

def update(self, *tags):
if not all(isinstance(tag, str) for tag in tags):
raise TypeError("Tags must be strings")
self.__load_tags()
old_tags = set(map(self.__tag_normalize,self.__tag_set))
old_tags = set(map(self.__tag_normalize, self.__tag_set))
new_tags = old_tags.union(set(map(self.__tag_normalize, tags)))
self.__write_tags(*new_tags)

Expand All @@ -147,15 +159,15 @@ def remove(self, tag):
self.__load_tags()
if not isinstance(tag, str):
raise TypeError("Tags must be strings")
tags = set(map(self.__tag_normalize,self.__tag_set))
tags = set(map(self.__tag_normalize, self.__tag_set))
tags.remove(self.__tag_normalize(tag))
self.__write_tags(*tags)

def discard(self, tag):
self.__load_tags()
if not isinstance(tag, str):
raise TypeError("Tags must be strings")
tags = set(map(self.__tag_normalize,self.__tag_set))
tags = set(map(self.__tag_normalize, self.__tag_set))
tags.discard(self.__tag_normalize(tag))
self.__write_tags(*tags)

Expand All @@ -169,7 +181,7 @@ def __write_tags(self, *tags):
"""
if not all(isinstance(tag, str) for tag in tags):
raise TypeError("Tags must be strings")
tag_plist = dumps(list(map(self.__tag_normalize, tags)),fmt=FMT_BINARY)
tag_plist = dumps(list(map(self.__tag_normalize, tags)), fmt=FMT_BINARY)
self.__attrs.set(_TAGS, tag_plist)

def __tag_colored(self, tag, color):
Expand All @@ -183,8 +195,8 @@ def __tag_colored(self, tag, color):
Return:
(str) the tag with encoded color.
"""
return '{}\n{}'.format(self.__tag_nocolor(tag), color)
return "{}\n{}".format(self.__tag_nocolor(tag), color)

def __tag_normalize(self, tag):
"""
Ensures a color is set if not none.
Expand All @@ -193,40 +205,42 @@ def __tag_normalize(self, tag):
"""
tag, color = self.__tag_split(tag)
if tag.title() in _COLORNAMES:
#ignore the color passed and set proper color name
return self.__tag_colored(tag.title(),_COLORNAMES[tag.title()])
# ignore the color passed and set proper color name
return self.__tag_colored(tag.title(), _COLORNAMES[tag.title()])
else:
return self.__tag_colored(tag, color)

def __tag_nocolor(self, tag):
"""
Removes the color information from a Finder tag.
"""
return tag.rsplit('\n', 1)[0]
return tag.rsplit("\n", 1)[0]

class OSXMetaData:

class OSXMetaData:
def __init__(self, fname):

self.__fname = Path(fname)
try:
os.path.exists(self.__fname)
except ValueError:
print('file does not exist %s' % (self.__fname),file=sys.stderr)
print("file does not exist %s" % (self.__fname), file=sys.stderr)

try:
self.__attrs = xattr(self.__fname)
except (IOError, OSError) as e:
quit(_onError(e))

#setup applescript for writing finder comments
self.__scpt_set_finder_comment = _applescript.AppleScript('''
# setup applescript for writing finder comments
self.__scpt_set_finder_comment = _applescript.AppleScript(
"""
on run {fname, fc}
set theFile to fname
set theComment to fc
tell application "Finder" to set comment of (POSIX file theFile as alias) to theComment
end run
''')
"""
)

# self.__setfc_script_fh = tempfile.NamedTemporaryFile(suffix=".scpt",prefix="osxmd",mode="w",delete=False)
# self.__setfc_script = self.__setfc_script_fh.name
Expand All @@ -235,16 +249,16 @@ def __init__(self, fname):
# fd.close()
# print("applescript = %s" % self.__setfc_script)

#initialize meta data
# initialize meta data
self.__tags = {}
self.__findercomment = None
self.__wherefrom = []
self.__downloaddate = None

self.tags = _Tags(self.__attrs)

#TODO: Lot's of repetitive code here
#need to read these dynamically
# TODO: Lot's of repetitive code here
# need to read these dynamically
""" Get Finder comment """
self.__load_findercomment()

Expand All @@ -256,7 +270,7 @@ def __init__(self, fname):

# @property
# def colors(self):
# """ return list of color labels from tags
# """ return list of color labels from tags
# do not return None (e.g. ignore tags with no color)
# """
# colors = []
Expand All @@ -277,7 +291,7 @@ def __del__(self):
def __load_findercomment(self):
try:
self.__fcvalue = self.__attrs[_FINDER_COMMENT]
#load the binary plist value
# load the binary plist value
self.__findercomment = loads(self.__fcvalue)
except KeyError:
self.__findercomment = None
Expand All @@ -289,29 +303,31 @@ def finder_comment(self):

@finder_comment.setter
def finder_comment(self, fc):
'''
"""
TODO: this creates a temporary script file which gets runs by osascript every time
not very efficient. Perhaps use py-applescript in the future but that increases
dependencies + PyObjC
'''
"""
if fc is None:
fc = ""
elif not isinstance(fc, str):
raise TypeError("Finder comment must be strings")

if len(fc) > _MAX_FINDERCOMMENT:
raise ValueError("Finder comment limited to %d characters" % _MAX_FINDERCOMMENT)
raise ValueError(
"Finder comment limited to %d characters" % _MAX_FINDERCOMMENT
)

fname = self.__fname.resolve().as_posix()

self.__scpt_set_finder_comment.run(fname,fc)
self.__scpt_set_finder_comment.run(fname, fc)

self.__load_findercomment()

def __load_download_wherefrom(self):
try:
self.__wfvalue = self.__attrs[_WHERE_FROM]
#load the binary plist value
# load the binary plist value
self.__wherefrom = loads(self.__wfvalue)
except KeyError:
self.__wherefrom = None
Expand All @@ -330,21 +346,23 @@ def where_from(self, wf):

for w in wf:
if len(w) > _MAX_WHEREFROM:
raise ValueError("Where from URL limited to %d characters" % _MAX_WHEREFROM)
raise ValueError(
"Where from URL limited to %d characters" % _MAX_WHEREFROM
)

wf_plist = dumps(wf,fmt=FMT_BINARY)
wf_plist = dumps(wf, fmt=FMT_BINARY)
self.__attrs.set(_WHERE_FROM, wf_plist)
self.__load_download_wherefrom()

def __load_download_date(self):
try:
self.__ddvalue = self.__attrs[_DOWNLOAD_DATE]
#load the binary plist value
#returns an array with a single datetime.datetime object
# load the binary plist value
# returns an array with a single datetime.datetime object
self.__downloaddate = loads(self.__ddvalue)[0]
except KeyError:
self.__downloaddate = None

@property
def download_date(self):
self.__load_download_date()
Expand All @@ -357,12 +375,10 @@ def download_date(self, dt):
elif not isinstance(dt, datetime.datetime):
raise TypeError("Download date must be a datetime object")

dt_plist = dumps([dt],fmt=FMT_BINARY)
dt_plist = dumps([dt], fmt=FMT_BINARY)
self.__attrs.set(_DOWNLOAD_DATE, dt_plist)
self.__load_download_date()

@property
def name(self):
return self.__fname.resolve().as_posix()


Loading

0 comments on commit 1b1384d

Please sign in to comment.