Skip to content

Commit

Permalink
ORM: Filter inconsequential warnings from sqlalchemy (#6192)
Browse files Browse the repository at this point in the history
Recently, the code was updated to be compatible with `sqlalchmey~=2.0`
which caused a lot of warnings to be emitted. As of `sqlalchemy==2.0.19`
the `sqlalchemy.orm.unitofwork.UOWTransaction.register_object` method
emits a warning whenever an object is registered that is not part of the
session. See for details:

https://docs.sqlalchemy.org/en/20/changelog/changelog_20.html#change-53740fe9731bbe0f3bb71e3453df07d3

This can happen when the session is committed or flushed and an
object inside the session contains a reference to another object, for
example through a relationship, is not explicitly part of the session.
If that referenced object is not already stored and persisted, it might
get lost. On the other hand, if the object was already persisted before,
there is no risk.

This situation occurs a lot in AiiDA's code base. Prime example is when
a new process is created. Typically the input nodes are either already
stored, or stored first. As soon as they get stored, the session is
committed and the session is reset by expiring all objects. Now, the
input links are created from the input nodes to the process node, and at
the end the process node is stored to commit and persist it with the
links. It is at this point that Sqlalchemy realises that the input nodes
are not explicitly part of the session.

One direct solution would be to add the input nodes again to the session
before committing the process node and the links. However, this code is
part of the backend independent :mod:`aiida.orm` module and this is a
backend-specific problem. This is also just one example and there are
most likely other places in the code where the problem arises. Therefore,
as a workaround, a warning filter is put in place to silence this
particular warning. Note that `pytest` undoes all registered warning
filters, so it has to be added again in the `pytest` configuration in
the `pyproject.toml`.
  • Loading branch information
sphuber authored Nov 30, 2023
1 parent 1dafdf2 commit 5b27ff3
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 0 deletions.
23 changes: 23 additions & 0 deletions aiida/storage/psql_dos/orm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,26 @@
# For further information please visit http://www.aiida.net #
###########################################################################
"""Implementation of ORM backend entities."""
import warnings

from sqlalchemy.exc import SAWarning

# The :meth:`sqlalchemy.orm.unitofwork.UOWTransaction.register_object` method emits a warning whenever an object is
# registered that is not part of the session. This can happen when the session is committed or flushed and an object
# inside the session contains a reference to another object, for example through a relationship, is not explicitly part
# of the session. If that referenced object is not already stored and persisted, it might get lost. On the other hand,
# if the object was already persisted before, there is no risk.
#
# This situation occurs a lot in AiiDA's code base. Prime example is when a new process is created. Typically the input
# nodes are either already stored, or stored first. As soon as they get stored, the session is committed and the session
# is reset by expiring all objects. Now, the input links are created from the input nodes to the process node, and at
# the end the process node is stored to commit and persist it with the links. It is at this point that Sqlalchemy
# realises that the input nodes are not explicitly part of the session.
#
# One direct solution would be to add the input nodes again to the session before committing the process node and the
# links. However, this code is part of the backend independent :mod:`aiida.orm` module and this is a backend-specific
# problem. This is also just one example and there are most likely other places in the code where the problem arises.
# Therefore, as a work around, the specific warning is ignored through a warrning filter.
warnings.filterwarnings(
'ignore', category=SAWarning, message='Object of type .* not in session, .* operation along .* will not proceed'
)
1 change: 1 addition & 0 deletions docs/source/nitpick-exceptions
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ py:class sqlalchemy.orm.decl_api.SqliteModel
py:class sqlalchemy.orm.decl_api.Base
py:class sqlalchemy.sql.compiler.TypeCompiler
py:class sqlalchemy.sql.elements.BooleanClauseList
py:meth sqlalchemy.orm.unitofwork.UOWTransaction.register_object

py:class sphinx.ext.autodoc.ClassDocumenter
py:class sphinx.util.docutils.SphinxDirective
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ filterwarnings = [
"ignore::DeprecationWarning:pymatgen:",
"ignore::DeprecationWarning:jsonbackend:",
"ignore::DeprecationWarning:pkg_resources:",
"ignore:Object of type .* not in session, .* operation along .* will not proceed:sqlalchemy.exc.SAWarning",
"ignore::pytest.PytestCollectionWarning",
"default::ResourceWarning",
]
Expand Down

0 comments on commit 5b27ff3

Please sign in to comment.