Skip to content

Commit 4db1819

Browse files
committed
Added kMDItemFSIsStationery, #18
1 parent ff09509 commit 4db1819

File tree

6 files changed

+166
-4
lines changed

6 files changed

+166
-4
lines changed

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,13 +166,25 @@ keywords kMDItemKeywords, com.apple.metadata:kMDItemKeywords;
166166
(_kMDItemUserTags) which are keywords/tags shown in the
167167
Finder and searchable in Spotlight using "tag:tag_name". A
168168
list of strings.
169+
participants kMDItemParticipants, com.apple.metadata:kMDItemParticipants;
170+
The list of people who are visible in an image or movie or
171+
written about in a document. A list of strings.
172+
projects kMDItemProjects, com.apple.metadata:kMDItemProjects; The
173+
list of projects that this file is part of. For example, if
174+
you were working on a movie all of the files could be marked
175+
as belonging to the project “My Movie”. A list of strings.
169176
rating kMDItemStarRating, com.apple.metadata:kMDItemStarRating;
170177
User rating of this item. For example, the stars rating of
171178
an iTunes track. An integer.
179+
stationary kMDItemFSIsStationery,
180+
com.apple.metadata:kMDItemFSIsStationery; Boolean indicating
181+
if this file is stationery.
172182
tags _kMDItemUserTags, com.apple.metadata:_kMDItemUserTags;
173183
Finder tags; searchable in Spotlight using "tag:tag_name".
174184
If you want tags/keywords visible in the Finder, use this
175185
instead of kMDItemKeywords. A list of Tag objects.
186+
version kMDItemVersion, com.apple.metadata:kMDItemVersion; The
187+
version number of this file. A string.
176188
wherefroms kMDItemWhereFroms, com.apple.metadata:kMDItemWhereFroms;
177189
Describes where the file was obtained from (e.g. URL
178190
downloaded from). A list of strings.
@@ -198,8 +210,12 @@ Information about commonly used MacOS metadata attributes is available from [App
198210
|FinderInfo|finderinfo|com.apple.FinderInfo|Color tag set by the Finder. Colors can also be set by _kMDItemUserTags. This is controlled by the Finder and it's recommended you don't directly access this attribute. If you set or remove a color tag via _kMDItemUserTag, osxmetadata will automatically handle processing of FinderInfo color tag.|
199211
|kMDItemHeadline|headline|com.apple.metadata:kMDItemHeadline|A publishable entry providing a synopsis of the contents of the file. A string.|
200212
|kMDItemKeywords|keywords|com.apple.metadata:kMDItemKeywords|Keywords associated with this file. For example, “Birthday”, “Important”, etc. This differs from Finder tags (_kMDItemUserTags) which are keywords/tags shown in the Finder and searchable in Spotlight using "tag:tag_name". A list of strings.|
201-
|kMDItemStarRating|rating|com.apple.metadata:kMDItemStarRating|User rating of this item. For example, the stars rating of an iTunes track. An int.|
213+
|kMDItemParticipants|participants|com.apple.metadata:kMDItemParticipants|The list of people who are visible in an image or movie or written about in a document. A list of strings.|
214+
|kMDItemProjects|projects|com.apple.metadata:kMDItemProjects|The list of projects that this file is part of. For example, if you were working on a movie all of the files could be marked as belonging to the project “My Movie”. A list of strings.|
215+
|kMDItemStarRating|rating|com.apple.metadata:kMDItemStarRating|User rating of this item. For example, the stars rating of an iTunes track. An integer.|
216+
|kMDItemFSIsStationery|stationary|com.apple.metadata:kMDItemFSIsStationery|Boolean indicating if this file is stationery.|
202217
|_kMDItemUserTags|tags|com.apple.metadata:_kMDItemUserTags|Finder tags; searchable in Spotlight using "tag:tag_name". If you want tags/keywords visible in the Finder, use this instead of kMDItemKeywords. A list of Tag objects.|
218+
|kMDItemVersion|version|com.apple.metadata:kMDItemVersion|The version number of this file. A string.|
203219
|kMDItemWhereFroms|wherefroms|com.apple.metadata:kMDItemWhereFroms|Describes where the file was obtained from (e.g. URL downloaded from). A list of strings.|
204220

205221
## Example uses of the package

osxmetadata/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
""" osxmetadata version """
22

3-
__version__ = "0.99.18"
3+
__version__ = "0.99.19"

osxmetadata/attributes.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,19 @@
311311
"The version number of this file. A string.",
312312
None,
313313
),
314+
"stationary": Attribute(
315+
"stationary",
316+
"kMDItemFSIsStationery",
317+
kMDItemFSIsStationery,
318+
bool,
319+
False,
320+
False,
321+
bool,
322+
False,
323+
False,
324+
"Boolean indicating if this file is stationery.",
325+
None,
326+
),
314327
}
315328

316329
# used for formatting output of --list
@@ -379,6 +392,13 @@ def validate_attribute_value(attribute, value):
379392
raise TypeError(
380393
f"{val} cannot be converted to expected type {attribute.type_}"
381394
)
395+
elif attribute.type_ == bool:
396+
try:
397+
new_val = bool(val)
398+
except ValueError:
399+
raise TypeError(
400+
f"{val} cannot be converted to expected type {attribute.type_}"
401+
)
382402
elif attribute.type_ == datetime.datetime:
383403
if isinstance(val, datetime.datetime):
384404
new_val = val

osxmetadata/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
kMDItemParticipants = "com.apple.metadata:kMDItemParticipants"
7777
kMDItemProjects = "com.apple.metadata:kMDItemProjects"
7878
kMDItemVersion = "com.apple.metadata:kMDItemVersion"
79+
kMDItemFSIsStationery = "com.apple.metadata:kMDItemFSIsStationery"
7980

8081

8182
# Special handling for Finder comments
@@ -108,4 +109,5 @@
108109
"kMDItemParticipants",
109110
"kMDItemProjects",
110111
"kMDItemVersion",
112+
"kMDItemFSIsStationery",
111113
]

osxmetadata/osxmetadata.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
kMDItemUserTags,
5252
kMDItemVersion,
5353
kMDItemWhereFroms,
54+
kMDItemFSIsStationery,
5455
)
5556
from .datetime_utils import (
5657
datetime_naive_to_utc,
@@ -81,7 +82,7 @@
8182
"kMDItemParticipants",
8283
"kMDItemProjects",
8384
"kMDItemVersion",
84-
"_FINDER_COMMENT_NAMES",
85+
"kMDItemFSIsStationery",
8586
]
8687

8788

@@ -137,6 +138,7 @@ class OSXMetaData:
137138
"participants",
138139
"projects",
139140
"version",
141+
"stationary",
140142
]
141143

142144
def __init__(self, fname, tz_aware=False):
@@ -159,7 +161,7 @@ def __init__(self, fname, tz_aware=False):
159161
# ATTRIBUTES contains both long and short names, want only the short names (attribute.name)
160162
for name in {attribute.name for attribute in ATTRIBUTES.values()}:
161163
attribute = ATTRIBUTES[name]
162-
if attribute.class_ not in [str, float, int, datetime.datetime]:
164+
if attribute.class_ not in [str, float, int, bool, datetime.datetime]:
163165
super().__setattr__(
164166
name, attribute.class_(attribute, self._attrs, self)
165167
)

tests/test_bool_attributes.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
""" Test bool attributes """
2+
3+
import platform
4+
from tempfile import NamedTemporaryFile, TemporaryDirectory
5+
6+
import pytest
7+
from osxmetadata.attributes import ATTRIBUTES
8+
9+
10+
@pytest.fixture(params=["file", "dir"])
11+
def temp_file(request):
12+
13+
# TESTDIR for temporary files usually defaults to "/tmp",
14+
# which may not have XATTR support (e.g. tmpfs);
15+
# manual override here.
16+
TESTDIR = None
17+
if request.param == "file":
18+
tempfile = NamedTemporaryFile(dir=TESTDIR)
19+
tempfilename = tempfile.name
20+
yield tempfilename
21+
tempfile.close()
22+
else:
23+
tempdir = TemporaryDirectory(dir=TESTDIR)
24+
tempdirname = tempdir.name
25+
yield tempdirname
26+
tempdir.cleanup()
27+
28+
29+
test_data = [
30+
(attr)
31+
for attr in sorted(list(ATTRIBUTES.keys()))
32+
if ATTRIBUTES[attr].class_ == bool
33+
]
34+
ids = [
35+
attr for attr in sorted(list(ATTRIBUTES.keys())) if ATTRIBUTES[attr].class_ == bool
36+
]
37+
38+
test_data2 = [
39+
(attribute_name)
40+
for attribute_name in {
41+
ATTRIBUTES[attr].name
42+
for attr in sorted(ATTRIBUTES)
43+
if ATTRIBUTES[attr].class_ == bool
44+
}
45+
]
46+
ids2 = [
47+
attribute_name
48+
for attribute_name in {
49+
ATTRIBUTES[attr].name
50+
for attr in sorted(ATTRIBUTES)
51+
if ATTRIBUTES[attr].class_ == bool
52+
}
53+
]
54+
55+
56+
@pytest.mark.parametrize("attribute", test_data, ids=ids)
57+
def test_str_attribute(temp_file, attribute):
58+
"""test set_attribute, get_attribute, etc"""
59+
from osxmetadata import OSXMetaData
60+
from osxmetadata.constants import _FINDER_COMMENT_NAMES
61+
62+
meta = OSXMetaData(temp_file)
63+
expected = True
64+
meta.set_attribute(attribute, expected)
65+
got = meta.get_attribute(attribute)
66+
assert expected == got
67+
68+
meta.set_attribute(attribute, not expected)
69+
assert not meta.get_attribute(attribute)
70+
71+
meta.clear_attribute(attribute)
72+
assert meta.get_attribute(attribute) is None
73+
74+
# test setting empty string
75+
# setting finder comment to empty string clears it
76+
# but other fields get set to empty string
77+
# this mirrors the way finder comments work in mdls
78+
meta.set_attribute(attribute, "")
79+
assert not meta.get_attribute(attribute)
80+
81+
with pytest.raises(AttributeError):
82+
meta.update_attribute(attribute, "foo")
83+
84+
with pytest.raises(TypeError):
85+
meta.discard_attribute(attribute, "foo")
86+
87+
with pytest.raises(TypeError):
88+
meta.remove_attribute(attribute, "foo")
89+
90+
91+
@pytest.mark.parametrize("attribute", test_data2, ids=ids2)
92+
def test_str_attribute_2(temp_file, attribute):
93+
"""test getting and setting attribute by name"""
94+
from osxmetadata import OSXMetaData
95+
96+
meta = OSXMetaData(temp_file)
97+
setattr(meta, attribute, True)
98+
test_attr = getattr(meta, attribute)
99+
assert test_attr
100+
assert meta.get_attribute(attribute)
101+
102+
103+
def test_stationary(temp_file):
104+
"""test string functions on one of the bool attributes"""
105+
from osxmetadata import OSXMetaData
106+
107+
meta = OSXMetaData(temp_file)
108+
meta.stationary = True
109+
assert meta.stationary
110+
assert meta.get_attribute("stationary")
111+
112+
meta.stationary = not meta.stationary
113+
assert not meta.stationary
114+
assert not meta.get_attribute("stationary")
115+
116+
meta.stationary = None
117+
assert meta.stationary is None
118+
assert meta.get_attribute("stationary") is None
119+
120+
meta.stationary = True
121+
assert meta.stationary
122+
assert meta.get_attribute("stationary")

0 commit comments

Comments
 (0)