-
-
Notifications
You must be signed in to change notification settings - Fork 55
Open
Labels
bugSomething isn't workingSomething isn't working
Description
Description
#533 which fixes #524 is insufficient, because (if I understand correctly) getattr(data, relationship.key, MISSING)
is done before the check on relationship.lazy
. If lazy=raise/raise_on_sql
it dies immediately.

URL to code causing the issue
No response
MCVE
#!/usr/bin/env -S uv run
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "sqlalchemy>=2.0",
# "advanced-alchemy",
# ]
# ///
from advanced_alchemy.base import UUIDBase
from sqlalchemy import ForeignKey, String, create_engine
from sqlalchemy.orm import Mapped, mapped_column, relationship, sessionmaker
from advanced_alchemy.repository import SQLAlchemySyncRepository
class Author(UUIDBase):
__tablename__ = "author"
name: Mapped[str] = mapped_column(String(100))
books: Mapped[list["Book"]] = relationship(back_populates="author", lazy="raise")
class Book(UUIDBase):
__tablename__ = "book"
title: Mapped[str] = mapped_column(String(200))
author_id: Mapped[int] = mapped_column(ForeignKey("author.id"))
author: Mapped[Author] = relationship(back_populates="books", lazy="raise")
class AuthorRepo(SQLAlchemySyncRepository[Author]):
model_type = Author
def update_triggers_lazy_raise_on_getattr():
engine = create_engine("sqlite:///:memory:")
session_factory = sessionmaker(engine)
with engine.begin() as conn:
UUIDBase.metadata.create_all(conn)
with session_factory() as session:
# Seed an author with a related book
author = Author(name="Original", books=[Book(title="B1")])
session.add(author)
session.commit()
session.refresh(author)
author_id = author.id
with session_factory() as session:
# Prepare repo
repo = AuthorRepo(session=session)
# Get a persisted author instance that will raise if .books is accessed
author = repo.get(author_id)
author.name = "Updated"
repo.update(author)
# Traceback (most recent call last):
# File "...\advanced_alchemy\exceptions.py", line 286, in wrap_sqlalchemy_exception
# yield
# File "...\advanced_alchemy\repository\_sync.py", line 1511, in update
# if (new_value := getattr(data, relationship.key, MISSING)) is not MISSING:
# ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# File "...\sqlalchemy\orm\attributes.py", line 569, in __get__
# return self.impl.get(state, dict_) # type: ignore[no-any-return]
# ~~~~~~~~~~~~~^^^^^^^^^^^^^^
# File "...\sqlalchemy\orm\attributes.py", line 1096, in get
# value = self._fire_loader_callables(state, key, passive)
# File "...\sqlalchemy\orm\attributes.py", line 1131, in _fire_loader_callables
# return self.callable_(state, passive)
# ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
# File "...\sqlalchemy\orm\strategies.py", line 915, in _load_for_state
# self._invoke_raise_load(state, passive, "raise")
# ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
# File "...\sqlalchemy\orm\strategies.py", line 867, in _invoke_raise_load
# raise sa_exc.InvalidRequestError(
# "'%s' is not available due to lazy='%s'" % (self, lazy)
# )
# sqlalchemy.exc.InvalidRequestError: 'Author.books' is not available due to lazy='raise'
if __name__ == "__main__":
update_triggers_lazy_raise_on_getattr()
Steps to reproduce
Run this file.
Screenshots
No response
Logs
Traceback (most recent call last):
File "...\advanced_alchemy\exceptions.py", line 286, in wrap_sqlalchemy_exception
yield
File "...\advanced_alchemy\repository\_sync.py", line 1511, in update
if (new_value := getattr(data, relationship.key, MISSING)) is not MISSING:
~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "...\sqlalchemy\orm\attributes.py", line 569, in __get__
return self.impl.get(state, dict_) # type: ignore[no-any-return]
~~~~~~~~~~~~~^^^^^^^^^^^^^^
File "...\sqlalchemy\orm\attributes.py", line 1096, in get
value = self._fire_loader_callables(state, key, passive)
File "...\sqlalchemy\orm\attributes.py", line 1131, in _fire_loader_callables
return self.callable_(state, passive)
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
File "...\sqlalchemy\orm\strategies.py", line 915, in _load_for_state
self._invoke_raise_load(state, passive, "raise")
~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
File "...\sqlalchemy\orm\strategies.py", line 867, in _invoke_raise_load
raise sa_exc.InvalidRequestError(
"'%s' is not available due to lazy='%s'" % (self, lazy)
)
sqlalchemy.exc.InvalidRequestError: 'Author.books' is not available due to lazy='raise'
Package Version
Python 3.13.7
dvanced-alchemy==1.6.3
sqlalchemy==2.0.43
Platform
- Linux
- Mac
- Windows
- Other (Please specify in the description above)
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working