Bonsoir à tous,

Je me tire les cheveux depuis un petit moment et ... je sèche complètement...
Je suis entrain de dev un petit soft pour le fun et surtout apprendre SQLAlchemy et je bloque

J'initialise le tout:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
from sqlalchemy.orm import declarative_base
 
DATABASE_URL = "sqlite+aiosqlite:///./db/test.db"
 
engine = create_async_engine(DATABASE_URL, future=True, echo=True)
async_session = async_sessionmaker(engine, expire_on_commit=False)
Base = declarative_base()
Puis j'ai créé 3 objects tel que:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class PremierObject(Base):
    __tablename__ = "premieretable"
 
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(String(30))
 
    deuxiemeobjets: Mapped[list["DeuxiemeObjet"]] = relationship("DeuxiemeObjet", back_populates="premierobjet")
 
 
class DeuxiemeObjet(Base):
    __tablename__ = "deuxiemetable"
 
    id: Mapped[int] = mapped_column(primary_key=True)
    premierobjet_id: Mapped[int] = mapped_column(ForeignKey("premieretable.id"))
    name: Mapped[str] = mapped_column(String(30))
    description: Mapped[Optional[str]]
    enable: Mapped[bool] = mapped_column(Boolean, default=True)
 
    premierobjet: Mapped["PremierObjet"] = relationship("PremierObject", back_populates="deuxiemeobjets")
    troisiemeobjets: Mapped[list["TroisiemeObjet"]] = relationship("TroisiemeObjet", back_populates="deuxiemeobjet")
 
 
class TroisiemeObjet(Base):
    __tablename__ = "troisiemetable"
 
    id: Mapped[int] = mapped_column(primary_key=True)
    deuxiemeobjet_id: Mapped[int] = mapped_column(ForeignKey("deuxiemetable.id"), nullable=True)
    description: Mapped[Optional[str]]
 
    deuxiemeobjet: Mapped[list["DeuxiemeObjet"]] = relationship("DeuxiemeObjet", back_populates="troisiemeobjets", secondary='deuxiemeobjet_troisiemeobjets')
 
 
 
class DeuxiemeObjetTroisiemeObjet(Base):
    __tablename__ = "deuxiemeobjet_troisiemeobjets"
 
    deuxiemeobjet_id: Mapped[int] = mapped_column("deuxiemeobjet_id", Integer, ForeignKey("deuxiemetable.id"), primary_key=True)
    troisiemeobjet_id: Mapped[int] = mapped_column("troisiemeobjet_id", Integer, ForeignKey("troisiemetable.id"), primary_key=True)
 
    deuxiemeobjet: Mapped["DeuxiemeObjet"] = relationship("DeuxiemeObjet", backref="deuxiemeobjet_assoc")
    troisiemeobjet: Mapped[list["TroisiemeObjet"]] = relationship("TroisiemeObjet", backref="troisiemeobjet_assoc")
J'arrive bien à créer mes objets, tout est inséré correctement en base.
Par contre, quand je tente de récupérer PremierObjet de la table premieretable, j'ai bien mon objet et je récupère bien les infos de DeuxiemeObjet par contre la liaison DeuxiemeObjet -> TroisiemeObjet semble avoir un soucis parce que je ne peux pas accéder à la liste de TroisiemeObjet

Le code complet
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
from sqlalchemy import Boolean, ForeignKey, Integer, String
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
from sqlalchemy.future import select
from sqlalchemy.orm import declarative_base, Mapped, mapped_column, relationship
from typing import Optional
import asyncio
 
DATABASE_URL = "sqlite+aiosqlite:///./test.db"
 
engine = create_async_engine(DATABASE_URL, future=True, echo=True)
async_session = async_sessionmaker(engine, expire_on_commit=False)
Base = declarative_base()
 
class PremierObject(Base):
    __tablename__ = "premieretable"
 
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(String(30))
 
    deuxiemeobjets: Mapped[list["DeuxiemeObjet"]] = relationship("DeuxiemeObjet", back_populates="premierobjet")
 
 
class DeuxiemeObjet(Base):
    __tablename__ = "deuxiemetable"
 
    id: Mapped[int] = mapped_column(primary_key=True)
    premierobjet_id: Mapped[int] = mapped_column(ForeignKey("premieretable.id"))
    name: Mapped[str] = mapped_column(String(30))
    description: Mapped[Optional[str]]
    enable: Mapped[bool] = mapped_column(Boolean, default=True)
 
    premierobjet: Mapped["PremierObjet"] = relationship("PremierObject", back_populates="deuxiemeobjets")
    troisiemeobjets: Mapped[list["TroisiemeObjet"]] = relationship("TroisiemeObjet", back_populates="deuxiemeobjet")
 
 
class TroisiemeObjet(Base):
    __tablename__ = "troisiemetable"
 
    id: Mapped[int] = mapped_column(primary_key=True)
    deuxiemeobjet_id: Mapped[int] = mapped_column(ForeignKey("deuxiemetable.id"), nullable=True)
    description: Mapped[Optional[str]]
 
    deuxiemeobjet: Mapped[list["DeuxiemeObjet"]] = relationship("DeuxiemeObjet", back_populates="troisiemeobjets", secondary='deuxiemeobjet_troisiemeobjets')
 
 
 
class DeuxiemeObjetTroisiemeObjet(Base):
    __tablename__ = "deuxiemeobjet_troisiemeobjets"
 
    deuxiemeobjet_id: Mapped[int] = mapped_column("deuxiemeobjet_id", Integer, ForeignKey("deuxiemetable.id"), primary_key=True)
    troisiemeobjet_id: Mapped[int] = mapped_column("troisiemeobjet_id", Integer, ForeignKey("troisiemetable.id"), primary_key=True)
 
    deuxiemeobjet: Mapped["DeuxiemeObjet"] = relationship("DeuxiemeObjet", backref="deuxiemeobjet_assoc")
    troisiemeobjet: Mapped[list["TroisiemeObjet"]] = relationship("TroisiemeObjet", backref="troisiemeobjet_assoc")
 
 
async def main():
    objet1 = PremierObject(name="Toto")
    objet2 = DeuxiemeObjet(premierobjet=objet1, name="objet2")
    objet3 = TroisiemeObjet(deuxiemeobjet=[objet2])
 
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.drop_all)
        await conn.run_sync(Base.metadata.create_all)
 
    async with async_session() as session:
        async with session.begin():
            session.add(objet3)
 
    async with async_session() as session:
        async with session.begin():
            objet1 = (await session.execute(select(PremierObject).where(PremierObject.name == "Toto"))).scalars().first()
            print(objet1.deuxiemeobjets)
 
 
 
asyncio.run(main())
L'erreur:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Traceback (most recent call last):
  File "/Users/Desktop/workspace/Python/perso/crypto/Gestionnaires/Scholars/test/test.py", line 77, in <module>
    asyncio.run(main())
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
    return future.result()
  File "/Users/Desktop/workspace/Python/perso/crypto/Gestionnaires/Scholars/test/test.py", line 73, in main
    print(objet1.deuxiemeobjets)
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/attributes.py", line 562, in __get__
    return self.impl.get(state, dict_)  # type: ignore[no-any-return]
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/attributes.py", line 1075, in get
    value = self._fire_loader_callables(state, key, passive)
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/attributes.py", line 1110, in _fire_loader_callables
    return self.callable_(state, passive)
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/strategies.py", line 948, in _load_for_state
    return self._emit_lazyload(
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/strategies.py", line 1111, in _emit_lazyload
    result = session.execute(
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 2229, in execute
    return self._execute_internal(
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 2124, in _execute_internal
    result: Result[Any] = compile_state_cls.orm_execute_statement(
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/context.py", line 252, in orm_execute_statement
    result = conn.execute(
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1414, in execute
    return meth(
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/sql/elements.py", line 489, in _execute_on_connection
    return connection._execute_clauseelement(
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1638, in _execute_clauseelement
    ret = self._execute_context(
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1842, in _execute_context
    return self._exec_single_context(
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1983, in _exec_single_context
    self._handle_dbapi_exception(
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 2328, in _handle_dbapi_exception
    raise exc_info[1].with_traceback(exc_info[2])
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1964, in _exec_single_context
    self.dialect.do_execute(
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 747, in do_execute
    cursor.execute(statement, parameters)
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 113, in execute
    self._adapt_connection._handle_exception(error)
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 254, in _handle_exception
    raise error
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 90, in execute
    _cursor = self.await_(self._connection.cursor())
  File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 93, in await_only
    raise exc.MissingGreenlet(
sqlalchemy.exc.MissingGreenlet: greenlet_spawn has not been called; can't call await_only() here. Was IO attempted in an unexpected place? (Background on this error at: https://sqlalche.me/e/20/xd2s)
sys:1: RuntimeWarning: coroutine 'Connection.cursor' was never awaited
Est-ce qu'une gentille âme serait capable de m'éclairer svp?
Cordialement,
Julien