Merge branch 'master' of github.com:Pylons/pyramid
| | |
| | | $ $VENV/bin/nosetests pyramid.tests.test_module:ClassName |
| | | |
| | | Optionally you can install a nose plugin, `nose-selecttests |
| | | <https://pypi.python.org/pypi/nose-selecttests/>`_, and use a regular |
| | | <https://pypi.org/project/nose-selecttests/>`_, and use a regular |
| | | expression with the ``-t`` parameter to run tests. |
| | | |
| | | # run a single test |
| | |
| | | Pyramid 1.x released. |
| | | |
| | | PyPI |
| | | https://pypi.python.org/pypi/pyramid/1.x |
| | | https://pypi.org/project/pyramid/1.x/ |
| | | |
| | | === One time only for new version, first pre-release === |
| | | What's New |
| | |
| | | for middleware exist, such as caching, content-transport |
| | | encoding, and other functions. See `WSGI documentation |
| | | <https://wsgi.readthedocs.io/en/latest/>`_ or `PyPI |
| | | <https://pypi.python.org/pypi>`_ to find middleware for your application. |
| | | <https://pypi.org/>`_ to find middleware for your application. |
| | | |
| | | pipeline |
| | | The :term:`PasteDeploy` term for a single configuration of a WSGI |
| | |
| | | between templates. |
| | | |
| | | Genshi |
| | | An `XML templating language <https://pypi.python.org/pypi/Genshi/>`_ |
| | | An `XML templating language <https://pypi.org/project/Genshi/>`_ |
| | | by Christopher Lenz. |
| | | |
| | | Jinja2 |
| | |
| | | subpath. See :ref:`star_subpath` for more information. |
| | | |
| | | interface |
| | | A `Zope interface <https://pypi.python.org/pypi/zope.interface>`_ |
| | | A `Zope interface <https://pypi.org/project/zope.interface/>`_ |
| | | object. In :app:`Pyramid`, an interface may be attached to a |
| | | :term:`resource` object or a :term:`request` object in order to |
| | | identify that the object is "of a type". Interfaces are used |
| | |
| | | |
| | | repoze.catalog |
| | | An indexing and search facility (fielded and full-text) based on |
| | | `zope.index <https://pypi.python.org/pypi/zope.index>`_. See `the |
| | | `zope.index <https://pypi.org/project/zope.index/>`_. See `the |
| | | documentation <http://docs.repoze.org/catalog>`_ for more |
| | | information. |
| | | |
| | |
| | | :ref:`multidict_narr` and :class:`pyramid.interfaces.IMultiDict`. |
| | | |
| | | PyPI |
| | | `The Python Package Index <https://pypi.python.org/pypi>`_, a collection |
| | | `The Python Package Index <https://pypi.org/>`_, a collection |
| | | of software available for Python. |
| | | |
| | | Agendaless Consulting |
| | |
| | | pyramid_redis_sessions |
| | | A package by Eric Rasmussen which allows you to store Pyramid session |
| | | data in a Redis database. See |
| | | https://pypi.python.org/pypi/pyramid_redis_sessions for more information. |
| | | https://pypi.org/project/pyramid_redis_sessions/ for more information. |
| | | |
| | | cache busting |
| | | A technique used when serving a cacheable static asset in order to force |
| | |
| | | description is provided in the ``description`` field. The ``long_description`` |
| | | is conventionally the content of the ``README`` and ``CHANGES`` files appended |
| | | together. The ``classifiers`` field is a list of `Trove classifiers |
| | | <https://pypi.python.org/pypi?%3Aaction=list_classifiers>`_ describing your |
| | | <https://pypi.org/pypi?%3Aaction=list_classifiers>`_ describing your |
| | | application. ``author`` and ``author_email`` are text fields which probably |
| | | don't need any description. ``url`` is a field that should point at your |
| | | application project's URL (if any). ``packages=find_packages()`` causes all |
| | |
| | | sessioning system. |
| | | ======================= ======= ============================= |
| | | |
| | | .. _pyramid_nacl_session: https://pypi.python.org/pypi/pyramid_nacl_session |
| | | .. _pyramid_nacl_session: https://pypi.org/project/pyramid_nacl_session/ |
| | | .. _PyNaCl: https://pynacl.readthedocs.io/en/latest/secret/ |
| | | |
| | | .. _pyramid_redis_sessions: https://pypi.python.org/pypi/pyramid_redis_sessions |
| | | .. _pyramid_redis_sessions: https://pypi.org/project/pyramid_redis_sessions/ |
| | | .. _Redis: https://redis.io/ |
| | | |
| | | .. _pyramid_beaker: https://pypi.python.org/pypi/pyramid_beaker |
| | | .. _pyramid_beaker: https://pypi.org/project/pyramid_beaker/ |
| | | .. _Beaker: https://beaker.readthedocs.io/en/latest/ |
| | | |
| | | .. index:: |
| | |
| | | |
| | | .. seealso:: See also :ref:`security_chapter`, |
| | | :ref:`AuthTktAuthenticationPolicy <authentication_module>`, `bcrypt |
| | | <https://pypi.python.org/pypi/bcrypt>`_ |
| | | <https://pypi.org/project/bcrypt/>`_ |
| | |
| | | Add dependencies |
| | | ~~~~~~~~~~~~~~~~ |
| | | |
| | | Just like in :ref:`wiki_defining_views`, we need a new dependency. We need to add the `bcrypt <https://pypi.python.org/pypi/bcrypt>`_ package, to our tutorial package's ``setup.py`` file by assigning this dependency to the ``requires`` parameter in the ``setup()`` function. |
| | | Just like in :ref:`wiki_defining_views`, we need a new dependency. We need to add the `bcrypt <https://pypi.org/project/bcrypt/>`_ package, to our tutorial package's ``setup.py`` file by assigning this dependency to the ``requires`` parameter in the ``setup()`` function. |
| | | |
| | | Open ``setup.py`` and edit it to look like the following: |
| | | |
| | |
| | | #. *Line 16*. Include support for the :term:`Chameleon` template rendering |
| | | bindings, allowing us to use the ``.pt`` templates. |
| | | |
| | | #. *Line 17*. Include support for ``pyramid_tm``, allowing Pyramid requests to join the active transaction as provided by the `transaction <https://pypi.python.org/pypi/transaction>`_ package. |
| | | #. *Line 17*. Include support for ``pyramid_tm``, allowing Pyramid requests to join the active transaction as provided by the `transaction <https://pypi.org/project/transaction/>`_ package. |
| | | |
| | | #. *Line 18*. Include support for ``pyramid_retry`` to retry a request when transient exceptions occur. |
| | | |
| | |
| | | ``tutorial-0.0.tar.gz``. You can send this file to your friends to show them |
| | | your cool new application. They should be able to install it by pointing the |
| | | ``pip install`` command directly at it. Or you can upload it to `PyPI |
| | | <https://pypi.python.org/pypi>`_ and share it with the rest of the world, where |
| | | <https://pypi.org/>`_ and share it with the rest of the world, where |
| | | it can be downloaded via ``pip install`` remotely like any other package people |
| | | download from PyPI. |
| | |
| | | application was generated by the cookiecutter; it doesn't know about our |
| | | custom application requirements. |
| | | |
| | | We need to add a dependency, the `bcrypt <https://pypi.python.org/pypi/bcrypt>`_ package, to our ``tutorial`` |
| | | We need to add a dependency, the `bcrypt <https://pypi.org/project/bcrypt/>`_ package, to our ``tutorial`` |
| | | package's ``setup.py`` file by assigning this dependency to the ``requires`` |
| | | parameter in the ``setup()`` function. |
| | | |
| | |
| | | ``tutorial-0.0.tar.gz``. You can send this file to your friends to show them |
| | | your cool new application. They should be able to install it by pointing the |
| | | ``pip install`` command directly at it. Or you can upload it to `PyPI |
| | | <https://pypi.python.org/pypi>`_ and share it with the rest of the world, where |
| | | <https://pypi.org/>`_ and share it with the rest of the world, where |
| | | it can be downloaded via ``pip install`` remotely like any other package people |
| | | download from PyPI. |
| | |
| | | https://docs.pylonsproject.org/projects/pyramid-tm/en/latest/ |
| | | |
| | | .. _zope.sqlalchemy: |
| | | https://pypi.python.org/pypi/zope.sqlalchemy |
| | | https://pypi.org/project/zope.sqlalchemy/ |
| | | |
| | | .. _transaction: |
| | | https://zodb.readthedocs.io/en/latest/transactions.html |
| | |
| | | from pyramid.request import Request |
| | | from pyramid.request import apply_request_extensions |
| | | |
| | | from pyramid.threadlocal import manager as threadlocal_manager |
| | | from pyramid.threadlocal import RequestContext |
| | | from pyramid.traversal import DefaultRootFactory |
| | | |
| | | def get_root(app, request=None): |
| | |
| | | registry = app.registry |
| | | if request is None: |
| | | request = _make_request('/', registry) |
| | | threadlocals = {'registry':registry, 'request':request} |
| | | app.threadlocal_manager.push(threadlocals) |
| | | def closer(request=request): # keep request alive via this function default |
| | | app.threadlocal_manager.pop() |
| | | request.registry = registry |
| | | ctx = RequestContext(request) |
| | | ctx.begin() |
| | | def closer(): |
| | | ctx.end() |
| | | root = app.root_factory(request) |
| | | return root, closer |
| | | |
| | |
| | | # NB: even though _make_request might have already set registry on |
| | | # request, we reset it in case someone has passed in their own |
| | | # request. |
| | | request.registry = registry |
| | | threadlocals = {'registry':registry, 'request':request} |
| | | threadlocal_manager.push(threadlocals) |
| | | request.registry = registry |
| | | ctx = RequestContext(request) |
| | | ctx.begin() |
| | | apply_request_extensions(request) |
| | | def closer(): |
| | | threadlocal_manager.pop() |
| | | ctx.end() |
| | | root_factory = registry.queryUtility(IRootFactory, |
| | | default=DefaultRootFactory) |
| | | root = root_factory(request) |
| | |
| | | def _makeRegistry(self): |
| | | return DummyRegistry([DummyFactory]) |
| | | |
| | | def setUp(self): |
| | | from pyramid.threadlocal import manager |
| | | self.manager = manager |
| | | self.default = manager.get() |
| | | |
| | | def test_it_norequest(self): |
| | | registry = self._makeRegistry() |
| | | app = DummyApp(registry=registry) |
| | | root, closer = self._callFUT(app) |
| | | self.assertEqual(len(app.threadlocal_manager.pushed), 1) |
| | | pushed = app.threadlocal_manager.pushed[0] |
| | | self.assertEqual(dummy_root, root) |
| | | pushed = self.manager.get() |
| | | self.assertEqual(pushed['registry'], registry) |
| | | self.assertEqual(pushed['request'].registry, app.registry) |
| | | self.assertEqual(len(app.threadlocal_manager.popped), 0) |
| | | self.assertEqual(pushed['request'].registry, registry) |
| | | self.assertEqual(pushed['request'].environ['path'], '/') |
| | | closer() |
| | | self.assertEqual(len(app.threadlocal_manager.popped), 1) |
| | | self.assertEqual(self.default, self.manager.get()) |
| | | |
| | | def test_it_withrequest(self): |
| | | registry = self._makeRegistry() |
| | | app = DummyApp(registry=registry) |
| | | request = DummyRequest({}) |
| | | root, closer = self._callFUT(app, request) |
| | | self.assertEqual(len(app.threadlocal_manager.pushed), 1) |
| | | pushed = app.threadlocal_manager.pushed[0] |
| | | self.assertEqual(dummy_root, root) |
| | | pushed = self.manager.get() |
| | | self.assertEqual(pushed['registry'], registry) |
| | | self.assertEqual(pushed['request'], request) |
| | | self.assertEqual(len(app.threadlocal_manager.popped), 0) |
| | | self.assertEqual(pushed['request'].registry, registry) |
| | | closer() |
| | | self.assertEqual(len(app.threadlocal_manager.popped), 1) |
| | | |
| | | def test_it_requestfactory_overridden(self): |
| | | registry = self._makeRegistry() |
| | | app = DummyApp(registry=registry) |
| | | root, closer = self._callFUT(app) |
| | | self.assertEqual(len(app.threadlocal_manager.pushed), 1) |
| | | pushed = app.threadlocal_manager.pushed[0] |
| | | self.assertEqual(pushed['request'].environ['path'], '/') |
| | | self.assertEqual(self.default, self.manager.get()) |
| | | |
| | | class Test_prepare(unittest.TestCase): |
| | | def _callFUT(self, request=None, registry=None): |
| | |
| | | |
| | | class DummyApp: |
| | | def __init__(self, registry=None): |
| | | self.threadlocal_manager = DummyThreadLocalManager() |
| | | if registry: |
| | | self.registry = registry |
| | | |
| | | def root_factory(self, environ): |
| | | return dummy_root |
| | | |
| | | class DummyThreadLocalManager: |
| | | def __init__(self): |
| | | self.pushed = [] |
| | | self.popped = [] |
| | | |
| | | def push(self, item): |
| | | self.pushed.append(item) |
| | | |
| | | def pop(self): |
| | | self.popped.append(True) |
| | | |
| | | class DummyRequest(object): |
| | | matchdict = None |
| | | matched_route = None |
| | |
| | | ``*remainder`` replacement value, it is tacked on to the URL |
| | | after being URL-quoted-except-for-embedded-slashes. |
| | | |
| | | If no ``_query`` keyword argument is provided, the request query string |
| | | will be returned in the URL. If it is present, it will be used to |
| | | compose a query string that will be tacked on to the end of the URL, |
| | | replacing any request query string. The value of ``_query`` may be a |
| | | sequence of two-tuples *or* a data structure with an ``.items()`` |
| | | method that returns a sequence of two-tuples (presumably a dictionary). |
| | | This data structure will be turned into a query string per the |
| | | documentation of :func:`pyramid.url.urlencode` function. This will |
| | | produce a query string in the ``x-www-form-urlencoded`` format. A |
| | | If ``_query`` is provided, it will be used to compose a query string |
| | | that will be tacked on to the end of the URL. The value of ``_query`` |
| | | may be a sequence of two-tuples *or* a data structure with an |
| | | ``.items()`` method that returns a sequence of two-tuples |
| | | (presumably a dictionary). This data structure will be turned into |
| | | a query string per the documentation of the |
| | | :func:`pyramid.url.urlencode` function. This will produce a query |
| | | string in the ``x-www-form-urlencoded`` format. A |
| | | non-``x-www-form-urlencoded`` query string may be used by passing a |
| | | *string* value as ``_query`` in which case it will be URL-quoted |
| | | (e.g. query="foo bar" will become "foo%20bar"). However, the result |
| | |
| | | ``elements`` are used, the generated URL will *not* |
| | | end in a trailing slash. |
| | | |
| | | If a keyword argument ``query`` is present, it will be used to compose |
| | | a query string that will be tacked on to the end of the URL. The value |
| | | of ``query`` may be a sequence of two-tuples *or* a data structure with |
| | | an ``.items()`` method that returns a sequence of two-tuples |
| | | (presumably a dictionary). This data structure will be turned into a |
| | | query string per the documentation of :func:`pyramid.url.urlencode` |
| | | function. This will produce a query string in the |
| | | ``x-www-form-urlencoded`` encoding. A non-``x-www-form-urlencoded`` |
| | | query string may be used by passing a *string* value as ``query`` in |
| | | which case it will be URL-quoted (e.g. query="foo bar" will become |
| | | "foo%20bar"). However, the result will not need to be in ``k=v`` form |
| | | as required by ``x-www-form-urlencoded``. After the query data is |
| | | turned into a query string, a leading ``?`` is prepended, and the |
| | | resulting string is appended to the generated URL. |
| | | If ``query`` is provided, it will be used to compose a query string |
| | | that will be tacked on to the end of the URL. The value of ``query`` |
| | | may be a sequence of two-tuples *or* a data structure with an |
| | | ``.items()`` method that returns a sequence of two-tuples |
| | | (presumably a dictionary). This data structure will be turned into |
| | | a query string per the documentation of the |
| | | :func:`pyramid.url.urlencode` function. This will produce a query |
| | | string in the ``x-www-form-urlencoded`` format. A |
| | | non-``x-www-form-urlencoded`` query string may be used by passing a |
| | | *string* value as ``query`` in which case it will be URL-quoted |
| | | (e.g. query="foo bar" will become "foo%20bar"). However, the result |
| | | will not need to be in ``k=v`` form as required by |
| | | ``x-www-form-urlencoded``. After the query data is turned into a query |
| | | string, a leading ``?`` is prepended, and the resulting string is |
| | | appended to the generated URL. |
| | | |
| | | .. note:: |
| | | |
| | |
| | | |
| | | install_requires = [ |
| | | 'setuptools', |
| | | 'WebOb >= 1.7.0rc2', # Response.has_body |
| | | 'WebOb >= 1.7.0', # Response.has_body |
| | | 'zope.interface >= 3.8.0', # has zope.interface.registry |
| | | 'zope.deprecation >= 3.5.0', # py3 compat |
| | | 'venusian >= 1.0a3', # ``ignore`` |
| | | 'venusian >= 1.0', # ``ignore`` |
| | | 'translationstring >= 0.4', # py3 compat |
| | | 'PasteDeploy >= 1.5.0', # py3 compat |
| | | 'plaster', |
| | |
| | | |
| | | |
| | | docs_extras = [ |
| | | 'Sphinx >= 1.3.5', |
| | | 'Sphinx >= 1.3.5, != 1.7.3', |
| | | 'docutils', |
| | | 'repoze.sphinx.autointerface', |
| | | 'pylons_sphinx_latesturl', |
| | |
| | | check-manifest |
| | | |
| | | [testenv:docs] |
| | | skip_install = True |
| | | basepython = python3.5 |
| | | whitelist_externals = make |
| | | commands = |
| | |
| | | make -C docs doctest html epub BUILDDIR={envdir} "SPHINXOPTS=-W -E" |
| | | |
| | | [testenv:pdf] |
| | | skip_install = True |
| | | basepython = python3.5 |
| | | whitelist_externals = make |
| | | commands = |