|
2 | 2 | import logging |
3 | 3 | import os |
4 | 4 | import sys |
| 5 | +import taglib |
5 | 6 |
|
6 | 7 | from beets import importer, plugins |
7 | 8 | from beets.autotag import AlbumMatch, TrackMatch |
@@ -216,7 +217,7 @@ def choose_match(self, task: importer.ImportTask): |
216 | 217 | duplicates = task.find_duplicates(self.lib) |
217 | 218 | if duplicates: |
218 | 219 | print_( |
219 | | - f'\nThis {"album" if task.is_album else "item"} is already in the library!' |
| 220 | + f"\nThis {'album' if task.is_album else 'item'} is already in the library!" |
220 | 221 | ) |
221 | 222 | self.status = "duplicate" |
222 | 223 | for duplicate in duplicates: |
@@ -246,13 +247,14 @@ def __init__( |
246 | 247 | tag_id: str | None = None, |
247 | 248 | ): |
248 | 249 | # make sure to start with clean slate |
| 250 | + # apply all tweaks to global config before initializing the basesession! |
249 | 251 | set_config_defaults() |
250 | 252 | config["import"]["search_ids"].set([match_url]) |
251 | 253 |
|
252 | 254 | if tag_id is not None: |
253 | 255 | config["import"]["set_fields"]["gui_import_id"] = tag_id |
254 | 256 |
|
255 | | - # this also merged config_overlay into the global config |
| 257 | + # this also merges config_overlay into the global config |
256 | 258 | super(MatchedImportSession, self).__init__(path, config_overlay) |
257 | 259 |
|
258 | 260 | # inconvenient: beets does not invoke a sessions resolve_duplicates() method if config["import"]["duplicate_action"] is set meaningfully (anything except 'ask'?). |
@@ -315,7 +317,7 @@ def resolve_duplicate(self, task: importer.ImportTask, found_duplicates): |
315 | 317 | config or config_overlay. |
316 | 318 | """ |
317 | 319 | print_( |
318 | | - f'\nThis {"album" if task.is_album else "item"} is already in the library!' |
| 320 | + f"\nThis {'album' if task.is_album else 'item'} is already in the library!" |
319 | 321 | ) |
320 | 322 | for duplicate in found_duplicates: |
321 | 323 | old_dir = colorize("import_path", duplicate.item_dir().decode("utf-8")) |
@@ -394,6 +396,92 @@ def track_paths_after_import(self) -> list[str]: |
394 | 396 | return [] |
395 | 397 |
|
396 | 398 |
|
| 399 | +class AsIsImportSession(MatchedImportSession): |
| 400 | + """ |
| 401 | + Import session to import without modifyin metadata. |
| 402 | +
|
| 403 | + Essentially `beet import --group-albums -A`, ideal for bootlegs and |
| 404 | + just getting a folder into your library where you are sure the metadata is correct. |
| 405 | +
|
| 406 | + This is a quick-and-dirty version before we rework with the newer sessions that |
| 407 | + are used for interactive imports. |
| 408 | + I derived this from MatchedImportSession, because it has some bits we need, |
| 409 | + but yeah, we should rethink this. |
| 410 | +
|
| 411 | + """ |
| 412 | + |
| 413 | + def __init__( |
| 414 | + self, |
| 415 | + path: str, |
| 416 | + tag_id: str | None = None, |
| 417 | + ): |
| 418 | + |
| 419 | + config_overlay = { |
| 420 | + "import": { |
| 421 | + "group_albums": True, |
| 422 | + "autotag": False, |
| 423 | + "search_ids": [], |
| 424 | + } |
| 425 | + } |
| 426 | + |
| 427 | + super().__init__( |
| 428 | + path=path, |
| 429 | + match_url=None, |
| 430 | + config_overlay=config_overlay, |
| 431 | + tag_id=tag_id, |
| 432 | + ) |
| 433 | + |
| 434 | + self.match_url = None |
| 435 | + self.match_album = None |
| 436 | + self.match_artist = None |
| 437 | + self.match_dist = None |
| 438 | + |
| 439 | + # getting track_paths_after_import does not work, because |
| 440 | + # afaik the import_task only gives paths when we _copied_ |
| 441 | + # so, because with as_is data its more likely that people |
| 442 | + # _move_ the files, we keep track of the paths before import |
| 443 | + self.track_paths_before_import = list(self.track_paths_before_import) |
| 444 | + self.taglib_tags = [ |
| 445 | + taglib.File(fp).tags for fp in self.track_paths_before_import |
| 446 | + ] |
| 447 | + |
| 448 | + def debug(self): |
| 449 | + return config |
| 450 | + |
| 451 | + def choose_match(self, task: importer.ImportTask): |
| 452 | + raise NotImplementedError( |
| 453 | + "AsIsImportSession should not need to choose matches." |
| 454 | + ) |
| 455 | + |
| 456 | + def run_and_capture_output(self) -> tuple[str, str]: |
| 457 | + err, out = super().run_and_capture_output() |
| 458 | + |
| 459 | + # add some basic info of the added items to the preview |
| 460 | + # I do not know how to get a quick dump of file metadata using beets, |
| 461 | + # so we simply use taglib for now |
| 462 | + self.preview += "\n\n" |
| 463 | + if len(self.track_paths_before_import) == 0: |
| 464 | + self.preview += "No files to import." |
| 465 | + else: |
| 466 | + self.preview += f"Metadata in {len(self.track_paths_before_import)} file(s)\n\n" |
| 467 | + for fp in self.track_paths_before_import: |
| 468 | + self.preview += f" {fp}\n" |
| 469 | + tags = taglib.File(fp).tags |
| 470 | + for tag in tags.keys(): |
| 471 | + self.preview += f" {tag.lower()}: {tags[tag][0]}\n" |
| 472 | + self.preview += "--------------------------------------------\n" |
| 473 | + |
| 474 | + |
| 475 | + self.preview += "\n\n (This is no guarantee the import worked)" |
| 476 | + # ... and this is a major TODO. How to get track paths _after_ an import, |
| 477 | + # even when using as is? |
| 478 | + self.preview = self.preview.strip() |
| 479 | + |
| 480 | + return out, err |
| 481 | + |
| 482 | + |
| 483 | + |
| 484 | + |
397 | 485 | def cli_command(beets_args: list[str], key: str = "s") -> tuple[str, str]: |
398 | 486 | """Simulate a cli interaction. |
399 | 487 |
|
|
0 commit comments