ValueError: not enough values to unpack (expected 2, got 1)
Hi,
I have a project in which I am attempting to retrieve match data. This code worked in the latter half of last year, but recently it throws me this error when I try to access a match from match history.
Here is the block I am attempting to run:
me = cass.get_account(name = "KC TARGHAMAS", tagline = "miku", region = "NA").summoner
len(me.match_history)
And here is the traceback:
ValueError Traceback (most recent call last)
Cell In[22], line 2
1 me = cass.get_account(name = "KC TARGHAMAS", tagline = "miku", region = "NA").summoner
----> 2 len(me.match_history)
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\merakicommons\container.py:363, in LazyList.__len__(self)
361 return super().__len__()
362 else:
--> 363 self._generate_more()
364 return super().__len__()
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\merakicommons\container.py:380, in LazyList._generate_more(self, count)
378 next(self)
379 else:
--> 380 for _ in self:
381 pass
382 assert self._empty
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\merakicommons\container.py:355, in LazyList.__iter__(self)
353 while not self._empty:
354 try:
--> 355 yield next(self)
356 except StopIteration:
357 return
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\merakicommons\container.py:368, in LazyList.__next__(self)
366 def __next__(self):
367 try:
--> 368 value = next(self._generator)
369 super().append(value)
370 except StopIteration as error:
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\cassiopeia\datastores\ghost.py:646, in UnloadedGhostStore.get_match_history.<locals>.generate_matchlists(start, count)
644 pulled_matches += 1
645 if pulled_matches > 0:
--> 646 match = Match.from_match_reference(matchrefdata)
647 yield match
648 if pulled_matches >= count:
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\cassiopeia\core\match.py:1961, in Match.from_match_reference(cls, ref)
1959 @classmethod
1960 def from_match_reference(cls, ref: MatchReferenceData):
-> 1961 platform, id = ref.id.split("_")
1962 id = int(id)
1963 platform = Platform(platform)
ValueError: not enough values to unpack (expected 2, got 1)
I have attempted trying different users, but I still get this. Not sure if I'm doing something wrong, as I'm not too experienced in dealing with APIs. I'm not 100% sure this is something on Cassiopeia's side that broke it, maybe changes in the API? Again, it's not my area of expertise, so I'd appreciate any guidance or help.
Thank you for your time.
Seems like the issue is here: https://github.com/meraki-analytics/cassiopeia/blame/48184665b79ecda0197b3a31f75f99ba6d462831/cassiopeia/datastores/common.py#L255
# Decode to text if a charset is included
match = re.search("CHARSET=(\S+)", content_type)
if match:
# Load JSON if necessary
if "APPLICATION/JSON" in content_type:
body = r.json()
else:
body = r.content.decode("utf-8")
elif "IMAGE/" in content_type:
body = r.content
else:
body = r.content.decode("utf-8")
I'm guessing the Riot API used to return charset=utf-8 in the Content-Type header, but no longer does so the logic breaks. Maybe it can be simplified to the below.
if "APPLICATION/JSON" in content_type:
body = r.json()
elif "IMAGE/" in content_type:
body = r.content
else:
body = r.content.decode("utf-8")
Hey,
This fix works for me. I'm now getting issues when fetching patches but I think that's a whole nother issue concerning how Riot changed their patch naming system.
Edit: After testing some more, it seems there may be a deeper issue at hand. Not sure if it's from your fix or is a separate issue that has arisen, but I get an assortment of errors when I try to fetch a variety of different things.
Here is an example:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\merakicommons\cache.py:15, in lazy.<locals>.wrapper(self)
14 try:
---> 15 return getattr(self, s)
16 except AttributeError:
AttributeError: 'ParticipantStats' object has no attribute '_lazy__items'
During handling of the above exception, another exception occurred:
AttributeError Traceback (most recent call last)
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\merakicommons\ghost.py:41, in ghost_load_on.<locals>.decorator.<locals>.wrapper(*args, **kwargs)
40 try:
---> 41 return method(*args, **kwargs)
42 except errors as error:
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\cassiopeia\core\staticdata\realm.py:63, in Realms.version(self)
60 @CassiopeiaGhost.property(RealmData)
61 @ghost_load_on
62 def version(self) -> str:
---> 63 return self._data[RealmData].version
AttributeError: 'RealmData' object has no attribute 'version'
During handling of the above exception, another exception occurred:
GhostLoadingRequiredError Traceback (most recent call last)
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\merakicommons\ghost.py:87, in Ghost.__property.__get__(self, obj, obj_type)
86 try:
---> 87 return self.fget(obj)
88 except GhostLoadingRequiredError:
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\merakicommons\ghost.py:43, in ghost_load_on.<locals>.decorator.<locals>.wrapper(*args, **kwargs)
42 except errors as error:
---> 43 raise GhostLoadingRequiredError(str(error))
GhostLoadingRequiredError: 'RealmData' object has no attribute 'version'
During handling of the above exception, another exception occurred:
TypeError Traceback (most recent call last)
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\datapipelines\sources.py:69, in DataSource.dispatch.<locals>.wrapper(self, type, query, context)
68 try:
---> 69 return call(self, query, context=context)
70 except TypeError:
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\datapipelines\queries.py:326, in validate_query.<locals>.wrapper.<locals>.wrapped(self, query, context)
325 validator(query)
--> 326 return method(self, query, context)
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\cassiopeia\datastores\ddragon.py:273, in DDragon.get_realms(self, query, context)
272 try:
--> 273 body = json.loads(self._client.get(url)[0])
275 except HTTPError as e:
File ~\AppData\Local\Programs\Python\Python312\Lib\json\__init__.py:339, in loads(s, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)
338 if not isinstance(s, (bytes, bytearray)):
--> 339 raise TypeError(f'the JSON object must be str, bytes or bytearray, '
340 f'not {s.__class__.__name__}')
341 s = s.decode(detect_encoding(s), 'surrogatepass')
TypeError: the JSON object must be str, bytes or bytearray, not dict
During handling of the above exception, another exception occurred:
UnsupportedError Traceback (most recent call last)
Cell In[42], line 4
2 match = me.match_history[0]
3 participant = match.teams[0].participants[0]
----> 4 participant.stats.items
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\merakicommons\cache.py:17, in lazy.<locals>.wrapper(self)
15 return getattr(self, s)
16 except AttributeError:
---> 17 value = method(self)
18 setattr(self, s, value)
19 return value
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\cassiopeia\core\match.py:56, in load_match_on_attributeerror.<locals>.wrapper(self, *args, **kwargs)
53 @functools.wraps(method)
54 def wrapper(self, *args, **kwargs):
55 try:
---> 56 return method(self, *args, **kwargs)
57 except AttributeError: # teamId
58 # The match has only partially loaded this participant and it doesn't have all it's data, so load the full match
59 match = getattr(self, "_{}__match".format(self.__class__.__name__))
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\cassiopeia\core\match.py:1349, in ParticipantStats.items(self)
1337 ids = [
1338 self._data[ParticipantStatsData].item0,
1339 self._data[ParticipantStatsData].item1,
(...)
1344 self._data[ParticipantStatsData].item6,
1345 ]
1346 version = _choose_staticdata_version(self.__match)
1347 return SearchableList(
1348 [
-> 1349 Item(id=id, version=version, region=self.__match.region) if id else None
1350 for id in ids
1351 ]
1352 )
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\cassiopeia\core\common.py:197, in GetFromPipeline.__call__(cls, *args, **kwargs)
191 query = cls.__get_query_from_kwargs__(**kwargs)
192 if (
193 hasattr(cls, "version")
194 and query.get("version", None) is None
195 and cls.__name__ not in ["Realms", "Match"]
196 ):
--> 197 query["version"] = get_latest_version(region=query["region"], endpoint=None)
198 return pipeline.get(cls, query=query)
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\cassiopeia\core\common.py:33, in get_latest_version(region, endpoint)
31 return Realms(region=region).latest_versions[endpoint]
32 else:
---> 33 return Realms(region=region).version
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\merakicommons\ghost.py:90, in Ghost.__property.__get__(self, obj, obj_type)
88 except GhostLoadingRequiredError:
89 load_group = self.fget._Ghost__load_group
---> 90 obj.__load__(load_group)
91 obj._Ghost__set_loaded(load_group)
93 return self.fget(obj)
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\cassiopeia\core\common.py:272, in CassiopeiaGhost.__load__(self, load_group, load_groups)
264 if (
265 hasattr(self.__class__, "version")
266 and "version" not in query
267 and self.__class__.__name__ not in ["Realms", "Match"]
268 ):
269 query["version"] = get_latest_version(
270 region=query["region"], endpoint=None
271 )
--> 272 data = configuration.settings.pipeline.get(
273 type=self._load_types[load_group], query=query
274 )
275 self.__load_hook__(load_group, data)
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\datapipelines\pipelines.py:459, in DataPipeline.get(self, type, query)
457 for handler in handlers:
458 try:
--> 459 return handler.get(query, context)
460 except NotFoundError:
461 pass
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\datapipelines\pipelines.py:185, in _SourceHandler.get(self, query, context)
170 def get(self, query: Mapping[str, Any], context: PipelineContext = None) -> T:
171 """Gets a query from the data source.
172
173 1) Extracts the query from the data source.
(...)
183 The requested object.
184 """
--> 185 result = self._source.get(self._source_type, deepcopy(query), context)
186 LOGGER.info("Got result \"{result}\" from query \"{query}\" of source \"{source}\"".format(result=result, query=query, source=self._source))
188 LOGGER.info("Sending result \"{result}\" to sinks before converting".format(result=result))
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\datapipelines\sources.py:71, in DataSource.dispatch.<locals>.wrapper(self, type, query, context)
69 return call(self, query, context=context)
70 except TypeError:
---> 71 raise DataSource.unsupported(type)
UnsupportedError: The type "RealmDto" is not supported by this DataSource!
I got these sorts of errors when also fetching match.patch, team.bans, participant.champion, participant.runes, and participant.summoner_spell_d (and f). Sometimes I didn't get the AttributeError: <x> object has no attribute '_lazy__<y>' or AttributeError: 'RealmData' object has no attribute 'version'.
The only common link is that each command that doesn't work is one that calls https://ddragon.leagueoflegends.com/realms/na.json, so I feel as if it has something to do with how it now interacts with datadragon/dto objects. I decided to install the cassiopeia-diskstore plugin to see if it would change anything as per this article but it didn't seem to really affect anything. Again, not sure if this is from your fix or in general.