Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ValueError: Attribute 'alt_names' does not accept objects of type <class 'list'> #53

Closed
Soulbadguy54 opened this issue Aug 20, 2023 · 3 comments

Comments

@Soulbadguy54
Copy link

Soulbadguy54 commented Aug 20, 2023

Hello, i took a break in programming. And for now the new type of error is appear, i think that its connected with new sqlalchemy 2.0 update.

I got this table:

class Game(Base):
    __tablename__ = "games"

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    other_id:  Mapped[int] = mapped_column(Integer, index=True, unique=True, nullable=False)
    name: Mapped[str] = mapped_column(String, index=True, nullable=False)
    alt_names: Mapped[list] = mapped_column(mutable_json_type(dbtype=JSONB))

and this class to work with object:

class GameObject(Game):
    def __init__(self, session: AsyncSession, **kw: Any):
        super().__init__(**kw)
        self._session = session

    def parse_data(self, data: dict):
        alt_name_data = data.get("alternative_names", [])

        self.name = data["name"]
        self.other_id = data["id"]
        self.alt_names: list[str] = [_['name'] for _ in alt_name_data if _['comment'] in ALLOWED_TYPES]

The insertion is performed by function:

async def add_game_to_db(self):
    mutable_columns = self.__table__.columns.keys()
    del mutable_columns["id"]

    stm = insert(Game).values(**{getattr(self, column_name) for column_name in mutable_columns})
    stm = stm.on_conflict_do_update(index_elements=["other_id"],
                                    set_={field: getattr(stm.excluded, field) for field in self.__table__.columns.keys()})
    await self._session.execute(stm)

this actions result in error with traceback:

future: <Task finished name='Task-1' coro=<run.<locals>.new_coro() done, defined at G:\python projects\rate_bot\.venv\lib\site-packages\aiorun.py:209> exception=ValueError("Attribute 'alt_names' does not accept objects of type <class 'list'>")>
Traceback (most recent call last):
  File "G:\python projects\rate_bot\.venv\lib\site-packages\aiorun.py", line 219, in new_coro
    await coro
  File "G:\python projects\rate_bot\parser_main.py", line 32, in main
    game.parse_data(data)
  File "G:\python projects\rate_bot\data\game_object.py", line 26, in parse_data
    self.alt_names: list = [_['name'] for _ in alt_name_data if _['comment'] in ALLOWED_TYPES]
  File "G:\python projects\rate_bot\.venv\lib\site-packages\sqlalchemy\orm\attributes.py", line 536, in __set__
    self.impl.set(
  File "G:\python projects\rate_bot\.venv\lib\site-packages\sqlalchemy\orm\attributes.py", line 1276, in set
    value = self.fire_replace_event(
  File "G:\python projects\rate_bot\.venv\lib\site-packages\sqlalchemy\orm\attributes.py", line 1291, in fire_replace_event
    value = fn(
  File "G:\python projects\rate_bot\.venv\lib\site-packages\sqlalchemy\orm\events.py", line 2562, in wrap
    return fn(target, *arg)
  File "G:\python projects\rate_bot\.venv\lib\site-packages\sqlalchemy\ext\mutable.py", line 535, in set_
    value = cls.coerce(key, value)
  File "G:\python projects\rate_bot\.venv\lib\site-packages\sqlalchemy\ext\mutable.py", line 865, in coerce
    return Mutable.coerce(key, value)
  File "G:\python projects\rate_bot\.venv\lib\site-packages\sqlalchemy\ext\mutable.py", line 454, in coerce
    raise ValueError(msg % (key, type(value)))
ValueError: Attribute 'alt_names' does not accept objects of type <class 'list'>

I dont understand what should i do to fix this. The only way i see is to write my own mutable object as described in docs, but this way is too complex and looks like the same as this package. Can you help me with the fix? Thank you and sorry for bad english! :)

@edelooff
Copy link
Owner

The core here is that the non-nested mutable doesn't support the list as the base type currently. The nested one does support that right now, so adding nested=True to your mapped_column(mutable_json_type(dbtype=JSONB)) ought to help with that.

A PR to resolve this was incidentally submitted just a little ago (#51) and I'll release a new version for that one shortly.

@Soulbadguy54
Copy link
Author

Big thanks for you! waiting for new pypi release version :) And yes the nested=True flag fix the exeption!

@edelooff
Copy link
Owner

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants