File: test_formats___init__.py

package info (click to toggle)
quodlibet 4.7.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 19,228 kB
  • sloc: python: 89,728; sh: 381; xml: 110; makefile: 91
file content (176 lines) | stat: -rw-r--r-- 5,789 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# Copyright 2012 Christoph Reiter
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

import sys

from senf import fsnative

from tests import TestCase, get_data_path
from .helper import capture_output

from quodlibet import formats
from quodlibet.formats import (
    AudioFile,
    load_audio_files,
    dump_audio_files,
    SerializationError,
)
from quodlibet.util.picklehelper import pickle_dumps
from quodlibet import config


class TFormats(TestCase):
    def setUp(self):
        config.init()

    def tearDown(self):
        config.quit()

    def test_presence(self):
        assert formats.aac
        assert formats.aiff
        assert formats.midi
        assert formats.mod
        assert formats.monkeysaudio
        assert formats.mp3
        assert formats.mp4
        assert formats.mpc
        assert formats.spc
        assert formats.trueaudio
        assert formats.vgm
        assert formats.wav
        assert formats.wavpack
        assert formats.wma
        assert formats.xiph

    def test_loaders(self):
        assert formats.loaders[".mp3"] is formats.mp3.MP3File

    def test_migration(self):
        assert formats.mp3 is sys.modules["quodlibet.formats.mp3"]
        assert formats.mp3 is sys.modules["quodlibet/formats/mp3"]
        assert formats.mp3 is sys.modules["formats.mp3"]

        assert formats.xiph is sys.modules["formats.flac"]
        assert formats.xiph is sys.modules["formats.oggvorbis"]

    def test_filter(self):
        assert formats.filter("foo.mp3")
        assert not formats.filter("foo.doc")
        assert not formats.filter("foomp3")

    def test_music_file(self):
        path = get_data_path("silence-44-s.mp3")
        assert formats.MusicFile(path)

        # non existing
        with capture_output() as (stdout, stderr):
            song = formats.MusicFile(get_data_path("nope.mp3"))
            assert not song
            assert stderr.getvalue()

        # unknown extension
        with capture_output() as (stdout, stderr):
            song = formats.MusicFile(get_data_path("nope.xxx"))
            assert not song
            assert not stderr.getvalue()


class TPickle(TestCase):
    def setUp(self):
        types = formats.types
        instances = []
        for t in types:
            i = AudioFile.__new__(t)
            # we want to pickle/unpickle everything, since historically
            # these things ended up in the file
            dict.__init__(
                i, {b"foo": "bar", "quux": b"baz", "a": "b", "b": 42, "c": 0.25}
            )
            instances.append(i)
        self.instances = instances

    def test_load_audio_files(self):
        for protocol in [0, 1, 2]:
            data = pickle_dumps(self.instances, protocol)
            items = load_audio_files(data)
            assert len(items) == len(formats.types)
            assert all(isinstance(i, AudioFile) for i in items)

    def test_sanitized_py3(self):
        i = AudioFile.__new__(list(formats.types)[0])
        # this is something that old py2 versions could pickle
        dict.__init__(
            i,
            {
                b"bytes": b"bytes",
                "unicode": "unicode",
                b"~filename": b"somefile",
                "~mountpoint": "somemount",
                "int": 42,
                b"float": 1.25,
            },
        )
        data = pickle_dumps([i], 1)
        items = load_audio_files(data, process=True)
        i = items[0]

        assert i["bytes"] == "bytes"
        assert i["unicode"] == "unicode"
        assert isinstance(i["~filename"], fsnative)
        assert isinstance(i["~mountpoint"], fsnative)
        assert i["int"] == 42
        assert i["float"] == 1.25

    def test_dump_audio_files(self):
        data = dump_audio_files(self.instances, process=False)
        items = load_audio_files(data, process=False)

        assert len(items) == len(self.instances)
        for a, b in zip(items, self.instances, strict=False):
            a = dict(a)
            b = dict(b)
            for key in a:
                assert b[key] == a[key]
            for key in b:
                assert b[key] == a[key]

    def test_save_ascii_keys_as_bytes_on_py3(self):
        i = AudioFile.__new__(list(formats.types)[0])
        dict.__setitem__(i, "foo", "bar")
        data = dump_audio_files([i], process=True)

        items = load_audio_files(data, process=False)
        assert isinstance(list(items[0].keys())[0], bytes)

    def test_dump_empty(self):
        data = dump_audio_files([])
        assert load_audio_files(data) == []

    def test_load_audio_files_missing_class(self):
        for protocol in [0, 1, 2]:
            data = pickle_dumps(self.instances, protocol)

            items = load_audio_files(data)
            self.assertEqual(len(items), len(formats.types))
            assert all(isinstance(i, AudioFile) for i in items)

            broken = data.replace(b"SPCFile", b"FooFile")
            items = load_audio_files(broken)
            self.assertEqual(len(items), len(formats.types) - 1)
            assert all(isinstance(i, AudioFile) for i in items)

            broken = data.replace(b"formats.spc", b"formats.foo")
            items = load_audio_files(broken)
            self.assertEqual(len(items), len(formats.types) - 1)
            assert all(isinstance(i, AudioFile) for i in items)

    def test_unpickle_random_class(self):
        for protocol in [0, 1, 2]:
            data = pickle_dumps([42], protocol)
            with self.assertRaises(SerializationError):
                load_audio_files(data)