Skip to content

importer: fix tar and 7z archive import#6696

Open
bcotton wants to merge 1 commit into
beetbox:masterfrom
bcotton:tarfile-bugfix
Open

importer: fix tar and 7z archive import#6696
bcotton wants to merge 1 commit into
beetbox:masterfrom
bcotton:tarfile-bugfix

Conversation

@bcotton
Copy link
Copy Markdown
Contributor

@bcotton bcotton commented May 31, 2026

Sorry about the delay.

  • Fixes Tarfile import fails with extraction failed: 'TarFile' object has no attribute 'infolist' #5664. Both tar and 7z archive imports were broken because ArchiveImportTask.extract calls archive.infolist(), but neither tarfile.TarFile (lost ZipFileCompat in Python 3) nor py7zr.SevenZipFile (exposes list() instead) provides it. Both surfaces produced '… object has no attribute 'infolist' and aborted the import.
  • Adds thin module-level wrappers — TarArchive (subclass of tarfile.TarFile) and SevenZipArchive (composition over py7zr.SevenZipFile, since py7zr is optional) — that expose a ZipFile-compatible infolist(). Tiny _TarMemberInfo / _SevenZipMemberInfo adapters carry only the two attributes the extract loop reads: filename and date_time.
  • Fixes a latent bug in the test suite: ImportTarTest.create_archive and Import7zTest's inheritance were dead code. The parent test_import_zip called the module-level create_archive(self) helper, which only knows how to build zips, so both tar and 7z tests were silently exercising the zip path. Routing through self.create_archive() makes them real regression tests for this bug.

This supersedes #5666; design follows @wisp3rwind's review feedback there (module-level wrappers, minimal adapters, shared test infrastructure via self.create_archive).

Test plan

  • pytest test/test_importer.py::ImportZipTest test/test_importer.py::ImportTarTest test/test_importer.py::Import7zTest — all pass
  • Reverting only beets/importer/tasks.py to master while keeping test changes reproduces the original 'TarFile' object has no attribute 'infolist' and 'SevenZipFile' object has no attribute 'infolist' errors (confirming the tests are real regression tests)
  • pytest test/test_importer.py — full module: 127 passed, 5 skipped (env-dependent: reflink, unrar, unimplemented)
  • Manual: beet import on a real .tar archive

Copilot AI review requested due to automatic review settings May 31, 2026 14:43
@bcotton bcotton requested a review from a team as a code owner May 31, 2026 14:43
Both `tarfile.TarFile` and `py7zr.SevenZipFile` lack an `infolist()`
method, which `ArchiveImportTask.extract` relies on to iterate members
and restore mtimes. `TarFile` lost it when `ZipFileCompat` was removed
in Python 3; `SevenZipFile` exposes `list()` instead. Both surfaces
raised `'... object has no attribute 'infolist'` during import.

Add thin module-level wrappers — `TarArchive` (subclass) and
`SevenZipArchive` (composition, since `py7zr` is optional) — that
adapt their respective backends to the ZipFile-compatible interface.
Members are exposed via tiny adapter classes carrying only the two
attributes the extract loop needs: `filename` and `date_time`.

Also fix a latent test bug: `ImportTarTest.create_archive` and
`Import7zTest`'s inheritance were dead code because the parent's
`test_import_zip` called the module-level `create_archive` helper
(which only knows how to make zips). Route through `self.create_archive`
so the tar and 7z tests actually exercise their archive types.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 31, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 72.60%. Comparing base (2efc80b) to head (764539b).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6696      +/-   ##
==========================================
+ Coverage   72.57%   72.60%   +0.03%     
==========================================
  Files         162      162              
  Lines       20810    20831      +21     
  Branches     3292     3292              
==========================================
+ Hits        15103    15125      +22     
  Misses       4982     4982              
+ Partials      725      724       -1     
Files with missing lines Coverage Δ
beets/importer/tasks.py 91.65% <100.00%> (+0.49%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tarfile import fails with extraction failed: 'TarFile' object has no attribute 'infolist'

1 participant