def test_tags_assign(temp_file): """ test assigning one tag object to another """ from osxmetadata import OSXMetaData, Tag # update tags meta = OSXMetaData(temp_file) tagset = [Tag("Test"), Tag("Green")] meta.tags = tagset assert meta.tags == tagset # create second temp file TESTDIR = None tempfile2 = NamedTemporaryFile(dir=TESTDIR) temp_file_2 = tempfile2.name meta2 = OSXMetaData(temp_file_2) tagset2 = [Tag("test2"), Tag("Blue")] meta2.tags = tagset2 assert meta2.tags == tagset2 meta.tags = meta2.tags assert meta.tags == tagset2 # close second tempfile, first gets closed automatically tempfile2.close()
def test_cli_copy_from(temp_file): # test copy from source file from osxmetadata import OSXMetaData, Tag from osxmetadata.__main__ import cli TESTDIR = None source_file = NamedTemporaryFile(dir=TESTDIR) source_filename = source_file.name meta_source = OSXMetaData(source_filename) meta_source.tags = [Tag("bar")] meta_source.keywords = ["foo"] meta_source.findercomment = "Bar" meta_source.comment = "Foo" runner = CliRunner() result = runner.invoke(cli, ["--copyfrom", source_filename, temp_file]) assert result.exit_code == 0 meta = OSXMetaData(temp_file) assert meta.tags == [Tag("bar")] assert meta.keywords == ["foo"] assert meta.findercomment == "Bar" assert meta.comment == "Foo" source_file.close()
def test_cli_walk_pattern(temp_dir): """test --walk with --pattern""" import os import pathlib from osxmetadata import OSXMetaData, Tag from osxmetadata.__main__ import cli dirname = pathlib.Path(temp_dir) os.makedirs(dirname / "temp" / "subfolder1") os.makedirs(dirname / "temp" / "subfolder2") create_file(dirname / "temp" / "temp1.txt") create_file(dirname / "temp" / "subfolder1" / "sub1.txt") create_file(dirname / "temp" / "subfolder1" / "sub1.pdf") runner = CliRunner() result = runner.invoke( cli, ["--set", "tags", "FOO", "--walk", "--pattern", "*.pdf", temp_dir]) assert result.exit_code == 0 md = OSXMetaData(dirname / "temp" / "subfolder1" / "sub1.pdf") assert md.tags == [Tag("FOO")] md = OSXMetaData(dirname / "temp" / "subfolder1" / "sub1.txt") assert not md.tags md = OSXMetaData(dirname / "temp" / "subfolder2") assert not md.tags
def test_cli_files_only(temp_dir): """test --files-only without --walk""" import glob import os import pathlib from osxmetadata import OSXMetaData, Tag from osxmetadata.__main__ import cli dirname = pathlib.Path(temp_dir) os.makedirs(dirname / "temp" / "subfolder1") os.makedirs(dirname / "temp" / "subfolder2") create_file(dirname / "temp" / "temp1.txt") create_file(dirname / "temp" / "subfolder1" / "sub1.txt") files = glob.glob(str(dirname / "temp" / "*")) runner = CliRunner() result = runner.invoke(cli, ["--set", "tags", "FOO", "--files-only", *files]) assert result.exit_code == 0 md = OSXMetaData(dirname / "temp" / "temp1.txt") assert md.tags == [Tag("FOO")] md = OSXMetaData(dirname / "temp" / "subfolder1") assert not md.tags md = OSXMetaData(dirname / "temp" / "subfolder1" / "sub1.txt") assert not md.tags
def test_cli_verbose_short_opts(temp_file): from osxmetadata import OSXMetaData, Tag from osxmetadata.__main__ import cli TESTDIR = None source_file = NamedTemporaryFile(dir=TESTDIR) source_filename = source_file.name meta_source = OSXMetaData(source_filename) meta_source.tags = [Tag("bar")] meta_source.keywords = ["foo"] meta_source.findercomment = "Bar" meta_source.comment = "Foo" runner = CliRunner() result = runner.invoke( cli, [ "-X", "-s", "keywords", "test", "-l", "-g", "keywords", "-c", "keywords", "-r", "keywords", "test", "-u", "keywords", "foo", "-m", "keywords", "tags", "-V", "-B", "-f", source_filename, temp_file, ], ) assert result.exit_code == 0 output = result.output assert "Processing file" in output assert "No metadata to wipe from" in output assert "Copying attributes from" in output assert "Copying com.apple.metadata:_kMDItemUserTags" in output assert "Copying com.apple.metadata:kMDItemComment" in output assert "Copying com.apple.metadata:kMDItemKeywords" in output assert "Copying com.apple.metadata:kMDItemFinderComment" in output assert "Clearing keywords" in output assert "Setting keywords=test" in output assert "Updating keywords=foo" in output assert "Removing keywords" in output assert "Mirroring keywords tags" in output assert "Backing up attribute data" in output source_file.close()
def test_cli_backup_restore_2(temp_file): # test set during restore import pathlib from osxmetadata import OSXMetaData, ATTRIBUTES, Tag from osxmetadata.constants import _BACKUP_FILENAME from osxmetadata.__main__ import cli runner = CliRunner() result = runner.invoke( cli, [ "--set", "tags", "Foo", "--set", "tags", "Bar", "--set", "comment", "Hello World!", "--list", temp_file, ], ) assert result.exit_code == 0 output = parse_cli_output(result.stdout) assert output["tags"] == "['Foo', 'Bar']" meta = OSXMetaData(temp_file) assert meta.get_attribute("tags") == [Tag("Foo"), Tag("Bar")] assert meta.get_attribute("comment") == "Hello World!" # test creation of backup file result = runner.invoke(cli, ["--backup", temp_file]) assert result.exit_code == 0 backup_file = pathlib.Path(pathlib.Path(temp_file).parent) / _BACKUP_FILENAME assert backup_file.exists() # clear the attributes to see if they can be restored meta.clear_attribute("tags") meta.clear_attribute("comment") assert meta.tags == [] assert meta.comment == None result = runner.invoke( cli, [ "--restore", "--append", "tags", "Flooz", "--set", "keywords", "FooBar", temp_file, ], ) assert result.exit_code == 0 assert meta.tags == [Tag("Foo"), Tag("Bar"), Tag("Flooz")] assert meta.comment == "Hello World!" assert meta.keywords == ["FooBar"]
def test_finder_comments_2(temp_file): """ test get/set attribute """ from osxmetadata import OSXMetaData from osxmetadata.constants import kMDItemFinderComment attribute = kMDItemFinderComment meta = OSXMetaData(temp_file) fc = "This is my new comment" meta.set_attribute(attribute, fc) assert meta.findercomment == fc meta.findercomment += ", foo" fc += ", foo" assert meta.findercomment == fc # set finder comment to "" results in null string but not deleted meta.set_attribute(attribute, "") assert meta.get_attribute(attribute) == "" 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.clear_attribute(attribute) assert meta.get_attribute(attribute) == None # can we set findercomment after is was set to None? meta.set_attribute(attribute, "bar") assert meta.get_attribute(attribute) == "bar"
def test_finder_comments(temp_file): from osxmetadata import OSXMetaData meta = OSXMetaData(temp_file) fc = "This is my new comment" meta.findercomment = fc assert meta.findercomment == fc meta.findercomment += ", foo" fc += ", foo" assert meta.findercomment == fc # set finder comment to "" results in null string but not deleted meta.findercomment = "" assert meta.findercomment == "" meta.findercomment = "foo" assert meta.findercomment == "foo" # set finder comment to None deletes it meta.findercomment = None assert meta.findercomment == None # can we set findercomment after is was set to None? meta.findercomment = "bar" assert meta.findercomment == "bar"
def test_cli_downloadeddate(temp_file): # pass ISO 8601 format with timezone, get back naive local time import datetime from osxmetadata import OSXMetaData, kMDItemDownloadedDate from osxmetadata.datetime_utils import ( datetime_naive_to_utc, datetime_utc_to_local, datetime_remove_tz, ) from osxmetadata.__main__ import cli runner = CliRunner() dt = "2020-02-23:00:00:00+00:00" # UTC time utc_time = datetime.datetime.fromisoformat(dt) local_time = datetime_remove_tz(datetime_utc_to_local(utc_time)) result = runner.invoke(cli, ["--set", "downloadeddate", dt, "--list", temp_file]) assert result.exit_code == 0 output = parse_cli_output(result.stdout) assert output["downloadeddate"] == f"['{local_time.isoformat()}']" meta = OSXMetaData(temp_file) meta.tz_aware = True assert meta.get_attribute(kMDItemDownloadedDate) == [utc_time] assert meta.downloadeddate == [utc_time]
def test_finderinfo_color_set_get_clear(temp_file): """Test ability to set_attribute, get_attribute, clear_attribute on finderinfo""" from osxmetadata import OSXMetaData, Tag from osxmetadata.constants import FINDER_COLOR_GREEN, FINDER_COLOR_BLUE from osxmetadata.findertags import get_tag_color_name meta = OSXMetaData(temp_file) assert meta.finderinfo.color == 0 meta.finderinfo.color = FINDER_COLOR_GREEN assert meta.finderinfo.color == FINDER_COLOR_GREEN assert {"color": FINDER_COLOR_GREEN}.items() <= meta.get_attribute( "finderinfo" ).items() meta.set_attribute("finderinfo", {"color": FINDER_COLOR_BLUE}) assert meta.finderinfo.color == FINDER_COLOR_BLUE meta.clear_attribute("finderinfo") assert meta.finderinfo.color == 0 meta.finderinfo.color = FINDER_COLOR_GREEN meta.finderinfo.color = None assert meta.finderinfo.color == 0 meta.finderinfo.color = FINDER_COLOR_GREEN meta.finderinfo = None assert meta.finderinfo.color == 0
def test_download_date_tz_4(temp_file): """ test tz_aware property """ from osxmetadata import OSXMetaData from osxmetadata.datetime_utils import datetime_naive_to_local import datetime meta = OSXMetaData(temp_file) dt = datetime.datetime.now() # test tz_aware assert not meta.tz_aware meta.tz_aware = True assert meta.tz_aware # test tz_aware dt_tz = datetime_naive_to_local(dt) meta.downloadeddate = dt_tz assert meta.downloadeddate == [dt_tz] assert meta.get_attribute("downloadeddate") == [dt_tz] # test timezone == UTC dld = meta.downloadeddate[0] tz = dld.tzinfo.tzname(dld) assert tz == "UTC" # turn tz_aware off meta.tz_aware = False assert meta.downloadeddate == [dt] assert meta.get_attribute("downloadeddate") == [dt] assert meta.downloadeddate[0].tzinfo is None
def test_str_attribute(temp_file, attribute): """test set_attribute, get_attribute, etc""" from osxmetadata import OSXMetaData from osxmetadata.constants import _FINDER_COMMENT_NAMES meta = OSXMetaData(temp_file) expected = datetime.datetime(2021, 7, 8) meta.set_attribute(attribute, expected) got = meta.get_attribute(attribute) assert expected == got meta.clear_attribute(attribute) assert meta.get_attribute(attribute) == None # test setting empty string meta.set_attribute(attribute, "") assert meta.get_attribute(attribute) is None with pytest.raises(TypeError): meta.update_attribute(attribute, "foo") with pytest.raises(TypeError): meta.discard_attribute(attribute, "foo") with pytest.raises(TypeError): meta.remove_attribute(attribute, "foo")
def test_tags_3(temp_file): from osxmetadata import OSXMetaData, Tag from osxmetadata.constants import kMDItemUserTags attribute = kMDItemUserTags # update tags meta = OSXMetaData(temp_file) tagset = [Tag("Test"), Tag("Green")] meta.set_attribute(attribute, tagset) tags = meta.get_attribute(attribute) assert tags == tagset meta.update_attribute(attribute, [Tag("Foo")]) tags = meta.get_attribute(attribute) assert tags == [Tag("Test"), Tag("Green"), Tag("Foo")] meta.remove_attribute(attribute, Tag("Foo")) tags = meta.get_attribute(attribute) assert tags == [Tag("Test"), Tag("Green")] meta.update_attribute(attribute, [Tag("Foo")]) tags = meta.get_attribute(attribute) assert tags == [Tag("Test"), Tag("Green"), Tag("Foo")] meta.clear_attribute(attribute) tags = meta.get_attribute(attribute) assert len(tags) == 0
def test_str_attribute(temp_file, attribute): """test set_attribute, get_attribute, etc""" from osxmetadata import OSXMetaData from osxmetadata.constants import _FINDER_COMMENT_NAMES meta = OSXMetaData(temp_file) expected = 2 meta.set_attribute(attribute, expected) got = meta.get_attribute(attribute) assert expected == got expected += 1 meta.append_attribute(attribute, 1) assert meta.get_attribute(attribute) == expected meta.clear_attribute(attribute) assert meta.get_attribute(attribute) is None with pytest.raises(TypeError): meta.set_attribute(attribute, "") with pytest.raises(TypeError): meta.update_attribute(attribute, "foo") with pytest.raises(TypeError): meta.discard_attribute(attribute, "foo") with pytest.raises(TypeError): meta.remove_attribute(attribute, "foo")
def test_str_attribute(temp_file, attribute): """test set_attribute, get_attribute, etc""" from osxmetadata import OSXMetaData from osxmetadata.constants import _FINDER_COMMENT_NAMES meta = OSXMetaData(temp_file) expected = True meta.set_attribute(attribute, expected) got = meta.get_attribute(attribute) assert expected == got meta.set_attribute(attribute, not expected) assert not meta.get_attribute(attribute) meta.clear_attribute(attribute) assert meta.get_attribute(attribute) is None # test setting empty string # setting finder comment to empty string clears it # but other fields get set to empty string # this mirrors the way finder comments work in mdls meta.set_attribute(attribute, "") assert not meta.get_attribute(attribute) with pytest.raises(AttributeError): meta.update_attribute(attribute, "foo") with pytest.raises(TypeError): meta.discard_attribute(attribute, "foo") with pytest.raises(TypeError): meta.remove_attribute(attribute, "foo")
def test_name(temp_file): from osxmetadata import OSXMetaData import pathlib meta = OSXMetaData(temp_file) fname = pathlib.Path(temp_file) assert meta.name == fname.resolve().as_posix()
def test_finder_comments_2(temp_file): """ test get/set attribute """ from osxmetadata import OSXMetaData from osxmetadata.constants import kMDItemFinderComment attribute = kMDItemFinderComment meta = OSXMetaData(temp_file) fc = "This is my new comment" meta.set_attribute(attribute, fc) assert meta.findercomment == fc meta.findercomment += ", foo" fc += ", foo" assert meta.findercomment == fc # set finder comment to "" deletes it as this mirrors mdls and Finder meta.set_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, None) assert meta.get_attribute(attribute) is None meta.clear_attribute(attribute) assert meta.get_attribute(attribute) is None # can we set findercomment after is was set to None? meta.set_attribute(attribute, "bar") assert meta.get_attribute(attribute) == "bar"
def test_list_attribute(temp_file, attribute): """test set_attribute, get_attribute, etc for list items""" from osxmetadata import OSXMetaData meta = OSXMetaData(temp_file) expected = ["Foo"] meta.set_attribute(attribute, expected) got = meta.get_attribute(attribute) assert expected == got expected += ["Bar"] meta.append_attribute(attribute, ["Bar"]) assert meta.get_attribute(attribute) == expected expected.remove("Bar") meta.remove_attribute(attribute, "Bar") assert meta.get_attribute(attribute) == expected with pytest.raises(ValueError): meta.remove_attribute(attribute, "Bar") expected += ["Flooz"] meta.update_attribute(attribute, ["Flooz"]) assert meta.get_attribute(attribute) == expected meta.discard_attribute(attribute, "foo") assert meta.get_attribute(attribute) == expected meta.clear_attribute(attribute) assert meta.get_attribute(attribute) is None expected = ["Foo"] meta.set_attribute(attribute, expected) got = meta.get_attribute(attribute) assert expected == got
def test_finder_comments(temp_file): from osxmetadata import OSXMetaData meta = OSXMetaData(temp_file) fc = "This is my new comment" meta.findercomment = fc assert meta.findercomment == fc meta.findercomment += ", foo" fc += ", foo" assert meta.findercomment == fc # set finder comment to "" deletes it as this mirrors Finder and mdls meta.findercomment = "" assert meta.findercomment is None meta.findercomment = "foo" assert meta.findercomment == "foo" # set finder comment to None deletes it meta.findercomment = None assert meta.findercomment is None # can we set findercomment after is was set to None? meta.findercomment = "bar" assert meta.findercomment == "bar"
def test_tags_4(temp_file): """ Test various list methods """ from osxmetadata import OSXMetaData, Tag from osxmetadata.constants import _kMDItemUserTags attribute = _kMDItemUserTags # update tags meta = OSXMetaData(temp_file) tagset = [Tag("Test"), Tag("Green"), Tag("Foo")] meta.tags = tagset assert meta.tags == tagset assert meta.get_attribute(attribute) == tagset idx = meta.tags.index(Tag("Green")) assert idx == 1 count = meta.tags.count(Tag("Test")) assert count == 1 count = meta.tags.count(Tag("Bar")) assert count == 0 meta.tags.sort() assert meta.tags == [Tag("Foo"), Tag("Green"), Tag("Test")] assert meta.get_attribute(attribute) == [ Tag("Foo"), Tag("Green"), Tag("Test") ] meta.tags.sort(reverse=True) assert meta.tags == [Tag("Test"), Tag("Green"), Tag("Foo")] assert meta.get_attribute(attribute) == [ Tag("Test"), Tag("Green"), Tag("Foo") ] # sort by key meta.tags.sort(key=lambda tag: len(tag)) assert meta.tags == [Tag("Foo"), Tag("Test"), Tag("Green")] assert meta.get_attribute(attribute) == [ Tag("Foo"), Tag("Test"), Tag("Green") ] # todo: reverse not working # meta.tags.reverse() # assert meta.tags == [Tag("Green"), Tag("Test"), Tag("Foo")] # assert meta.get_attribute(attribute) == [Tag("Green"), Tag("Test"), Tag("Foo")] # tag_expected = Tag("Test") # tag_got = meta.tags.pop(1) # assert tag_got == tag_expected # assert meta.tags == [Tag("Green"), Tag("Foo")] # assert meta.get_attribute(attribute) == [Tag("Green"), Tag("Foo")] tag_expected = Tag("Test") tag_got = meta.tags.pop(1) assert tag_got == tag_expected assert meta.tags == [Tag("Foo"), Tag("Green")] assert meta.get_attribute(attribute) == [Tag("Foo"), Tag("Green")]
def test_file_not_exists(temp_file): from osxmetadata import OSXMetaData with pytest.raises(Exception): # kludge to create a file that almost certainly doesn't exist # TODO: make this less kludgy bad_filename = str(temp_file + temp_file) _ = OSXMetaData(bad_filename)
def test_cli_backup_restore_all(temp_file): """Test --backup/--restore with --all""" import pathlib from osxmetadata import ATTRIBUTES, OSXMetaData, Tag from osxmetadata.__main__ import cli from osxmetadata.constants import _BACKUP_FILENAME runner = CliRunner() result = runner.invoke( cli, [ "--set", "tags", "Foo", "--set", "tags", "Bar", "--set", "comment", "Hello World!", "--list", temp_file, ], ) assert result.exit_code == 0 meta = OSXMetaData(temp_file) # set a value osxmetadata doesn't know about meta._attrs.set("com.foo.bar", b"FOOBAR") # backup result = runner.invoke(cli, ["--backup", "--all", temp_file]) assert result.exit_code == 0 # clear the attributes to see if they can be restored meta.clear_attribute("tags") meta.clear_attribute("comment") meta._attrs.remove("com.foo.bar") assert meta.tags == [] assert meta.comment is None assert "com.foo.bar" not in meta._list_attributes() # first run restore without --all result = runner.invoke(cli, ["--restore", temp_file]) assert result.exit_code == 0 assert meta.tags == [Tag("Foo"), Tag("Bar")] assert meta.comment == "Hello World!" with pytest.raises(KeyError): assert meta._attrs["com.foo.bar"] == b"FOOBAR" # next run restore with --all result = runner.invoke(cli, ["--restore", "--all", temp_file]) assert result.exit_code == 0 assert meta.tags == [Tag("Foo"), Tag("Bar")] assert meta.comment == "Hello World!" assert meta._attrs["com.foo.bar"] == b"FOOBAR"
def test_str_attribute_2(temp_file, attribute): """test getting and setting attribute by name""" from osxmetadata import OSXMetaData meta = OSXMetaData(temp_file) setattr(meta, attribute, datetime.datetime(2021, 7, 8)) test_attr = getattr(meta, attribute) assert test_attr == datetime.datetime(2021, 7, 8) assert meta.get_attribute(attribute) == datetime.datetime(2021, 7, 8)
def test_str_attribute_2(temp_file, attribute): """test getting and setting attribute by name""" from osxmetadata import OSXMetaData meta = OSXMetaData(temp_file) setattr(meta, attribute, True) test_attr = getattr(meta, attribute) assert test_attr assert meta.get_attribute(attribute)
def test_download_date(temp_file): from osxmetadata import OSXMetaData import datetime meta = OSXMetaData(temp_file) dt = datetime.datetime.now() meta.downloadeddate = dt assert meta.downloadeddate == [dt] assert meta.get_attribute("downloadeddate") == [dt]
def test_list_attribute_2(temp_file, attribute): """test getting and setting attribute by name""" from osxmetadata import OSXMetaData meta = OSXMetaData(temp_file) setattr(meta, attribute, ["Foo", "Bar"]) test_attr = getattr(meta, attribute) assert test_attr == ["Foo", "Bar"] assert meta.get_attribute(attribute) == ["Foo", "Bar"]
def test_download_where_from(temp_file): from osxmetadata import OSXMetaData meta = OSXMetaData(temp_file) expected = ["http://google.com", "https://apple.com"] meta.wherefroms = expected wf = meta.wherefroms assert sorted(wf) == sorted(expected) assert sorted(meta.get_attribute("wherefroms")) == sorted(expected)
def test_invalid_findercolor_colorid(temp_file): from osxmetadata import OSXMetaData from osxmetadata.constants import _MAX_FINDER_COLOR, _MIN_FINDER_COLOR meta = OSXMetaData(temp_file) with pytest.raises(ValueError): meta.findercolor = _MAX_FINDER_COLOR + 1 with pytest.raises(ValueError): meta.findercolor = _MIN_FINDER_COLOR - 1
def test_tags_exception(temp_file): from osxmetadata import OSXMetaData, Tag # update tags meta = OSXMetaData(temp_file) with pytest.raises(TypeError): meta.tags = ["Foo"] with pytest.raises(TypeError): meta.tags = "Foo"
def test_download_date_tz_3(temp_file): """ set tz_aware and return naive """ from osxmetadata import OSXMetaData from osxmetadata.datetime_utils import datetime_naive_to_local import datetime meta = OSXMetaData(temp_file, tz_aware=False) dt = datetime.datetime.now() dt_tz = datetime_naive_to_local(dt) meta.downloadeddate = dt_tz assert meta.downloadeddate == [dt] assert meta.get_attribute("downloadeddate") == [dt]