NiceAesth / aiosu

Simple and fast asynchronous osu! API v1 and v2 library
https://aiosu.readthedocs.io
GNU General Public License v3.0
15 stars 3 forks source link

[BUG] get_user_beatmap_scores ERR #159

Closed EnricoBaivo closed 1 year ago

EnricoBaivo commented 1 year ago

Describe the bug trying to use get_user_beatmap_scores and the function throws the following error:

File c:\Python311\Lib\site-packages\pydantic\main.py:866, in BaseModel.repr(self) 865 def repr(self) -> str: --> 866 return f'{self.repr_name()}({self.repr_str(", ")})'

File c:\Python311\Lib\site-packages\pydantic_internal_repr.py:55, in Representation.repr_str__(self, join_str) 54 def repr_str(self, join_str: str) -> str: ---> 55 return join_str.join(repr(v) if a is None else f'{a}={v!r}' for a, v in self.repr_args__())

File c:\Python311\Lib\site-packages\pydantic_internal_repr.py:55, in (.0) 54 def repr_str(self, join_str: str) -> str: ---> 55 return join_str.join(repr(v) if a is None else f'{a}={v!r}' for a, v in self.repr_args())

File c:\Python311\Lib\site-packages\pydantic\main.py:876, in BaseModel.__repr_args__(self) 874 if pydantic_extra is not None: 875 yield from ((k, v) for k, v in pydantic_extra.items()) --> 876 yield from ((k, getattr(self, k)) for k, v in self.model_computed_fields.items() if v.repr) ... --> 171 raise ValueError("Beatmap object is not set.") 173 if self.passed: 174 return 100.0

ValueError: Beatmap object is not set. ` To Reproduce Steps to reproduce the behavior: try: user_beatmap_scores = await client.get_user_beatmap_scores(user_id=7562902, beatmap_id=46827) await print(user_beatmap_scores) except exceptions.APIException as e: print("error", e.status)

Expected behavior The function should return a List of scores from the OSU v2 API

Library version: latest Python version: 3.11

NiceAesth commented 1 year ago

This is a regression from pydantic 2.0 computed fields, which always call the decorators post-init, causing scores without beatmap information to fail to process. Previously it would only raise an exception when attempting to use the property when it was not accesible. Changing it to be an optional instead in #160

NiceAesth commented 1 year ago

Please pull version https://github.com/NiceAesth/aiosu/releases/tag/v2.0.3 from PyPI. Release has been made with the fixes. (Also, of note is to look at the changelog as there has been a breaking change related to replays in this release.)

EnricoBaivo commented 1 year ago

i will check up each api aiosu endpoint for more typing errors.

If you want to i will contribute a list of example json responses from the endpoints.

One more Optional error that i found: dumped: get_user_most_played.json Error serializing to JSON: ValueError: Beatmap contains no object count information.

Thanks for fast fix

NiceAesth commented 1 year ago

That issue was also fixed in the same release. You can check if you want to, currently it passes mypy testing so there shouldn't(?) be any other issues.

Up to date test data would be a welcome change if you are up for it. https://bin.aesth.dev/qibawewodo.py is what I was currently using.

What I intended to create was an integration testing script that could also dump the json response data for every single request (this could be ran in a github action periodically to automatically update test data. I will handle this part myself.)

If you wish to contribute, I would recommend going this path as there is quite a lot of data to be parsed otherwise.

EnricoBaivo commented 1 year ago

Everything runs like expected no issues 💯

Thanks alot !

[!NOTE] Im not really a python advanced developer, so i think that my code isnt good enough to use as a reference.

What i did is to use some relevant aiosu endpoints and saved the result from youre model_dump_json to the acutal files and for the replay file i did the same.


async def run_bumps(client: v2.Client, user_id: int, beatmap_id: int, beatmap_set_id: int, score_id: int):
    """ runs all relavant dump functions for the api """
    if beatmap_id == 0 | beatmap_id == None:
        beatmap_id = 3912744
    if beatmap_set_id == 0 | beatmap_set_id == None:
        beatmap_set_id = 3912744
    if user_id == 0 | user_id == None:
        user_id = 3912744
    if score_id == 0 | score_id == None:
        user_id = 3567661456
    print("running dumps")
    await dump_get_user_recent_scores(client, user_id)
    await dump_get_user_beatmap_scores(client, user_id, beatmap_id)
    await dump_get_user_most_played(client, user_id)
    await dump_get_user_bests(client, user_id)
    await dump_get_user_firsts(client)
    await dump_get_beatmap_set(client, beatmap_set_id)
    await dump_get_own_friends(client)
    await dump_get_user(client, user_id)
    await dump_get_beatmap(client, beatmap_id)
    await dump_get_beatmap_attributes(client, beatmap_id)
    await dump_get_beatmap_scores(client, beatmap_id)
    await dump_beatmapset_events(client)
    await calculate_pp_attributes_from_score(client, user_id, beatmap_id)
    await dump_get_score(client, score_id)
    await dump_get_score_replay(client, score_id)
    await dump_get_beatmaps(client, beatmap_id)

Which results in the following filestruckture:

image

[!IMPORTANT] If you think this could be useful, let me know.