Skip to content

Commit 4093ac1

Browse files
committed
add type annotations in ui/commands/import
also add necessary type annotations in `importer/session.py` to prevent additional mypy errors
1 parent 4dd9402 commit 4093ac1

File tree

4 files changed

+515
-243
lines changed

4 files changed

+515
-243
lines changed

beets/importer/session.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
import os
1717
import time
18-
from typing import TYPE_CHECKING, Sequence
18+
from typing import TYPE_CHECKING
1919

2020
from beets import config, dbcore, library, logging, plugins, util
2121
from beets.importer.tasks import Action
@@ -25,6 +25,10 @@
2525
from .state import ImportState
2626

2727
if TYPE_CHECKING:
28+
from typing import Literal, Sequence
29+
30+
from beets.autotag import AlbumMatch, TrackMatch
31+
from beets.importer.tasks import SingletonImportTask
2832
from beets.util import PathBytes
2933

3034
from .tasks import ImportTask
@@ -60,7 +64,7 @@ def __init__(
6064
lib: library.Library,
6165
loghandler: logging.Handler | None,
6266
paths: Sequence[PathBytes] | None,
63-
query: dbcore.Query | None,
67+
query: dbcore.Query | str | list[str] | tuple[str] | None,
6468
):
6569
"""Create a session.
6670
@@ -173,16 +177,20 @@ def log_choice(self, task: ImportTask, duplicate=False):
173177
elif task.choice_flag is Action.SKIP:
174178
self.tag_log("skip", paths)
175179

176-
def should_resume(self, path: PathBytes):
180+
def should_resume(self, path: PathBytes) -> bool:
177181
raise NotImplementedError
178182

179-
def choose_match(self, task: ImportTask):
183+
def choose_match(
184+
self, task: ImportTask
185+
) -> Literal[Action.ASIS, Action.SKIP] | AlbumMatch | TrackMatch:
180186
raise NotImplementedError
181187

182-
def resolve_duplicate(self, task: ImportTask, found_duplicates):
188+
def resolve_duplicate(self, task: ImportTask, found_duplicates) -> None:
183189
raise NotImplementedError
184190

185-
def choose_item(self, task: ImportTask):
191+
def choose_item(
192+
self, task: SingletonImportTask
193+
) -> Literal[Action.ASIS, Action.SKIP] | AlbumMatch | TrackMatch:
186194
raise NotImplementedError
187195

188196
def run(self):

beets/ui/commands/import_/__init__.py

Lines changed: 64 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
"""The `import` command: import new music into the library."""
22

3+
from __future__ import annotations
4+
35
import os
6+
from typing import TYPE_CHECKING
47

58
from beets import config, logging, plugins
69
from beets.ui._common import UserError
@@ -10,11 +13,23 @@
1013
from .._utils import parse_logfiles
1114
from .session import TerminalImportSession
1215

16+
if TYPE_CHECKING:
17+
from logging import FileHandler
18+
from optparse import Values
19+
20+
from beets.dbcore import Query
21+
from beets.library import Library
22+
23+
1324
# Global logger.
1425
log = logging.getLogger("beets")
1526

1627

17-
def import_files(lib, paths: list[bytes], query):
28+
def import_files(
29+
lib: Library,
30+
paths: list[bytes],
31+
query: Query | str | list[str] | tuple[str] | None,
32+
) -> None:
1833
"""Import the files in the given list of paths or matching the
1934
query.
2035
"""
@@ -24,7 +39,8 @@ def import_files(lib, paths: list[bytes], query):
2439

2540
# Open the log.
2641
if config["import"]["log"].get() is not None:
27-
logpath = syspath(config["import"]["log"].as_filename())
42+
logpath: str = syspath(config["import"]["log"].as_filename())
43+
loghandler: FileHandler | None
2844
try:
2945
loghandler = logging.FileHandler(logpath, encoding="utf-8")
3046
except OSError:
@@ -39,39 +55,52 @@ def import_files(lib, paths: list[bytes], query):
3955
if config["import"]["resume"].get() == "ask" and config["import"]["quiet"]:
4056
config["import"]["resume"] = False
4157

42-
session = TerminalImportSession(lib, loghandler, paths, query)
58+
session: TerminalImportSession = TerminalImportSession(
59+
lib, loghandler, paths, query
60+
)
4361
session.run()
4462

4563
# Emit event.
46-
plugins.send("import", lib=lib, paths=paths)
64+
_ = plugins.send("import", lib=lib, paths=paths)
4765

4866

49-
def import_func(lib, opts, args: list[str]):
67+
def import_func(
68+
lib: Library,
69+
opts: Values,
70+
args: list[str] | tuple[str],
71+
) -> None:
5072
config["import"].set_args(opts)
5173

5274
# Special case: --copy flag suppresses import_move (which would
5375
# otherwise take precedence).
5476
if opts.copy:
5577
config["import"]["move"] = False
5678

79+
query: Query | str | list[str] | tuple[str] | None
80+
byte_paths: list[bytes]
5781
if opts.library:
5882
query = args
5983
byte_paths = []
6084
else:
6185
query = None
62-
paths = args
86+
paths: list[str] | tuple[str] = args
6387

6488
# The paths from the logfiles go into a separate list to allow handling
6589
# errors differently from user-specified paths.
66-
paths_from_logfiles = list(parse_logfiles(opts.from_logfiles or []))
90+
paths_from_logfiles: list[str] = list(
91+
parse_logfiles(opts.from_logfiles or [])
92+
)
6793

6894
if not paths and not paths_from_logfiles:
6995
raise UserError("no path specified")
7096

7197
byte_paths = [os.fsencode(p) for p in paths]
72-
paths_from_logfiles = [os.fsencode(p) for p in paths_from_logfiles]
98+
byte_paths_from_logfiles: list[bytes] = [
99+
os.fsencode(p) for p in paths_from_logfiles
100+
]
73101

74102
# Check the user-specified directories.
103+
path: bytes
75104
for path in byte_paths:
76105
if not os.path.exists(syspath(normpath(path))):
77106
raise UserError(
@@ -82,7 +111,7 @@ def import_func(lib, opts, args: list[str]):
82111
# case those paths don't exist. Maybe some of those paths have already
83112
# been imported and moved separately, so logging a warning should
84113
# suffice.
85-
for path in paths_from_logfiles:
114+
for path in byte_paths_from_logfiles:
86115
if not os.path.exists(syspath(normpath(path))):
87116
log.warning(
88117
"No such file or directory: {}", displayable_path(path)
@@ -102,177 +131,177 @@ def import_func(lib, opts, args: list[str]):
102131
import_cmd = Subcommand(
103132
"import", help="import new music", aliases=("imp", "im")
104133
)
105-
import_cmd.parser.add_option(
134+
_ = import_cmd.parser.add_option(
106135
"-c",
107136
"--copy",
108137
action="store_true",
109138
default=None,
110139
help="copy tracks into library directory (default)",
111140
)
112-
import_cmd.parser.add_option(
141+
_ = import_cmd.parser.add_option(
113142
"-C",
114143
"--nocopy",
115144
action="store_false",
116145
dest="copy",
117146
help="don't copy tracks (opposite of -c)",
118147
)
119-
import_cmd.parser.add_option(
148+
_ = import_cmd.parser.add_option(
120149
"-m",
121150
"--move",
122151
action="store_true",
123152
dest="move",
124153
help="move tracks into the library (overrides -c)",
125154
)
126-
import_cmd.parser.add_option(
155+
_ = import_cmd.parser.add_option(
127156
"-w",
128157
"--write",
129158
action="store_true",
130159
default=None,
131160
help="write new metadata to files' tags (default)",
132161
)
133-
import_cmd.parser.add_option(
162+
_ = import_cmd.parser.add_option(
134163
"-W",
135164
"--nowrite",
136165
action="store_false",
137166
dest="write",
138167
help="don't write metadata (opposite of -w)",
139168
)
140-
import_cmd.parser.add_option(
169+
_ = import_cmd.parser.add_option(
141170
"-a",
142171
"--autotag",
143172
action="store_true",
144173
dest="autotag",
145174
help="infer tags for imported files (default)",
146175
)
147-
import_cmd.parser.add_option(
176+
_ = import_cmd.parser.add_option(
148177
"-A",
149178
"--noautotag",
150179
action="store_false",
151180
dest="autotag",
152181
help="don't infer tags for imported files (opposite of -a)",
153182
)
154-
import_cmd.parser.add_option(
183+
_ = import_cmd.parser.add_option(
155184
"-p",
156185
"--resume",
157186
action="store_true",
158187
default=None,
159188
help="resume importing if interrupted",
160189
)
161-
import_cmd.parser.add_option(
190+
_ = import_cmd.parser.add_option(
162191
"-P",
163192
"--noresume",
164193
action="store_false",
165194
dest="resume",
166195
help="do not try to resume importing",
167196
)
168-
import_cmd.parser.add_option(
197+
_ = import_cmd.parser.add_option(
169198
"-q",
170199
"--quiet",
171200
action="store_true",
172201
dest="quiet",
173202
help="never prompt for input: skip albums instead",
174203
)
175-
import_cmd.parser.add_option(
204+
_ = import_cmd.parser.add_option(
176205
"--quiet-fallback",
177206
type="string",
178207
dest="quiet_fallback",
179208
help="decision in quiet mode when no strong match: skip or asis",
180209
)
181-
import_cmd.parser.add_option(
210+
_ = import_cmd.parser.add_option(
182211
"-l",
183212
"--log",
184213
dest="log",
185214
help="file to log untaggable albums for later review",
186215
)
187-
import_cmd.parser.add_option(
216+
_ = import_cmd.parser.add_option(
188217
"-s",
189218
"--singletons",
190219
action="store_true",
191220
help="import individual tracks instead of full albums",
192221
)
193-
import_cmd.parser.add_option(
222+
_ = import_cmd.parser.add_option(
194223
"-t",
195224
"--timid",
196225
dest="timid",
197226
action="store_true",
198227
help="always confirm all actions",
199228
)
200-
import_cmd.parser.add_option(
229+
_ = import_cmd.parser.add_option(
201230
"-L",
202231
"--library",
203232
dest="library",
204233
action="store_true",
205234
help="retag items matching a query",
206235
)
207-
import_cmd.parser.add_option(
236+
_ = import_cmd.parser.add_option(
208237
"-i",
209238
"--incremental",
210239
dest="incremental",
211240
action="store_true",
212241
help="skip already-imported directories",
213242
)
214-
import_cmd.parser.add_option(
243+
_ = import_cmd.parser.add_option(
215244
"-I",
216245
"--noincremental",
217246
dest="incremental",
218247
action="store_false",
219248
help="do not skip already-imported directories",
220249
)
221-
import_cmd.parser.add_option(
250+
_ = import_cmd.parser.add_option(
222251
"-R",
223252
"--incremental-skip-later",
224253
action="store_true",
225254
dest="incremental_skip_later",
226255
help="do not record skipped files during incremental import",
227256
)
228-
import_cmd.parser.add_option(
257+
_ = import_cmd.parser.add_option(
229258
"-r",
230259
"--noincremental-skip-later",
231260
action="store_false",
232261
dest="incremental_skip_later",
233262
help="record skipped files during incremental import",
234263
)
235-
import_cmd.parser.add_option(
264+
_ = import_cmd.parser.add_option(
236265
"--from-scratch",
237266
dest="from_scratch",
238267
action="store_true",
239268
help="erase existing metadata before applying new metadata",
240269
)
241-
import_cmd.parser.add_option(
270+
_ = import_cmd.parser.add_option(
242271
"--flat",
243272
dest="flat",
244273
action="store_true",
245274
help="import an entire tree as a single album",
246275
)
247-
import_cmd.parser.add_option(
276+
_ = import_cmd.parser.add_option(
248277
"-g",
249278
"--group-albums",
250279
dest="group_albums",
251280
action="store_true",
252281
help="group tracks in a folder into separate albums",
253282
)
254-
import_cmd.parser.add_option(
283+
_ = import_cmd.parser.add_option(
255284
"--pretend",
256285
dest="pretend",
257286
action="store_true",
258287
help="just print the files to import",
259288
)
260-
import_cmd.parser.add_option(
289+
_ = import_cmd.parser.add_option(
261290
"-S",
262291
"--search-id",
263292
dest="search_ids",
264293
action="append",
265294
metavar="ID",
266295
help="restrict matching to a specific metadata backend ID",
267296
)
268-
import_cmd.parser.add_option(
297+
_ = import_cmd.parser.add_option(
269298
"--from-logfile",
270299
dest="from_logfiles",
271300
action="append",
272301
metavar="PATH",
273302
help="read skipped paths from an existing logfile",
274303
)
275-
import_cmd.parser.add_option(
304+
_ = import_cmd.parser.add_option(
276305
"--set",
277306
dest="set_fields",
278307
action="callback",

0 commit comments

Comments
 (0)