• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Olezhich / CueTools / 20865990014

09 Jan 2026 09:24PM UTC coverage: 90.231%. First build
20865990014

Pull #37

github

web-flow
Merge ab94b4c30 into 412edc5e3
Pull Request #37: Dev

22 of 28 new or added lines in 2 files covered. (78.57%)

351 of 389 relevant lines covered (90.23%)

0.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.91
/cuetools/parser/parser.py
1
from pathlib import Path
1✔
2
from typing import Iterator
1✔
3
from cuetools.models import AlbumData, TrackData
1✔
4
from cuetools.parser.errors import CueParseError, CueValidationError
1✔
5
from cuetools.parser.handlers import title_case_handler
1✔
6
from cuetools.parser.lex import Token, lex
1✔
7

8
WAVE_EXTENSIONS = ['.flac', '.ape', '.wav']
1✔
9

10

11
def load_f_iter(cue: Iterator[str], strict_title_case: bool = False) -> AlbumData:
1✔
12
    """loading an object from an iterator"""
13
    album = AlbumData()
1✔
14
    current_file = None
1✔
15
    current_track = None
1✔
16

17
    current_line = 0
1✔
18

19
    for line in cue:
1✔
20
        current_line += 1
1✔
21
        tokens = [i for i in lex(line)]
1✔
22
        try:
1✔
23
            match tokens[0].type:
1✔
24
                case Token.PERFORMER:
1✔
25
                    performer = tokens[1]
1✔
26
                    if not current_track:
1✔
27
                        title_case_handler(
1✔
28
                            performer,
29
                            strict_title_case,
30
                            lambda x: setattr(album, 'performer', x),
31
                            album.set_performer,
32
                            current_line,
33
                            line,
34
                            'album performer name',
35
                        )
36
                    else:
37
                        title_case_handler(
×
38
                            performer,
39
                            strict_title_case,
40
                            lambda x: setattr(current_track, 'performer', x),
41
                            current_track.set_performer,
42
                            current_line,
43
                            line,
44
                            'track performer name',
45
                        )
46
                case Token.TITLE:
1✔
47
                    title = tokens[1]
1✔
48
                    if not current_track:
1✔
49
                        title_case_handler(
1✔
50
                            title,
51
                            strict_title_case,
52
                            lambda x: setattr(album, 'title', x),
53
                            album.set_title,
54
                            current_line,
55
                            line,
56
                            'album title',
57
                        )
58
                    else:
59
                        title_case_handler(
1✔
60
                            title,
61
                            strict_title_case,
62
                            lambda x: setattr(current_track, 'title', x),
63
                            current_track.set_title,
64
                            current_line,
65
                            line,
66
                            'track title',
67
                        )
68
                case Token.FILE:
1✔
69
                    filepath = tokens[1]
1✔
70
                    match filepath.type:
1✔
71
                        case Token.ARG_QUOTES:
1✔
72
                            file_type = tokens[2]
1✔
73
                            match file_type.type:
1✔
74
                                case Token.WAVE:
1✔
75
                                    if not any(
1✔
76
                                        filepath.lexeme.endswith(ext)
77
                                        for ext in WAVE_EXTENSIONS
78
                                    ):
79
                                        raise CueParseError(
1✔
80
                                            current_line,
81
                                            line,
82
                                            f"""current WAVE file type like {', '.join(f"'{i}'" for i in WAVE_EXTENSIONS)}""",
83
                                            file_type.lexeme,
84
                                            file_type.pos,
85
                                        )
86
                                case _:
×
87
                                    raise CueParseError(
×
88
                                        current_line,
89
                                        line,
90
                                        'file type tag',
91
                                        file_type.lexeme,
92
                                        file_type.pos,
93
                                    )
94

95
                            current_file = (  # noqa: F841 # type: ignore
1✔
96
                                Path(filepath.lexeme),
97
                                current_line,
98
                                line,
99
                                filepath.pos,
100
                                filepath.lexeme,
101
                            )
102
                        case _:
×
103
                            CueParseError(
×
104
                                current_line,
105
                                line,
106
                                'audiofile path',
107
                                filepath.lexeme,
108
                                filepath.pos,
109
                            )
110
                case Token.REM:
1✔
111
                    rem_type = tokens[1]
1✔
112
                    value = tokens[2]
1✔
113
                    match rem_type.type:
1✔
114
                        case Token.GENRE:
1✔
115
                            title_case_handler(
1✔
116
                                value,
117
                                strict_title_case,
118
                                lambda x: setattr(album.rem, 'genre', x),
119
                                album.rem.set_genre,
120
                                current_line,
121
                                line,
122
                                'album genre',
123
                            )
124
                        case Token.DATE:
1✔
125
                            try:
1✔
126
                                album.rem.date = int(value.lexeme)
1✔
127
                            except ValueError as e:
1✔
128
                                raise CueValidationError(
1✔
129
                                    current_line, line, value.pos, value.lexeme, e
130
                                )
131
                        case Token.REPLAYGAIN_ALBUM_GAIN:
1✔
132
                            try:
1✔
133
                                album.rem.replaygain_gain = value.lexeme  # type: ignore[assignment]
1✔
134
                            except ValueError as e:
1✔
135
                                raise CueValidationError(
1✔
136
                                    current_line, line, value.pos, value.lexeme, e
137
                                )
138
                        case Token.REPLAYGAIN_ALBUM_PEAK:
1✔
139
                            try:
1✔
140
                                album.rem.replaygain_peak = value.lexeme  # type: ignore[assignment]
1✔
NEW
141
                            except ValueError as e:
×
NEW
142
                                raise CueValidationError(
×
143
                                    current_line, line, value.pos, value.lexeme, e
144
                                )
145
                        case Token.REPLAYGAIN_TRACK_GAIN:
1✔
146
                            if not current_track:
1✔
NEW
147
                                raise CueParseError(
×
148
                                    current_line,
149
                                    line,
150
                                    'any TRACK tag before',
151
                                    tokens[0].lexeme,
152
                                    tokens[1].pos,
153
                                )
154
                            try:
1✔
155
                                current_track.rem.replaygain_gain = value.lexeme  # type: ignore[assignment]
1✔
NEW
156
                            except ValueError as e:
×
NEW
157
                                raise CueValidationError(
×
158
                                    current_line, line, value.pos, value.lexeme, e
159
                                )
160
                        case Token.REPLAYGAIN_TRACK_PEAK:
1✔
161
                            if not current_track:
1✔
NEW
162
                                raise CueParseError(
×
163
                                    current_line,
164
                                    line,
165
                                    'any TRACK tag before',
166
                                    tokens[0].lexeme,
167
                                    tokens[1].pos,
168
                                )
169
                            try:
1✔
170
                                current_track.rem.replaygain_peak = value.lexeme  # type: ignore[assignment]
1✔
171
                            except ValueError as e:
×
172
                                raise CueValidationError(
×
173
                                    current_line, line, value.pos, value.lexeme, e
174
                                )
175
                        case Token.DISCID:
1✔
176
                            ...
1✔
177
                        case Token.COMMENT:
1✔
178
                            ...
1✔
179
                        case _:
×
180
                            raise CueParseError(
1✔
181
                                current_line,
182
                                line,
183
                                'Correct REM parameter',
184
                                rem_type.lexeme,
185
                                rem_type.pos,
186
                            )
187
                case Token.TRACK:
1✔
188
                    if not current_file:
1✔
189
                        raise CueParseError(
×
190
                            current_line,
191
                            line,
192
                            'any FILE tag before',
193
                            tokens[1].lexeme,
194
                            tokens[0].pos,
195
                        )
196
                    if len(tokens) < 2 or tokens[1].type != Token.AUDIO:
1✔
197
                        raise CueParseError(
×
198
                            current_line,
199
                            line,
200
                            'AUDIO tag',
201
                            tokens[1].lexeme if len(tokens) > 1 else 'Nothing',
202
                            tokens[0].pos,
203
                        )
204
                    if current_track:
1✔
205
                        try:
1✔
206
                            album.add_track(current_track)
1✔
207
                        except ValueError as e:
×
208
                            raise CueValidationError(
×
209
                                current_line, line, 0, 'Invalid previous track', e
210
                            )
211
                    current_track = TrackData(
1✔
212
                        track=int(tokens[0].lexeme),
213
                        file=current_file[0],
214
                    )
215
                case Token.INDEX:
1✔
216
                    if not current_track:
1✔
217
                        raise CueParseError(
1✔
218
                            current_line,
219
                            line,
220
                            'any TRACK tag before',
221
                            tokens[0].lexeme,
222
                            tokens[1].pos,
223
                        )
224
                    index_type = int(tokens[0].lexeme)
1✔
225
                    if index_type == 0:
1✔
226
                        if current_track.index00:
1✔
227
                            raise CueParseError(
×
228
                                current_line,
229
                                line,
230
                                'one INDEX 00 value',
231
                                'dublicate INDEX 00 value',
232
                                tokens[0].pos,
233
                            )
234
                        current_track.index00 = tokens[1].lexeme  # type: ignore[assignment]
1✔
235
                    elif index_type == 1:
1✔
236
                        current_track.index01 = tokens[1].lexeme  # type: ignore[assignment]
1✔
237
                case _:
×
238
                    raise CueParseError(
×
239
                        current_line,
240
                        line,
241
                        'Correct CUE keyword',
242
                        tokens[0].lexeme,
243
                        tokens[0].pos,
244
                    )
245
        except IndexError:
1✔
246
            raise CueParseError(
1✔
247
                current_line, line, 'More tokens to parse the string correctly', line, 0
248
            )
249

250
    if current_track:
1✔
251
        album.add_track(current_track)
1✔
252

253
    return album
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc