Skip to content

Commit cd9b52e

Browse files
committed
Added backup/restore to CLI
1 parent 6149d21 commit cd9b52e

File tree

10 files changed

+404
-85
lines changed

10 files changed

+404
-85
lines changed

README.md

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ Options:
5151
--update ATTRIBUTE VALUE Update ATTRIBUTE with VALUE; for multi-valued
5252
attributes, this adds VALUE to the attribute if
5353
not already in the list
54+
--backup Backup FILE attributes. Backup file
55+
'.osxmetadata.json' will be created in same folder
56+
as FILE
57+
--restore Restore FILE attributes from backup file. Restore
58+
will look for backup file '.osxmetadata.json' in
59+
same folder as FILE
60+
-V, --verbose Print verbose output
5461
--help Show this message and exit.
5562
5663
Valid attributes for ATTRIBUTE: Each attribute has a short name, a constant
@@ -67,44 +74,44 @@ set keywords to ['foo', 'bar']
6774
6875
Short Name Description
6976
authors kMDItemAuthors, com.apple.metadata:kMDItemAuthors; The
70-
author, or authors, of the contents of the file. A list of
77+
author, or authors, of the contents of the file. A list of
7178
strings.
7279
comment kMDItemComment, com.apple.metadata:kMDItemComment; A comment
73-
related to the file. This differs from the Finder comment,
74-
kMDItemFinderComment. A string.
80+
related to the file. This differs from the Finder comment,
81+
kMDItemFinderComment. A string.
7582
copyright kMDItemCopyright, com.apple.metadata:kMDItemCopyright; The
76-
copyright owner of the file contents. A string.
83+
copyright owner of the file contents. A string.
7784
creator kMDItemCreator, com.apple.metadata:kMDItemCreator;
7885
Application used to create the document content (for example
79-
“Word”, “Pages”, and so on). A string.
86+
“Word”, “Pages”, and so on). A string.
8087
description kMDItemDescription, com.apple.metadata:kMDItemDescription; A
81-
description of the content of the resource. The description
88+
description of the content of the resource. The description
8289
may include an abstract, table of contents, reference to a
8390
graphical representation of content or a free-text account
84-
of the content. A string.
91+
of the content. A string.
8592
downloadeddate kMDItemDownloadedDate,
8693
com.apple.metadata:kMDItemDownloadedDate; The date the item
8794
was downloaded. A date in ISO 8601 format: e.g.
8895
2000-01-12T12:00:00 or 2000-12-31 (ISO 8601 w/o time zone)
8996
findercomment kMDItemFinderComment,
9097
com.apple.metadata:kMDItemFinderComment; Finder comments for
91-
this file. A string.
98+
this file. A string.
9299
headline kMDItemHeadline, com.apple.metadata:kMDItemHeadline; A
93100
publishable entry providing a synopsis of the contents of
94-
the file. A string.
101+
the file. A string.
95102
keywords kMDItemKeywords, com.apple.metadata:kMDItemKeywords;
96103
Keywords associated with this file. For example, “Birthday”,
97104
“Important”, etc. This differs from Finder tags
98105
(_kMDItemUserTags) which are keywords/tags shown in the
99-
Finder and searchable in Spotlight using "tag:tag_name"A
106+
Finder and searchable in Spotlight using "tag:tag_name". A
100107
list of strings.
101108
tags _kMDItemUserTags, com.apple.metadata:_kMDItemUserTags;
102109
Finder tags; searchable in Spotlight using "tag:tag_name".
103110
If you want tags/keywords visible in the Finder, use this
104-
instead of kMDItemKeywords. A list of strings.
111+
instead of kMDItemKeywords. A list of strings.
105112
wherefroms kMDItemWhereFroms, com.apple.metadata:kMDItemWhereFroms;
106113
Describes where the file was obtained from (e.g. URL
107-
downloaded from). A list of strings.
114+
downloaded from). A list of strings.
108115
```
109116

110117

@@ -259,6 +266,11 @@ meta.clear_attribute("tags")
259266

260267
## Programmatic Interface:
261268

269+
### name
270+
`name()`
271+
272+
Returns POSIX path of the file OSXMetaData is operating on.
273+
262274
### get_attribute
263275
`get_attribute(attribute_name)`
264276

@@ -326,6 +338,11 @@ Clear anttribute (remove it from the file).
326338

327339
List the Apple metadata attributes set on the file. e.g. those in com.apple.metadata namespace.
328340

341+
### to_json
342+
`to_json()`
343+
344+
Return dict in JSON format with all attributes for this file. Format is the same as used by the command line --backup/--restore functions.
345+
329346
## Usage Notes
330347

331348
Changes are immediately written to the file. For example, OSXMetaData.tags.append("Foo") immediately writes the tag 'Foo' to the file.

osxmetadata/__init__.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
# the same MIT license. See: https://github.com/scooby/osx-tags
77

88
import datetime
9+
import json
910
import logging
1011
import pathlib
1112
import plistlib
@@ -119,6 +120,55 @@ def name(self):
119120
""" POSIX path of the file OSXMetaData is operating on """
120121
return self._fname.resolve().as_posix()
121122

123+
def _to_dict(self):
124+
""" Return dict with all attributes for this file
125+
key of dict is filename and value is another dict with attributes """
126+
127+
attribute_list = self.list_metadata()
128+
json_data = {}
129+
json_data["_version"] = __version__
130+
json_data["_filepath"] = self._posix_name
131+
json_data["_filename"] = self._fname.name
132+
for attr in attribute_list:
133+
try:
134+
attribute = ATTRIBUTES[attr]
135+
if attribute.type_ == datetime.datetime:
136+
# need to convert datetime.datetime to string to serialize
137+
value = self.get_attribute(attribute.name)
138+
if type(value) == list:
139+
value = [v.isoformat() for v in value]
140+
else:
141+
value = value.isoformat()
142+
json_data[attribute.constant] = value
143+
else:
144+
# get raw value
145+
json_data[attribute.constant] = self.get_attribute(attribute.name)
146+
except KeyError:
147+
# unknown attribute, ignore it
148+
pass
149+
return json_data
150+
151+
def to_json(self):
152+
""" Returns a string in JSON format for all attributes in this file """
153+
json_data = self._to_dict()
154+
json_str = json.dumps(json_data)
155+
return json_str
156+
157+
def _restore_attributes(self, attr_dict):
158+
""" restore attributes from attr_dict
159+
for each attribute in attr_dict, will set the attribute
160+
will not clear/erase any attributes on file that are not in attr_dict
161+
attr_dict: an attribute dict as produced by OSXMetaData._to_dict() """
162+
163+
for key, val in attr_dict.items():
164+
if key.startswith("_"):
165+
# skip private keys like _version and _filepath
166+
continue
167+
try:
168+
self.set_attribute(key, val)
169+
except:
170+
logging.warning(f"Unable to restore attribute {attr} for {self._fname}")
171+
122172
def get_attribute(self, attribute_name):
123173
""" load attribute and return value or None if attribute was not set
124174
attribute_name: name of attribute

0 commit comments

Comments
 (0)