Repository: mopidy/mopidy-spotify

Issue:
TypeError: Expected length to be a <class 'int'>, not 156923.0
Today I'm receiving multiple errors when adding tracks to the queue.
```
ERROR    2024-02-27 12:54:10,020 [1:Core-6 (_actor_loop)] mopidy.core.library
  SpotifyBackend backend caused an exception.
Traceback (most recent call last):
  File "/opt/mopidy/lib64/python3.11/site-packages/mopidy/core/library.py", line 17, in _backend_error_handling
    yield
  File "/opt/mopidy/lib64/python3.11/site-packages/mopidy/core/library.py", line 230, in lookup
    result = future.get()
             ^^^^^^^^^^^^
  File "/opt/mopidy/lib64/python3.11/site-packages/pykka/_threading.py", line 68, in get
    raise exc_value
  File "/opt/mopidy/lib64/python3.11/site-packages/pykka/_actor.py", line 238, in _actor_loop_running
    response = self._handle_receive(envelope.message)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/mopidy/lib64/python3.11/site-packages/pykka/_actor.py", line 349, in _handle_receive
    return callee(*message.args, **message.kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/mopidy/lib64/python3.11/site-packages/mopidy_spotify/library.py", line 38, in lookup
    return lookup.lookup(self._config, self._backend._web_client, uri)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/mopidy/lib64/python3.11/site-packages/mopidy_spotify/lookup.py", line 27, in lookup
    return list(_lookup_track(config, web_client, link))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/mopidy/lib64/python3.11/site-packages/mopidy_spotify/lookup.py", line 51, in _lookup_track
    track = translator.web_to_track(web_track, bitrate=config["bitrate"])
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/mopidy/lib64/python3.11/site-packages/mopidy_spotify/translator.py", line 252, in web_to_track
    return models.Track(
           ^^^^^^^^^^^^^
  File "/opt/mopidy/lib64/python3.11/site-packages/mopidy/models/immutable.py", line 159, in __call__
    instance = super().__call__(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/mopidy/lib64/python3.11/site-packages/mopidy/models/immutable.py", line 35, in __init__
    self._set_field(key, value)
  File "/opt/mopidy/lib64/python3.11/site-packages/mopidy/models/immutable.py", line 188, in _set_field
    object.__setattr__(self, name, value)
  File "/opt/mopidy/lib64/python3.11/site-packages/mopidy/models/fields.py", line 50, in __set__
    value = self.validate(value)
            ^^^^^^^^^^^^^^^^^^^^
  File "/opt/mopidy/lib64/python3.11/site-packages/mopidy/models/fields.py", line 133, in validate
    value = super().validate(value)
            ^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/mopidy/lib64/python3.11/site-packages/mopidy/models/fields.py", line 34, in validate
    raise TypeError(
TypeError: Expected length to be a <class 'int'>, not 156923.0
```

Comments:

Patch:
diff --git a/mopidy_spotify/translator.py b/mopidy_spotify/translator.py
index 229730a..00c6fdf 100644
--- a/mopidy_spotify/translator.py
+++ b/mopidy_spotify/translator.py
@@ -236,6 +236,11 @@ def web_to_album(web_album):
     return models.Album(uri=ref.uri, name=name, artists=artists)
 
 
+def int_or_none(inp):
+    if inp is not None:
+        return int(float(inp))
+
+
 def web_to_track(web_track, bitrate=None, album=None):
     ref = web_to_track_ref(web_track)
     if ref is None:
@@ -254,8 +259,8 @@ def web_to_track(web_track, bitrate=None, album=None):
         name=ref.name,
         artists=artists,
         album=album,
-        length=web_track.get("duration_ms"),
-        disc_no=web_track.get("disc_number"),
-        track_no=web_track.get("track_number"),
+        length=int_or_none(web_track.get("duration_ms")),
+        disc_no=int_or_none(web_track.get("disc_number")),
+        track_no=int_or_none(web_track.get("track_number")),
         bitrate=bitrate,
     )


Test patch:
diff --git a/tests/test_translator.py b/tests/test_translator.py
index ec9e8d6..db778e1 100644
--- a/tests/test_translator.py
+++ b/tests/test_translator.py
@@ -683,3 +683,29 @@ class TestWebToTrack:
 
         assert track.name == "ABC 123"
         assert track.album is None
+
+    @pytest.mark.parametrize(
+        "data",
+        [
+            (123),
+            (123.0),
+            ("123"),
+            ("123.0"),
+        ],
+    )
+    def test_int_or_none_number(self, data):
+        assert translator.int_or_none(data) == 123
+
+    def test_int_or_none_none(self):
+        assert translator.int_or_none(None) is None
+
+    def test_ints_might_be_floats(self, web_track_mock):
+        web_track_mock["duration_ms"] = 123.0
+        web_track_mock["disc_number"] = "456.0"
+        web_track_mock["track_number"] = 99.9
+
+        track = translator.web_to_track(web_track_mock)
+
+        assert track.length == 123
+        assert track.disc_no == 456
+        assert track.track_no == 99