Commits

Mike Orr committed a5e77e4

Import 'pyramid_beaker', rename to 'pyramid_beaker_flash'.

  • Participants

Comments (0)

Files changed (19)

+syntax: glob
+.coverage
+*.egg-info
+*.egg
+*.pyc
+dist/
+0.2 (2010-11-27)
+----------------
+
+- Add cache_region support via
+  ``pyramid_beaker.set_cache_regions_from_settings`` (and documented).
+
+0.1
+---
+
+- Initial release.
+Pylons Project Contributor Agreement
+====================================
+
+The submitter agrees by adding his or her name within the section below named
+"Contributors" and submitting the resulting modified document to the
+canonical shared repository location for this software project (whether
+directly, as a user with "direct commit access", or via a "pull request"), he
+or she is signing a contract electronically.  The submitter becomes a
+Contributor after a) he or she signs this document by adding their name
+beneath the "Contributors" section below, and b) the resulting document is
+accepted into the canonical version control repository.
+
+Treatment of Account
+---------------------
+
+Contributor will not allow anyone other than the Contributor to use his or
+her username or source repository login to submit code to a Pylons Project
+source repository. Should Contributor become aware of any such use,
+Contributor will immediately by notifying Agendaless Consulting.
+Notification must be performed by sending an email to
+webmaster@agendaless.com.  Until such notice is received, Contributor will be
+presumed to have taken all actions made through Contributor's account. If the
+Contributor has direct commit access, Agendaless Consulting will have
+complete control and discretion over capabilities assigned to Contributor's
+account, and may disable Contributor's account for any reason at any time.
+
+Legal Effect of Contribution
+----------------------------
+
+Upon submitting a change or new work to a Pylons Project source Repository (a
+"Contribution"), you agree to assign, and hereby do assign, a one-half
+interest of all right, title and interest in and to copyright and other
+intellectual property rights with respect to your new and original portions
+of the Contribution to Agendaless Consulting. You and Agendaless Consulting
+each agree that the other shall be free to exercise any and all exclusive
+rights in and to the Contribution, without accounting to one another,
+including without limitation, the right to license the Contribution to others
+under the Repoze Public License. This agreement shall run with title to the
+Contribution. Agendaless Consulting does not convey to you any right, title
+or interest in or to the Program or such portions of the Contribution that
+were taken from the Program. Your transmission of a submission to the Pylons
+Project source Repository and marks of identification concerning the
+Contribution itself constitute your intent to contribute and your assignment
+of the work in accordance with the provisions of this Agreement.
+
+License Terms
+-------------
+
+Code committed to the Pylons Project source repository (Committed Code) must
+be governed by the Repoze Public License (http://repoze.org/LICENSE.txt, aka
+"the RPL") or another license acceptable to Agendaless Consulting.  Until
+Agendaless Consulting declares in writing an acceptable license other than
+the RPL, only the RPL shall be used.  A list of exceptions is detailed within
+the "Licensing Exceptions" section of this document, if one exists.
+
+Representations, Warranty, and Indemnification
+----------------------------------------------
+
+Contributor represents and warrants that the Committed Code does not violate
+the rights of any person or entity, and that the Contributor has legal
+authority to enter into this Agreement and legal authority over Contributed
+Code. Further, Contributor indemnifies Agendaless Consulting against
+violations.
+
+Cryptography
+------------
+
+Contributor understands that cryptographic code may be subject to government
+regulations with which Agendaless Consulting and/or entities using Committed
+Code must comply. Any code which contains any of the items listed below must
+not be checked-in until Agendaless Consulting staff has been notified and has
+approved such contribution in writing.
+
+- Cryptographic capabilities or features
+
+- Calls to cryptographic features
+
+- User interface elements which provide context relating to cryptography
+
+- Code which may, under casual inspection, appear to be cryptographic.
+
+Notices
+-------
+
+Contributor confirms that any notices required will be included in any
+Committed Code.
+
+Licensing Exceptions
+====================
+
+Code committed within the ``docs/`` subdirectory of the Pyramid source
+control repository and "docstrings" which appear in the documentation
+generated by runnning "make" within this directory is licensed under the
+Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States
+License (http://creativecommons.org/licenses/by-nc-sa/3.0/us/).
+
+List of Contributors
+====================
+
+The below-signed are contributors to a code repository that is part of the
+project named "pyramid_beaker".  Each below-signed contributor has read,
+understand and agrees to the terms above in the section within this document
+entitled "Pylons Project Contributor Agreement" as of the date beside his or
+her name.
+
+Contributors
+------------
+
+- Chris McDonough, 2010/11/08
+
+- Marcin Lulek, 2010/11/15
+
+- Tres Seaver, 2010/11/09
+Copyright (c) 2010 Agendaless Consulting and Contributors.
+(http://www.agendaless.com), All Rights Reserved
+
+License
+
+  A copyright notice accompanies this license document that identifies
+  the copyright holders.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are
+  met:
+
+  1.  Redistributions in source code must retain the accompanying
+      copyright notice, this list of conditions, and the following
+      disclaimer.
+
+  2.  Redistributions in binary form must reproduce the accompanying
+      copyright notice, this list of conditions, and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+  3.  Names of the copyright holders must not be used to endorse or
+      promote products derived from this software without prior
+      written permission from the copyright holders.
+
+  4.  If any files are modified, you must cause the modified files to
+      carry prominent notices stating that you changed the files and
+      the date of any change.
+
+  Disclaimer
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND
+    ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+    ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+
+Metadata-Version: 1.0
+Name: pyramid_beaker
+Version: 0.2
+Summary: Beaker session factory backend for Pyramid
+Home-page: http://docs.pylonshq.com
+Author: Chris McDonough, Agendaless Consulting
+Author-email: pylons-devel@googlegroups.com
+License: BSD-derived (http://www.repoze.org/LICENSE.txt)
+Description: pyramid_beaker
+        ==============
+        
+        Provides a session factory for the `Pyramid <http://docs.pylonshq.com>`_ web
+        framework backed by the `Beaker <http://beaker.groovie.org/>`_ sessioning
+        system.
+        
+        See `the Pylons Project documentation <http://docs.pylonshq.com>`_ for more
+        information.
+        
+        
+        0.2 (2010-11-27)
+        ----------------
+        
+        - Add cache_region support via
+        ``pyramid_beaker.set_cache_regions_from_settings`` (and documented).
+        
+        0.1
+        ---
+        
+        - Initial release.
+        
+Keywords: web wsgi pylons pyramid
+Platform: UNKNOWN
+Classifier: Intended Audience :: Developers
+Classifier: Framework :: Pylons
+Classifier: Programming Language :: Python
+pyramid_beaker
+==============
+
+Provides a session factory for the `Pyramid <http://docs.pylonshq.com>`_ web
+framework backed by the `Beaker <http://beaker.groovie.org/>`_ sessioning
+system.
+
+See `the Pylons Project documentation <http://docs.pylonshq.com>`_ for more
+information.
+_themes/
+.build/

docs/.static/logo_hi.gif

Added
New image

docs/.static/repoze.css

+@import url('default.css');
+body {
+    background-color: #006339;
+}
+ 
+div.document {
+    background-color: #dad3bd;
+}
+
+div.sphinxsidebar h3, h4, h5, a {
+    color: #127c56 !important;
+}
+
+div.related {
+    color: #dad3bd !important;
+    background-color: #00744a;
+}
+ 
+div.related a {
+    color: #dad3bd !important;
+}
+
+div.body p, div.body dd, div.body li {
+  text-align: left;
+}
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d .build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html web pickle htmlhelp latex changes linkcheck
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html      to make standalone HTML files"
+	@echo "  pickle    to make pickle files (usable by e.g. sphinx-web)"
+	@echo "  htmlhelp  to make HTML files and a HTML help project"
+	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  changes   to make an overview over all changed/added/deprecated items"
+	@echo "  linkcheck to check all external links for integrity"
+
+clean:
+	-rm -rf .build/*
+
+html: _themes/
+	mkdir -p .build/html .build/doctrees
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) .build/html
+	@echo
+	@echo "Build finished. The HTML pages are in .build/html."
+
+pickle:
+	mkdir -p .build/pickle .build/doctrees
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) .build/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files or run"
+	@echo "  sphinx-web .build/pickle"
+	@echo "to start the sphinx-web server."
+
+web: pickle
+
+htmlhelp: _themes/
+	mkdir -p .build/htmlhelp .build/doctrees
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) .build/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in .build/htmlhelp."
+
+latex:
+	mkdir -p .build/latex .build/doctrees
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) .build/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in .build/latex."
+	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+	      "run these through (pdf)latex."
+
+changes:
+	mkdir -p .build/changes .build/doctrees
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) .build/changes
+	@echo
+	@echo "The overview file is in .build/changes."
+
+linkcheck:
+	mkdir -p .build/linkcheck .build/doctrees
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) .build/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in .build/linkcheck/output.txt."
+
+_themes:
+	git clone git://github.com/Pylons/pylons_sphinx_theme.git _themes
+API Documentation 
+-----------------
+
+.. automodule:: pyramid_beaker
+
+.. autofunction:: set_cache_regions_from_settings
+
+.. autofunction:: session_factory_from_settings
+
+.. autofunction:: BeakerSessionFactoryConfig
+
+# -*- coding: utf-8 -*-
+#
+# pyramid_beaker documentation build configuration file
+#
+# This file is execfile()d with the current directory set to its containing
+# dir.
+#
+# The contents of this file are pickled, so don't put values in the
+# namespace that aren't pickleable (module imports are okay, they're
+# removed automatically).
+#
+# All configuration values have a default value; values that are commented
+# out serve to show the default value.
+
+# If your extensions are in another directory, add it here. If the
+# directory is relative to the documentation root, use os.path.abspath to
+# make it absolute, like shown here.
+#sys.path.append(os.path.abspath('some/directory'))
+
+import sys, os
+
+parent = os.path.dirname(os.path.dirname(__file__))
+sys.path.append(os.path.abspath(parent))
+wd = os.getcwd()
+os.chdir(parent)
+os.system('%s setup.py test -q' % sys.executable)
+os.chdir(wd)
+
+for item in os.listdir(parent):
+    if item.endswith('.egg'):
+        sys.path.append(os.path.join(parent, item))
+
+# General configuration
+# ---------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['.templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General substitutions.
+project = 'pyramid_beaker'
+copyright = '2010, Agendaless Consulting <chrism@plope.com>'
+
+# The default replacements for |version| and |release|, also used in various
+# other places throughout the built documents.
+#
+# The short X.Y version.
+version = '0.2'
+# The full version, including alpha/beta/rc tags.
+release = version
+
+# There are two options for replacing |today|: either, you set today to
+# some non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directories, that shouldn't be
+# searched for source files.
+#exclude_dirs = []
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+# Options for HTML output
+# -----------------------
+
+# Add and use Pylons theme
+sys.path.append(os.path.abspath('_themes'))
+html_theme_path = ['_themes']
+html_theme = 'pylons'
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+# html_style = 'repoze.css'
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as
+# html_title.
+#html_short_title = None
+
+# The name of an image file (within the static path) to place at the top of
+# the sidebar.
+# html_logo = '.static/logo_hi.gif'
+
+# The name of an image file (within the static path) to use as favicon of
+# the docs.  This file should be a Windows icon file (.ico) being 16x16 or
+# 32x32 pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets)
+# here, relative to this directory. They are copied after the builtin
+# static files, so a file named "default.css" will overwrite the builtin
+# "default.css".
+html_static_path = ['.static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page
+# bottom, using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_use_modindex = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, the reST sources are included in the HTML build as
+# _sources/<name>.
+#html_copy_source = True
+
+# If true, an OpenSearch description file will be output, and all pages
+# will contain a <link> tag referring to it.  The value of this option must
+# be the base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'atemplatedoc'
+
+
+# Options for LaTeX output
+# ------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+#  author, document class [howto/manual]).
+latex_documents = [
+  ('index', 'pyramid_beaker.tex', 'pyramid_beaker Documentation',
+   'Repoze Developers', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the
+# top of the title page.
+latex_logo = '.static/logo_hi.gif'
+
+# For "manual" documents, if this is true, then toplevel headings are
+# parts, not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True

docs/glossary.rst

+.. _glossary:
+
+Glossary
+========
+
+.. glossary::
+   :sorted:
+
+   session factory
+      A callable, which, when called with a single argument named
+      ``request``, returns a session object.
+
+   Beaker
+      A `sessioning and caching package <http://beaker.groovie.org/>`_
+      by Ben Bangert.
+
+   Pyramid
+      A `web framework <http://pylonshq.com/pyramid>`_.
+pyramid_beaker
+==============
+
+A :term:`Beaker` session factory backend for :term:`Pyramid`, also cache
+configurator.
+
+Usage
+-----
+
+Session management
+``````````````````
+
+In the configuration portion of your :term:`Pyramid` app, use the
+:func:`pyramid_beaker.BeakerSessionFactoryConfig` function or the
+:func:`pyramid_beaker.session_factory_from_settings` function to
+create a Pyramid :term:`session factory`.  Subsequently register that
+session factory with Pyramid.  At that point, accessing
+``request.session`` will provide a Pyramid session using Beaker as a
+backend.
+
+:func:`pyramid_beaker.session_factory_from_settings` obtains session
+settings from the ``**settings`` dictionary passed to the
+Configurator.  It assumes that you've placed session configuration
+parameters prefixed with ``session.`` in your Pyramid application's
+``.ini`` file.  For example:
+
+.. code-block:: ini
+
+   [app:myapp]
+   .. other settings ..
+   session.type = file
+   session.data_dir = %(here)s/data/sessions/data
+   session.lock_dir = %(here)s/data/sessions/lock
+   session.key = mykey
+   session.secret = mysecret
+
+If your ``.ini`` file has such settings, you can use
+:func:`pyramid_beaker.session_factory_from_settings` in your
+application's configuration.  For example, let's assume this code is
+in the ``__init__.py`` of your Pyramid application that uses an
+``.ini`` file with the ``session.`` settings above to obtain its
+``**settings`` dictionary.
+
+.. code-block:: python
+
+   from pyramid_beaker import session_factory_from_settings
+   from pyramid.configuration import configurator
+
+   def app(global_config, **settings):
+       """ This function returns a WSGI application.
+       
+       It is usually called by the PasteDeploy framework during 
+       ``paster serve``.
+       """
+       zcml_file = settings.get('configure_zcml', 'configure.zcml')
+       session_factory = session_factory_from_settings(settings)
+       config = Configurator(root_factory=get_root, settings=settings)
+       config.begin()
+       config.set_session_factory(session_factory)
+       # ... other configuration stuff...
+       config.end()
+       return config.make_wsgi_app()
+
+
+Beaker cache region support
+```````````````````````````
+
+In the configuration portion of your :term:`Pyramid` app, use the
+:func:`pyramid_beaker.set_cache_regions_from_settings` function to
+set Beaker's cache regions. At that point, you can use Beaker's `cache_region`
+functionality to enable caching for Your application. 
+
+:func:`pyramid_beaker.set_cache_regions_from_settings` obtains region
+settings from the ``**settings`` dictionary passed to the
+Configurator.  It assumes that you've placed cache configuration
+parameters prefixed with ``cache.`` in your Pyramid application's
+``.ini`` file.  For example:
+
+.. code-block:: ini
+
+   [app:myapp]
+   .. other settings ..
+   cache.regions = default_term, second, short_term, long_term
+   cache.type = memory
+   cache.second.expire = 1
+   cache.short_term.expire = 60
+   cache.default_term.expire = 300
+   cache.long_term.expire = 3600
+
+If your ``.ini`` file has such settings, you can use
+:func:`pyramid_beaker.set_cache_regions_from_settings` in your
+application's configuration.  For example, let's assume this code is
+in the ``__init__.py`` of your Pyramid application that uses an
+``.ini`` file with the ``cache.`` settings above to obtain its
+``**settings`` dictionary.
+
+.. code-block:: python
+
+   from pyramid_beaker import set_cache_regions_from_settings
+   from pyramid.configuration import configurator
+
+   def app(global_config, **settings):
+       """ This function returns a WSGI application.
+       
+       It is usually called by the PasteDeploy framework during 
+       ``paster serve``.
+       """
+       zcml_file = settings.get('configure_zcml', 'configure.zcml')
+       set_cache_regions_from_settings(settings)
+       config = Configurator(root_factory=get_root, settings=settings)
+       config.begin()
+       # ... other configuration stuff...
+       config.end()
+       return config.make_wsgi_app()
+
+API
+---
+
+.. toctree::
+   :maxdepth: 2
+
+   api.rst
+
+Indices and tables
+------------------
+
+* :ref:`glossary`
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`

pyramid_beaker_flash/__init__.py

+from beaker import cache
+from beaker.session import SessionObject
+from beaker.util import coerce_session_params
+
+from pyramid.interfaces import ISession
+from zope.interface import implements
+
+def BeakerSessionFactoryConfig(**options):
+    """ Return a Pyramid session factory using Beaker session settings
+    supplied directly as ``**options``"""
+    class PyramidBeakerSessionObject(SessionObject):
+        implements(ISession)
+        _options = options
+
+        def __init__(self, request):
+            SessionObject.__init__(self, request.environ, **self._options)
+
+            def session_callback(request, response):
+                exception = getattr(request, 'exception', None)
+                if exception is None and self.accessed():
+                    self.persist()
+                    headers = self.__dict__['_headers']
+                    if headers['set_cookie'] and headers['cookie_out']:
+                        response.headerlist.append(
+                            ('Set-Cookie', headers['cookie_out']))
+            request.add_response_callback(session_callback)
+
+        # ISession API
+
+        @property
+        def new(self):
+            return self.last_accessed is None
+
+        changed = SessionObject.save
+
+        # modifying dictionary methods
+
+        @call_save
+        def clear(self):
+            return self._session().clear()
+
+        @call_save
+        def update(self, d, **kw):
+            return self._session().update(d, **kw)
+
+        @call_save
+        def setdefault(self, k, d=None):
+            return self._session().setdefault(k, d)
+
+        @call_save
+        def pop(self, k, d=None):
+            return self._session().pop(k, d)
+
+        @call_save
+        def popitem(self):
+            return self._session().popitem()
+
+        __setitem__ = call_save(SessionObject.__setitem__)
+        __delitem__ = call_save(SessionObject.__delitem__)
+
+    return PyramidBeakerSessionObject
+
+
+def call_save(wrapped):
+    """ By default, in non-auto-mode beaker badly wants people to
+    call save even though it should know something has changed when
+    a mutating method is called.  This hack should be removed if
+    Beaker ever starts to do this by default. """
+    def save(session, *arg, **kw):
+        value = wrapped(session, *arg, **kw)
+        session.save()
+        return value
+    save.__doc__ = wrapped.__doc__
+    return save
+
+
+def session_factory_from_settings(settings):
+    """ Return a Pyramid session factory using Beaker session settings
+    supplied from a Paste configuration file"""
+    prefixes = ('session.', 'beaker.session.')
+    options = {}
+
+    # Pull out any config args meant for beaker session. if there are any
+    for k, v in settings.items():
+        for prefix in prefixes:
+            if k.startswith(prefix):
+                option_name = k[len(prefix):]
+                options[option_name] = v
+
+    options = coerce_session_params(options)
+    return BeakerSessionFactoryConfig(**options)
+
+def set_cache_regions_from_settings(settings):
+    """ Add cache support to the Pylons application.
+    
+    The ``settings`` passed to the configurator are used to setup
+    the cache options. Cache options in the settings should start
+    with either 'beaker.cache.' or 'cache.'.
+    
+    """
+    cache_settings = {'regions':None}
+    for key in settings.keys():
+        for prefix in ['beaker.cache.', 'cache.']:
+            if key.startswith(prefix):
+                name = key.split(prefix)[1].strip()
+                cache_settings[name] = settings[key].strip()
+    if cache_settings['regions']:
+        for region in cache_settings['regions'].split(','):
+            region = region.strip()
+            region_settings = {}
+            for key, value in cache_settings.items():
+                if key.startswith(region):
+                    region_settings[key.split('.')[1]] = value
+            region_settings['expire'] = int(region_settings.get('expire', 60))
+            region_settings.setdefault('lock_dir',
+                                       cache_settings.get('lock_dir'))
+            if 'type' not in region_settings:
+                region_settings['type'] = cache_settings.get('type', 'memory')
+            cache.cache_regions[region] = region_settings

pyramid_beaker_flash/tests.py

+import unittest
+
+class TestPyramidBeakerSessionObject(unittest.TestCase):
+    def _makeOne(self, request, **options):
+        from pyramid_beaker_flash import BeakerSessionFactoryConfig
+        return BeakerSessionFactoryConfig(**options)(request)
+
+    def test_instance_conforms(self):
+        from zope.interface.verify import verifyObject
+        from pyramid.interfaces import ISession
+        request = DummyRequest()
+        session = self._makeOne(request)
+        verifyObject(ISession, session)
+
+    def test_callback(self):
+        request = DummyRequest()
+        session = self._makeOne(request)
+        session['fred'] = 42
+        session.save()
+        self.assertEqual(session.accessed(), True)
+        self.failUnless(len(request.callbacks) > 0)
+        response= DummyResponse()
+        request.callbacks[0](request, response)
+        self.failUnless(response.headerlist)
+
+    def test_new(self):
+        request = DummyRequest()
+        session = self._makeOne(request)
+        self.failUnless(session.new)
+
+    def test___setitem__calls_save(self):
+        request = DummyRequest()
+        session = self._makeOne(request)
+        session['a'] = 1
+        self.assertEqual(session.__dict__['_dirty'], True)
+
+    def test___delitem__calls_save(self):
+        request = DummyRequest()
+        session = self._makeOne(request)
+        session['a'] = 1
+        del session.__dict__['_dirty']
+        del session['a']
+        self.assertEqual(session.__dict__['_dirty'], True)
+
+    def test_changed(self):
+        request = DummyRequest()
+        session = self._makeOne(request)
+        session.changed()
+        self.assertEqual(session.__dict__['_dirty'], True)
+        
+    def test_clear(self):
+        request = DummyRequest()
+        session = self._makeOne(request)
+        session['a'] = 1
+        session.clear()
+        self.failIf('a' in session)
+        self.assertEqual(session.__dict__['_dirty'], True)
+
+    def test_update(self):
+        request = DummyRequest()
+        session = self._makeOne(request)
+        session.update({'a':1}, b=2)
+        self.failUnless('a' in session)
+        self.failUnless('b' in session)
+        self.assertEqual(session.__dict__['_dirty'], True)
+
+    def test_setdefault(self):
+        request = DummyRequest()
+        session = self._makeOne(request)
+        session.setdefault('a', 'b')
+        self.failUnless('a' in session)
+        self.assertEqual(session.__dict__['_dirty'], True)
+        
+    def test_pop(self):
+        request = DummyRequest()
+        session = self._makeOne(request)
+        session['a'] = 1
+        session.__dict__['_dirty'] = False
+        result = session.pop('a')
+        self.failIf('a' in session)
+        self.assertEqual(result, 1)
+        self.assertEqual(session.__dict__['_dirty'], True)
+
+    def test_popitem(self):
+        request = DummyRequest()
+        session = self._makeOne(request)
+        session['a'] = 1
+        session.__dict__['_dirty'] = False
+        result = session.popitem()
+        self.failIf('a' in session)
+        self.assertEqual(result, ('a', 1))
+        self.assertEqual(session.__dict__['_dirty'], True)
+
+class Test_session_factory_from_settings(unittest.TestCase):
+    def _callFUT(self, settings):
+        from pyramid_beaker_flash import session_factory_from_settings
+        return session_factory_from_settings(settings)
+
+    def test_it(self):
+        settings = {'session.auto':'true', 'session.key':'foo'}
+        factory = self._callFUT(settings)
+        self.assertEqual(factory._options, {'auto':True, 'key':'foo'})
+    
+class DummyRequest:
+    def __init__(self):
+        self.callbacks = []
+        self.environ = {}
+
+    def add_response_callback(self, callback):
+        self.callbacks.append(callback)
+
+class DummyResponse:
+    def __init__(self):
+        self.headerlist = []
+        
+class TestCacheConfiguration(unittest.TestCase):
+    def _set_settings(self):
+        return {'cache.regions':'default_term, second, short_term, long_term',
+                'cache.type':'memory',
+                'cache.second.expire':'1',
+                'cache.short_term.expire':'60',
+                'cache.default_term.expire':'300',
+                'cache.long_term.expire':'3600',
+                }
+    
+    def test_add_cache_no_regions(self):
+        from pyramid_beaker_flash import set_cache_regions_from_settings
+        import beaker
+        settings = self._set_settings()
+        beaker.cache.cache_regions = {}
+        settings['cache.regions'] = ''
+        set_cache_regions_from_settings(settings)
+        self.assertEqual(beaker.cache.cache_regions, {})
+
+    def test_add_cache_single_region_no_expire(self):
+        from pyramid_beaker_flash import set_cache_regions_from_settings
+        import beaker
+        settings = self._set_settings()
+        beaker.cache.cache_regions = {}
+        settings['cache.regions'] = 'default_term'
+        del settings['cache.default_term.expire']
+        set_cache_regions_from_settings(settings)
+        default_term = beaker.cache.cache_regions.get('default_term')
+        self.assertEqual(default_term, {'expire': 60, 'type': 'memory',
+                                      'lock_dir': None})
+    
+    def test_add_cache_multiple_region(self):
+        from pyramid_beaker_flash import set_cache_regions_from_settings
+        import beaker
+        settings = self._set_settings()
+        beaker.cache.cache_regions = {}
+        settings['cache.regions'] = 'default_term, short_term'
+        settings['cache.lock_dir'] = 'foo'
+        settings['cache.short_term.expire'] = '60'
+        settings['cache.default_term.type'] = 'file'
+        settings['cache.default_term.expire'] = '300'
+        set_cache_regions_from_settings(settings)
+        default_term = beaker.cache.cache_regions.get('default_term')
+        short_term = beaker.cache.cache_regions.get('short_term')
+        self.assertEqual(short_term.get('expire'),
+                         int(settings['cache.short_term.expire']))
+        self.assertEqual(short_term.get('lock_dir'), settings['cache.lock_dir'])
+        self.assertEqual(short_term.get('type'), 'memory')
+
+        self.assertEqual(default_term.get('expire'),
+                         int(settings['cache.default_term.expire']))
+        self.assertEqual(default_term.get('lock_dir'),
+                         settings['cache.lock_dir'])
+        self.assertEqual(default_term.get('type'),
+                         settings['cache.default_term.type'])
+[easy_install]
+zip_ok = false
+
+[nosetests]
+cover-package = pyramid_beaker_flash
+nocapture = 1
+cover-erase = 1
+where = pyramid_beaker_flash
+match = ^test
+
+[egg_info]
+tag_build = 
+tag_date = 0
+tag_svn_revision = 0
+
+##############################################################################
+#
+# Copyright (c) 2010 Agendaless Consulting and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the BSD-like license at
+# http://www.repoze.org/LICENSE.txt.  A copy of the license should accompany
+# this distribution.  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL
+# EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND
+# FITNESS FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+import os
+
+from setuptools import setup
+from setuptools import find_packages
+
+here = os.path.abspath(os.path.dirname(__file__))
+README = open(os.path.join(here, 'README.txt')).read()
+CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+
+requires = ['pyramid', 'beaker']
+
+setup(name='pyramid_beaker_flash',
+      version='0.2.1',
+      description='Fork of Beaker session factory backend for Pyramid, '
+        'adding flash messages',
+      long_description=README + '\n\n' +  CHANGES,
+      classifiers=[
+        "Intended Audience :: Developers",
+        "Framework :: Pylons",
+        "Programming Language :: Python",
+        ],
+      keywords='web wsgi pylons pyramid',
+      author="Chris McDonough, Agendaless Consulting",
+      author_email="pylons-devel@googlegroups.com",
+      url="http://docs.pylonshq.com",
+      license="BSD-derived (http://www.repoze.org/LICENSE.txt)",
+      packages=find_packages(),
+      include_package_data=True,
+      zip_safe=False,
+      tests_require = requires,
+      install_requires = requires,
+      test_suite="pyramid_beaker_flash",
+      )
+