Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#!/usr/local/bin/python
2# encoding: utf-8
3"""
4*Add tags and ratings to your macOS files and folders*
6:Author:
7 David Young
8"""
9import sys
10import os
11os.environ['TERM'] = 'vt100'
12from fundamentals import tools
13from subprocess import Popen, PIPE, STDOUT
14from datetime import datetime, date, time
15import codecs
17def tag(
18 log,
19 filepath,
20 tags=False,
21 rating=False,
22 wherefrom=False):
23 """Add tags and ratings to your macOS files and folders
25 **Key Arguments**
27 - ``log`` -- logger
28 - ``filepath`` -- the path to the file needing tagged
29 - ``tags`` -- comma or space-separated string, or list of tags. Use `False` to leave file tags as they are. Use "" or [] to remove tags. Default *False*.
30 - ``rating`` -- a rating to add to the file. Use 0 to remove rating or `False` to leave file rating as it is. Default *False*.
31 - ``wherefrom`` -- add a URL to indicate where the file come from. Use `False` to leave file location as it is. Use "" to remove location. Default *False*.
34 **Return**
36 - None
39 **Usage**
41 To add any combination of tags, rating and a source URL to a file on macOS, use the following:
43 ```python
44 from fundamentals.files.tag import tag
45 tag(
46 log=log,
47 filepath="/path/to/my.file",
48 tags="test,tags, fundamentals",
49 rating=3,
50 wherefrom="http://www.thespacedoctor.co.uk"
51 )
52 ```
54 """
55 log.debug('starting the ``tag`` function')
57 if isinstance(tags, list):
58 tags = (" ").join(tags)
60 if tags and len(tags):
61 tags = tags.replace(",", " ")
62 tags = "<string>" + tags.replace(" ", " ").replace(
63 " ", " ").replace(" ", "</string><string>") + "</string>"
65 if tags != False:
66 now = datetime.now()
67 now = now.strftime("%Y%m%dt%H%M%S%f")
68 tagPlist = "/tmp/fund-%(now)s-tags.plist" % locals()
69 # GENERATE THE TAGS PLIST FILE
70 try:
71 writeFile = codecs.open(
72 tagPlist, encoding='utf-8', mode='w')
73 except IOError as e:
74 message = 'could not open the file %s' % (tagPlist,)
75 raise IOError(message)
76 writeFile.write("""
77<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
78<plist version="1.0">
79<array>
80%(tags)s
81</array>
82</plist>""" % locals())
83 writeFile.close()
85 # CONVERT PLIST TO BINARY
86 cmd = """plutil -convert binary1 %(tagPlist)s""" % locals(
87 )
88 p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
89 stdout, stderr = p.communicate()
90 log.debug('output: %(stdout)s' % locals())
91 log.debug('output: %(stderr)s' % locals())
93 # ASSIGN TAGS TO FILE
94 cmd = 'xattr -wx "com.apple.metadata:_kMDItemUserTags" "`xxd -ps %(tagPlist)s`" "%(filepath)s"' % locals(
95 )
96 p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
97 stdout, stderr = p.communicate()
98 log.debug('output: %(stdout)s' % locals())
99 log.debug('output: %(stderr)s' % locals())
101 # DELETE PLIST
102 os.remove(tagPlist)
104 if rating != False:
106 ratingsContainer = os.path.dirname(__file__) + "/resources/ratings/"
107 ratingPlist = "%(ratingsContainer)s%(rating)s.plist" % locals(
108 )
110 # ASSIGN RATING TO FILE
111 cmd = 'xattr -wx "com.apple.metadata:kMDItemStarRating" "`xxd -ps %(ratingPlist)s`" "%(filepath)s"' % locals(
112 )
113 p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
114 stdout, stderr = p.communicate()
115 log.debug('output: %(stdout)s' % locals())
116 log.debug('output: %(stderr)s' % locals())
117 cmd = 'xattr -wx "org.openmetainfo:kMDItemStarRating" "`xxd -ps %(ratingPlist)s`" "%(filepath)s"' % locals(
118 )
119 p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
120 stdout, stderr = p.communicate()
121 log.debug('output: %(stdout)s' % locals())
122 log.debug('output: %(stderr)s' % locals())
124 if wherefrom != False:
126 if len(wherefrom):
127 wherefrom = "<string>%(wherefrom)s</string>" % locals()
129 # DAYONE LINK
130 now = datetime.now()
131 now = now.strftime("%Y%m%dt%H%M%S%f")
132 urlPlist = "/tmp/fund-%(now)s-url.plist" % locals()
133 # GENERATE THE WHEREFROM PLIST FILE
134 try:
135 writeFile = codecs.open(
136 urlPlist, encoding='utf-8', mode='w')
137 except IOError as e:
138 message = 'could not open the file %s' % (urlPlist,)
139 raise IOError(message)
140 writeFile.write("""
141<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
142<plist version="1.0">
143%(wherefrom)s
144</plist>""" % locals())
145 writeFile.close()
147 # ASSIGN WHEREFORM TO FILE
148 cmd = 'xattr -wx "com.apple.metadata:kMDItemURL" "`xxd -ps %(urlPlist)s`" "%(filepath)s"' % locals(
149 )
150 # cmd = 'xattr -wx "com.apple.metadata:kMDItemURL" "`plutil -convert binary1 %(urlPlist)s -o - | xxd -p`" "%(filepath)s"' % locals()
152 p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
153 stdout, stderr = p.communicate()
154 log.debug('output URL: %(stdout)s' % locals())
155 log.debug('output URL: %(stderr)s' % locals())
157 now = datetime.now()
158 now = now.strftime("%Y%m%dt%H%M%S%f")
159 urlPlist = "/tmp/fund-%(now)s-url.plist" % locals()
160 # GENERATE THE WHEREFROM PLIST FILE
161 try:
162 writeFile = codecs.open(
163 urlPlist, encoding='utf-8', mode='w')
164 except IOError as e:
165 message = 'could not open the file %s' % (urlPlist,)
166 raise IOError(message)
167 writeFile.write("""
168<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
169<plist version="1.0">
170<array>
171%(wherefrom)s
172</array>
173</plist>""" % locals())
174 writeFile.close()
176 # ASSIGN WHEREFORM TO FILE
177 cmd = 'xattr -wx "com.apple.metadata:kMDItemWhereFroms" "`xxd -ps %(urlPlist)s`" "%(filepath)s"' % locals(
178 )
179 p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
180 stdout, stderr = p.communicate()
181 log.debug('output URL: %(stdout)s' % locals())
182 log.debug('output URL: %(stderr)s' % locals())
184 # DELETE PLIST
185 # os.remove(urlPlist)
187 log.debug('completed the ``tag`` function')
188 return None