fix: resolve ipod_device import conflict with lazy imports
main.py imports our local ipod_device first, which caches it in sys.modules. When ipod_nano7_db later tried 'from ipod_device import ChecksumType', Python returned the cached local module (which lacks ChecksumType), causing 'ipod_nano7_db not available' and falling back to simple file copy into wrong /Music/ directory. Fix: replace top-level iOpenPod imports with lazy _import_iop() helper that temporarily evicts local ipod_device from sys.modules, adds /tmp/iOpenPod to sys.path, loads the iOpenPod module, then restores the path. All iOpenPod imports now happen inside method bodies only.
This commit is contained in:
parent
4c4a19640d
commit
4f7bd2709c
@ -20,6 +20,7 @@ Public API preserved for main.py compatibility:
|
||||
delete_orphaned_files(paths) — remove orphan files
|
||||
"""
|
||||
|
||||
import importlib
|
||||
import os
|
||||
import sys
|
||||
import hashlib
|
||||
@ -31,25 +32,38 @@ import struct
|
||||
import time
|
||||
from typing import Any, Optional
|
||||
|
||||
os.environ.setdefault("IOPENOD_HOME", "/tmp/iOpenPod")
|
||||
_iop = "/tmp/iOpenPod"
|
||||
if _iop not in sys.path:
|
||||
sys.path.insert(0, _iop)
|
||||
|
||||
from mutagen import File as MutagenFile
|
||||
from mutagen.easyid3 import EasyID3
|
||||
|
||||
from iTunesDB_Writer.mhit_writer import TrackInfo as IopTrackInfo
|
||||
from iTunesDB_Writer.mhyp_writer import PlaylistInfo
|
||||
from iTunesDB_Writer import write_itunesdb as iop_write_itunesdb
|
||||
from SQLiteDB_Writer import write_sqlite_databases
|
||||
from ipod_device import (
|
||||
DeviceCapabilities,
|
||||
ChecksumType,
|
||||
get_firewire_id,
|
||||
capabilities_for_family_gen,
|
||||
get_current_device,
|
||||
)
|
||||
_IOP_ROOT = "/tmp/iOpenPod"
|
||||
|
||||
|
||||
def _import_iop(module_name: str):
|
||||
"""Import a module from iOpenPod, bypassing any locally-cached conflict.
|
||||
|
||||
main.py imports our local ``ipod_device`` first, which caches it in
|
||||
``sys.modules``. When ipod_nano7_db later tries ``from ipod_device
|
||||
import ChecksumType``, Python returns the cached *local* module
|
||||
(which lacks ChecksumType). This helper temporarily evicts the
|
||||
conflicting local modules, adds the iOpenPod root to sys.path, loads
|
||||
the requested module from there, then restores the path.
|
||||
"""
|
||||
# Modules that may be cached as our local copies and need eviction.
|
||||
_conflicting = {"ipod_device"}
|
||||
_saved = {}
|
||||
for name in _conflicting & set(sys.modules):
|
||||
_saved[name] = sys.modules.pop(name)
|
||||
|
||||
had_iop = _IOP_ROOT in sys.path
|
||||
if not had_iop:
|
||||
sys.path.insert(0, _IOP_ROOT)
|
||||
|
||||
try:
|
||||
return importlib.import_module(module_name)
|
||||
finally:
|
||||
if not had_iop:
|
||||
sys.path.remove(_IOP_ROOT)
|
||||
sys.modules.update(_saved)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -165,9 +179,10 @@ def _read_audio_tags(filepath: str) -> dict[str, Any]:
|
||||
|
||||
|
||||
def _scanned_tracks_to_iop(mountpoint: str,
|
||||
scanned: list[dict]) -> list[IopTrackInfo]:
|
||||
scanned: list[dict]) -> list:
|
||||
"""Convert our scanned track dicts to iOpenPod TrackInfo objects."""
|
||||
tracks: list[IopTrackInfo] = []
|
||||
IopTrackInfo = _import_iop("iTunesDB_Writer.mhit_writer").TrackInfo
|
||||
tracks: list = []
|
||||
for s in scanned:
|
||||
fpath = s["file_path"]
|
||||
fname = os.path.basename(fpath)
|
||||
@ -467,11 +482,12 @@ class Nano7Database:
|
||||
logger.info("Built %d iOpenPod TrackInfo objects", len(tracks))
|
||||
|
||||
# 3. Determine capabilities for this device
|
||||
ipod_device = _import_iop("ipod_device")
|
||||
capabilities = None
|
||||
try:
|
||||
dev = get_current_device()
|
||||
dev = ipod_device.get_current_device()
|
||||
if dev and dev.model_family:
|
||||
capabilities = capabilities_for_family_gen(
|
||||
capabilities = ipod_device.capabilities_for_family_gen(
|
||||
dev.model_family, dev.generation or "",
|
||||
)
|
||||
if capabilities:
|
||||
@ -481,10 +497,11 @@ class Nano7Database:
|
||||
|
||||
# 4. Generate and write binary iTunesDB first (to get db_pid)
|
||||
try:
|
||||
firewire_id = get_firewire_id(self.mountpoint)
|
||||
firewire_id = ipod_device.get_firewire_id(self.mountpoint)
|
||||
except Exception:
|
||||
firewire_id = self.firewire_id
|
||||
|
||||
iop_write_itunesdb = _import_iop("iTunesDB_Writer").write_itunesdb
|
||||
ok = iop_write_itunesdb(
|
||||
self.mountpoint,
|
||||
tracks,
|
||||
@ -501,8 +518,8 @@ class Nano7Database:
|
||||
# 5. Extract db_pid from the binary DB for SQLite cross-reference
|
||||
db_pid = 0
|
||||
try:
|
||||
from ipod_device import resolve_itdb_path
|
||||
cdb_path = resolve_itdb_path(self.mountpoint)
|
||||
ipod_dev = _import_iop("ipod_device")
|
||||
cdb_path = ipod_dev.resolve_itdb_path(self.mountpoint)
|
||||
if cdb_path:
|
||||
with open(cdb_path, "rb") as f:
|
||||
hdr = f.read(0x20)
|
||||
@ -514,6 +531,7 @@ class Nano7Database:
|
||||
|
||||
# 6. Write SQLite databases (Nano 6G/7G require this)
|
||||
try:
|
||||
write_sqlite_databases = _import_iop("SQLiteDB_Writer").write_sqlite_databases
|
||||
sqlite_ok = write_sqlite_databases(
|
||||
ipod_path=self.mountpoint,
|
||||
tracks=tracks,
|
||||
@ -532,23 +550,26 @@ class Nano7Database:
|
||||
|
||||
def _write_empty_databases(self) -> None:
|
||||
"""Write minimal empty databases when no tracks exist."""
|
||||
empty_tracks: list[IopTrackInfo] = []
|
||||
ipod_device = _import_iop("ipod_device")
|
||||
iop_write_itunesdb = _import_iop("iTunesDB_Writer").write_itunesdb
|
||||
write_sqlite_databases = _import_iop("SQLiteDB_Writer").write_sqlite_databases
|
||||
|
||||
try:
|
||||
fwid = get_firewire_id(self.mountpoint)
|
||||
fwid = ipod_device.get_firewire_id(self.mountpoint)
|
||||
except Exception:
|
||||
fwid = self.firewire_id
|
||||
capabilities = None
|
||||
try:
|
||||
dev = get_current_device()
|
||||
dev = ipod_device.get_current_device()
|
||||
if dev and dev.model_family:
|
||||
capabilities = capabilities_for_family_gen(
|
||||
capabilities = ipod_device.capabilities_for_family_gen(
|
||||
dev.model_family, dev.generation or "")
|
||||
except Exception:
|
||||
pass
|
||||
iop_write_itunesdb(self.mountpoint, empty_tracks, firewire_id=fwid,
|
||||
iop_write_itunesdb(self.mountpoint, [], firewire_id=fwid,
|
||||
backup=True, capabilities=capabilities)
|
||||
write_sqlite_databases(
|
||||
ipod_path=self.mountpoint, tracks=empty_tracks,
|
||||
ipod_path=self.mountpoint, tracks=[],
|
||||
master_playlist_name="iPod",
|
||||
db_pid=random.getrandbits(64),
|
||||
capabilities=capabilities, firewire_id=fwid, backup=True,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user