fix: Resolve Mopidy v4 ModuleNotFoundError on startup

The Mopidy v4.0 development versions have removed the `mopidy.models.serialize` module, which causes a `ModuleNotFoundError` in Iris on startup.

This commit introduces a check to detect the Mopidy version. It conditionally uses the new Pydantic `.model_dump()` method for serialization on v4 while falling back to the legacy `ModelJSONEncoder` for older versions. This makes Iris compatible with both Mopidy v3 and the new v4 pre-releases.
This commit is contained in:
jojo141185
2025-09-06 10:10:03 +00:00
parent 19cd70533c
commit 4954f6de54

View File

@ -13,11 +13,20 @@ import pickle
from pkg_resources import parse_version
from tornado.escape import json_encode
from tornado.httpclient import AsyncHTTPClient, HTTPRequest
from mopidy.models.serialize import ModelJSONEncoder
from . import Extension
from .system import IrisSystemThread
# Check for Mopidy v4+ compatibility.
# We try to import the old serialization class.
# If it fails, we assume we're running on Mopidy v4+.
try:
from mopidy.models.serialize import ModelJSONEncoder
MOPIDY_V4 = False
except ImportError:
ModelJSONEncoder = None
MOPIDY_V4 = True
if sys.platform == "win32":
import ctypes
@ -1165,19 +1174,31 @@ class IrisCore(pykka.ThreadingActor):
meta = {}
if track:
# Convert the Track to JSON, but to make it a response-ready JSON we need to load it.
# Required because ModelJSONEncoder produces single-quote JSON, and we need standard
# double-quoted json.
track = json.loads(json.dumps(track, cls=ModelJSONEncoder))
images = self.core.library.get_images([track["uri"]]).get()
if images:
meta["images"] = json.loads(
json.dumps(images[track["uri"]], cls=ModelJSONEncoder)
)
meta["name"] = track["name"]
meta["uri"] = track["uri"]
meta["artists"] = track["artists"]
meta["album"] = track["album"]
# Convert the Track to JSON,
# We use different serialization methods depending on the Mopidy version
if MOPIDY_V4:
# Mopidy v4+ uses Pydantic models with .model_dump()
track_data = track.model_dump()
images_result = self.core.library.get_images([track_data["uri"]]).get()
if images_result and track_data["uri"] in images_result:
images = images_result[track_data["uri"]]
# Images in Mopidy v4 are a list of Image objects
meta["images"] = [img.model_dump() for img in images]
else:
# Older versions use the legacy ModelJSONEncoder:
# Convert the Track to JSON, but to make it a response-ready JSON we need to load it.
# Required because ModelJSONEncoder produces single-quote JSON, and we need standard
# double-quoted json.
track_data = json.loads(json.dumps(track, cls=ModelJSONEncoder))
images_result = self.core.library.get_images([track_data["uri"]]).get()
if images_result and track_data["uri"] in images_result:
images = images_result[track_data["uri"]]
meta["images"] = json.loads(json.dumps(images, cls=ModelJSONEncoder))
meta["name"] = track_data["name"]
meta["uri"] = track_data["uri"]
meta["artists"] = track_data["artists"]
meta["album"] = track_data["album"]
url = "http"
if self.config["iris"]["snapcast_ssl"]: