Browse Source

_tag_interface.OggOpus: implement get_uuid

Fabian Peter Hammerle 4 years ago
parent
commit
aeea3ce78c

+ 1 - 1
.githooks/pre-commit

@@ -4,5 +4,5 @@ set -ex
 
 pipenv clean
 pipenv sync --dev
-pipenv run pytest
+pipenv run pytest --doctest-modules
 pipenv run pylint --disable=fixme symuid tests

+ 15 - 1
Pipfile.lock

@@ -22,6 +22,13 @@
             ],
             "version": "==1.42.0"
         },
+        "python-dateutil": {
+            "hashes": [
+                "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb",
+                "sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e"
+            ],
+            "version": "==2.8.0"
+        },
         "pytz": {
             "hashes": [
                 "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d",
@@ -29,6 +36,13 @@
             ],
             "version": "==2019.3"
         },
+        "six": {
+            "hashes": [
+                "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
+                "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
+            ],
+            "version": "==1.12.0"
+        },
         "symuid": {
             "editable": true,
             "path": "."
@@ -157,7 +171,7 @@
                 "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
                 "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
             ],
-            "version": "==1.12"
+            "version": "==1.12.0"
         },
         "typed-ast": {
             "hashes": [

+ 1 - 0
setup.py

@@ -11,6 +11,7 @@ setuptools.setup(
     },
     install_requires=[
         'mutagen < 2',
+        'python-dateutil < 3',
         'pytz',
     ],
     setup_requires=[

+ 9 - 5
symuid/_tag_interface.py

@@ -5,6 +5,8 @@ import typing
 import mutagen.id3
 import mutagen.mp4
 
+from symuid._uuid import uuid_str_to_bytes
+
 
 class TagInterface(abc.ABC):
 
@@ -215,7 +217,8 @@ class OggOpus(_MutagenTagInterface):
 
     # https://github.com/cmus/cmus/blob/9a0723f7a90dc7de0898be87963d5105a999aa6c/ip/opus.c#L229
     # https://github.com/cmus/cmus/blob/17bf542c6b120d9dcf6642b259d78badfc1143eb/comment.c#L224
-    _COMMENT_TAG = 'comment'
+    _COMMENT_TAG_KEY = 'comment'
+    _UUID_TAG_KEY = 'symuid:uuid'
 
     def __init__(self, mutagen_file):
         assert isinstance(mutagen_file.tags, mutagen.oggopus.OggOpusVComment), \
@@ -233,13 +236,14 @@ class OggOpus(_MutagenTagInterface):
         return tag[0]
 
     def get_comment(self) -> typing.Optional[str]:
-        return self._get_single_text(self._COMMENT_TAG)
+        return self._get_single_text(self._COMMENT_TAG_KEY)
 
     def set_comment(self, comment: str) -> None:
-        self._mutagen_file[self._COMMENT_TAG] = comment
+        self._mutagen_file[self._COMMENT_TAG_KEY] = comment
 
-    def get_track_uuid(self):
-        raise NotImplementedError()
+    def get_track_uuid(self) -> typing.Optional[bytes]:
+        uuid_str = self._get_single_text(self._UUID_TAG_KEY)
+        return uuid_str_to_bytes(uuid_str) if uuid_str else None
 
     def set_track_uuid(self, uuid):
         raise NotImplementedError()

+ 28 - 0
symuid/_uuid.py

@@ -0,0 +1,28 @@
+def uuid_str_to_int(uuid_str: str) -> int:
+    """
+    >>> uuid_str_to_int('613ea4ac-a4cf-4026-8e99-1904b2bb5cd0')
+    129260377989791042510121038559452028112
+    >>> uuid_str_to_int('779d1046-d163-4b2b-8126-254f631cb6a5')
+    158993652234522396927268087548725737125
+    """
+    return int(uuid_str.replace('-', ''), 16)
+
+
+def uuid_int_to_bytes(uuid_siv: int) -> bytes:
+    """
+    >>> uuid_int_to_bytes(129260377989791042510121038559452028112)
+    b'a>\\xa4\\xac\\xa4\\xcf@&\\x8e\\x99\\x19\\x04\\xb2\\xbb\\\\\\xd0'
+    >>> uuid_int_to_bytes(158993652234522396927268087548725737125)
+    b'w\\x9d\\x10F\\xd1cK+\\x81&%Oc\\x1c\\xb6\\xa5'
+    """
+    return uuid_siv.to_bytes(16, byteorder='big')
+
+
+def uuid_str_to_bytes(uuid_str: str) -> bytes:
+    """
+    >>> uuid_str_to_bytes('613ea4ac-a4cf-4026-8e99-1904b2bb5cd0')
+    b'a>\\xa4\\xac\\xa4\\xcf@&\\x8e\\x99\\x19\\x04\\xb2\\xbb\\\\\\xd0'
+    >>> uuid_str_to_bytes('779d1046-d163-4b2b-8126-254f631cb6a5')
+    b'w\\x9d\\x10F\\xd1cK+\\x81&%Oc\\x1c\\xb6\\xa5'
+    """
+    return uuid_int_to_bytes(uuid_str_to_int(uuid_str))

+ 22 - 0
tests/tag_interface/test_ogg_vorbis.py

@@ -15,6 +15,19 @@ def test_get_track_path(tracks_dir_path, track_name):
     assert track_path == iface.track_path
 
 
+@pytest.mark.parametrize(('track_name', 'tag_label', 'expected_text'), [
+    ('ogg-opus-empty.opus', 'artist', None),
+    ('ogg-opus-typical.opus', 'artist', 'some artist'),
+    ('ogg-opus-typical.opus', 'comment', 'some comment'),
+    ('ogg-opus-typical.opus', 'com', None),
+    ('ogg-opus-typical.opus', 'symuid:uuid',
+     '613ea4ac-a4cf-4026-8e99-1904b2bb5cd0'),
+])
+def test__get_single_text(tracks_dir_path, track_name, tag_label, expected_text):
+    iface = OggOpus(mutagen.File(os.path.join(tracks_dir_path, track_name)))
+    assert expected_text == iface._get_single_text(tag_label)
+
+
 @pytest.mark.parametrize(('track_name', 'expected_comment'), [
     ('ogg-opus-empty.opus', None),
     ('ogg-opus-typical.opus', 'some comment'),
@@ -37,3 +50,12 @@ def test_set_comment(empty_ogg_opus_path):
     tags = mutagen.File(iface.track_path).tags
     assert len(tags) == 1
     assert tags.items()[0] == ('comment', ['你好'])
+
+
+@pytest.mark.parametrize(('track_name', 'expected_uuid'), [
+    ('ogg-opus-empty.opus', None),
+    ('ogg-opus-typical.opus', b'a>\xa4\xac\xa4\xcf@&\x8e\x99\x19\x04\xb2\xbb\\\xd0'),
+])
+def test_get_track_uuid(tracks_dir_path, track_name, expected_uuid):
+    iface = OggOpus(mutagen.File(os.path.join(tracks_dir_path, track_name)))
+    assert expected_uuid == iface.get_track_uuid()

BIN
tests/tracks/ogg-opus-typical.opus