summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/quick_tour.rst2
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/models/__init__.py62
-rw-r--r--docs/tutorials/wiki2/src/authentication/tutorial/models/__init__.py62
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/models/__init__.py62
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/models/__init__.py62
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py62
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/models/__init__.py62
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/models/__init__.py62
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/models/__init__.py62
9 files changed, 417 insertions, 81 deletions
diff --git a/docs/quick_tour.rst b/docs/quick_tour.rst
index be53a3344..add25f1d2 100644
--- a/docs/quick_tour.rst
+++ b/docs/quick_tour.rst
@@ -938,7 +938,7 @@ system, can then easily get at the data thanks to SQLAlchemy:
.. literalinclude:: quick_tour/sqla_demo/sqla_demo/views/default.py
:language: python
:lineno-match:
- :lines: 13
+ :pyobject: my_view
.. seealso:: See also:
:ref:`Quick Tutorial Databases <qtut_databases>`, `SQLAlchemy
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/models/__init__.py b/docs/quick_tour/sqla_demo/sqla_demo/models/__init__.py
index 71f9f36b5..b00b8de9e 100644
--- a/docs/quick_tour/sqla_demo/sqla_demo/models/__init__.py
+++ b/docs/quick_tour/sqla_demo/sqla_demo/models/__init__.py
@@ -3,12 +3,12 @@ from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import configure_mappers
import zope.sqlalchemy
-# import or define all models here to ensure they are attached to the
-# Base.metadata prior to any initialization routines
+# Import or define all models here to ensure they are attached to the
+# ``Base.metadata`` prior to any initialization routines.
from .mymodel import MyModel # flake8: noqa
-# run configure_mappers after defining all of the models to ensure
-# all relationships can be setup
+# Run ``configure_mappers`` after defining all of the models to ensure
+# all relationships can be setup.
configure_mappers()
@@ -22,7 +22,7 @@ def get_session_factory(engine):
return factory
-def get_tm_session(session_factory, transaction_manager):
+def get_tm_session(session_factory, transaction_manager, request=None):
"""
Get a ``sqlalchemy.orm.Session`` instance backed by a transaction.
@@ -33,7 +33,9 @@ def get_tm_session(session_factory, transaction_manager):
depending on whether an exception is raised.
- When using scripts you should wrap the session in a manager yourself.
- For example::
+ For example:
+
+ .. code-block:: python
import transaction
@@ -42,10 +44,43 @@ def get_tm_session(session_factory, transaction_manager):
with transaction.manager:
dbsession = get_tm_session(session_factory, transaction.manager)
+ This function may be invoked with a ``request`` kwarg, such as when invoked
+ by the reified ``.dbsession`` Pyramid request attribute which is configured
+ via the ``includeme`` function below. The default value, for backwards
+ compatibility, is ``None``.
+
+ The ``request`` kwarg is used to populate the ``sqlalchemy.orm.Session``'s
+ "info" dict. The "info" dict is the official namespace for developers to
+ stash session-specific information. For more information, please see the
+ SQLAlchemy docs:
+ https://docs.sqlalchemy.org/en/stable/orm/session_api.html#sqlalchemy.orm.session.Session.params.info
+
+ By placing the active ``request`` in the "info" dict, developers will be
+ able to access the active Pyramid request from an instance of an SQLAlchemy
+ object in one of two ways:
+
+ - Classic SQLAlchemy. This uses the ``Session``'s utility class method:
+
+ .. code-block:: python
+
+ from sqlalchemy.orm.session import Session as sa_Session
+
+ dbsession = sa_Session.object_session(dbObject)
+ request = dbsession.info["request"]
+
+ - Modern SQLAlchemy. This uses the "Runtime Inspection API":
+
+ .. code-block:: python
+
+ from sqlalchemy import inspect as sa_inspect
+
+ dbsession = sa_inspect(dbObject).session
+ request = dbsession.info["request"]
"""
- dbsession = session_factory()
+ dbsession = session_factory(info={"request": request})
zope.sqlalchemy.register(
- dbsession, transaction_manager=transaction_manager)
+ dbsession, transaction_manager=transaction_manager
+ )
return dbsession
@@ -59,7 +94,12 @@ def includeme(config):
settings = config.get_settings()
settings['tm.manager_hook'] = 'pyramid_tm.explicit_manager'
- # use pyramid_tm to hook the transaction lifecycle to the request
+ # Use ``pyramid_tm`` to hook the transaction lifecycle to the request.
+ # Note: the packages ``pyramid_tm`` and ``transaction`` work together to
+ # automatically close the active database session after every request.
+ # If your project migrates away from ``pyramid_tm``, you may need to use a
+ # Pyramid callback function to close the database session after each
+ # request.
config.include('pyramid_tm')
# use pyramid_retry to retry a request when transient exceptions occur
@@ -79,7 +119,9 @@ def includeme(config):
dbsession = request.environ.get('app.dbsession')
if dbsession is None:
# request.tm is the transaction manager used by pyramid_tm
- dbsession = get_tm_session(session_factory, request.tm)
+ dbsession = get_tm_session(
+ session_factory, request.tm, request=request
+ )
return dbsession
config.add_request_method(dbsession, reify=True)
diff --git a/docs/tutorials/wiki2/src/authentication/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/authentication/tutorial/models/__init__.py
index 47d77ef01..6f9f6586a 100644
--- a/docs/tutorials/wiki2/src/authentication/tutorial/models/__init__.py
+++ b/docs/tutorials/wiki2/src/authentication/tutorial/models/__init__.py
@@ -3,13 +3,13 @@ from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import configure_mappers
import zope.sqlalchemy
-# import or define all models here to ensure they are attached to the
-# Base.metadata prior to any initialization routines
+# Import or define all models here to ensure they are attached to the
+# ``Base.metadata`` prior to any initialization routines.
from .page import Page # flake8: noqa
from .user import User # flake8: noqa
-# run configure_mappers after defining all of the models to ensure
-# all relationships can be setup
+# Run ``configure_mappers`` after defining all of the models to ensure
+# all relationships can be setup.
configure_mappers()
@@ -23,7 +23,7 @@ def get_session_factory(engine):
return factory
-def get_tm_session(session_factory, transaction_manager):
+def get_tm_session(session_factory, transaction_manager, request=None):
"""
Get a ``sqlalchemy.orm.Session`` instance backed by a transaction.
@@ -34,7 +34,9 @@ def get_tm_session(session_factory, transaction_manager):
depending on whether an exception is raised.
- When using scripts you should wrap the session in a manager yourself.
- For example::
+ For example:
+
+ .. code-block:: python
import transaction
@@ -43,10 +45,43 @@ def get_tm_session(session_factory, transaction_manager):
with transaction.manager:
dbsession = get_tm_session(session_factory, transaction.manager)
+ This function may be invoked with a ``request`` kwarg, such as when invoked
+ by the reified ``.dbsession`` Pyramid request attribute which is configured
+ via the ``includeme`` function below. The default value, for backwards
+ compatibility, is ``None``.
+
+ The ``request`` kwarg is used to populate the ``sqlalchemy.orm.Session``'s
+ "info" dict. The "info" dict is the official namespace for developers to
+ stash session-specific information. For more information, please see the
+ SQLAlchemy docs:
+ https://docs.sqlalchemy.org/en/stable/orm/session_api.html#sqlalchemy.orm.session.Session.params.info
+
+ By placing the active ``request`` in the "info" dict, developers will be
+ able to access the active Pyramid request from an instance of an SQLAlchemy
+ object in one of two ways:
+
+ - Classic SQLAlchemy. This uses the ``Session``'s utility class method:
+
+ .. code-block:: python
+
+ from sqlalchemy.orm.session import Session as sa_Session
+
+ dbsession = sa_Session.object_session(dbObject)
+ request = dbsession.info["request"]
+
+ - Modern SQLAlchemy. This uses the "Runtime Inspection API":
+
+ .. code-block:: python
+
+ from sqlalchemy import inspect as sa_inspect
+
+ dbsession = sa_inspect(dbObject).session
+ request = dbsession.info["request"]
"""
- dbsession = session_factory()
+ dbsession = session_factory(info={"request": request})
zope.sqlalchemy.register(
- dbsession, transaction_manager=transaction_manager)
+ dbsession, transaction_manager=transaction_manager
+ )
return dbsession
@@ -60,7 +95,12 @@ def includeme(config):
settings = config.get_settings()
settings['tm.manager_hook'] = 'pyramid_tm.explicit_manager'
- # use pyramid_tm to hook the transaction lifecycle to the request
+ # Use ``pyramid_tm`` to hook the transaction lifecycle to the request.
+ # Note: the packages ``pyramid_tm`` and ``transaction`` work together to
+ # automatically close the active database session after every request.
+ # If your project migrates away from ``pyramid_tm``, you may need to use a
+ # Pyramid callback function to close the database session after each
+ # request.
config.include('pyramid_tm')
# use pyramid_retry to retry a request when transient exceptions occur
@@ -80,7 +120,9 @@ def includeme(config):
dbsession = request.environ.get('app.dbsession')
if dbsession is None:
# request.tm is the transaction manager used by pyramid_tm
- dbsession = get_tm_session(session_factory, request.tm)
+ dbsession = get_tm_session(
+ session_factory, request.tm, request=request
+ )
return dbsession
config.add_request_method(dbsession, reify=True)
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/authorization/tutorial/models/__init__.py
index 47d77ef01..6f9f6586a 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/models/__init__.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/models/__init__.py
@@ -3,13 +3,13 @@ from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import configure_mappers
import zope.sqlalchemy
-# import or define all models here to ensure they are attached to the
-# Base.metadata prior to any initialization routines
+# Import or define all models here to ensure they are attached to the
+# ``Base.metadata`` prior to any initialization routines.
from .page import Page # flake8: noqa
from .user import User # flake8: noqa
-# run configure_mappers after defining all of the models to ensure
-# all relationships can be setup
+# Run ``configure_mappers`` after defining all of the models to ensure
+# all relationships can be setup.
configure_mappers()
@@ -23,7 +23,7 @@ def get_session_factory(engine):
return factory
-def get_tm_session(session_factory, transaction_manager):
+def get_tm_session(session_factory, transaction_manager, request=None):
"""
Get a ``sqlalchemy.orm.Session`` instance backed by a transaction.
@@ -34,7 +34,9 @@ def get_tm_session(session_factory, transaction_manager):
depending on whether an exception is raised.
- When using scripts you should wrap the session in a manager yourself.
- For example::
+ For example:
+
+ .. code-block:: python
import transaction
@@ -43,10 +45,43 @@ def get_tm_session(session_factory, transaction_manager):
with transaction.manager:
dbsession = get_tm_session(session_factory, transaction.manager)
+ This function may be invoked with a ``request`` kwarg, such as when invoked
+ by the reified ``.dbsession`` Pyramid request attribute which is configured
+ via the ``includeme`` function below. The default value, for backwards
+ compatibility, is ``None``.
+
+ The ``request`` kwarg is used to populate the ``sqlalchemy.orm.Session``'s
+ "info" dict. The "info" dict is the official namespace for developers to
+ stash session-specific information. For more information, please see the
+ SQLAlchemy docs:
+ https://docs.sqlalchemy.org/en/stable/orm/session_api.html#sqlalchemy.orm.session.Session.params.info
+
+ By placing the active ``request`` in the "info" dict, developers will be
+ able to access the active Pyramid request from an instance of an SQLAlchemy
+ object in one of two ways:
+
+ - Classic SQLAlchemy. This uses the ``Session``'s utility class method:
+
+ .. code-block:: python
+
+ from sqlalchemy.orm.session import Session as sa_Session
+
+ dbsession = sa_Session.object_session(dbObject)
+ request = dbsession.info["request"]
+
+ - Modern SQLAlchemy. This uses the "Runtime Inspection API":
+
+ .. code-block:: python
+
+ from sqlalchemy import inspect as sa_inspect
+
+ dbsession = sa_inspect(dbObject).session
+ request = dbsession.info["request"]
"""
- dbsession = session_factory()
+ dbsession = session_factory(info={"request": request})
zope.sqlalchemy.register(
- dbsession, transaction_manager=transaction_manager)
+ dbsession, transaction_manager=transaction_manager
+ )
return dbsession
@@ -60,7 +95,12 @@ def includeme(config):
settings = config.get_settings()
settings['tm.manager_hook'] = 'pyramid_tm.explicit_manager'
- # use pyramid_tm to hook the transaction lifecycle to the request
+ # Use ``pyramid_tm`` to hook the transaction lifecycle to the request.
+ # Note: the packages ``pyramid_tm`` and ``transaction`` work together to
+ # automatically close the active database session after every request.
+ # If your project migrates away from ``pyramid_tm``, you may need to use a
+ # Pyramid callback function to close the database session after each
+ # request.
config.include('pyramid_tm')
# use pyramid_retry to retry a request when transient exceptions occur
@@ -80,7 +120,9 @@ def includeme(config):
dbsession = request.environ.get('app.dbsession')
if dbsession is None:
# request.tm is the transaction manager used by pyramid_tm
- dbsession = get_tm_session(session_factory, request.tm)
+ dbsession = get_tm_session(
+ session_factory, request.tm, request=request
+ )
return dbsession
config.add_request_method(dbsession, reify=True)
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/models/__init__.py
index 1c3ec5ee8..c12abdc85 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/models/__init__.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/models/__init__.py
@@ -3,12 +3,12 @@ from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import configure_mappers
import zope.sqlalchemy
-# import or define all models here to ensure they are attached to the
-# Base.metadata prior to any initialization routines
+# Import or define all models here to ensure they are attached to the
+# ``Base.metadata`` prior to any initialization routines.
from .mymodel import MyModel # flake8: noqa
-# run configure_mappers after defining all of the models to ensure
-# all relationships can be setup
+# Run ``configure_mappers`` after defining all of the models to ensure
+# all relationships can be setup.
configure_mappers()
@@ -22,7 +22,7 @@ def get_session_factory(engine):
return factory
-def get_tm_session(session_factory, transaction_manager):
+def get_tm_session(session_factory, transaction_manager, request=None):
"""
Get a ``sqlalchemy.orm.Session`` instance backed by a transaction.
@@ -33,7 +33,9 @@ def get_tm_session(session_factory, transaction_manager):
depending on whether an exception is raised.
- When using scripts you should wrap the session in a manager yourself.
- For example::
+ For example:
+
+ .. code-block:: python
import transaction
@@ -42,10 +44,43 @@ def get_tm_session(session_factory, transaction_manager):
with transaction.manager:
dbsession = get_tm_session(session_factory, transaction.manager)
+ This function may be invoked with a ``request`` kwarg, such as when invoked
+ by the reified ``.dbsession`` Pyramid request attribute which is configured
+ via the ``includeme`` function below. The default value, for backwards
+ compatibility, is ``None``.
+
+ The ``request`` kwarg is used to populate the ``sqlalchemy.orm.Session``'s
+ "info" dict. The "info" dict is the official namespace for developers to
+ stash session-specific information. For more information, please see the
+ SQLAlchemy docs:
+ https://docs.sqlalchemy.org/en/stable/orm/session_api.html#sqlalchemy.orm.session.Session.params.info
+
+ By placing the active ``request`` in the "info" dict, developers will be
+ able to access the active Pyramid request from an instance of an SQLAlchemy
+ object in one of two ways:
+
+ - Classic SQLAlchemy. This uses the ``Session``'s utility class method:
+
+ .. code-block:: python
+
+ from sqlalchemy.orm.session import Session as sa_Session
+
+ dbsession = sa_Session.object_session(dbObject)
+ request = dbsession.info["request"]
+
+ - Modern SQLAlchemy. This uses the "Runtime Inspection API":
+
+ .. code-block:: python
+
+ from sqlalchemy import inspect as sa_inspect
+
+ dbsession = sa_inspect(dbObject).session
+ request = dbsession.info["request"]
"""
- dbsession = session_factory()
+ dbsession = session_factory(info={"request": request})
zope.sqlalchemy.register(
- dbsession, transaction_manager=transaction_manager)
+ dbsession, transaction_manager=transaction_manager
+ )
return dbsession
@@ -59,7 +94,12 @@ def includeme(config):
settings = config.get_settings()
settings['tm.manager_hook'] = 'pyramid_tm.explicit_manager'
- # use pyramid_tm to hook the transaction lifecycle to the request
+ # Use ``pyramid_tm`` to hook the transaction lifecycle to the request.
+ # Note: the packages ``pyramid_tm`` and ``transaction`` work together to
+ # automatically close the active database session after every request.
+ # If your project migrates away from ``pyramid_tm``, you may need to use a
+ # Pyramid callback function to close the database session after each
+ # request.
config.include('pyramid_tm')
# use pyramid_retry to retry a request when transient exceptions occur
@@ -79,7 +119,9 @@ def includeme(config):
dbsession = request.environ.get('app.dbsession')
if dbsession is None:
# request.tm is the transaction manager used by pyramid_tm
- dbsession = get_tm_session(session_factory, request.tm)
+ dbsession = get_tm_session(
+ session_factory, request.tm, request=request
+ )
return dbsession
config.add_request_method(dbsession, reify=True)
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py
index 1c3ec5ee8..c12abdc85 100644
--- a/docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py
+++ b/docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py
@@ -3,12 +3,12 @@ from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import configure_mappers
import zope.sqlalchemy
-# import or define all models here to ensure they are attached to the
-# Base.metadata prior to any initialization routines
+# Import or define all models here to ensure they are attached to the
+# ``Base.metadata`` prior to any initialization routines.
from .mymodel import MyModel # flake8: noqa
-# run configure_mappers after defining all of the models to ensure
-# all relationships can be setup
+# Run ``configure_mappers`` after defining all of the models to ensure
+# all relationships can be setup.
configure_mappers()
@@ -22,7 +22,7 @@ def get_session_factory(engine):
return factory
-def get_tm_session(session_factory, transaction_manager):
+def get_tm_session(session_factory, transaction_manager, request=None):
"""
Get a ``sqlalchemy.orm.Session`` instance backed by a transaction.
@@ -33,7 +33,9 @@ def get_tm_session(session_factory, transaction_manager):
depending on whether an exception is raised.
- When using scripts you should wrap the session in a manager yourself.
- For example::
+ For example:
+
+ .. code-block:: python
import transaction
@@ -42,10 +44,43 @@ def get_tm_session(session_factory, transaction_manager):
with transaction.manager:
dbsession = get_tm_session(session_factory, transaction.manager)
+ This function may be invoked with a ``request`` kwarg, such as when invoked
+ by the reified ``.dbsession`` Pyramid request attribute which is configured
+ via the ``includeme`` function below. The default value, for backwards
+ compatibility, is ``None``.
+
+ The ``request`` kwarg is used to populate the ``sqlalchemy.orm.Session``'s
+ "info" dict. The "info" dict is the official namespace for developers to
+ stash session-specific information. For more information, please see the
+ SQLAlchemy docs:
+ https://docs.sqlalchemy.org/en/stable/orm/session_api.html#sqlalchemy.orm.session.Session.params.info
+
+ By placing the active ``request`` in the "info" dict, developers will be
+ able to access the active Pyramid request from an instance of an SQLAlchemy
+ object in one of two ways:
+
+ - Classic SQLAlchemy. This uses the ``Session``'s utility class method:
+
+ .. code-block:: python
+
+ from sqlalchemy.orm.session import Session as sa_Session
+
+ dbsession = sa_Session.object_session(dbObject)
+ request = dbsession.info["request"]
+
+ - Modern SQLAlchemy. This uses the "Runtime Inspection API":
+
+ .. code-block:: python
+
+ from sqlalchemy import inspect as sa_inspect
+
+ dbsession = sa_inspect(dbObject).session
+ request = dbsession.info["request"]
"""
- dbsession = session_factory()
+ dbsession = session_factory(info={"request": request})
zope.sqlalchemy.register(
- dbsession, transaction_manager=transaction_manager)
+ dbsession, transaction_manager=transaction_manager
+ )
return dbsession
@@ -59,7 +94,12 @@ def includeme(config):
settings = config.get_settings()
settings['tm.manager_hook'] = 'pyramid_tm.explicit_manager'
- # use pyramid_tm to hook the transaction lifecycle to the request
+ # Use ``pyramid_tm`` to hook the transaction lifecycle to the request.
+ # Note: the packages ``pyramid_tm`` and ``transaction`` work together to
+ # automatically close the active database session after every request.
+ # If your project migrates away from ``pyramid_tm``, you may need to use a
+ # Pyramid callback function to close the database session after each
+ # request.
config.include('pyramid_tm')
# use pyramid_retry to retry a request when transient exceptions occur
@@ -79,7 +119,9 @@ def includeme(config):
dbsession = request.environ.get('app.dbsession')
if dbsession is None:
# request.tm is the transaction manager used by pyramid_tm
- dbsession = get_tm_session(session_factory, request.tm)
+ dbsession = get_tm_session(
+ session_factory, request.tm, request=request
+ )
return dbsession
config.add_request_method(dbsession, reify=True)
diff --git a/docs/tutorials/wiki2/src/models/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/models/tutorial/models/__init__.py
index 47d77ef01..6f9f6586a 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/models/__init__.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/models/__init__.py
@@ -3,13 +3,13 @@ from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import configure_mappers
import zope.sqlalchemy
-# import or define all models here to ensure they are attached to the
-# Base.metadata prior to any initialization routines
+# Import or define all models here to ensure they are attached to the
+# ``Base.metadata`` prior to any initialization routines.
from .page import Page # flake8: noqa
from .user import User # flake8: noqa
-# run configure_mappers after defining all of the models to ensure
-# all relationships can be setup
+# Run ``configure_mappers`` after defining all of the models to ensure
+# all relationships can be setup.
configure_mappers()
@@ -23,7 +23,7 @@ def get_session_factory(engine):
return factory
-def get_tm_session(session_factory, transaction_manager):
+def get_tm_session(session_factory, transaction_manager, request=None):
"""
Get a ``sqlalchemy.orm.Session`` instance backed by a transaction.
@@ -34,7 +34,9 @@ def get_tm_session(session_factory, transaction_manager):
depending on whether an exception is raised.
- When using scripts you should wrap the session in a manager yourself.
- For example::
+ For example:
+
+ .. code-block:: python
import transaction
@@ -43,10 +45,43 @@ def get_tm_session(session_factory, transaction_manager):
with transaction.manager:
dbsession = get_tm_session(session_factory, transaction.manager)
+ This function may be invoked with a ``request`` kwarg, such as when invoked
+ by the reified ``.dbsession`` Pyramid request attribute which is configured
+ via the ``includeme`` function below. The default value, for backwards
+ compatibility, is ``None``.
+
+ The ``request`` kwarg is used to populate the ``sqlalchemy.orm.Session``'s
+ "info" dict. The "info" dict is the official namespace for developers to
+ stash session-specific information. For more information, please see the
+ SQLAlchemy docs:
+ https://docs.sqlalchemy.org/en/stable/orm/session_api.html#sqlalchemy.orm.session.Session.params.info
+
+ By placing the active ``request`` in the "info" dict, developers will be
+ able to access the active Pyramid request from an instance of an SQLAlchemy
+ object in one of two ways:
+
+ - Classic SQLAlchemy. This uses the ``Session``'s utility class method:
+
+ .. code-block:: python
+
+ from sqlalchemy.orm.session import Session as sa_Session
+
+ dbsession = sa_Session.object_session(dbObject)
+ request = dbsession.info["request"]
+
+ - Modern SQLAlchemy. This uses the "Runtime Inspection API":
+
+ .. code-block:: python
+
+ from sqlalchemy import inspect as sa_inspect
+
+ dbsession = sa_inspect(dbObject).session
+ request = dbsession.info["request"]
"""
- dbsession = session_factory()
+ dbsession = session_factory(info={"request": request})
zope.sqlalchemy.register(
- dbsession, transaction_manager=transaction_manager)
+ dbsession, transaction_manager=transaction_manager
+ )
return dbsession
@@ -60,7 +95,12 @@ def includeme(config):
settings = config.get_settings()
settings['tm.manager_hook'] = 'pyramid_tm.explicit_manager'
- # use pyramid_tm to hook the transaction lifecycle to the request
+ # Use ``pyramid_tm`` to hook the transaction lifecycle to the request.
+ # Note: the packages ``pyramid_tm`` and ``transaction`` work together to
+ # automatically close the active database session after every request.
+ # If your project migrates away from ``pyramid_tm``, you may need to use a
+ # Pyramid callback function to close the database session after each
+ # request.
config.include('pyramid_tm')
# use pyramid_retry to retry a request when transient exceptions occur
@@ -80,7 +120,9 @@ def includeme(config):
dbsession = request.environ.get('app.dbsession')
if dbsession is None:
# request.tm is the transaction manager used by pyramid_tm
- dbsession = get_tm_session(session_factory, request.tm)
+ dbsession = get_tm_session(
+ session_factory, request.tm, request=request
+ )
return dbsession
config.add_request_method(dbsession, reify=True)
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/tests/tutorial/models/__init__.py
index 47d77ef01..6f9f6586a 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/models/__init__.py
+++ b/docs/tutorials/wiki2/src/tests/tutorial/models/__init__.py
@@ -3,13 +3,13 @@ from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import configure_mappers
import zope.sqlalchemy
-# import or define all models here to ensure they are attached to the
-# Base.metadata prior to any initialization routines
+# Import or define all models here to ensure they are attached to the
+# ``Base.metadata`` prior to any initialization routines.
from .page import Page # flake8: noqa
from .user import User # flake8: noqa
-# run configure_mappers after defining all of the models to ensure
-# all relationships can be setup
+# Run ``configure_mappers`` after defining all of the models to ensure
+# all relationships can be setup.
configure_mappers()
@@ -23,7 +23,7 @@ def get_session_factory(engine):
return factory
-def get_tm_session(session_factory, transaction_manager):
+def get_tm_session(session_factory, transaction_manager, request=None):
"""
Get a ``sqlalchemy.orm.Session`` instance backed by a transaction.
@@ -34,7 +34,9 @@ def get_tm_session(session_factory, transaction_manager):
depending on whether an exception is raised.
- When using scripts you should wrap the session in a manager yourself.
- For example::
+ For example:
+
+ .. code-block:: python
import transaction
@@ -43,10 +45,43 @@ def get_tm_session(session_factory, transaction_manager):
with transaction.manager:
dbsession = get_tm_session(session_factory, transaction.manager)
+ This function may be invoked with a ``request`` kwarg, such as when invoked
+ by the reified ``.dbsession`` Pyramid request attribute which is configured
+ via the ``includeme`` function below. The default value, for backwards
+ compatibility, is ``None``.
+
+ The ``request`` kwarg is used to populate the ``sqlalchemy.orm.Session``'s
+ "info" dict. The "info" dict is the official namespace for developers to
+ stash session-specific information. For more information, please see the
+ SQLAlchemy docs:
+ https://docs.sqlalchemy.org/en/stable/orm/session_api.html#sqlalchemy.orm.session.Session.params.info
+
+ By placing the active ``request`` in the "info" dict, developers will be
+ able to access the active Pyramid request from an instance of an SQLAlchemy
+ object in one of two ways:
+
+ - Classic SQLAlchemy. This uses the ``Session``'s utility class method:
+
+ .. code-block:: python
+
+ from sqlalchemy.orm.session import Session as sa_Session
+
+ dbsession = sa_Session.object_session(dbObject)
+ request = dbsession.info["request"]
+
+ - Modern SQLAlchemy. This uses the "Runtime Inspection API":
+
+ .. code-block:: python
+
+ from sqlalchemy import inspect as sa_inspect
+
+ dbsession = sa_inspect(dbObject).session
+ request = dbsession.info["request"]
"""
- dbsession = session_factory()
+ dbsession = session_factory(info={"request": request})
zope.sqlalchemy.register(
- dbsession, transaction_manager=transaction_manager)
+ dbsession, transaction_manager=transaction_manager
+ )
return dbsession
@@ -60,7 +95,12 @@ def includeme(config):
settings = config.get_settings()
settings['tm.manager_hook'] = 'pyramid_tm.explicit_manager'
- # use pyramid_tm to hook the transaction lifecycle to the request
+ # Use ``pyramid_tm`` to hook the transaction lifecycle to the request.
+ # Note: the packages ``pyramid_tm`` and ``transaction`` work together to
+ # automatically close the active database session after every request.
+ # If your project migrates away from ``pyramid_tm``, you may need to use a
+ # Pyramid callback function to close the database session after each
+ # request.
config.include('pyramid_tm')
# use pyramid_retry to retry a request when transient exceptions occur
@@ -80,7 +120,9 @@ def includeme(config):
dbsession = request.environ.get('app.dbsession')
if dbsession is None:
# request.tm is the transaction manager used by pyramid_tm
- dbsession = get_tm_session(session_factory, request.tm)
+ dbsession = get_tm_session(
+ session_factory, request.tm, request=request
+ )
return dbsession
config.add_request_method(dbsession, reify=True)
diff --git a/docs/tutorials/wiki2/src/views/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/views/tutorial/models/__init__.py
index 47d77ef01..6f9f6586a 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/models/__init__.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/models/__init__.py
@@ -3,13 +3,13 @@ from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import configure_mappers
import zope.sqlalchemy
-# import or define all models here to ensure they are attached to the
-# Base.metadata prior to any initialization routines
+# Import or define all models here to ensure they are attached to the
+# ``Base.metadata`` prior to any initialization routines.
from .page import Page # flake8: noqa
from .user import User # flake8: noqa
-# run configure_mappers after defining all of the models to ensure
-# all relationships can be setup
+# Run ``configure_mappers`` after defining all of the models to ensure
+# all relationships can be setup.
configure_mappers()
@@ -23,7 +23,7 @@ def get_session_factory(engine):
return factory
-def get_tm_session(session_factory, transaction_manager):
+def get_tm_session(session_factory, transaction_manager, request=None):
"""
Get a ``sqlalchemy.orm.Session`` instance backed by a transaction.
@@ -34,7 +34,9 @@ def get_tm_session(session_factory, transaction_manager):
depending on whether an exception is raised.
- When using scripts you should wrap the session in a manager yourself.
- For example::
+ For example:
+
+ .. code-block:: python
import transaction
@@ -43,10 +45,43 @@ def get_tm_session(session_factory, transaction_manager):
with transaction.manager:
dbsession = get_tm_session(session_factory, transaction.manager)
+ This function may be invoked with a ``request`` kwarg, such as when invoked
+ by the reified ``.dbsession`` Pyramid request attribute which is configured
+ via the ``includeme`` function below. The default value, for backwards
+ compatibility, is ``None``.
+
+ The ``request`` kwarg is used to populate the ``sqlalchemy.orm.Session``'s
+ "info" dict. The "info" dict is the official namespace for developers to
+ stash session-specific information. For more information, please see the
+ SQLAlchemy docs:
+ https://docs.sqlalchemy.org/en/stable/orm/session_api.html#sqlalchemy.orm.session.Session.params.info
+
+ By placing the active ``request`` in the "info" dict, developers will be
+ able to access the active Pyramid request from an instance of an SQLAlchemy
+ object in one of two ways:
+
+ - Classic SQLAlchemy. This uses the ``Session``'s utility class method:
+
+ .. code-block:: python
+
+ from sqlalchemy.orm.session import Session as sa_Session
+
+ dbsession = sa_Session.object_session(dbObject)
+ request = dbsession.info["request"]
+
+ - Modern SQLAlchemy. This uses the "Runtime Inspection API":
+
+ .. code-block:: python
+
+ from sqlalchemy import inspect as sa_inspect
+
+ dbsession = sa_inspect(dbObject).session
+ request = dbsession.info["request"]
"""
- dbsession = session_factory()
+ dbsession = session_factory(info={"request": request})
zope.sqlalchemy.register(
- dbsession, transaction_manager=transaction_manager)
+ dbsession, transaction_manager=transaction_manager
+ )
return dbsession
@@ -60,7 +95,12 @@ def includeme(config):
settings = config.get_settings()
settings['tm.manager_hook'] = 'pyramid_tm.explicit_manager'
- # use pyramid_tm to hook the transaction lifecycle to the request
+ # Use ``pyramid_tm`` to hook the transaction lifecycle to the request.
+ # Note: the packages ``pyramid_tm`` and ``transaction`` work together to
+ # automatically close the active database session after every request.
+ # If your project migrates away from ``pyramid_tm``, you may need to use a
+ # Pyramid callback function to close the database session after each
+ # request.
config.include('pyramid_tm')
# use pyramid_retry to retry a request when transient exceptions occur
@@ -80,7 +120,9 @@ def includeme(config):
dbsession = request.environ.get('app.dbsession')
if dbsession is None:
# request.tm is the transaction manager used by pyramid_tm
- dbsession = get_tm_session(session_factory, request.tm)
+ dbsession = get_tm_session(
+ session_factory, request.tm, request=request
+ )
return dbsession
config.add_request_method(dbsession, reify=True)