# pyramid_session_multi
Build Status: 
Provides a framework for making multiple ad-hoc binds of `ISession` compliant Sessions onto
a `request.session_multi` namespace.
In other words...
Instead of having a single `request.session` configured, you can configure multiple Pyramid session handlers to use `request.session_multi["your_identifier"]`
# Usage
Include `pyramid_session_multi`, then register some `ISessionFactory` factories
that are compliant with the `ISession` interface -- just like you would with
Pyramid's built-in `.session` system.
from pyramid.session import SignedCookieSessionFactory
session_factory_a = SignedCookieSessionFactory(
'secret', cookie_name='session_a'
)
session_factory_b = SignedCookieSessionFactory(
'secret', cookie_name='session_b'
)
def main(global_config, **settings):
config = Configurator(settings=settings)
config.include('pyramid_session_multi')
pyramid_session_multi.register_session_factory(
config, 'session1', session_factory_a
)
pyramid_session_multi.register_session_factory(
config, 'session2', session_factory_b
)
return config.make_wsgi_app()
Note: The second argument to `pyramid_session_multi.register_session_factory`
is a namespace, which we then use to access Session data in views/etc:
request.session_multi['session1']['foo'] = "bar"
request.session_multi['session2']['bar'] = "foo"
`pyramid_session_multi` lazily evaluates each Session namespace independently of
each other, so accessing `request.session_multi` will not instantiate any of the
component Sessions.
`pyramid_session_multi` is completely independent of Pyramid's built-in Session
support, so you can still use `request.session` alongside this library!
# Advanced Usage
`register_session_factory` accepts an optional argument: "discriminator".
A "discriminator" is a callable function that will receive a single argument:
the active request.
If the discriminator function returns `True`, the SessionFactory will be invoked
and a Session object will be mounted onto the namespace.
If the discriminator function returns a non-`True` value (e.g. `False` or `None`),
the SessionFactory will NOT be invoked, and `None` will be mounted onto the
session's namespace.
Consider an application that is run on both http and https protocols. In the
following example, `.session_multi["weak"]` can always be accessed, but
`.session_multi["https_only"]` will only be available on https connections.
from pyramid.session import SignedCookieSessionFactory
session_factory_a = SignedCookieSessionFactory(
'secret', cookie_name='weak_cookie'
)
session_factory_b = SignedCookieSessionFactory(
'secret', cookie_name='secure_cookie', secure=True, httponly=True
)
def session_b_discriminator(request):
if request.scheme == 'https'
return True
return False
def main(global_config, **settings):
config = Configurator(settings=settings)
config.include('pyramid_session_multi')
pyramid_session_multi.register_session_factory(
config, 'weak', session_factory_a
)
pyramid_session_multi.register_session_factory(
config, 'https_only', session_factory_b, discriminator=session_b_discriminator
)
return config.make_wsgi_app()
With this discriminator in place, `.session_multi["https_only"]` will only be
a Pyramid `ISession` on https connections; on http connections it will be `None`.
# why?
Pyramid ships with support for a single Session, which is bound to
`request.session`. That design is great for many/most web applications, but as
your applications scale, your needs may grow:
* If you have a HTTP site that uses HTTPS for account management, you may need
to support separate Sessions for HTTP and HTTPS, otherwise a
"man in the middle" or network traffic spy could use HTTP cookie to access the
HTTPS endpoints.
* Client-side Sessions and signed cookies are usually faster, but sometimes you
have data that needs to be saved as server-side Sessions because it has
security implications (like a third-party oAuth token) or is too big.
* You may have multiple interconnected apps that each need to save/share
isolated bits of Session data.
# built-in pyramid_debugtoolbar support!
Just add to your "development.ini" or equivalent configuration method
debugtoolbar.includes = pyramid_session_multi.debugtoolbar
The debugtoolbar will now have a `SessionMulti` panel which has the following
info:
* configuration data on all Session namespaces
* ingress Request values of all accessed Sessions
* egress Response values of all accessed Sessions
The `SessionMulti` panel can also be enabled to track Sessions on every Request,
regardless of the Sessions being accessed or not.
There are two ways to enable the extended Session display used by the
:guilabel:`SessionMulti` panel.
#. Under the :guilabel:`Settings` tab in the navigation bar, click the red
:guilabel:`X` mark. When there is a green :guilabel:`check` mark, each
request will have the ingress and egress data tracked and displayed on the
:guilabel:`Settings` panel output regardless of the Session being accessed
during the request. When there is a red :guilabel:`X` mark, only requests
which accessed the Session will have the ingress and egress data displayed.
#. Send a ``pdtb_active`` cookie on a per-request basis.
This panel's name for cookie activation is "session_multi".
## What does the Panel look like?

# How does this library work?
Instead of registering one Session factory to `request.session`, this library
creates a Request attribute `request.session_multi` and registers the various
session factories to namespaces provided within it.
`request.session_multi` is a special dict that maps the namespace keys to your
`ISession` compliant Sessions. Sessions are lazily created on-demand, so you
won't incur any costs/cookies/backend-data until you use them.
This should work with most Session libraries written for Pyramid. Pyramid's
session support *mostly* just binds a Session factory to the `request.session`
property. Most libraries and implementations of Pyramid's `ISession` interface
act completely independent of the framework and implement of their own logic for
detecting changes and deciding what to do when something changes.
This library has been used in production for several years with:
* Pyramid's `SignedCookieSessionFactory`
* [pyramid_session_redis](https://github.com/jvanasco/pyramid_session_redis)
# Miscellaneous
There are a few "safety" checks for conflicts.
1. A `pyramid.exceptions.ConfigurationError` will be raised if a namespace of
Session factory is null
2. A `pyramid.exceptions.ConfigurationError` will be raised if a namespace or
factory or cookie name is re-used.
A given **factory** instance can not be re-used, because that can cause conflicts
with cookies or backend storage keys.
You can re-use a single cookie library/type multiple times by creating a factory
for each setting (see the example above, which re-uses
`SignedCookieSessionFactory` twice).
If you do not register a factory with a `cookie_name`, this library will
try to derive one based on a `._cooke_name` attribute. If neither option is
available, an Exception will be raised on configuration.
# What if Sessions should only run in certain situations?
`register_session_factory` accepts a kwarg for `discriminator`, which is a
function that expects a single argument of a `Request` object.
If provided and the discriminator function returns an non-``True`` value, the
`.session_multi` namespace will be set to `None`, otherwise the namespace will be
populated with the result of the factory.
License
=======
MIT
Raw data
{
"_id": null,
"home_page": "https://github.com/jvanasco/pyramid_session_multi",
"name": "pyramid-session-multi",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "pyramid session web",
"author": "Jonathan Vanasco",
"author_email": "jonathan@findmeon.com",
"download_url": "https://files.pythonhosted.org/packages/a8/dd/db6dc3c1f1af2ed1d6e01d819d9de8334d7c8138f37abe4b539de29f2f78/pyramid_session_multi-0.4.0.tar.gz",
"platform": null,
"description": "# pyramid_session_multi\n\nBuild Status: \n\nProvides a framework for making multiple ad-hoc binds of `ISession` compliant Sessions onto\na `request.session_multi` namespace.\n\nIn other words...\n\nInstead of having a single `request.session` configured, you can configure multiple Pyramid session handlers to use `request.session_multi[\"your_identifier\"]`\n\n# Usage\n\nInclude `pyramid_session_multi`, then register some `ISessionFactory` factories\nthat are compliant with the `ISession` interface -- just like you would with \nPyramid's built-in `.session` system.\n\n\n\tfrom pyramid.session import SignedCookieSessionFactory\n\n\tsession_factory_a = SignedCookieSessionFactory(\n\t\t'secret', cookie_name='session_a'\n\t)\n\tsession_factory_b = SignedCookieSessionFactory(\n\t\t'secret', cookie_name='session_b'\n\t)\n\n def main(global_config, **settings):\n config = Configurator(settings=settings)\n config.include('pyramid_session_multi')\n pyramid_session_multi.register_session_factory(\n \tconfig, 'session1', session_factory_a\n )\n pyramid_session_multi.register_session_factory(\n \tconfig, 'session2', session_factory_b\n )\n return config.make_wsgi_app()\n\nNote: The second argument to `pyramid_session_multi.register_session_factory`\nis a namespace, which we then use to access Session data in views/etc:\n\n request.session_multi['session1']['foo'] = \"bar\"\n request.session_multi['session2']['bar'] = \"foo\"\n\n`pyramid_session_multi` lazily evaluates each Session namespace independently of\neach other, so accessing `request.session_multi` will not instantiate any of the\ncomponent Sessions.\n\n`pyramid_session_multi` is completely independent of Pyramid's built-in Session\nsupport, so you can still use `request.session` alongside this library!\n\n\n# Advanced Usage\n\n`register_session_factory` accepts an optional argument: \"discriminator\".\n\nA \"discriminator\" is a callable function that will receive a single argument:\nthe active request.\n\nIf the discriminator function returns `True`, the SessionFactory will be invoked\nand a Session object will be mounted onto the namespace.\n\nIf the discriminator function returns a non-`True` value (e.g. `False` or `None`),\nthe SessionFactory will NOT be invoked, and `None` will be mounted onto the\nsession's namespace.\n\nConsider an application that is run on both http and https protocols. In the\nfollowing example, `.session_multi[\"weak\"]` can always be accessed, but\n`.session_multi[\"https_only\"]` will only be available on https connections.\n\n\tfrom pyramid.session import SignedCookieSessionFactory\n\n\tsession_factory_a = SignedCookieSessionFactory(\n\t\t'secret', cookie_name='weak_cookie'\n\t)\n\tsession_factory_b = SignedCookieSessionFactory(\n\t\t'secret', cookie_name='secure_cookie', secure=True, httponly=True\n\t)\n\n\tdef session_b_discriminator(request):\n\t\tif request.scheme == 'https'\n\t\t\treturn True\n\t\treturn False\n\n def main(global_config, **settings):\n config = Configurator(settings=settings)\n config.include('pyramid_session_multi')\n pyramid_session_multi.register_session_factory(\n \tconfig, 'weak', session_factory_a\n )\n pyramid_session_multi.register_session_factory(\n \tconfig, 'https_only', session_factory_b, discriminator=session_b_discriminator\n )\n return config.make_wsgi_app()\n \nWith this discriminator in place, `.session_multi[\"https_only\"]` will only be\na Pyramid `ISession` on https connections; on http connections it will be `None`.\n\n\n# why?\n\nPyramid ships with support for a single Session, which is bound to\n`request.session`. That design is great for many/most web applications, but as\nyour applications scale, your needs may grow:\n\n* If you have a HTTP site that uses HTTPS for account management, you may need\n to support separate Sessions for HTTP and HTTPS, otherwise a \n \"man in the middle\" or network traffic spy could use HTTP cookie to access the\n HTTPS endpoints.\n* Client-side Sessions and signed cookies are usually faster, but sometimes you\n have data that needs to be saved as server-side Sessions because it has\n security implications (like a third-party oAuth token) or is too big.\n* You may have multiple interconnected apps that each need to save/share\n isolated bits of Session data.\n\n# built-in pyramid_debugtoolbar support!\n\nJust add to your \"development.ini\" or equivalent configuration method\n\n\tdebugtoolbar.includes = pyramid_session_multi.debugtoolbar\n\nThe debugtoolbar will now have a `SessionMulti` panel which has the following\ninfo:\n\n* configuration data on all Session namespaces\n* ingress Request values of all accessed Sessions\n* egress Response values of all accessed Sessions\n\nThe `SessionMulti` panel can also be enabled to track Sessions on every Request,\nregardless of the Sessions being accessed or not.\n\nThere are two ways to enable the extended Session display used by the\n:guilabel:`SessionMulti` panel.\n\n#. Under the :guilabel:`Settings` tab in the navigation bar, click the red\n :guilabel:`X` mark. When there is a green :guilabel:`check` mark, each\n request will have the ingress and egress data tracked and displayed on the\n :guilabel:`Settings` panel output regardless of the Session being accessed\n during the request. When there is a red :guilabel:`X` mark, only requests\n which accessed the Session will have the ingress and egress data displayed.\n\n#. Send a ``pdtb_active`` cookie on a per-request basis.\n This panel's name for cookie activation is \"session_multi\".\n\n\n## What does the Panel look like?\n\n\n\n\n# How does this library work?\n\nInstead of registering one Session factory to `request.session`, this library\ncreates a Request attribute `request.session_multi` and registers the various\nsession factories to namespaces provided within it.\n\n`request.session_multi` is a special dict that maps the namespace keys to your\n`ISession` compliant Sessions. Sessions are lazily created on-demand, so you\nwon't incur any costs/cookies/backend-data until you use them.\n\nThis should work with most Session libraries written for Pyramid. Pyramid's\nsession support *mostly* just binds a Session factory to the `request.session`\nproperty. Most libraries and implementations of Pyramid's `ISession` interface\nact completely independent of the framework and implement of their own logic for\ndetecting changes and deciding what to do when something changes.\n\nThis library has been used in production for several years with:\n\n* Pyramid's `SignedCookieSessionFactory`\n* [pyramid_session_redis](https://github.com/jvanasco/pyramid_session_redis)\n\n\n# Miscellaneous\n\nThere are a few \"safety\" checks for conflicts.\n\n1. A `pyramid.exceptions.ConfigurationError` will be raised if a namespace of\n Session factory is null\n2. A `pyramid.exceptions.ConfigurationError` will be raised if a namespace or\n factory or cookie name is re-used. \n\nA given **factory** instance can not be re-used, because that can cause conflicts\nwith cookies or backend storage keys.\n\nYou can re-use a single cookie library/type multiple times by creating a factory\nfor each setting (see the example above, which re-uses \n`SignedCookieSessionFactory` twice).\n\nIf you do not register a factory with a `cookie_name`, this library will\ntry to derive one based on a `._cooke_name` attribute. If neither option is\navailable, an Exception will be raised on configuration.\n\n# What if Sessions should only run in certain situations?\n\n`register_session_factory` accepts a kwarg for `discriminator`, which is a\nfunction that expects a single argument of a `Request` object.\n\nIf provided and the discriminator function returns an non-``True`` value, the\n`.session_multi` namespace will be set to `None`, otherwise the namespace will be\npopulated with the result of the factory.\n\nLicense\n=======\n\nMIT\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Provides a framwork for creating multiple adhoc session binds in Pyramid.",
"version": "0.4.0",
"project_urls": {
"Homepage": "https://github.com/jvanasco/pyramid_session_multi"
},
"split_keywords": [
"pyramid",
"session",
"web"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "a8dddb6dc3c1f1af2ed1d6e01d819d9de8334d7c8138f37abe4b539de29f2f78",
"md5": "92ff9e8db17c2f40e17b4c8328094237",
"sha256": "4bdbd55a4c941e48dfb89143b300c397dcee09c364fb3f83e895f2037a60a91a"
},
"downloads": -1,
"filename": "pyramid_session_multi-0.4.0.tar.gz",
"has_sig": false,
"md5_digest": "92ff9e8db17c2f40e17b4c8328094237",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 22457,
"upload_time": "2025-08-31T17:50:52",
"upload_time_iso_8601": "2025-08-31T17:50:52.563698Z",
"url": "https://files.pythonhosted.org/packages/a8/dd/db6dc3c1f1af2ed1d6e01d819d9de8334d7c8138f37abe4b539de29f2f78/pyramid_session_multi-0.4.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-31 17:50:52",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "jvanasco",
"github_project": "pyramid_session_multi",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "pyramid-session-multi"
}