pax_global_header00006660000000000000000000000064145610673360014525gustar00rootroot0000000000000052 comment=b5953e11ca3b80c1a210066cd475838557d191cb pyramid_jinja2-2.10.1/000077500000000000000000000000001456106733600145105ustar00rootroot00000000000000pyramid_jinja2-2.10.1/.coveragerc000066400000000000000000000003361456106733600166330ustar00rootroot00000000000000[run] source = pyramid_jinja2 [paths] source = pyramid_jinja2 */pyramid_jinja2 */site-packages/pyramid_jinja2 [report] omit = */pyramid_jinja2/scaffolds/__init__.py show_missing = true precision = 2 pyramid_jinja2-2.10.1/.flake8000066400000000000000000000005651456106733600156710ustar00rootroot00000000000000[flake8] max-line-length = 88 ignore = # E203: whitespace before ':' (black fails to be PEP8 compliant) E203 # E731: do not assign a lambda expression, use a def E731 # W503: line break before binary operator (flake8 is not PEP8 compliant) W503 # W504: line break after binary operator (flake8 is not PEP8 compliant) W504 show-source = True pyramid_jinja2-2.10.1/.github/000077500000000000000000000000001456106733600160505ustar00rootroot00000000000000pyramid_jinja2-2.10.1/.github/dependabot.yml000066400000000000000000000003321456106733600206760ustar00rootroot00000000000000# Set update schedule for GitHub Actions version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: # Check for updates to GitHub Actions every weekday interval: "daily" pyramid_jinja2-2.10.1/.github/workflows/000077500000000000000000000000001456106733600201055ustar00rootroot00000000000000pyramid_jinja2-2.10.1/.github/workflows/ci-tests.yml000066400000000000000000000067201456106733600223700ustar00rootroot00000000000000name: Build and test on: # Only on pushes to main or one of the release branches we build on push push: branches: - main - "[0-9].[0-9]+-branch" tags: # Build pull requests pull_request: jobs: test: strategy: matrix: py: - "3.7" - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" - "pypy-3.8" os: - "ubuntu-latest" - "windows-latest" - "macos-latest" architecture: - x64 - x86 exclude: # Linux and macOS don't have x86 python - os: "ubuntu-latest" architecture: x86 - os: "macos-latest" architecture: x86 name: "Python: ${{ matrix.py }}-${{ matrix.architecture }} on ${{ matrix.os }}" runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - name: Setup python uses: actions/setup-python@v5 with: python-version: ${{ matrix.py }} architecture: ${{ matrix.architecture }} - run: pip install tox - name: Running tox run: tox -e py test_old_pyramids: strategy: matrix: pyramid: - "pyramid13" - "pyramid14" - "pyramid15" - "pyramid16" - "pyramid17" - "pyramid18" - "pyramid19" - "pyramid110" - "pyramid20" - "pyramid110-jinja2legacy" - "pyramid20-jinja2legacy" name: "Python: py310-${{ matrix.pyramid }}" runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup python uses: actions/setup-python@v5 with: python-version: "3.10" architecture: x64 - run: pip install tox - name: Running tox run: tox -e py310-${{ matrix.pyramid }} coverage: runs-on: ubuntu-latest name: Validate coverage steps: - uses: actions/checkout@v4 - name: Setup python 3.10 uses: actions/setup-python@v5 with: python-version: "3.10" architecture: x64 - run: pip install tox - run: tox -e py310,py310-jinja2legacy,coverage docs: runs-on: ubuntu-latest name: Build the documentation steps: - uses: actions/checkout@v4 - name: Setup python uses: actions/setup-python@v5 with: python-version: "3.10" architecture: x64 - run: pip install tox - run: tox -e docs lint: runs-on: ubuntu-latest name: Lint the package steps: - uses: actions/checkout@v4 - name: Setup python uses: actions/setup-python@v5 with: python-version: "3.10" architecture: x64 - run: pip install tox - run: tox -e lint pyramid_jinja2-2.10.1/.gitignore000066400000000000000000000002241456106733600164760ustar00rootroot00000000000000bookenv/ /build .coverage .coverage.* coverage.xml dist/ /env* env*/ *.egg *.egg-info .eggs/ jyenv/ *.pyc *$py.class pypyenv/ *~ .*.swp .tox/ venv/ pyramid_jinja2-2.10.1/.readthedocs.yaml000066400000000000000000000003771456106733600177460ustar00rootroot00000000000000# https://docs.readthedocs.io/en/stable/config-file/v2.html version: 2 build: os: ubuntu-22.04 tools: python: '3.12' sphinx: configuration: docs/conf.py python: install: - method: pip path: . extra_requirements: - docs pyramid_jinja2-2.10.1/CHANGES.rst000066400000000000000000000356711456106733600163260ustar00rootroot000000000000002.10.1 (2023-02-07) =================== - Rename "master" git branch to "main" - Add Python 3.11 and 3.12 support. - Replace usage of private Pyramid APIs. 2.10 (2022-03-27) ================= - Add ``jinja2.i18n_extension`` configuration setting. See https://github.com/Pylons/pyramid_jinja2/pull/165 2.9.2 (2022-03-19) ================== - Support Jinja2 >= 3.0. - Only import ``jinja2.pass_context`` if available on Jinja2 >= 3.0, otherwise fallback to ``jinja2.contextfilter``. See https://github.com/Pylons/pyramid_jinja2/pull/164 2.9.1 (2022-03-12) ================== **This release has been yanked and is no longer available.** - Fix package metadata. No changes from 2.9. 2.9 (2022-03-12) ================ **This release has been yanked and is no longer available.** - Drop Python 3.6 support. - Add Python 3.9 and 3.10 support. - Refactor project structure to make wheel distribution smaller. - Blackify the codebase. - Use the newer ``@jinja2.pass_context`` in favor of the deprecated ``@jinja2.contextfilter``. See https://github.com/Pylons/pyramid_jinja2/pull/159 2.8 (2019-01-25) ================ - Drop Python 3.3 support. - Add Python 3.6 and 3.7 support. - Support the ``mapping`` argument in the injected ``gettext`` function. See https://github.com/Pylons/pyramid_jinja2/pull/143 2.7 (2016-11-15) ================ - Drop Python 2.6 and 3.2 support. - Add Python 3.5 support. - #123: Switch to pytest and pip for testing and installation in the documentation and scaffold. nose and coverage are still used in the core pyramid_jinja2 package [stevepiercy]. - Prefer ``resource_url`` over deprecated ``model_url``. Pyramid has changed its vocabulary, so let's reflect the changes. [Mikko Ohtamaa] - Support a dotted path to a gettext wrapper for the ``jinja2.i18n.gettext`` setting. [mmerickel] 2.6.2 (2016-01-23) ================== - Officially drop support for Python 3.2, test under Python 3.5 and pypy3 [Domen Kozar] 2.6.1 (2016-01-20) ================== - Don't include .pyc in wheel file [Domen Kozar] 2.6 (2016-01-20) ================ - #116: Update scaffold to be consistent with Pyramid's default scaffolds [stevepiercy] 2.5 (2015-04-16) ================ - #106: Allow specifying a custom pyramid_jinja.i18n.GetTextWrapper [dstufft] 2.4 (2015-03-27) ================ - #105: Support ``jinja2.finalize`` configuration setting. [dstufft] - #94: Fix loading of templates with relative names on Windows [zart] - Support Python 3.4 [mmerickel] - Improve scaffold [marioidival] - #98: Avoid get_current_request where possible [housleyjk] - #99: Add resource_path filter [javex] 2.3.3 (2014-07-02) ================== - #91: Fix a recursion error while attempting to include a template with the same name as one of the parents that was already loaded. [mmerickel] 2.3.2 (2014-06-13) ================== - Fix 2.3.1 brownbag release. It had some erroneous didn't-mean-to-push changes that are now solved. Brought coverage back up to 100%. 2.3.1 (2014-06-13) ================== - Improve the template-relative searchpath logic to search more possibilities in the include-chain built up from templates including or extending other templates. The logic for when the chain was longer than just one template including another template was broken. 2.3 (2014-05-30) ================ - Require ``pyramid_jinja2`` to be included even when using ``pyramid_jinja2.renderer_factory``. It is now a thin wrapper around the default renderer and can be used to share the same settings with another file extension. [mmerickel] Backward Incompatible Changes ----------------------------- - ``pyramid_jinja2`` **must** be included into the ``Configurator`` in order to use ``pyramid_jinja2.renderer_factory`` otherwise you may see the exception:: ValueError: As of pyramid_jinja2 2.3, the use of the "pyramid_jinja2.renderer_factory" requires that pyramid_jinja2 be configured via config.include("pyramid_jinja2") or the equivalent "pyramid.includes" setting. The fix is to include ``pyramid_jinja2``:: config.include("pyramid_jinja2") 2.2 (2014-05-30) ================ - #88: Formalize template loading order and allow all lookups to fallback to the search path. A template is now always searched for relative to its parent template. If not found, the lookup will fallback to the search path. [mmerickel] - Add ``prepend`` option to ``config.add_jinja2_search_path`` to allow prepending of paths to the beginning of the search path if a path should override previously defined paths. [mmerickel] 2.1 (2014-05-16) ================ - The 2.0 series started adding the package that invoked ``config.add_jinja2_renderer`` to the template search path. This is being removed in favor of explicit search paths and will hopefully not affect many people as it has only been available for a couple weeks. The only automatic search path left is the one added by the default ``.jinja2`` renderer created when including ``pyramid_jinja2``. [mmerickel] - Adjust the ``config.include("pyramid_jinja2")`` to add any packages from ``jinja2.directories`` **before** the default search path at the base of the app. Previously there was no way to override that search path. [mmerickel] 2.0.2 (2014-05-06) ================== - The path of the child template is always considered when inheriting from a base template. Therefore when doing ``render("templates/foo.jinja2")`` and ``foo.jinja2`` has an ``{% extends "base.jinja2" %}``, the template will be searched for as ``"templates/base.jinja2"`` on the search path. Previously the path of the child template was ignored when doing the lookup for the base, causing some very subtle and unrecoverable lookup errors when the child template was found relative to the caller instead of being found on the search path. [mmerickel] - This release restores the default search path behaviors from the 1.x series that were inadvertently removed in the 2.x. The project's root package is added to the search path by default. [mmerickel] 2.0.1 (2014-04-23) ================== - #86: Fix a regression caused by the new support for extending a template relative to itself. Using ``{% extends "some_asset:spec.jinja2" %}`` was no longer working and is now fixed. [mmerickel] 2.0 (2014-04-21) ================ - Claim Python 3.4 support [mmerickel] - #75: Fix the missing piece of relative template loading by allowing a template to inherit from a template relative to itself, instead of forcing the parent to be on the search path. [mmerickel] - #73: Added a new ``config.add_jinja2_renderer`` API that can create and override multiple Jinja2 renderers, each loaded using potentially different settings and extensions. The other APIs are now keyed on the renderer extension, as each extension may have different settings. Thus ``config.add_jinja2_search_path``, ``config.add_jinja2_extension``, and ``config.get_jinja2_environment`` accept a ``name`` argument, which defaults to ``.jinja2``. This deprecates the old ``pyramid_jinja2.renderer_factory`` mechanism for adding renderers with alternate extensions. Configuration of the renderers has been updated to follow Pyramid's standard mechanisms for conflict detection. This means that if two modules both try to add a renderer for the ``.jinja2`` extension, they may raise a conflict or the modifications made by the invocation closest to the ``Configurator`` in the call-stack will win. This behavior can be affected by calling ``config.commit`` at appropriate times to force a configuration to take effect immediately. As such, configuration is deferred until commit-time, meaning that it is now possible ``config.get_jinja2_environment`` will return ``None`` because the changes have not yet been committed. [mmerickel] Backward Incompatible Changes ----------------------------- - The creation and configuration of the Jinja2 ``Environment`` is now deferred until commit-type in the Pyramid ``Configurator``. This means that ``config.get_jinja2_environment`` may return ``None``. To resolve this, invoke ``config.commit()`` before attempting to get the environment. 1.10 (2014-01-11) ================= - #77: Change semantics of ``jinja2.bytecode_caching`` setting. The new default is false (no bytecode caching) -- ``bytecode_caching`` must explicitly be set to true to enable a filesystem bytecode cache. In addition, an atexit callback to clean the cache is no longer registered (as this seemed to defeat most of the purpose of having a bytecode cache.) Finally, a more complex bytecode cache may be configured by setting ``jinja2.bytecode_caching`` directly to a ``jinja2.BytecodeCache`` instance. (This can not be done in a paste .ini file, it must be done programatically.) [dairiki] - prevent error when using `python setup.py bdist_wheel` [msabramo] 1.9 (2013-11-08) ================ - fix indentation level for Jinja2ProjectTemplate in scaffolds/__init__.py [Bruno Binet] - Remove unnecessary dependency on ``pyramid.interfaces.ITemplateRenderer`` which was deprecated in Pyramid 1.5. [mmerickel] - #68: Added `model_path_filter`, `route_path_filter` and `static_path_filter` filters [Remco] - #74: Fixed issue with route being converted as_const by jinja2 engine when using btyecode cache [Remco] 1.8 (2013-10-03) ================ - #70: Do not pin for py3.2 compatibility unless running under py3.2 [dairiki] 1.7 (2013-08-07) ================ - #56: python3.3: Non-ASCII characters in changelog breaks pip installation [Domen Kozar] - #57: Remove useless warning: `DeprecationWarning: reload_templates setting is deprecated, use pyramid.reload_templates instead.` [Marc Abramowitz] 1.6 (2013-01-23) ================ - Set `jinja2.i18n.domain` default to the package name of the pyramid application. [Domen Kozar] - Add `jinja2.globals` setting to add global objects into the template context [Eugene Fominykh] - Add `jinja2.newstyle` setting to enable newstyle gettext calls [Thomas Schussler] 1.5 (2012-11-24) ================ - Add `pyramid.reload_templates` to set `jinja2.auto_reload` instead of using `reload_templates`. Deprecate the latter. [Domen Kozar] - Clear bytecode cache on atexit [Domen Kozar] - Add support for more Jinja2 options. Note support for jinja2.autoescape is limited to boolean only. * jinja2.block_start_string * jinja2.block_end_string * jinja2.variable_start_string * jinja2.variable_end_string * jinja2.comment_start_string * jinja2.comment_end_string * jinja2.line_statement_prefix * jinja2.line_comment_prefix * jinja2.trim_blocks * jinja2.newline_sequence * jinja2.optimized * jinja2.cache_size * jinja2.autoescape [Michael Ryabushkin] 1.4.2 (2012-10-17) ================== - Add `jinja2.undefined` setting to change handling of undefined types. [Robert Buchholz] - Remove redundant decoding error handling [Domen Kozar] - Configure bytecode caching by default. Introduce `jinja2.bytecode_caching` and `jinja2.bytecode_caching_directory` settings. [Domen Kozar] - Allow to add custom Jinja2 tests in `jinja2.tests` setting. [Sebastian Kalinowski] 1.4.1 (2012-09-12) ================== - Fix brown-bag release [Domen Kozar] 1.4 (2012-09-12) ================ - Correctly resolve relative search paths passed to ``add_jinja2_search_path`` and ``jinja2.directories`` [Domen Kozar] - #34: Don't recreate ``jinja2.Environment`` for ``add_jinja2_extension`` [Domen Kozar] - Drop Python 2.5 compatibility [Domen Kozar] - Addition of ``static_url`` filter. - Add ``dev`` and ``docs`` setup.py aliases (ala Pyramid). - Changed template loading relative to package calling the renderer so it works like the Chameleon template loader. 1.3 (2011-12-14) ================ - Make scaffolding compatible with Pyramid 1.3a2+. 1.2 (2011-09-27) ================ - Make tests pass on Pyramid 1.2dev. - Make compatible with Python 3.2 (requires Pyramid 1.3dev+). 1.1 (2011-07-24) ================ - Add ``get_jinja2_environment`` directive. - Add all configurator directives to documentation. 1.0 (2011-05-12) ================ - Message domain can now be specified with *jinja2.i18n.domain* for i18n - Paster template now sets up starter locale pot/po/mo files - pyramid_jinja2 now depends on Jinja2 >= 2.5.0 due to ``jinja2.Environment.install_gettext_callables`` use https://github.com/Pylons/pyramid_jinja2/pull/21 - Added demo app just to visualize i18n work 0.6.2 (2011-04-06) ================== - ``jinja2.ext.i18n`` is now added by default, see ``i18n.rst`` for details - Added ``add_jinja2_extension`` directive to the Configurator - Updated jinja2.extensions parsing mechanism - Fixed docs to indicate using asset: prefix is no longer necessary 0.6.1 (2011-03-03) ================== - Asset-based loading now takes precedance and does not require "asset:" prefix - Fixed the "current" package mechanism of asset: loading so that it more accurately finds the current package - Dependency on ``pyramid_zcml`` removed. 0.6 (2011-02-15) ================ - Documentation overhauled. - Templates can now be looked up by asset spec completely bypassing the search path by specifying a prefix of ``asset:``. - Updated paster template to more closely relate to changes made to paster templmates in Pyramid core. - Add new directive ``add_jinja2_search_path`` to the configurator when ``includeme`` is used. 0.5 (2011-01-18) ================ - Add ``includeme`` function (meant to be used via ``config.include``). - Fix documentation bug related to ``paster create`` reported at https://github.com/Pylons/pyramid_jinja2/issues/12 - Depend upon Pyramid 1.0a10 + (to make ZCML work). 0.4 (2010-12-16) ================ Paster Template --------------- - Changes to normalize with default templates shipping with Pyramid core: remove calls to ``config.begin()`` and ``config.end()`` from ``__init__.main``, entry point name changed to ``main``, entry ``__init__.py`` function name changed to ``main``, depend on WebError, use ``paster_plugins`` argument to setup function in setup.py, depend on Pyramid 1.0a6+ (use ``config`` rather than ``configurator``). Tests ----- - Use ``testing.setUp`` and ``testing.tearDown`` rather than constructing a Configurator (better fwd compat). Features -------- - Add ``model_url`` and ``route_url`` filter implementations (and documented). Documentation ------------- - Use Makefile which pulls in Pylons theme automagically. 0.3 (2010-11-26) ================ - Add ``jinja2.filters`` and ``jinja2.extensions`` settings (thanks to aodag). - Document all known settings. 0.2 (2010-11-06) ================ - Template autoreloading did not function, even if ``reload_templates`` was set to ``True``. 0.1 (2010-11-05) ================ - First release. *Not* backwards compatible with ``repoze.bfg.jinja2``: we use a filesystem loader (the directories to load from come from the ``jinja2.directories`` setting). No attention is paid to the current package when resolving a renderer= line. pyramid_jinja2-2.10.1/CONTRIBUTORS.txt000066400000000000000000000124151456106733600172110ustar00rootroot00000000000000Pylons 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 notify 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 (see 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_jinja2". 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 Tres Seaver, 2010/11/09 Blaise Laflamme, 2010/11/14 Rocky Burt, 2011/02/13 Kiall Mac Innes, 2012/05/13 Domen Kožar, 2012/09/11 Joao Paulo F Farias, 2012/09/11 Sebastian Kalinowski, 2012/10/14 Michael Ryabushkin, 2012/11/15 Eugene Fominykh, 2013/01/16 Thomas Schüßler, 2013/01/17 Michael Merickel, 2013/10/19 Remco Verhoef (nl5887), 2013/11/08 Geoffrey Dairiki, 2013/11/22 Steve Piercy, 2016/01/07 Jonathan Vanasco, 2022/11/15 pyramid_jinja2-2.10.1/COPYRIGHT.txt000066400000000000000000000001551456106733600166220ustar00rootroot00000000000000Copyright (c) 2010 Agendaless Consulting and Contributors. (http://www.agendaless.com), All Rights Reserved pyramid_jinja2-2.10.1/LICENSE.txt000066400000000000000000000033771456106733600163450ustar00rootroot00000000000000License 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. pyramid_jinja2-2.10.1/MANIFEST.in000066400000000000000000000005751456106733600162550ustar00rootroot00000000000000graft src/pyramid_jinja2 graft tests graft docs graft demo graft .github include README.rst include CHANGES.rst include LICENSE.txt include CONTRIBUTORS.txt include COPYRIGHT.txt include pyproject.toml include setup.cfg include .coveragerc include .flake8 include tox.ini include .readthedocs.yaml prune docs/_build prune docs/_themes recursive-exclude * __pycache__ *.py[cod] pyramid_jinja2-2.10.1/README.rst000066400000000000000000000005501456106733600161770ustar00rootroot00000000000000Jinja2 bindings for Pyramid =========================== These are bindings for the `Jinja2 templating system `_ for the `Pyramid `_ web framework. See https://docs.pylonsproject.org/projects/pyramid-jinja2/en/latest/ for documentation or ``index.rst`` in the ``docs`` sub-directory of the source distribution. pyramid_jinja2-2.10.1/demo/000077500000000000000000000000001456106733600154345ustar00rootroot00000000000000pyramid_jinja2-2.10.1/demo/__init__.py000066400000000000000000000022261456106733600175470ustar00rootroot00000000000000from pyramid.config import Configurator from pyramid.i18n import TranslationStringFactory, get_locale_name, get_localizer _ = TranslationStringFactory("messages") def root_view(request): request.locale_name = "fr" localizer = get_localizer(request) return { "pyramid_translated": localizer.translate(_("Hello World")), "locale_name": get_locale_name(request), } def app(global_settings, **settings): config = Configurator(settings=settings) config.include("pyramid_jinja2") config.add_route(name="root", pattern="/") config.add_view(root_view, renderer="helloworld.jinja2") config.add_translation_dirs("demo:locale/") return config.make_wsgi_app() class Mainer(object): import wsgiref.simple_server make_server = wsgiref.simple_server.make_server def main(self): port = 8080 app_config = {"DEBUG": True, "reload_templates": True} pyramid_app = app({}, **app_config) httpd = self.make_server("", port, pyramid_app) # Serve until process is killed httpd.serve_forever() main = Mainer().main if __name__ == "__main__": main() # pragma: nocover pyramid_jinja2-2.10.1/demo/helloworld.jinja2000066400000000000000000000013741456106733600207130ustar00rootroot00000000000000 Demo App
Metadata
Locale Name
{{ locale_name }}
I18N Demo
No Translation (english)
Hello World
Translated using Pyramid directly
{{ pyramid_translated }}
Translated using Jinja2
{% trans %}Hello World{% endtrans %}
pyramid_jinja2-2.10.1/demo/locale/000077500000000000000000000000001456106733600166735ustar00rootroot00000000000000pyramid_jinja2-2.10.1/demo/locale/fr/000077500000000000000000000000001456106733600173025ustar00rootroot00000000000000pyramid_jinja2-2.10.1/demo/locale/fr/LC_MESSAGES/000077500000000000000000000000001456106733600210675ustar00rootroot00000000000000pyramid_jinja2-2.10.1/demo/locale/fr/LC_MESSAGES/messages.mo000066400000000000000000000007271456106733600232410ustar00rootroot00000000000000,< =I Hello WorldProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2011-05-12 09:14-0430 PO-Revision-Date: 2011-05-12 09:19-0330 Last-Translator: FULL NAME Language-Team: fr Plural-Forms: nplurals=2; plural=(n > 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 0.9.6 Bonjour Mondepyramid_jinja2-2.10.1/demo/locale/fr/LC_MESSAGES/messages.po000066400000000000000000000012051456106733600232340ustar00rootroot00000000000000# Translations template for PROJECT. # Copyright (C) 2011 ORGANIZATION # This file is distributed under the same license as the PROJECT project. # FIRST AUTHOR , 2011. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2011-05-12 09:14-0330\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" msgid "Hello World" msgstr "Bonjour Monde" pyramid_jinja2-2.10.1/demo/locale/messages.pot000066400000000000000000000011701456106733600212250ustar00rootroot00000000000000# Translations template for PROJECT. # Copyright (C) 2011 ORGANIZATION # This file is distributed under the same license as the PROJECT project. # FIRST AUTHOR , 2011. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2011-05-12 09:14-0330\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" msgid "Hello World" msgstr "" pyramid_jinja2-2.10.1/demo/test_demo.py000066400000000000000000000015641456106733600177770ustar00rootroot00000000000000import unittest import pyramid.testing class DemoTests(unittest.TestCase): def test_root_view(self): from demo import root_view m = pyramid.testing.DummyRequest() root_view(m) self.assertEqual(m.locale_name, "fr") def test_app(self): from demo import app webapp = app({}) self.assertTrue(callable(webapp)) def test_main(self): from demo import Mainer class MyMainer(Mainer): def serve_forever(self): self.serving = True def make_server(self, *args, **kwargs): return Mock(args=args, kwargs=kwargs, serve_forever=self.serve_forever) mainer = MyMainer() mainer.main() self.assertTrue(getattr(mainer, "serving", False)) class Mock(object): def __init__(self, **kwargs): self.__dict__.update(kwargs) pyramid_jinja2-2.10.1/docs/000077500000000000000000000000001456106733600154405ustar00rootroot00000000000000pyramid_jinja2-2.10.1/docs/.gitignore000066400000000000000000000000211456106733600174210ustar00rootroot00000000000000_themes/ _build/ pyramid_jinja2-2.10.1/docs/Makefile000066400000000000000000000052111456106733600170770ustar00rootroot00000000000000# 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 ' where 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: mkdir -p _build/html _build/doctrees $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html @echo @echo "Build finished. The HTML pages are in _build/html." text: mkdir -p _build/text _build/doctrees $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) _build/text @echo @echo "Build finished. The HTML pages are in _build/text." 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: 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 cp _static/*.png _build/latex ./convert_images.sh cp _static/latex-warning.png _build/latex cp _static/latex-note.png _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." epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) _build/epub @echo @echo "Build finished. The epub file is in _build/epub." pyramid_jinja2-2.10.1/docs/api.rst000066400000000000000000000006531456106733600167470ustar00rootroot00000000000000.. _pyramid_jinja2_api: :mod:`pyramid_jinja2` API ------------------------- .. automodule:: pyramid_jinja2 .. autofunction:: includeme .. autofunction:: add_jinja2_renderer .. autofunction:: add_jinja2_search_path .. autofunction:: add_jinja2_extension .. autofunction:: get_jinja2_environment .. autoclass:: Jinja2TemplateRenderer .. autoclass:: SmartAssetSpecLoader .. automodule:: pyramid_jinja2.i18n :members:pyramid_jinja2-2.10.1/docs/changes.rst000066400000000000000000000001771456106733600176070ustar00rootroot00000000000000.. _changes: Changes ******* .. the ******-heading is used to override the ===== in CHANGES.rst .. include:: ../CHANGES.rst pyramid_jinja2-2.10.1/docs/conf.py000066400000000000000000000150721456106733600167440ustar00rootroot00000000000000# pyramid_jinja2 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 datetime import pkg_resources import pylons_sphinx_themes # 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", "sphinx.ext.intersphinx"] # Add any paths that contain templates here, relative to this directory. templates_path = [".templates"] # The suffix of source filenames. source_suffix = ".rst" # The main toctree document. master_doc = "index" # General substitutions. project = "pyramid_jinja2" thisyear = datetime.datetime.now().year copyright = "2011-%s, Agendaless Consulting" % thisyear # The default replacements for |version| and |release|, also used in various # other places throughout the built documents. # # The short X.Y version. version = pkg_resources.get_distribution(project).version # 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 = [] exclude_patterns = [ "_themes/README.rst", ] # 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 html_theme_path = pylons_sphinx_themes.get_html_themes_path() html_theme = "pyramid" html_theme_options = {"github_url": "https://github.com/Pylons/pyramid_jinja2"} # 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 # " v 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" # Do not use smart quotes. smartquotes = False # Custom sidebar templates, maps document names to template names. # Control display of sidebars and include ethical ads from RTD html_sidebars = { "**": [ "localtoc.html", "ethicalads.html", "relations.html", "sourcelink.html", "searchbox.html", ] } # 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/. # html_copy_source = True # If true, an OpenSearch description file will be output, and all pages # will contain a 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" # for cross referencing documentations intersphinx_mapping = { "jinja2": ("https://jinja.palletsprojects.com/en/latest/", None), "pyramid": ("https://docs.pylonsproject.org/projects/pyramid/en/latest/", None), "pyramid_zcml": ( "https://docs.pylonsproject.org/projects/pyramid_zcml/en/latest/", None, ), "pytest": ("https://docs.pytest.org/en/latest/", None), } # 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_jinja2.tex", "pyramid_jinja2 Documentation", "Pylons Project 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 pyramid_jinja2-2.10.1/docs/glossary.rst000066400000000000000000000020341456106733600200340ustar00rootroot00000000000000.. _glossary: Glossary ======== .. glossary:: :sorted: Jinja2 A `templating system written by Armin Ronacher `_. Pyramid A `web framework `_. Configurator :py:class:`pyramid.config.Configurator` pyramid_jinja2 A set of bindings that make templates written for the :term:`Jinja2` templating system work under the :term:`Pyramid` web framework. Template Inheritance Allows you to build a base “skeleton” template that contains all the common elements of your site and defines blocks that child templates can override. See :ref:`Template Inheritance ` in the Jinja2 documentation. Asset Specification A string representing the path to a directory or file present in a Python module. See :ref:`Understanding Asset Specifications ` in the Pyramid documentation for more information. pyramid_jinja2-2.10.1/docs/index.rst000066400000000000000000000571151456106733600173120ustar00rootroot00000000000000============== pyramid_jinja2 ============== .. _overview: Overview ======== :term:`pyramid_jinja2` is a set of bindings that make templates written for the :term:`Jinja2` templating system work under the :term:`Pyramid` web framework. .. _installation: Installation ============ Install using ``pip``, where ``$VENV`` is the path to a virtual environment. .. code-block:: bash $ $VENV/bin/pip install pyramid_jinja2 .. _setup: Setup ===== .. note:: If you start a project from scratch, consider using the :ref:`project template ` which comes with a working setup and sensible defaults. There are multiple ways to make sure that ``pyramid_jinja2`` is active. All are completely equivalent: #) Use the :py:func:`~pyramid_jinja2.includeme` function via :py:meth:`~pyramid.config.Configurator.include`. .. code-block:: python config = Configurator() config.include("pyramid_jinja2") #) Add ``pyramid_jinja2`` to the list of your ``pyramid.includes`` in your :file:`.ini` settings file. .. code-block:: python pyramid.includes = pyramid_jinja2 #) If you use :ref:`pyramid_zcml:index` instead of imperative configuration, ensure that some ZCML file with an analogue of the following contents is executed by your Pyramid application: .. code-block:: xml Once activated in any of these ways, the following happens: #) Files with the :file:`.jinja2` extension are considered to be :term:`Jinja2` templates and a :class:`jinja2.Environment` is registered to handle this extension. #) The :func:`pyramid_jinja2.add_jinja2_renderer` directive is added to the :term:`Configurator` instance. #) The :func:`pyramid_jinja2.add_jinja2_search_path` directive is added to the :term:`Configurator` instance. #) The :func:`pyramid_jinja2.add_jinja2_extension` directive is added to the :term:`Configurator` instance. #) The :func:`pyramid_jinja2.get_jinja2_environment` directive is added to the :term:`Configurator` instance. Preparing for distribution -------------------------- If you want to make sure your :file:`.jinja2` template files are included in your package's source distribution (e.g., when using ``python setup.py sdist``), add ``*.jinja2`` to your :file:`MANIFEST.in`: .. code-block:: text recursive-include yourapp *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.jinja2 *.js *.html *.xml Usage ===== Once ``pyramid_jinja2`` has been activated, :file:`.jinja2` templates can be used by the Pyramid rendering system. When used as the ``renderer`` argument of a view, the view must return a Python ``dict`` which will be passed into the template as the set of available variables. Template Lookup Mechanisms -------------------------- There are several ways to configure ``pyramid_jinja2`` to find your templates. Asset Specifications ~~~~~~~~~~~~~~~~~~~~ Templates may always be defined using an :term:`asset specification`. These are strings which define an absolute location of the template relative to some Python package. For example ``myapp.views:templates/home.jinja2``. These specifications are supported throughout Pyramid and provide a fool-proof way to find any supporting assets bundled with your application. Here's an example view configuration which uses an :term:`asset specification`: .. code-block:: python :linenos: @view_config(renderer="mypackage:templates/foo.jinja2") def hello_world(request): return {"a": 1} Asset specifications have some significant benefits in Pyramid, as they can be fully overridden. An add-on package can ship with code that renders using asset specifications. Later, another package can externally override the templates without having to actually modify the add-on in any way. See :ref:`pyramid:overriding_assets_section` for more information. Caller-Relative Template Lookup ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ By default, templates are discovered relative to the caller's package. This means that if you define a view in a Python module, the templates would be found relative to the module's directory on the filesystem. Let's look at an example: .. code-block:: python :linenos: @view_config(renderer="templates/mytemplate.jinja2") def my_view(request): return {"foo": 1, "bar": 2} Imagine that the above code is in a ``myapp.admin.views`` module. The template would be relative to that module on the filesystem, as shown below: .. code-block:: text myapp |- __init__.py `- admin |- views.py `- templates |- base.jinja2 `- mytemplate.jinja2 Caller-relative lookup avoids naming collisions which can be common in a search path-based approach. A caller-relative template lookup is converted to a :term:`asset specification` underneath the hood. This means that it's almost always possible to override the actual template in an add-on package without having to fork the add-on itself. For example, the full asset specification for the view above would be ``myapp.admin.views:templates/mytemplate.jinja2``. This template, or the entire ``templates`` folder, may be overridden. .. code-block:: python config.override_asset( to_override="myapp.admin.views:templates/mytemplate.jinja2", override_with="yourapp:templates/sometemplate.jinja2", ) See :ref:`pyramid:overriding_assets_section` for more information. Search Path-Based Template Lookup ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When used outside of Pyramid, Jinja2's default lookup mechanism is a search path. To use a search path within Pyramid, simply define the ``jinja2.directories`` configuration setting, or use the :func:`~pyramid_jinja2.add_jinja2_search_path` configurator directive. Rendering :term:`Jinja2` templates with a search path is typically done as follows: .. code-block:: python @view_config(renderer="mytemplate.jinja2") def my_view(request): return {"foo": 1, "bar": 2} If ``mytemplate.jinja2`` is not found in the same directory as the module, then it will be searched for on the search path. We are now dependent on our configuration settings to tell us where the template may be located. Commonly a ``templates`` directory is created at the base of the package and the configuration file will include the following directive: .. code-block:: python jinja2.directories = mypkg:templates .. warning:: It is possible to specify a relative path to the templates folder, such as ``jinja2.directories = templates``. This folder will be found relative to the first package that includes ``pyramid_jinja2``, which will normally be the root of your application. It is always better to be explicit when in doubt. .. note:: The package that includes ``pyramid_jinja2`` will always be added to the search path (in most cases this is the top-level package in your application). This behavior may be deprecated or removed in the future. It is always better to specify your search path explicitly. Templates Including Templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :term:`Jinja2` allows :term:`template inheritance` as well as other mechanisms for templates to load each other. The lookup mechanisms supported in these cases include asset specifications, template-relative names, and normal template names found on the search path. The search path will always be consulted if a template cannot be found relative to the parent template. For example, if you had a template named ``templates/child.jinja2`` that wanted to extend ``templates/base.jinja2``, then it could use ``{% extends "base.jinja2" %}`` and locate the file relative to itself. Alternatively it could use ``{% extends "templates/base.jinja2" %}`` to find the template in a ``templates`` sub-folder rooted on the search path. The template-relative option will always override the search path. An example: .. code-block:: html+django :linenos: Hello World!
{% block content %}{% endblock %}
.. code-block:: html+django :linenos: {% extends "templates/layout.jinja2" %} {% block content %}

Yes

Some random paragraph.

{% endblock %} For further information on :term:`Template Inheritance` in Jinja2 templates please see :ref:`Template Inheritance ` in Jinja2 documentation. Adding or Overriding a Renderer ------------------------------- By default, only templates ending in the ``.jinja2`` file extension are supported. However, it is very easy to add support for alternative file extensions using the :func:`pyramid_jinja2.add_jinja2_renderer` directive. .. code-block:: python config.include("pyramid_jinja2") config.add_jinja2_renderer(".html") It would now be possible to use templates named ``foo.html`` and ``foo.jinja2``. Each renderer extension will use its own :class:`jinja2.Environment`. These alternative renderers can be extended at runtime using the ``name`` parameter to the other directives such as :func:`pyramid_jinja2.get_jinja2_environment`. .. code-block:: python config.include("pyramid_jinja2") config.add_jinja2_renderer(".html") config.add_jinja2_search_path("myapp:templates", name=".html") It is also possible to set up different renderers that use different search paths, configuration settings, and environments if necessary. This technique can come in handy when different defaults are required for rendering templates with different content types. For example, a plain text email body versus an HTML page. For this reason, :func:`pyramid_jinja2.add_jinja2_renderer` accepts an optional parameter ``settings_prefix`` which can point a renderer at a different group of settings. .. code-block:: python settings = { "jinja2.directories": "myapp:html_templates", "mail.jinja2.directories": "myapp:email_templates", } config = Configurator(settings=settings) config.include("pyramid_jinja2") config.add_jinja2_renderer(".email", settings_prefix="mail.jinja2.") Now ``foo.email`` will be rendered using the ``mail.jinja2.*`` settings. Internalization (i18n) ---------------------- When :term:`pyramid_jinja2` is included in a Pyramid application, either :ref:`jinja2.ext.i18n ` or the extension configured by ``jinja2.i18n_extension`` is automatically activated. Be sure to configure ``jinja2.i18n.domain`` according to ``setup.cfg`` domain settings. By default, ``jinja2.i18n.domain`` is set to the name of the package that included ``pyramid_jinja2``. If no package was found, it will use ``messages``. .. _settings: Settings ======== :term:`Jinja2` derives additional settings to configure its template renderer. Many of these settings are optional and only need to be set if they should be different from the default. The below values can be present in the :file:`.ini` file used to configure the Pyramid application (in the ``app`` section representing your Pyramid app) or they can be passed directly within the ``settings`` argument passed to a Pyramid Configurator. Generic Settings ---------------- These settings correspond to the ones documented in Jinja2. Set them accordingly. For reference please see: http://jinja.pocoo.org/docs/api/#high-level-api .. note:: For the boolean settings, use ``true`` or ``false``. jinja2.block_start_string jinja2.block_end_string jinja2.variable_start_string jinja2.variable_end_string jinja2.comment_start_string jinja2.comment_end_string jinja2.line_statement_prefix jinja2.line_comment_prefix jinja2.trim_blocks jinja2.newline_sequence jinja2.optimized jinja2.cache_size jinja2.autoescape ----------------- Jinja2 autoescape setting. Possible values: ``true`` or ``false``. .. warning:: By default Jinja2 sets ``autoescape`` to ``False``. pyramid_jinja2 sets it to ``True`` as it is considered a good security practice in a web setting where we want to prevent XSS attacks from rendering unsanitized user-generated content. To turn off escaping on a case-by-case basis, you may use the ``safe`` filter such as ``{{ html_blob|safe }}``. .. _setting_reload_templates: pyramid.reload_templates ------------------------ For usage see :ref:`Pyramid: Automatically Reloading Templates `. ``True`` or ``False`` represent whether Jinja2 templates should be reloaded when they change on disk. In development, it is useful to set it to ``True``. This setting sets the Jinja2 ``auto_reload`` setting. reload_templates ---------------- .. warning:: Deprecated as of version 1.5, use :ref:`setting_reload_templates` instead. .. _setting_jinja2_autoreload: jinja2.auto_reload ------------------ Use Pyramid :ref:`setting_reload_templates` setting. .. _setting_jinja2_directories: jinja2.directories ------------------ A list of directory names, or a newline-delimited string, where each line represents a directory name. These locations are where Jinja2 will search for templates. Each can optionally be an absolute resource specification (e.g., ``package:subdirectory/``). .. _setting_jinja2_input_encoding: jinja2.input_encoding --------------------- The input encoding of templates. Defaults to ``utf-8``. .. _setting_jinja2_undefined: jinja2.undefined ---------------- Changes the undefined types that are used when a variable name lookup fails. If unset, defaults to :py:class:`~jinja2.Undefined` (silent ignore). Setting it to ``strict`` will trigger :py:class:`~jinja2.StrictUndefined` behavior (which raises an error, and is recommended for development). Setting it to ``debug`` will trigger :py:class:`~jinja2.DebugUndefined`, which outputs debug information in some cases. See `Undefined Types `_. .. _setting_jinja2_extensions: jinja2.extensions ----------------- A list of extension objects, or a newline-delimited set of dotted import locations, where each line represents an extension. Either :ref:`jinja2.ext.i18n ` or the i18n extension configured using ``jinja2.i18n_extension`` is automatically activated. .. _setting_jinja2_i18n_extension: jinja2.i18n_extension --------------------- The name of the i18n extension to activate. Defaults to :ref:`jinja2.ext.i18n `. .. _setting_jinja2_i18n_domain: jinja2.i18n.domain ------------------ Pyramid domain for translations. See :term:`pyramid:Translation Domain` in the Pyramid documentation. Defaults to the name of the package that activated `pyramid_jinja2` or if that fails it will use ``messages`` as the domain. .. _setting_jinja2_i18n_gettext: jinja2.i18n.gettext ------------------- A subclass of :class:`pyramid_jinja2.i18n.GetTextWrapper` to override ``gettext`` and ``ngettext`` methods in Jinja i18n extension. The Subclass can be either a dotted name or the subclass itself. .. _setting_jinja2_filers: jinja2.filters -------------- A dictionary mapping a filter name to a filter object, or a newline-delimited string with each line in the format: .. code-block:: python name = dotted.name.to.filter representing :ref:`Jinja2 filters `. .. _setting_jinja2_globals: jinja2.globals -------------- A dictionary mapping a global name to a global template object, or a newline-delimited string with each line in the format: .. code-block:: python name = dotted.name.to.globals representing :ref:`Jinja2 globals ` .. _setting_jinja2_tests: jinja2.tests ------------ A dictionary mapping a test name to a test object, or a newline-delimited string with each line in the format: .. code-block:: python name = dotted.name.to.test representing :ref:`Jinja2 tests `. .. _setting_jinja2_byte_cache: jinja2.bytecode_caching ----------------------- If set to ``true``, a file system bytecode cache will be configured in a directory determined by :ref:`setting_jinja2_byte_cache_dir`. To configure other types of bytecode caching, ``jinja2.bytecode_caching`` may also be set directly to an instance of :class:`jinja2.BytecodeCache`. However doing so cannot be done in a paste ``.ini`` file and it must be done programmatically. By default, no bytecode cache is configured. .. versionchanged:: 1.10 Previously, ``jinja2.bytecode_caching`` defaulted to ``true``. Note that configuring a filesystem bytecode cache will (not surprisingly) generate files in the cache directory. As templates are changed, some of these will become stale, pointless wastes of disk space. You are advised to consider a clean up strategy (such as a cron job) to check for and remove such files. See the :ref:`Jinja2 Documentation ` for more information on bytecode caching. .. versionchanged:: 1.10 Previously, an ``atexit`` callback which called :py:meth:`jinja2.BytecodeCache.clear` was registered in an effort to delete the cache files. This is no longer done. .. _setting_jinja2_byte_cache_dir: jinja2.bytecode_caching_directory --------------------------------- Absolute path to directory to store bytecode cache files. Defaults to the system temporary directory. This is only used if ``jinja2.bytecode_caching`` is set to ``true``. .. _setting_jinja2_newstyle: jinja2.newstyle --------------- ``true`` or ``false`` to enable the use of ``newstyle`` ``gettext`` calls. Defaults to ``false``. See :ref:`jinja2:newstyle-gettext`. .. _setting_jinja2_finalize: jinja2.finalize --------------- A callable or a dotted-import string. .. _jinja2_filters: Jinja2 Filters ============== ``pyramid_jinja2`` comes with Pyramid routing specific filters. All Jinja2 built-in filters are enabled in templates. Read how :ref:`jinja2:filters` work in Jinja2. Installing filters ------------------ To use these filters, configure the settings of ``jinja2.filters``: .. code-block:: ini :linenos: [app:yourapp] # ... other stuff ... jinja2.filters = model_url = pyramid_jinja2.filters:model_url_filter route_url = pyramid_jinja2.filters:route_url_filter static_url = pyramid_jinja2.filters:static_url_filter Filter reference ---------------- .. currentmodule:: pyramid_jinja2.filters .. autofunction:: resource_url_filter .. autofunction:: model_url_filter .. autofunction:: route_url_filter .. autofunction:: static_url_filter .. autofunction:: model_path_filter .. autofunction:: route_path_filter .. autofunction:: static_path_filter .. _jinja2_starter_template: Creating a Jinja2 Pyramid project ================================= After you have installed ``pyramid_jinja2``, you can invoke the following command to create a Jinja2-based Pyramid project from its included scaffold. .. code-block:: bash $ $VENV/bin/pcreate -s pyramid_jinja2_starter myproject After it's created, you can visit the ``myproject`` directory and install the project in development mode. .. code-block:: bash $ cd myproject $ $VENV/bin/pip install -e . At this point you can start the application like any other Pyramid application. .. code-block:: bash $ $VENV/bin/pserve development.ini This is a good way to see a working Pyramid application that uses Jinja2, even if you do not end up using the result. .. seealso:: See also :ref:`pyramid:project_narr`. Running tests for your application ---------------------------------- The scaffold provides a convenience for the developer to install ``pytest`` and ``pytest-cov`` as the test runner and test coverage. To run unit tests for your application, you must first install the testing dependencies. .. code-block:: bash $ $VENV/bin/pip install -e ".[testing]" Once the testing requirements are installed, then you can run the tests using the ``py.test`` command that was just installed in the ``bin`` directory of your virtual environment. The ``-q`` option means "quiet" output, and the ``--cov`` option includes test coverage. .. code-block:: bash $ $VENV/bin/py.test -q --cov The scaffold includes configuration defaults for ``py.test`` and test coverage. These configuration files are ``pytest.ini`` and ``.coveragerc``, located at the root of your package. Without these defaults, we would need to specify the path to the module on which we want to run tests and coverage. .. code-block:: bash $ $VENV/bin/py.test -q --cov=myproject myproject/tests.py .. seealso:: See py.test's documentation for :ref:`pytest:usage` or invoke ``py.test -h`` to see its full set of options. pcreate template i18n --------------------- The pcreate template automatically sets up pot/po/mo locale files for use with the generated project. The usual pattern for working with i18n in pyramid_jinja2 is as follows: .. code-block:: bash # make sure Babel is installed $ $VENV/bin/pip install Babel # extract translatable strings from *.jinja2 / *.py $ $VENV/bin/python setup.py extract_messages $ $VENV/bin/python setup.py update_catalog # Translate strings in /locale//LC_MESSAGES/.po # and re-compile *.po files $ $VENV/bin/python setup.py compile_catalog If you see the following output: .. code-block:: text running compile_catalog 1 of 1 messages (100%) translated in myproject/locale/de/LC_MESSAGES/myproject.po catalog myproject/locale/de/LC_MESSAGES/myproject.po is marked as fuzzy, skipping 1 of 1 messages (100%) translated in myproject/locale/fr/LC_MESSAGES/myproject.po catalog myproject/locale/fr/LC_MESSAGES/myproject.po is marked as fuzzy, skipping When an item is marked as fuzzy, then you should review your `.po` files to make sure translations are correct. Fuzzy is not exact matching, but matches most of a word (its root) or phrase. When you are satisfied that the translations are good, you can either remove the line marked with `#, fuzzy` immediately above its related `msgid` line (preferred) or force Babel to compile the message catalog with the `-f` flag. .. code-block:: bash $ $VENV/bin/python setup.py compile_catalog -f Assuming you have already created a project following the instructions under :ref:`jinja2_starter_template`, and started your application with ``pserve``, then you should be able to view the various translations. Simply append a GET parameter, such as http://localhost:6543/?_LOCALE_=de for German, http://localhost:6543/?_LOCALE_=fr for French, or http://localhost:6543/?_LOCALE_=en for English. The default language does not require GET parameter. The application could set the user's language preference with a cookie based on request parameters sent on the first request. Alternatively, and usually as a fallback, the application could read the web browser's `Accept-Language` header sent with each request and set the appropriate language. For example: .. code-block:: python @subscriber(NewRequest) def prepare_env(event): request = event.request # set locale depending on browser settings settings = request.registry.settings locale = settings.get("pyramid.default_locale_name", "en") available = [loc["code"] for loc in AVAILABLE_LOCALES] if request.accept_language: accepted = request.accept_language locale = accepted.best_match(available, locale) request._LOCALE_ = locale More Information ================ .. toctree:: :maxdepth: 1 api.rst changes.rst glossary.rst Reporting Bugs / Development Versions ===================================== Visit https://github.com/Pylons/pyramid_jinja2 to download development or tagged versions. Visit https://github.com/Pylons/pyramid_jinja2/issues to report bugs. Indices and tables ------------------ * :ref:`glossary` * :ref:`genindex` * :ref:`modindex` * :ref:`search` pyramid_jinja2-2.10.1/pyproject.toml000066400000000000000000000007621456106733600174310ustar00rootroot00000000000000[build-system] requires = ["setuptools >= 41"] build-backend = "setuptools.build_meta" [tool.black] target-version = ['py37', 'py38', 'py39', 'py310'] exclude = ''' /( \.git | .tox )/ ''' [tool.isort] profile = "black" multi_line_output = 3 src_paths = ["src", "tests"] skip_glob = ["docs/*"] include_trailing_comma = true force_grid_wrap = false combine_as_imports = true line_length = 88 force_sort_within_sections = true default_section = "THIRDPARTY" known_first_party = "pyramid_jinja2" pyramid_jinja2-2.10.1/setup.cfg000066400000000000000000000037261456106733600163410ustar00rootroot00000000000000[metadata] name = pyramid_jinja2 version = 2.10.1 description = Jinja2 template bindings for the Pyramid web framework long_description = file: README.rst, CHANGES.rst long_description_content_type = text/x-rst keywords = web wsgi pylons pyramid jinja2 license = BSD-derived (Repoze) license_files = LICENSE.txt classifiers = Development Status :: 6 - Mature Intended Audience :: Developers Programming Language :: Python Programming Language :: Python :: 3 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 Programming Language :: Python :: 3.12 Framework :: Pyramid License :: Repoze Public License url = https://github.com/Pylons/pyramid_jinja2 project_urls = Documentation = https://docs.pylonsproject.org/projects/pyramid_jinja2/en/latest/ Changelog = https://github.com/Pylons/pyramid_jinja2/blob/main/CHANGES.rst Issue Tracker = https://github.com/Pylons/pyramid_jinja2/issues author = Rocky Burt author_email = pylons-discuss@googlegroups.com maintainer = Pylons Project maintainer_email = pylons-discuss@googlegroups.com [options] package_dir= =src packages = find_namespace: include_package_data = True python_requires = >=3.7.0 install_requires = jinja2>=2.5.0,!=2.11.0,!=2.11.1,!=2.11.2 markupsafe pyramid>=1.3.0 # pyramid.path.DottedNameResolver zope.deprecation [options.packages.find] where = src [options.entry_points] pyramid.scaffold = pyramid_jinja2_starter = pyramid_jinja2.scaffolds:Jinja2ProjectTemplate [options.extras_require] testing = webtest coverage pytest>=5.4.2 pytest-cov docs = setuptools # needed for pkg_resources in conf.py pylons-sphinx-themes >= 0.3 sphinx>=1.7.5 [check-manifest] ignore-bad-ideas = *.mo [tool:pytest] python_files = test_*.py testpaths = demo tests addopts = -W always --cov pyramid_jinja2-2.10.1/setup.py000066400000000000000000000000461456106733600162220ustar00rootroot00000000000000from setuptools import setup setup() pyramid_jinja2-2.10.1/src/000077500000000000000000000000001456106733600152775ustar00rootroot00000000000000pyramid_jinja2-2.10.1/src/pyramid_jinja2/000077500000000000000000000000001456106733600202015ustar00rootroot00000000000000pyramid_jinja2-2.10.1/src/pyramid_jinja2/__init__.py000066400000000000000000000404341456106733600223170ustar00rootroot00000000000000import inspect import os import posixpath import sys from jinja2 import Environment as _Jinja2Environment from jinja2.exceptions import TemplateNotFound from jinja2.loaders import FileSystemLoader from jinja2.utils import open_if_exists from pyramid.path import AssetResolver, DottedNameResolver from zope.deprecation import deprecated from zope.interface import Interface from .settings import ( parse_env_options_from_settings, parse_loader_options_from_settings, parse_multiline, ) ENV_CONFIG_PHASE = 0 EXTRAS_CONFIG_PHASE = 1 PARENT_RELATIVE_DELIM = "@@FROM_PARENT@@" class IJinja2Environment(Interface): pass class Environment(_Jinja2Environment): def join_path(self, uri, parent): if os.path.isabs(uri) or ":" in uri: # we have an asset spec or absolute path return uri # uri may be relative to the parent, shuffle it through to the loader return uri + PARENT_RELATIVE_DELIM + parent class FileInfo(object): open_if_exists = staticmethod(open_if_exists) getmtime = staticmethod(os.path.getmtime) def __init__(self, filename, encoding="utf-8"): self.filename = filename self.encoding = encoding def _delay_init(self): if "_mtime" in self.__dict__: return f = self.open_if_exists(self.filename) if f is None: raise TemplateNotFound(self.filename) self._mtime = self.getmtime(self.filename) try: data = f.read() finally: f.close() if not isinstance(data, str): data = data.decode(self.encoding) self._contents = data @property def contents(self): self._delay_init() return self._contents @property def mtime(self): self._delay_init() return self._mtime def uptodate(self): try: return os.path.getmtime(self.filename) == self.mtime except OSError: return False class _PackageFinder(object): inspect = staticmethod(inspect) def caller_package(self, excludes=()): """A list of excluded patterns, optionally containing a `.` suffix. For example, ``'pyramid.'`` would exclude exclude ``'pyramid.config'`` but not ``'pyramid'``. """ f = None for t in self.inspect.stack(): f = t[0] name = f.f_globals.get("__name__") if name: excluded = False for pattern in excludes: if pattern[-1] == "." and name.startswith(pattern): excluded = True break elif name == pattern: excluded = True break if not excluded: break if f is None: return None pname = f.f_globals.get("__name__") or "__main__" m = sys.modules[pname] f = getattr(m, "__file__", "") if ("__init__.py" in f) or ("__init__$py" in f): # empty at >>> return m pname = m.__name__.rsplit(".", 1)[0] return sys.modules[pname] _caller_package = _PackageFinder().caller_package class SmartAssetSpecLoader(FileSystemLoader): """A Jinja2 template loader that knows how to handle asset specifications. """ def __init__(self, searchpath=(), encoding="utf-8", debug=False): FileSystemLoader.__init__(self, searchpath, encoding) self.debug = debug def list_templates(self): raise TypeError("this loader cannot iterate over all templates") def _get_absolute_source(self, template): filename = AssetResolver().resolve(template).abspath() fi = FileInfo(filename, self.encoding) if os.path.isfile(fi.filename): return fi.contents, fi.filename, fi.uptodate def _relative_searchpath(self, chain): """Combine paths in the chain to construct search paths. The precedence is for the most-specific paths to be tested first, anchored at an absolute path or asset spec. From there, less-specific paths are tested. For example:: chain = [ '../forms.jinja2', 'sub/nav.jinja2', 'base.jinja2', 'myapp:templates/index.jinja2', ] searchpath = ['myapp:templates/sub/..', 'sub/..', '..', ''] """ # the initial empty string is important because not only does it allow # the stack to always contain something join, but it allows the # later for-loops to fallback to the original search path by # joining to an empty string since os.path.join('', 'foo') == 'foo' stack = [""] for path in chain: is_abspath = os.path.isabs(path) is_spec = not is_abspath and ":" in path if not is_abspath and is_spec: ppkg, ppath = path.split(":", 1) path = "{0}:{1}".format(ppkg, posixpath.dirname(ppath)) else: # this should split windows and posix paths path = os.path.dirname(path) if not path: # skip empty directories continue subpath = stack[-1] path = posixpath.join(path, subpath) stack.append(path) # do not continue further, all paths are relative to this if is_abspath or is_spec: break return list(reversed(stack)) def get_source(self, environment, template): # keep legacy asset: prefix checking that bypasses # source path checking altogether if template.startswith("asset:"): template = template[6:] # split the template into the chain of relative-imports rel_chain = template.split(PARENT_RELATIVE_DELIM) template, rel_chain = rel_chain[0], rel_chain[1:] # load the template directly if it's an absolute path or asset spec if os.path.isabs(template) or ":" in template: src = self._get_absolute_source(template) if src is not None: return src else: # fallback to the search path just incase return FileSystemLoader.get_source(self, environment, template) # try to import the template as an asset spec or absolute path # relative to its parents rel_searchpath = self._relative_searchpath(rel_chain) for parent in rel_searchpath: if os.path.isabs(parent): uri = os.path.join(parent, template) # avoid recursive includes if uri not in rel_chain: src = self._get_absolute_source(uri) if src is not None: return src # avoid doing "':' in" and then redundant "split" parts = parent.split(":", 1) if len(parts) > 1: # parent is an asset spec ppkg, ppath = parts ppath = posixpath.join(ppath, template) uri = "{0}:{1}".format(ppkg, ppath) # avoid recursive includes if uri not in rel_chain: src = self._get_absolute_source(uri) if src is not None: return src # try to load the template from the default search path for parent in rel_searchpath: try: uri = os.path.join(parent, template) # avoid recursive includes if uri not in rel_chain: return FileSystemLoader.get_source(self, environment, uri) except TemplateNotFound: pass # we're here because of an exception during the last step so extend # the message and raise an appropriate error # there should always be an exception because the rel_searchpath is # guaranteed to contain at least one element ('') searchpath = [p for p in rel_searchpath if p] + self.searchpath message = "{0}; searchpath={1}".format(template, searchpath) raise TemplateNotFound(name=template, message=message) class Jinja2TemplateRenderer(object): """Renderer for a jinja2 template""" def __init__(self, template_loader): self.template_loader = template_loader def __call__(self, value, system): try: system.update(value) except (TypeError, ValueError) as ex: raise ValueError( "renderer was passed non-dictionary " "as value: %s" % str(ex) ) template = self.template_loader() return template.render(system) class Jinja2RendererFactory(object): environment = None def __call__(self, info): name, package = info.name, info.package def template_loader(): # attempt to turn the name into a caller-relative asset spec if ":" not in name and package is not None: try: name_with_package = "%s:%s" % (package.__name__, name) return self.environment.get_template(name_with_package) except TemplateNotFound: pass return self.environment.get_template(name) return Jinja2TemplateRenderer(template_loader) def renderer_factory(info): registry = info.registry env = registry.queryUtility(IJinja2Environment, name=".jinja2") if env is None: raise ValueError( "As of pyramid_jinja2 2.3, the use of the " '"pyramid_jinja2.renderer_factory" requires that pyramid_jinja2 ' 'be configured via config.include("pyramid_jinja2") or the ' 'equivalent "pyramid.includes" setting.' ) factory = Jinja2RendererFactory() factory.environment = env return factory(info) deprecated( "renderer_factory", "The pyramid_jinja2.renderer_factory was deprecated in version 2.0 and " "will be removed in the future. You should upgrade to the newer " "config.add_jinja2_renderer() API.", ) def add_jinja2_search_path(config, searchpath, name=".jinja2", prepend=False): """ This function is added as a method of a :term:`Configurator`, and should not be called directly. Instead it should be called like so after ``pyramid_jinja2`` has been passed to ``config.include``: .. code-block:: python config.add_jinja2_search_path('anotherpackage:templates/') It will add the directory or :term:`asset specification` passed as ``searchpath`` to the current search path of the :class:`jinja2.Environment` used by the renderer identified by ``name``. By default the path is appended to the end of the search path. If ``prepend`` is set to ``True`` then the path will be inserted at the start of the search path. """ def register(): env = get_jinja2_environment(config, name) searchpaths = parse_multiline(searchpath) resolve = AssetResolver(config.package).resolve for folder in searchpaths: path = resolve(folder).abspath() if prepend: env.loader.searchpath.insert(0, path) else: env.loader.searchpath.append(path) config.action(None, register, order=EXTRAS_CONFIG_PHASE) def add_jinja2_extension(config, ext, name=".jinja2"): """ This function is added as a method of a :term:`Configurator`, and should not be called directly. Instead it should be called like so after ``pyramid_jinja2`` has been passed to ``config.include``: .. code-block:: python config.add_jinja2_extension(myext) It will add the Jinja2 extension passed as ``ext`` to the current :class:`jinja2.Environment` used by the renderer named ``name``. """ ext = config.maybe_dotted(ext) def register(): env = get_jinja2_environment(config, name) env.add_extension(ext) config.action(None, register, order=EXTRAS_CONFIG_PHASE) def get_jinja2_environment(config, name=".jinja2"): """ This function is added as a method of a :term:`Configurator`, and should not be called directly. Instead it should be called like so after ``pyramid_jinja2`` has been passed to ``config.include``: .. code-block:: python config.get_jinja2_environment() It will return the configured ``jinja2.Environment`` for the renderer named ``name``. The environment is created as an :term:`action` which is deferred to allow users to override the configuration. In order to get back the configured environment, you must either force a commit via ``config.commit`` or schedule an action which can setup the environment after it has been created: .. code-block:: python def setup_jinja2_env(): env = config.get_jinja2_environment() # ... config.action(None, setup_jinja2_env, order=999) """ registry = config.registry return registry.queryUtility(IJinja2Environment, name=name) def create_environment_from_options(env_opts, loader_opts): loader = SmartAssetSpecLoader(**loader_opts) newstyle = env_opts.pop("newstyle", False) gettext = env_opts.pop("gettext", None) filters = env_opts.pop("filters", {}) tests = env_opts.pop("tests", {}) globals = env_opts.pop("globals", {}) env = Environment(loader=loader, **env_opts) env.install_gettext_callables(gettext.gettext, gettext.ngettext, newstyle=newstyle) env.filters.update(filters) env.tests.update(tests) env.globals.update(globals) return env def add_jinja2_renderer(config, name, settings_prefix="jinja2.", package=None): """ This function is added as a method of a :term:`Configurator`, and should not be called directly. Instead it should be called like so after ``pyramid_jinja2`` has been passed to ``config.include``: .. code-block:: python config.add_jinja2_renderer('.html', settings_prefix='jinja2.') It will register a new renderer, loaded from settings at the specified ``settings_prefix`` prefix. This renderer will be active for files using the specified extension ``name``. """ renderer_factory = Jinja2RendererFactory() config.add_renderer(name, renderer_factory) package = package or config.package resolver = DottedNameResolver(package=package) def register(): registry = config.registry settings = config.get_settings() loader_opts = parse_loader_options_from_settings( settings, settings_prefix, resolver.maybe_resolve, package, ) env_opts = parse_env_options_from_settings( settings, settings_prefix, resolver.maybe_resolve, package, ) env = create_environment_from_options(env_opts, loader_opts) renderer_factory.environment = env registry.registerUtility(env, IJinja2Environment, name=name) config.action(("jinja2-renderer", name), register, order=ENV_CONFIG_PHASE) def includeme(config): """Set up standard configurator registrations. Use via: .. code-block:: python config = Configurator() config.include('pyramid_jinja2') Once this function has been invoked, the ``.jinja2`` renderer is available for use in Pyramid and these new directives are available as methods of the configurator: - ``add_jinja2_renderer``: Add a new Jinja2 renderer, with a different file extension and/or settings. - ``add_jinja2_search_path``: Add a new location to the search path for the specified renderer. - ``add_jinja2_extension``: Add a list of extensions to the Jinja2 environment used by the specified renderer. - ``get_jinja2_environment``: Return the :class:`jinja2.Environment` used by the specified renderer. """ config.add_directive("add_jinja2_renderer", add_jinja2_renderer) config.add_directive("add_jinja2_search_path", add_jinja2_search_path) config.add_directive("add_jinja2_extension", add_jinja2_extension) config.add_directive("get_jinja2_environment", get_jinja2_environment) package = _caller_package(("pyramid", "pyramid.", "pyramid_jinja2")) config.add_jinja2_renderer(".jinja2", package=package) # always insert default search path relative to package default_search_path = "%s:" % (package.__name__,) config.add_jinja2_search_path(default_search_path, name=".jinja2") pyramid_jinja2-2.10.1/src/pyramid_jinja2/configure.zcml000066400000000000000000000003151456106733600230500ustar00rootroot00000000000000 pyramid_jinja2-2.10.1/src/pyramid_jinja2/filters.py000066400000000000000000000063531456106733600222320ustar00rootroot00000000000000from pyramid.threadlocal import get_current_request from pyramid.url import resource_url, route_path, route_url, static_path, static_url try: from jinja2 import pass_context except ImportError: # jinja2 < 3.0 fallback from jinja2 import contextfilter as pass_context __all__ = [ "resource_url_filter", "model_url_filter", "route_url_filter", "route_path_filter", "static_url_filter", "static_path_filter", ] @pass_context def resource_url_filter(ctx, model, *elements, **kw): """A filter from ``model`` to a string representing the absolute URL. This filter calls :py:func:`pyramid.url.resource_url`. Example:: See my object You can also specify optional view name attached at the end of a path:: Edit my object """ request = ctx.get("request") or get_current_request() return resource_url(model, request, *elements, **kw) @pass_context def model_url_filter(ctx, model, *elements, **kw): """A filter from ``model`` to a string representing the absolute URL. This filter calls :py:func:`pyramid.url.resource_url`. .. note :: This is being deprecated. See :py:func:`pyramid_jinja2.filters.resource_url` """ request = ctx.get("request") or get_current_request() return resource_url(model, request, *elements, **kw) @pass_context def model_path_filter(ctx, model, *elements, **kw): """A filter from ``model`` to a string representing the relative URL. This filter calls :py:meth:`pyramid.request.Request.resource_path`. """ request = ctx.get("request") or get_current_request() return request.resource_path(model, *elements, **kw) @pass_context def route_url_filter(ctx, route_name, *elements, **kw): """A filter from ``route_name`` to a string representing the absolute URL. This filter calls :py:func:`pyramid.url.route_url`. Example:: Sign in """ request = ctx.get("request") or get_current_request() return route_url(route_name, request, *elements, **kw) @pass_context def route_path_filter(ctx, route_name, *elements, **kw): """A filter from ``route_name`` to a string representing the relative URL. This filter calls :py:func:`pyramid.url.route_path`. """ request = ctx.get("request") or get_current_request() return route_path(route_name, request, *elements, **kw) @pass_context def static_url_filter(ctx, path, **kw): """A filter from ``path`` to a string representing the absolute URL. This filter calls :py:func:`pyramid.url.static_url`. Example:: """ request = ctx.get("request") or get_current_request() return static_url(path, request, **kw) @pass_context def static_path_filter(ctx, path, **kw): """A filter from ``path`` to a string representing the relative URL. This filter calls :py:func:`pyramid.url.static_path`. """ request = ctx.get("request") or get_current_request() return static_path(path, request, **kw) pyramid_jinja2-2.10.1/src/pyramid_jinja2/i18n.py000066400000000000000000000016261456106733600213370ustar00rootroot00000000000000from pyramid import i18n from pyramid.threadlocal import get_current_request class GetTextWrapper(object): """Implements `gettext` and `ngettext` functions for :meth:`jinja2.Environment.install_gettext_translations` """ def __init__(self, domain): self.domain = domain @property def localizer(self): request = get_current_request() try: return request.localizer except AttributeError: # pragma: nocover (pyramid < 1.5) return i18n.get_localizer(request) def gettext(self, message, mapping=None): """Implements jinja.ext.i18n `gettext` function""" return self.localizer.translate(message, domain=self.domain, mapping=mapping) def ngettext(self, singular, plural, n): """Implements jinja.ext.i18n `ngettext` function""" return self.localizer.pluralize(singular, plural, n, domain=self.domain) pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/000077500000000000000000000000001456106733600221455ustar00rootroot00000000000000pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/__init__.py000066400000000000000000000014571456106733600242650ustar00rootroot00000000000000try: # pragma: no cover (pyramid 1.0.X) # "pyramid.paster.paste_script_template_renderer" doesn't exist past 1.0.X from pyramid.paster import PyramidTemplate, paste_script_template_renderer except ImportError: # pragma: no cover try: # pragma: no cover (pyramid 1.1.X, 1.2.X) # trying to import "paste_script_template_renderer" fails on 1.3.X from pyramid.scaffolds import PyramidTemplate, paste_script_template_renderer except ImportError: # pragma: no cover (pyramid >=1.3a2) paste_script_template_renderer = None from pyramid.scaffolds import PyramidTemplate class Jinja2ProjectTemplate(PyramidTemplate): _template_dir = "jinja2_starter" summary = "Pyramid Jinja2 starter project" template_renderer = staticmethod(paste_script_template_renderer) pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/000077500000000000000000000000001456106733600250665ustar00rootroot00000000000000pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+dot+coveragerc_tmpl000066400000000000000000000000641456106733600310220ustar00rootroot00000000000000[run] source = {{package}} omit = {{package}}/test* pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/000077500000000000000000000000001456106733600266075ustar00rootroot00000000000000pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/__init__.py_tmpl000066400000000000000000000013761456106733600317630ustar00rootroot00000000000000from pyramid.config import Configurator from {{package}}.resources import get_root def main(global_config, **settings): """ This function returns a WSGI application. It is usually called by the PasteDeploy framework during ``paster serve``. """ settings = dict(settings) settings.setdefault('jinja2.i18n.domain', '{{project}}') config = Configurator(root_factory=get_root, settings=settings) config.add_translation_dirs('locale/') config.include('pyramid_jinja2') config.add_static_view('static', 'static') config.add_view('{{package}}.views.my_view', context='{{package}}.resources.MyResource', renderer="templates/mytemplate.jinja2") return config.make_wsgi_app() pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/locale/000077500000000000000000000000001456106733600300465ustar00rootroot00000000000000pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/locale/+project+.pot000066400000000000000000000011671456106733600323730ustar00rootroot00000000000000# Translations template for PROJECT. # Copyright (C) 2011 ORGANIZATION # This file is distributed under the same license as the PROJECT project. # FIRST AUTHOR , 2011. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2011-05-12 09:14-0330\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" msgid "Welcome to" msgstr "" pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/locale/de/000077500000000000000000000000001456106733600304365ustar00rootroot00000000000000pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/locale/de/LC_MESSAGES/000077500000000000000000000000001456106733600322235ustar00rootroot00000000000000+project+.mo000066400000000000000000000007141456106733600342770ustar00rootroot00000000000000pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/locale/de/LC_MESSAGES,<=DHello!Project-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2011-05-12 09:14-0430 PO-Revision-Date: 2011-05-12 10:12-0330 Last-Translator: FULL NAME Language-Team: de Plural-Forms: nplurals=2; plural=(n != 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 0.9.6 Hallo!+project+.po000066400000000000000000000012051456106733600342760ustar00rootroot00000000000000pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/locale/de/LC_MESSAGES# Translations template for PROJECT. # Copyright (C) 2011 ORGANIZATION # This file is distributed under the same license as the PROJECT project. # FIRST AUTHOR , 2011. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2011-05-12 09:14-0330\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" msgid "Welcome to" msgstr "Willkommen zum" pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/locale/fr/000077500000000000000000000000001456106733600304555ustar00rootroot00000000000000pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/locale/fr/LC_MESSAGES/000077500000000000000000000000001456106733600322425ustar00rootroot00000000000000+project+.mo000066400000000000000000000007151456106733600343170ustar00rootroot00000000000000pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/locale/fr/LC_MESSAGES,<=DHello!Project-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2011-05-12 09:14-0430 PO-Revision-Date: 2011-05-12 10:12-0330 Last-Translator: FULL NAME Language-Team: fr Plural-Forms: nplurals=2; plural=(n > 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 0.9.6 Bonjour!+project+.po000066400000000000000000000012031456106733600343130ustar00rootroot00000000000000pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/locale/fr/LC_MESSAGES# Translations template for PROJECT. # Copyright (C) 2011 ORGANIZATION # This file is distributed under the same license as the PROJECT project. # FIRST AUTHOR , 2011. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2011-05-12 09:14-0330\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" msgid "Welcome to" msgstr "Bienvenue au" pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/resources.py000066400000000000000000000001421456106733600311700ustar00rootroot00000000000000class MyResource(object): pass root = MyResource() def get_root(request): return root pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/static/000077500000000000000000000000001456106733600300765ustar00rootroot00000000000000pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/static/favicon.ico000066400000000000000000000025761456106733600322310ustar00rootroot00000000000000h( " A>;)'%+=420520;96 GDA/-+LHF+\XUt,BO/Vi531WSP+O--..-.QNK       #!!!!!!"   $$$$$$$$$$$$$$$$pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/static/pyramid-16x16.png000066400000000000000000000024471456106733600330430ustar00rootroot00000000000000PNG  IHDRatEXtSoftwareAdobe ImageReadyqe<#iTXtXML:com.adobe.xmp n#IDATxڌM(DQg2i$4Svb!e#dž`llD4PRfA$ % )Q$SgfWs7ν߹9Î6qXqʏb^LGyG_E` t-=^ @/Fw,.JûZY.+8|C1LCHr&c\B+T ΡfiXT#}*8F NgIХIpY'ȁj IDgMɥ'+:2e8^ Od@A><@6| ]peiP.0caAȸƠT ڨ9X8;3T0lS'}JIw3h1ᰊ!' jۯ1+S:wIENDB`pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/static/pyramid.png000066400000000000000000000311451456106733600322550ustar00rootroot00000000000000PNG  IHDRX AiCCPICC ProfileH wTSϽ7" %z ;HQIP&vDF)VdTG"cE b PQDE݌k 5ޚYg}׺PtX4X\XffGD=HƳ.d,P&s"7C$ E6<~&S2)212 "įl+ɘ&Y4Pޚ%ᣌ\%g|eTI(L0_&l2E9r9hxgIbטifSb1+MxL 0oE%YmhYh~S=zU&ϞAYl/$ZUm@O ޜl^ ' lsk.+7oʿ9V;?#I3eE妧KD d9i,UQ h A1vjpԁzN6p\W p G@ K0ށiABZyCAP8C@&*CP=#t] 4}a ٰ;GDxJ>,_“@FXDBX$!k"EHqaYbVabJ0՘cVL6f3bձX'?v 6-V``[a;p~\2n5׌ &x*sb|! ߏƿ' Zk! $l$T4QOt"y\b)AI&NI$R$)TIj"]&=&!:dGrY@^O$ _%?P(&OJEBN9J@y@yCR nXZOD}J}/G3ɭk{%Oחw_.'_!JQ@SVF=IEbbbb5Q%O@%!BӥyҸM:e0G7ӓ e%e[(R0`3R46i^)*n*|"fLUo՝mO0j&jajj.ϧwϝ_4갺zj=U45nɚ4ǴhZ ZZ^0Tf%9->ݫ=cXgN].[7A\SwBOK/X/_Q>QG[ `Aaac#*Z;8cq>[&IIMST`ϴ kh&45ǢYYF֠9<|y+ =X_,,S-,Y)YXmĚk]c}džjcΦ浭-v};]N"&1=xtv(}'{'IߝY) Σ -rqr.d._xpUەZM׍vm=+KGǔ ^WWbj>:>>>v}/avO8 FV> 2 u/_$\BCv< 5 ]s.,4&yUx~xw-bEDCĻHGKwFGEGME{EEKX,YFZ ={$vrK .3\rϮ_Yq*©L_wד+]eD]cIIIOAu_䩔)3ѩiB%a+]3='/40CiU@ёL(sYfLH$%Y jgGeQn~5f5wugv5k֮\۹Nw]m mHFˍenQQ`hBBQ-[lllfjۗ"^bO%ܒY}WwvwXbY^Ю]WVa[q`id2JjGէ{׿m>PkAma꺿g_DHGGu;776ƱqoC{P38!9 ҝˁ^r۽Ug9];}}_~imp㭎}]/}.{^=}^?z8hc' O*?f`ϳgC/Oϩ+FFGGόzˌㅿ)ѫ~wgbk?Jި9mdwi獵ޫ?cǑOO?w| x&mf2:Y~ pHYs  $iTXtXML:com.adobe.xmp 1 5 72 1 72 200 1 200 2014-01-03T20:01:68 Pixelmator 3.0 ћ7#IDATx ŕǣDpW6Q#&j1n!qfƸD$11ȸ/c&h\Q'(ʌ݈!AI\ \E]{oWuWu[:ԩSKsҳ* L-bŊt@ZfWYeE\y@h kÚF.v`+Fpsx<5P@,@O-)t+irӴ2 +RC9 thZÆ7rFTc@e*n_0G~_94BHQ٩E@,X}lZ;7v&KgA໰ֹUyIVޔʫ>-a_V5&U& 0_+Š+k#Еy#LmM^47ݲ-6\THT/Yω64υdzoσkAV4؟xRa*6=@-,`n*M't4O?&rz=~5)fNEMq ]v@듞D:' ΙeC>~ Y 3б)- eO9|@,'FAY=VX  qi /TO^H9y*0*++a2c:Ҕ qi O1,$=5L@];5yPIrc!`Fp0x*B ҩ(l@p43#|tFNO  3Aq_A}6P@Tm7݁Tѹ1 -@.QFG do* 8Gfo ee΢Fln @x H;/ j ղvC{\휔IZ㤯6*@zP>gPF Wr-PVWdyŬ!W% j%BVF̳"4|]^d(;NEh SS'ę)Q@~Ytt]@8&`J:˾JAwvhž1ߝ C@v2)ArZ5Qi}r[ *:$zHk> (DOhp2h <˱bOhS'uU@)軜kfds&85}*F8pPM&!y,@ELIWy;ĶeUc&0!mVC hz,+W4F BUc`KK8:%Tup6K:Q<0+D R1[faSRø:_+v`HJ?D%,^QO 5Pz+=@G=`M"]]ߌM@*M@%=ZzkfSYr}R!zwBO}`V\:yVCID:ek w~/  Qrl^WQlBmN; >@49-*gbU} <=8er\L]Dmq*S$j&BB1hl4yW}q.=&!i2M.KiN`J'\sfAh,HI(q7yƶD! 'J&=0*K͍j T 5ӻ\d*qozaveϿHh0 y [&>#5Z)^Jo`<r1&'S#j`?Q}y P9GRZ7ξ6|KqI$YZOH^k VA֓:x+Z蛦#@Oh#Q2z{]Zo4PՐ~ L=1UVAKWmEsܽc7]:$Ӏ[s ւ- '\r@0&^Ē -oD˪ET|՛3W|uIRy}9LvjMT"(J̀NELbHyvT%Ai|&R7{A,ױvE$G;zvM MRxiSPz hߊ/QۡOr!Kt9 LvG՝Wo5]ՕҾ>`u_5ޛ@n t4n1!A힨ۑ*Qym ˣqLÓ@n ݆NĞW$ݎ&HEŗg P շ_zVK`b1kq Y`Q|hhB;WvB[-~q2ZM, Qhs1~<6cW79TL$74 +(4$ʤ#z*4H=g?u1fur?b[Ԍ<,JWXcfGDLT-kg}Utfc1O( !]I[w7zdfA=! +Jbn@뀢A"4L]5s!4!2hN++:դAIE3"!C0r].,ҢTE6 ~u"-? Md"Mp5g {,Co!P 07Zno}Tio5=&8)|׋‚2Ei&GM&L%!Eט q>=9ʨÇIÈZ>Ҙ r`M@ZU nffeAZy !Hx-q_JF,4ɮGAm@ /ը' >[NPO„QmJBxϷAic"qȏWMV#< ԜҦl!{QM$%\PMAl ]S,2|1q_7LQj1"iLͼ7+mKzj^or2Ou2^ &!n} #8Fw N>Ҝ?* Dg* "Jk%xi["6T`0l$' d.ՊTW+F GLB'I\I0ȥ<*ӓ UoYwl0hUói},Rhq!@ u@a !'4R|0?P[^tzX? HG?e@] AG0-;!KWA@ rT>@ #&!Z$S3#(e49B,@qG#ڨ8:4M`*WGp7%JC0(3@ 8qX 5 @Xv-d0N#n( :2I'taZ \"4*R7@Bv}_]x{nˣ0 I{x,gw;u(}=/`K HvLpr=hAX& RdGyp?} Q2}RQRzۥAw\zuj%32ej@AD5VWKq&Zqv@{7H-dCAT.?GͰ%^-} ;אSɇ{:<$L]7#"eI0 ٠ճzǀ\QҌ667Lf&Ȩ>Sp_+a2?]W{zXzc 89 \j}EJz Ti %˱uYGT7zKSIإdTa6z( -q3,1dHjӠrv]ZpR _CڪgZ򕻶]7+I~1mjW%)izHlR w${ 8lQ+Bڗ0T-mWCMSC]v):@ݸ/Q@2z{Jk<~\[5cwW,݀O,yM/H/vOJNS 7޴<{? kF,1No _/ vt3w4AZ U-SOvG ݙC ۃ "@xGpY(:Z^'zB +%*ON^]D'0A@6-HϢ@>v>@3PBKW2'~<Ԋ\jL1]Gzk˜ADml'v8@l((x" fpc%#3/t 㪑SoUvC egಁյE&.}҇0%*b}%s,/t8_PTb\XQ)y}qMQU} gY+Pj ]o-##}V"SP~D #o+bF̖5T%4bLo"ݱ-{.AJJ֢,Yic4S^-J D<қ(B Tr ~ҊWsVΉ9Lq2IXs #6J}GԉJ$+zi2KTz(Չtzh\U7,cW51@d<(^T^uơY%@S`cVDwHp t ZԛR='ZjIh ~gP5/PPM@(NrsW#5>@9EK?? :kuj鍺Vi ".K=Kɑ* .p-8*5kT^q?U(yNCK? B?KNVE^9@ݻ&۵ 19-hBc yRxP˻Tl(i.K78:Z445 ܃>Zfᜐhqt.?4mB PH:B>B'R 4Ew݆\U/.H{ϝAV۱@N /*Yi 9or 'MF_`|BF+қl+f|~Mձ:5}Dy(Ҫ\X[Md]M%9 ~#SIIR5;xp x I~.׌]5{?|6 51w a7 =4R*idJۯ}!қ3 9TU6 DJrsA^yqD&${|C!_|1wW^B=ḌR]iRK[O8Z4 Bc:@:4(ћwT5{D76Z;\x 9G!wWt"Lvp(w Rs*qoDif!&~T\·%8Wm !?h"5g ^cC /qЏgβB$CnV$z5-ч_jEƵU:(TЉ% ]%!ɟ6;j0K r :O"AI!n y~+G B;"- ;&OZ` v.bi ;A1`K[@/&]5P@T* -Ҽњh4؇vE^ SQ,]4Nlɴ 2/0]LITk D x 25i-z.,@%x8ˉw!AQ`2Ii 8T- ȇk-34~D։}󑛠EZ(DaPJ*T%d#j½b[HyqXD *Z6 ̙ nnX>$IENDB`pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/static/theme.css000066400000000000000000000054731456106733600317230ustar00rootroot00000000000000@import url(//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700); body { font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 300; color: #ffffff; background: #bc2131; } h1, h2, h3, h4, h5, h6 { font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 300; } p { font-weight: 300; } .font-normal { font-weight: 400; } .font-semi-bold { font-weight: 600; } .font-bold { font-weight: 700; } .starter-template { margin-top: 250px; } .starter-template .content { margin-left: 10px; } .starter-template .content h1 { margin-top: 10px; font-size: 60px; } .starter-template .content h1 .smaller { font-size: 40px; color: #f2b7bd; } .starter-template .content .lead { font-size: 25px; color: #f2b7bd; } .starter-template .content .lead .font-normal { color: #ffffff; } .starter-template .links { float: right; right: 0; margin-top: 125px; } .starter-template .links ul { display: block; padding: 0; margin: 0; } .starter-template .links ul li { list-style: none; display: inline; margin: 0 10px; } .starter-template .links ul li:first-child { margin-left: 0; } .starter-template .links ul li:last-child { margin-right: 0; } .starter-template .links ul li.current-version { color: #f2b7bd; font-weight: 400; } .starter-template .links ul li a { color: #ffffff; } .starter-template .links ul li a:hover { text-decoration: underline; } .starter-template .links ul li .icon-muted { color: #eb8b95; margin-right: 5px; } .starter-template .links ul li:hover .icon-muted { color: #ffffff; } .starter-template .copyright { margin-top: 10px; font-size: 0.9em; color: #f2b7bd; text-transform: lowercase; float: right; right: 0; } @media (max-width: 1199px) { .starter-template .content h1 { font-size: 45px; } .starter-template .content h1 .smaller { font-size: 30px; } .starter-template .content .lead { font-size: 20px; } } @media (max-width: 991px) { .starter-template { margin-top: 0; } .starter-template .logo { margin: 40px auto; } .starter-template .content { margin-left: 0; text-align: center; } .starter-template .content h1 { margin-bottom: 20px; } .starter-template .links { float: none; text-align: center; margin-top: 60px; } .starter-template .copyright { float: none; text-align: center; } } @media (max-width: 767px) { .starter-template .content h1 .smaller { font-size: 25px; display: block; } .starter-template .content .lead { font-size: 16px; } .starter-template .links { margin-top: 40px; } .starter-template .links ul li { display: block; margin: 0; } .starter-template .links ul li .icon-muted { display: none; } .starter-template .copyright { margin-top: 20px; } } pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/templates/000077500000000000000000000000001456106733600306055ustar00rootroot00000000000000mytemplate.jinja2_tmpl000066400000000000000000000062061456106733600350460ustar00rootroot00000000000000pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/templates Starter Scaffold for Pyramid Jinja2

Pyramid Jinja2 scaffold

{% trans %}Welcome to{% endtrans %} \{\{ project \}\}, an application generated by
the Pyramid Web Framework {{pyramid_version}}.

pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/tests.py_tmpl000066400000000000000000000007601456106733600313620ustar00rootroot00000000000000import unittest from pyramid import testing from pyramid.i18n import TranslationStringFactory _ = TranslationStringFactory('{{package}}') class ViewTests(unittest.TestCase): def setUp(self): testing.setUp() def tearDown(self): testing.tearDown() def test_my_view(self): from {{package}}.views import my_view request = testing.DummyRequest() response = my_view(request) self.assertEqual(response['project'], '{{project}}') pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/+package+/views.py_tmpl000066400000000000000000000002351456106733600313520ustar00rootroot00000000000000from pyramid.i18n import TranslationStringFactory _ = TranslationStringFactory('{{project}}') def my_view(request): return {'project': '{{project}}'} pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/CHANGES.rst_tmpl000066400000000000000000000000331456106733600277200ustar00rootroot000000000000000.0 --- - Initial version pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/MANIFEST.in_tmpl000066400000000000000000000002171456106733600276600ustar00rootroot00000000000000include *.txt *.ini *.cfg *.rst recursive-include {{package}} *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.jinja2 *.js *.html *.xml pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/README.rst_tmpl000066400000000000000000000000261456106733600276070ustar00rootroot00000000000000{{project}} README pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/development.ini_tmpl000066400000000000000000000022531456106733600311470ustar00rootroot00000000000000### # app configuration # http://docs.pylonsproject.org/projects/pyramid/en/{{pyramid_docs_branch}}/narr/environment.html ### [app:main] use = egg:{{project}} pyramid.reload_templates = true pyramid.debug_authorization = false pyramid.debug_notfound = false pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.default_locale_name = en pyramid.includes = pyramid_debugtoolbar # By default, the toolbar only appears for clients from IP addresses # '127.0.0.1' and '::1'. # debugtoolbar.hosts = 127.0.0.1 ::1 ### # wsgi server configuration ### [server:main] use = egg:waitress#main host = 127.0.0.1 port = 6543 ### # logging configuration # http://docs.pylonsproject.org/projects/pyramid/en/{{pyramid_docs_branch}}/narr/logging.html ### [loggers] keys = root, {{package_logger}} [handlers] keys = console [formatters] keys = generic [logger_root] level = INFO handlers = console [logger_{{package_logger}}] level = DEBUG handlers = qualname = {{package}} [handler_console] class = StreamHandler args = (sys.stderr,) level = NOTSET formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/message-extraction.ini000066400000000000000000000000651456106733600313720ustar00rootroot00000000000000[python: **.py] [jinja2: **.jinja2] encoding = utf-8 pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/pytest.ini_tmpl000066400000000000000000000000651456106733600301540ustar00rootroot00000000000000[pytest] testpaths = {{package}} python_files = *.py pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/setup.cfg_tmpl000066400000000000000000000007461456106733600277520ustar00rootroot00000000000000[compile_catalog] directory = {{package}}/locale domain = {{project}} statistics = true [extract_messages] add_comments = TRANSLATORS: output_file = {{package}}/locale/{{project}}.pot width = 80 mapping_file = message-extraction.ini [init_catalog] domain = {{project}} input_file = {{package}}/locale/{{project}}.pot output_dir = {{package}}/locale [update_catalog] domain = {{project}} input_file = {{package}}/locale/{{project}}.pot output_dir = {{package}}/locale previous = true pyramid_jinja2-2.10.1/src/pyramid_jinja2/scaffolds/jinja2_starter/setup.py_tmpl000066400000000000000000000022541456106733600276370ustar00rootroot00000000000000import os from setuptools import setup, find_packages here = os.path.abspath(os.path.dirname(__file__)) with open(os.path.join(here, 'README.rst')) as f: README = f.read() with open(os.path.join(here, 'CHANGES.rst')) as f: CHANGES = f.read() requires = [ 'pyramid', 'pyramid_jinja2', 'pyramid_debugtoolbar', 'waitress', ] tests_require = [ 'WebTest >= 1.3.1', # py3 compat 'pytest', # includes virtualenv 'pytest-cov', ] setup(name='{{project}}', version='0.0', description='{{project}}', long_description=README + '\n\n' + CHANGES, classifiers=[ "Programming Language :: Python", "Framework :: Pyramid", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", ], author='', author_email='', url='', keywords='web pyramid pylons', packages=find_packages(), include_package_data=True, zip_safe=False, extras_require={ 'testing': tests_require, }, install_requires=requires, entry_points="""\ [paste.app_factory] main = {{package}}:main """, ) pyramid_jinja2-2.10.1/src/pyramid_jinja2/settings.py000066400000000000000000000117701456106733600224210ustar00rootroot00000000000000from jinja2 import ( BytecodeCache, DebugUndefined, FileSystemBytecodeCache, StrictUndefined, Undefined, ) from pyramid.path import AssetResolver from pyramid.settings import asbool from .i18n import GetTextWrapper _JINJA2_ENVIRONMENT_DEFAULTS = { "autoescape": True, } def splitlines(s): return filter(None, [x.strip() for x in s.splitlines()]) def parse_named_assetspecs(input, maybe_dotted): """ Parse a dictionary of asset specs. Parses config values from .ini file and returns a dictionary with imported objects """ # input must be a string or dict result = {} if isinstance(input, str): for f in splitlines(input): name, impl = f.split("=", 1) result[name.strip()] = maybe_dotted(impl.strip()) else: for name, impl in input.items(): result[name] = maybe_dotted(impl) return result def parse_multiline(extensions): if isinstance(extensions, str): extensions = list(splitlines(extensions)) return extensions def parse_undefined(undefined): if undefined == "strict": return StrictUndefined if undefined == "debug": return DebugUndefined return Undefined def parse_loader_options_from_settings(settings, prefix, maybe_dotted, package): """Parse options for use with the SmartAssetSpecLoader.""" package = package or "__main__" def sget(name, default=None): return settings.get(prefix + name, default) debug = sget("debug_templates", None) if debug is None: # bw-compat prior to checking debug_templates for specific prefix debug = settings.get("debug_templates", None) debug = asbool(debug) input_encoding = sget("input_encoding", "utf-8") # get jinja2 directories resolve = AssetResolver(package).resolve directories = parse_multiline(sget("directories") or "") directories = [resolve(d).abspath() for d in directories] return dict( debug=debug, encoding=input_encoding, searchpath=directories, ) def parse_env_options_from_settings( settings, prefix, maybe_dotted, package, defaults=None, ): """Parse options for use with the Jinja2 Environment.""" def sget(name, default=None): return settings.get(prefix + name, default) if defaults is None: defaults = _JINJA2_ENVIRONMENT_DEFAULTS opts = {} reload_templates = sget("reload_templates") if reload_templates is None: reload_templates = settings.get("pyramid.reload_templates") opts["auto_reload"] = asbool(reload_templates) # set string settings for key_name in ( "block_start_string", "block_end_string", "variable_start_string", "variable_end_string", "comment_start_string", "comment_end_string", "line_statement_prefix", "line_comment_prefix", "newline_sequence", ): value = sget(key_name, defaults.get(key_name)) if value is not None: opts[key_name] = value # boolean settings for key_name in ("autoescape", "trim_blocks", "optimized", "lstrip_blocks"): value = sget(key_name, defaults.get(key_name)) if value is not None: opts[key_name] = asbool(value) # integer settings for key_name in ("cache_size",): value = sget(key_name, defaults.get(key_name)) if value is not None: opts[key_name] = int(value) opts["undefined"] = parse_undefined(sget("undefined", "")) # get supplementary jinja2 settings domain = sget("i18n.domain", package and package.__name__ or "messages") gettext_wrapper = maybe_dotted(sget("i18n.gettext", GetTextWrapper)) opts["gettext"] = gettext_wrapper(domain=domain) # get jinja2 extensions extensions = parse_multiline(sget("extensions", "")) i18n_extension = sget("i18n_extension", "jinja2.ext.i18n") if i18n_extension not in extensions: extensions.append(i18n_extension) opts["extensions"] = extensions # get jinja2 bytecode caching settings and set up bytecaching bytecode_caching = sget("bytecode_caching", False) if isinstance(bytecode_caching, BytecodeCache): opts["bytecode_cache"] = bytecode_caching elif asbool(bytecode_caching): bytecode_caching_directory = sget("bytecode_caching_directory", None) opts["bytecode_cache"] = FileSystemBytecodeCache(bytecode_caching_directory) # should newstyle gettext calls be enabled? opts["newstyle"] = asbool(sget("newstyle", False)) # Do we have a finalize function? finalize = sget("finalize") if finalize is not None: opts["finalize"] = maybe_dotted(finalize) # add custom jinja2 filters opts["filters"] = parse_named_assetspecs(sget("filters", ""), maybe_dotted) # add custom jinja2 tests opts["tests"] = parse_named_assetspecs(sget("tests", ""), maybe_dotted) # add custom jinja2 functions opts["globals"] = parse_named_assetspecs(sget("globals", ""), maybe_dotted) return opts pyramid_jinja2-2.10.1/tests/000077500000000000000000000000001456106733600156525ustar00rootroot00000000000000pyramid_jinja2-2.10.1/tests/__init__.py000066400000000000000000000000201456106733600177530ustar00rootroot00000000000000# tests package pyramid_jinja2-2.10.1/tests/babel.cfg000066400000000000000000000001061456106733600173750ustar00rootroot00000000000000[jinja2: **.jinja2] extensions=jinja2.ext.autoescape,jinja2.ext.with_ pyramid_jinja2-2.10.1/tests/base.py000066400000000000000000000010271456106733600171360ustar00rootroot00000000000000from pyramid import testing class Base(object): def setUp(self): self.request = testing.DummyRequest() self.config = testing.setUp(request=self.request) self.request.registry = self.config.registry import os here = os.path.abspath(os.path.dirname(__file__)) self.templates_dir = os.path.join(here, "templates") def tearDown(self): testing.tearDown() del self.config class Mock(object): def __init__(self, **kwargs): self.__dict__.update(kwargs) pyramid_jinja2-2.10.1/tests/extensions.py000066400000000000000000000003321456106733600204210ustar00rootroot00000000000000from jinja2 import nodes from jinja2.ext import Extension class TestExtension(Extension): tags = {"test_ext"} def parse(self, parser): return nodes.Const("This is test extension") # pragma: nocover pyramid_jinja2-2.10.1/tests/locale/000077500000000000000000000000001456106733600171115ustar00rootroot00000000000000pyramid_jinja2-2.10.1/tests/locale/en/000077500000000000000000000000001456106733600175135ustar00rootroot00000000000000pyramid_jinja2-2.10.1/tests/locale/en/LC_MESSAGES/000077500000000000000000000000001456106733600213005ustar00rootroot00000000000000pyramid_jinja2-2.10.1/tests/locale/en/LC_MESSAGES/messages.mo000066400000000000000000000011171456106733600234440ustar00rootroot000000000000004L`a%{"1some translated text heresome translated text with ${var} hereProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2011-04-06 16:16-0430 PO-Revision-Date: 2011-04-06 16:17-0530 Last-Translator: FULL NAME Language-Team: en Plural-Forms: nplurals=2; plural=(n != 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 0.9.6 yay it worked!yay it works with ${var} too!pyramid_jinja2-2.10.1/tests/locale/en/LC_MESSAGES/messages.po000066400000000000000000000015101456106733600234440ustar00rootroot00000000000000# English translations for PROJECT. # Copyright (C) 2011 ORGANIZATION # This file is distributed under the same license as the PROJECT project. # FIRST AUTHOR , 2011. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2011-04-06 16:16-0430\n" "PO-Revision-Date: 2011-04-06 16:17-0530\n" "Last-Translator: FULL NAME \n" "Language-Team: en \n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" #: templates/i18n.jinja2:2 msgid "some translated text here" msgstr "yay it worked!" #: templates/i18n.jinja2:3 msgid "some translated text with ${var} here" msgstr "yay it works with ${var} too!" pyramid_jinja2-2.10.1/tests/locale/messages.pot000066400000000000000000000013661456106733600214520ustar00rootroot00000000000000# Translations template for PROJECT. # Copyright (C) 2011 ORGANIZATION # This file is distributed under the same license as the PROJECT project. # FIRST AUTHOR , 2011. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2011-04-06 16:16-0330\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" #: templates/i18n.jinja2:2 msgid "some translated text here" msgstr "" #: templates/i18n.jinja2:3 msgid "some translated text with ${var} here" msgstr "" pyramid_jinja2-2.10.1/tests/templates/000077500000000000000000000000001456106733600176505ustar00rootroot00000000000000pyramid_jinja2-2.10.1/tests/templates/bar/000077500000000000000000000000001456106733600204145ustar00rootroot00000000000000pyramid_jinja2-2.10.1/tests/templates/bar/mytemplate.jinja2000066400000000000000000000000041456106733600236660ustar00rootroot00000000000000bar pyramid_jinja2-2.10.1/tests/templates/baz1/000077500000000000000000000000001456106733600205055ustar00rootroot00000000000000pyramid_jinja2-2.10.1/tests/templates/baz1/base.jinja2000066400000000000000000000000641456106733600225160ustar00rootroot00000000000000baz1 {% block baz1_body %} {% endblock baz1_body %} pyramid_jinja2-2.10.1/tests/templates/baz1/middle.jinja2000066400000000000000000000000341456106733600230370ustar00rootroot00000000000000{% extends "base.jinja2" %} pyramid_jinja2-2.10.1/tests/templates/baz1/mytemplate.jinja2000066400000000000000000000001251456106733600237630ustar00rootroot00000000000000{% extends "middle.jinja2" %} {% block baz1_body %}baz1 body{% endblock baz1_body %} pyramid_jinja2-2.10.1/tests/templates/baz2/000077500000000000000000000000001456106733600205065ustar00rootroot00000000000000pyramid_jinja2-2.10.1/tests/templates/baz2/base.jinja2000066400000000000000000000000751456106733600225210ustar00rootroot00000000000000baz2 {% block baz2_body %} baz1 foo {% endblock baz2_body %} pyramid_jinja2-2.10.1/tests/templates/baz2/mytemplate.jinja2000066400000000000000000000001231456106733600237620ustar00rootroot00000000000000{% extends "base.jinja2" %} {% block baz2_body %}baz2 body{% endblock baz2_body %} pyramid_jinja2-2.10.1/tests/templates/deep/000077500000000000000000000000001456106733600205655ustar00rootroot00000000000000pyramid_jinja2-2.10.1/tests/templates/deep/base.jinja2000066400000000000000000000000541456106733600225750ustar00rootroot00000000000000deep-base {% block content %}{% endblock %} pyramid_jinja2-2.10.1/tests/templates/deep/forms.jinja2000066400000000000000000000000131456106733600230040ustar00rootroot00000000000000deep-forms pyramid_jinja2-2.10.1/tests/templates/deep/leaf.jinja2000066400000000000000000000001461456106733600225740ustar00rootroot00000000000000{% extends "base.jinja2" %} {% include "sub/nav.jinja2" %} {% block content %}deep-leaf{% endblock %} pyramid_jinja2-2.10.1/tests/templates/deep/sub/000077500000000000000000000000001456106733600213565ustar00rootroot00000000000000pyramid_jinja2-2.10.1/tests/templates/deep/sub/base.jinja2000066400000000000000000000001561456106733600233710ustar00rootroot00000000000000{% extends "../base.jinja2" %} {% block content %}sub-base {% block subcontent %}{% endblock %}{% endblock %} pyramid_jinja2-2.10.1/tests/templates/deep/sub/leaf.jinja2000066400000000000000000000001101456106733600233540ustar00rootroot00000000000000{% extends "base.jinja2" %} {% block subcontent %}sub-leaf{% endblock%} pyramid_jinja2-2.10.1/tests/templates/deep/sub/nav.jinja2000066400000000000000000000000511456106733600232350ustar00rootroot00000000000000sub-nav {% include "../forms.jinja2" %} pyramid_jinja2-2.10.1/tests/templates/extends.jinja2000066400000000000000000000001101456106733600224110ustar00rootroot00000000000000{% extends "helloworld.jinja2" %} {% block content %}Yo!{% endblock %} pyramid_jinja2-2.10.1/tests/templates/extends_missing.jinja2000066400000000000000000000001121456106733600241440ustar00rootroot00000000000000{% extends "missing/tmpl.jinja2" %} {% block content %}Yo!{% endblock %} pyramid_jinja2-2.10.1/tests/templates/extends_relbase.jinja2000066400000000000000000000001221456106733600241110ustar00rootroot00000000000000{% extends "templates/helloworld.jinja2" %} {% block content %}Yo!{% endblock %} pyramid_jinja2-2.10.1/tests/templates/extends_spec.jinja2000066400000000000000000000001301456106733600234250ustar00rootroot00000000000000{% extends "tests:templates/helloworld.jinja2" %} {% block content %}Yo!{% endblock %} pyramid_jinja2-2.10.1/tests/templates/foo/000077500000000000000000000000001456106733600204335ustar00rootroot00000000000000pyramid_jinja2-2.10.1/tests/templates/foo/mytemplate.jinja2000066400000000000000000000000041456106733600237050ustar00rootroot00000000000000foo pyramid_jinja2-2.10.1/tests/templates/helloworld.jinja2000066400000000000000000000001171456106733600231210ustar00rootroot00000000000000{% set a, b = "foo", "föö" %} Hello {{ b }}{% block content %}{% endblock %} pyramid_jinja2-2.10.1/tests/templates/i18n.jinja2000066400000000000000000000002341456106733600215250ustar00rootroot00000000000000some untranslated text here {% trans %}some translated text here{% endtrans %} {{ gettext("some translated text with ${var} here", mapping={"var": var}) }} pyramid_jinja2-2.10.1/tests/templates/newstyle.jinja2000066400000000000000000000000771456106733600226250ustar00rootroot00000000000000{{ gettext("my hovercraft is full of %(what)s!", what=what) }} pyramid_jinja2-2.10.1/tests/templates/recursive/000077500000000000000000000000001456106733600216575ustar00rootroot00000000000000pyramid_jinja2-2.10.1/tests/templates/recursive/admin/000077500000000000000000000000001456106733600227475ustar00rootroot00000000000000pyramid_jinja2-2.10.1/tests/templates/recursive/admin/base.html000066400000000000000000000000321456106733600245420ustar00rootroot00000000000000{% extends "base.html" %} pyramid_jinja2-2.10.1/tests/templates/recursive/admin/index.html000066400000000000000000000000401456106733600247360ustar00rootroot00000000000000{% extends "admin/base.html" %} pyramid_jinja2-2.10.1/tests/templates/recursive/base.html000066400000000000000000000000041456106733600234510ustar00rootroot00000000000000foo pyramid_jinja2-2.10.1/tests/templates/tests_and_filters.jinja2000066400000000000000000000001471456106733600244650ustar00rootroot00000000000000{{ "some text"|my_filter }} {% if "other text" is my_test %}is not False{% endif %} {{ my_global(1) }} pyramid_jinja2-2.10.1/tests/test_ext.py000066400000000000000000000042511456106733600200650ustar00rootroot00000000000000import unittest from pyramid.path import DottedNameResolver from .base import Base class TestExtensions(Base, unittest.TestCase): def test_custom_extension(self): from pyramid_jinja2 import create_environment_from_options from pyramid_jinja2.settings import parse_env_options_from_settings options = { "extensions": "tests.extensions.TestExtension", } settings = parse_env_options_from_settings(options, "", maybe_dotted, None) env = create_environment_from_options(settings, {}) ext = env.extensions["tests.extensions.TestExtension"] from . import extensions self.assertEqual(ext.__class__, extensions.TestExtension) def test_i18n(self): from pyramid_jinja2 import create_environment_from_options from pyramid_jinja2.settings import parse_env_options_from_settings settings = parse_env_options_from_settings({}, "", maybe_dotted, None) env = create_environment_from_options(settings, {}) self.assertTrue(hasattr(env, "install_gettext_translations")) self.config.add_translation_dirs("tests:locale/") self.request.locale_name = "en" template = env.get_template("tests:templates/i18n.jinja2") context = {"var": "variables"} self.assertEqual( template.render(**context), "some untranslated text here\nyay it worked!\n" "yay it works with variables too!", ) resolver = DottedNameResolver() maybe_dotted = resolver.maybe_resolve class GetTextWrapperTests(unittest.TestCase): def test_it(self): from pyramid_jinja2.i18n import GetTextWrapper class MyGetTextWrapper(GetTextWrapper): class localizer: @staticmethod def translate(s, domain, mapping): return s @staticmethod def pluralize(s1, s2, n, domain): return s2 def __init__(self): GetTextWrapper.__init__(self, "messages") self.assertEqual(MyGetTextWrapper().gettext("foo"), "foo") self.assertEqual(MyGetTextWrapper().ngettext("foo", "foos", 3), "foos") pyramid_jinja2-2.10.1/tests/test_filters.py000066400000000000000000000156341456106733600207440ustar00rootroot00000000000000import unittest from pyramid import testing class DummyRoot(object): __name__ = __parent__ = None class DummyModel(object): __name__ = "dummy" __parent__ = DummyRoot() class Base(object): def setUp(self): self.request = testing.DummyRequest() self.config = testing.setUp(request=self.request) self.request.registry = self.config.registry from pyramid_jinja2 import Environment self.environment = Environment() self._addFilters() def tearDown(self): testing.tearDown() def _addFilters(self): pass # pragma: nocover def _callFUT(self, context, tmpl): tmpl = self.environment.from_string(tmpl) return tmpl.render(**context) class Test_model_url_filter(Base, unittest.TestCase): def _addFilters(self): from pyramid_jinja2.filters import model_url_filter self.environment.filters["model_url"] = model_url_filter def test_filter(self): model = DummyModel() rendered = self._callFUT({"model": model}, "{{ model|model_url }}") self.assertEqual(rendered, "http://example.com/dummy/") def test_filter_with_elements(self): model = DummyModel() rendered = self._callFUT({"model": model}, "{{ model|model_url('edit') }}") self.assertEqual(rendered, "http://example.com/dummy/edit") class Test_resource_url_filter(Base, unittest.TestCase): def _addFilters(self): from pyramid_jinja2.filters import resource_url_filter self.environment.filters["resource_url"] = resource_url_filter def test_filter(self): model = DummyModel() rendered = self._callFUT({"model": model}, "{{ model|resource_url }}") self.assertEqual(rendered, "http://example.com/dummy/") def test_filter_with_elements(self): model = DummyModel() rendered = self._callFUT({"model": model}, "{{ model|resource_url('edit') }}") self.assertEqual(rendered, "http://example.com/dummy/edit") class Test_model__filter(Base, unittest.TestCase): def _addFilters(self): from pyramid_jinja2.filters import model_path_filter self.environment.filters["model_path"] = model_path_filter def test_filter(self): model = DummyModel() rendered = self._callFUT({"model": model}, "{{ model|model_path }}") self.assertEqual(rendered, "/dummy/") def test_filter_with_elements(self): model = DummyModel() rendered = self._callFUT({"model": model}, "{{ model|model_path('edit') }}") self.assertEqual(rendered, "/dummy/edit") class Test_route_url_filter(Base, unittest.TestCase): def _addFilters(self): from pyramid_jinja2.filters import route_url_filter self.environment.filters["route_url"] = route_url_filter self.config.add_route("dummy_route1", "/dummy/") self.config.add_route("dummy_route2", "/dummy/:name/") def test_filter(self): rendered = self._callFUT({}, "{{ 'dummy_route1'|route_url }}") self.assertEqual(rendered, "http://example.com/dummy/") def test_filter_with_arguments(self): rendered = self._callFUT({}, "{{ 'dummy_route2'|route_url('x', name='test') }}") self.assertEqual(rendered, "http://example.com/dummy/test/x") class Test_route_path_filter(Base, unittest.TestCase): def _addFilters(self): from pyramid_jinja2.filters import route_path_filter self.environment.filters["route_path"] = route_path_filter self.config.add_route("dummy_route1", "/dummy/") self.config.add_route("dummy_route2", "/dummy/:name/") def test_filter(self): rendered = self._callFUT({}, "{{ 'dummy_route1'|route_path }}") self.assertEqual(rendered, "/dummy/") def test_filter_with_arguments(self): rendered = self._callFUT( {}, "{{ 'dummy_route2'|route_path('x', name='test') }}" ) self.assertEqual(rendered, "/dummy/test/x") class Test_static_url_filter(Base, unittest.TestCase): def _addFilters(self): from pyramid_jinja2.filters import static_url_filter self.environment.filters["static_url"] = static_url_filter self.config.add_static_view("myfiles", "dummy1:static") self.config.add_static_view("otherfiles/{owner}", "dummy2:files") def test_filter(self): rendered = self._callFUT( {}, "{{ 'dummy1:static/the/quick/brown/fox.svg'|static_url }}" ) self.assertEqual(rendered, "http://example.com/myfiles/the/quick/brown/fox.svg") def test_filter_with_arguments(self): rendered = self._callFUT( {}, "{{ 'dummy2:files/report.txt'|static_url(owner='foo') }}" ) self.assertEqual(rendered, "http://example.com/otherfiles/foo/report.txt") class Test_static_path_filter(Base, unittest.TestCase): def _addFilters(self): from pyramid_jinja2.filters import static_path_filter self.environment.filters["static_path"] = static_path_filter self.config.add_static_view("myfiles", "dummy1:static") self.config.add_static_view("otherfiles/{owner}", "dummy2:files") def test_filter(self): rendered = self._callFUT( {}, "{{ 'dummy1:static/the/quick/brown/fox.svg'|static_path }}" ) self.assertEqual(rendered, "/myfiles/the/quick/brown/fox.svg") def test_filter_with_arguments(self): rendered = self._callFUT( {}, "{{ 'dummy2:files/report.txt'|static_path(owner='foo') }}" ) self.assertEqual(rendered, "/otherfiles/foo/report.txt") class Test_filters_not_caching(Base, unittest.TestCase): def _addFilters(self): from pyramid_jinja2.filters import route_url_filter self.environment.filters["route_url"] = route_url_filter self.config.add_route("dummy_route1", "/dummy/") self.config.add_route("dummy_route2", "/dummy/:name/") def test_filter(self): self.request.application_url = "http://example.com" self.request.host = "example.com:80" rendered = self._callFUT({}, "{{ 'dummy_route1'|route_url }}") self.assertEqual(rendered, "http://example.com/dummy/") self.request.application_url = "http://sub.example.com" self.request.host = "sub.example.com:80" rendered = self._callFUT({}, "{{ 'dummy_route1'|route_url }}") self.assertEqual(rendered, "http://sub.example.com/dummy/") def test_filter_with_arguments(self): self.request.application_url = "http://example.com" self.request.host = "example.com:80" rendered = self._callFUT({}, "{{ 'dummy_route2'|route_url('x', name='test') }}") self.assertEqual(rendered, "http://example.com/dummy/test/x") self.request.application_url = "http://sub.example.com" self.request.host = "sub.example.com:80" rendered = self._callFUT({}, "{{ 'dummy_route2'|route_url('x', name='test') }}") self.assertEqual(rendered, "http://sub.example.com/dummy/test/x") pyramid_jinja2-2.10.1/tests/test_it.py000066400000000000000000000647431456106733600177150ustar00rootroot00000000000000from io import StringIO import unittest from pyramid import testing from .base import Base, Mock def dummy_filter(value): return "hoge" # pragma: nocover class Test_renderer_factory(Base, unittest.TestCase): def setUp(self): Base.setUp(self) import warnings self.warnings = warnings.catch_warnings() self.warnings.__enter__() warnings.simplefilter("ignore", DeprecationWarning) def tearDown(self): self.warnings.__exit__(None, None, None) Base.tearDown(self) def _callFUT(self, info): from pyramid_jinja2 import renderer_factory return renderer_factory(info) def test_require_default_renderer(self): info = DummyRendererInfo( { "name": "helloworld.jinja2", "package": None, "registry": self.config.registry, } ) self.assertRaises(ValueError, lambda: self._callFUT(info)) def test_no_directories(self): from jinja2.exceptions import TemplateNotFound self.config.include("pyramid_jinja2") info = DummyRendererInfo( { "name": "helloworld.jinja2", "package": None, "registry": self.config.registry, } ) renderer = self._callFUT(info) self.assertRaises(TemplateNotFound, lambda: renderer({}, {"system": 1})) def test_no_environment(self): self.config.registry.settings.update({"jinja2.directories": self.templates_dir}) self.config.include("pyramid_jinja2") info = DummyRendererInfo( { "name": "helloworld.jinja2", "package": None, "registry": self.config.registry, } ) renderer = self._callFUT(info) environ = self.config.get_jinja2_environment() self.assertEqual(environ.loader.searchpath[0], self.templates_dir) self.assertTrue(renderer.template_loader is not None) def test_composite_directories_path(self): twice = self.templates_dir + "\n" + self.templates_dir self.config.registry.settings["jinja2.directories"] = twice self.config.include("pyramid_jinja2") info = DummyRendererInfo( { "name": "helloworld.jinja2", "package": None, "registry": self.config.registry, } ) self._callFUT(info) environ = self.config.get_jinja2_environment() self.assertEqual(environ.loader.searchpath[:2], [self.templates_dir] * 2) def test_with_environ(self): from pyramid_jinja2 import IJinja2Environment environ = DummyEnviron() self.config.registry.registerUtility( environ, IJinja2Environment, name=".jinja2" ) info = DummyRendererInfo( { "name": "helloworld.jinja2", "package": None, "registry": self.config.registry, } ) renderer = self._callFUT(info) self.assertTrue(renderer.template_loader) def test_with_filters_object(self): self.config.registry.settings.update( { "jinja2.directories": self.templates_dir, "jinja2.filters": {"dummy": dummy_filter}, } ) self.config.include("pyramid_jinja2") info = DummyRendererInfo( { "name": "helloworld.jinja2", "package": None, "registry": self.config.registry, } ) self._callFUT(info) environ = self.config.get_jinja2_environment() self.assertEqual(environ.filters["dummy"], dummy_filter) def test_with_filters_string(self): m = "tests.test_it" self.config.registry.settings.update( { "jinja2.directories": self.templates_dir, "jinja2.filters": "dummy=%s:dummy_filter" % m, } ) self.config.include("pyramid_jinja2") info = DummyRendererInfo( { "name": "helloworld.jinja2", "package": None, "registry": self.config.registry, } ) self._callFUT(info) environ = self.config.get_jinja2_environment() self.assertEqual(environ.filters["dummy"], dummy_filter) class TestJinja2TemplateRenderer(Base, unittest.TestCase): def _getTargetClass(self): from pyramid_jinja2 import Jinja2TemplateRenderer return Jinja2TemplateRenderer def _makeOne(self, *arg, **kw): klass = self._getTargetClass() return klass(*arg, **kw) def test_call(self): template = DummyTemplate() instance = self._makeOne(lambda: template) result = instance({}, {"system": 1}) self.assertTrue(isinstance(result, str)) self.assertEqual(result, "result") def test_call_with_system_context(self): template = DummyTemplate() instance = self._makeOne(lambda: template) result = instance({}, {"context": 1}) self.assertTrue(isinstance(result, str)) self.assertEqual(result, "result") def test_call_with_nondict_value(self): template = DummyTemplate() instance = self._makeOne(lambda: template) self.assertRaises(ValueError, instance, None, {"context": 1}) class SearchPathTests(object): def test_relative_tmpl_helloworld(self): from pyramid.renderers import render result = render("templates/helloworld.jinja2", {}) self.assertEqual(result, "\nHello föö") def test_relative_tmpl_extends(self): from pyramid.renderers import render result = render("templates/extends.jinja2", {}) self.assertEqual(result, "\nHello fööYo!") def test_relative_tmpl_extends_spec(self): from pyramid.renderers import render result = render("templates/extends_spec.jinja2", {"a": 1}) self.assertEqual(result, "\nHello fööYo!") def test_asset_tmpl_helloworld(self): from pyramid.renderers import render result = render("tests:templates/helloworld.jinja2", {"a": 1}) self.assertEqual(result, "\nHello föö") def test_asset_tmpl_extends(self): from pyramid.renderers import render result = render("tests:templates/extends.jinja2", {"a": 1}) self.assertEqual(result, "\nHello fööYo!") def test_asset_tmpl_extends_spec(self): from pyramid.renderers import render result = render("tests:templates/extends_spec.jinja2", {"a": 1}) self.assertEqual(result, "\nHello fööYo!") def test_asset_tmpl_deep_sub_leaf(self): from pyramid.renderers import render result = render("tests:templates/deep/sub/leaf.jinja2", {}) self.assertEqual(result, "deep-base sub-base sub-leaf") def test_asset_tmpl_deep_leaf(self): from pyramid.renderers import render result = render("tests:templates/deep/leaf.jinja2", {}) self.assertEqual(result, "sub-nav\n\ndeep-formsdeep-base deep-leaf") def test_abs_tmpl_extends(self): import os.path from pyramid.renderers import render here = os.path.abspath(os.path.dirname(__file__)) result = render(os.path.join(here, "templates", "extends.jinja2"), {"a": 1}) self.assertEqual(result, "\nHello fööYo!") def test_abs_tmpl_extends_missing(self): import os.path from jinja2 import TemplateNotFound from pyramid.renderers import render here = os.path.abspath(os.path.dirname(__file__)) templates_dir = os.path.join(here, "templates") self.assertRaises( TemplateNotFound, lambda: render(os.path.join(templates_dir, "/extends_missing.jinja2"), {}), ) class TestIntegrationWithSearchPath(SearchPathTests, unittest.TestCase): def setUp(self): config = testing.setUp() config.add_settings({"jinja2.directories": "tests:templates"}) config.include("pyramid_jinja2") self.config = config def tearDown(self): testing.tearDown() def test_tmpl_helloworld(self): from pyramid.renderers import render result = render("helloworld.jinja2", {"a": 1}) self.assertEqual(result, "\nHello föö") def test_tmpl_extends(self): from pyramid.renderers import render result = render("extends.jinja2", {"a": 1}) self.assertEqual(result, "\nHello fööYo!") def test_tmpl_extends_spec(self): from pyramid.renderers import render result = render("extends_spec.jinja2", {"a": 1}) self.assertEqual(result, "\nHello fööYo!") def test_tmpl_extends_relbase(self): from pyramid.renderers import render # this should pass as it will fallback to the new search path # and find it from there self.config.add_jinja2_search_path("tests:") result = render("extends_relbase.jinja2", {"a": 1}) self.assertEqual(result, "\nHello fööYo!") def test_caller_relative_tmpl_extends_relbase(self): from pyramid.renderers import render # this should pass as it will fallback to the new search path # and find it from there self.config.add_jinja2_search_path("tests:") result = render("templates/extends_relbase.jinja2", {"a": 1}) self.assertEqual(result, "\nHello fööYo!") def test_recursive_tmpl(self): from pyramid.renderers import render self.config.add_jinja2_renderer(".html") self.config.add_jinja2_search_path("tests:templates/recursive", name=".html") result = render("admin/index.html", {}) self.assertEqual(result, "foo") class TestIntegrationDefaultSearchPath(SearchPathTests, unittest.TestCase): def setUp(self): config = testing.setUp() config.include("pyramid_jinja2") def tearDown(self): testing.tearDown() class TestIntegrationReloading(unittest.TestCase): def setUp(self): config = testing.setUp() config.add_settings( { "pyramid.reload_templates": "true", } ) config.include("pyramid_jinja2") self.config = config def tearDown(self): testing.tearDown() def test_render_reload_templates(self): import os import tempfile import time from webtest import TestApp fd, path = tempfile.mkstemp(".jinja2") try: with open(path, "wb") as fp: fp.write(b"foo") self.config.add_view(lambda r: {}, renderer=path) app = TestApp(self.config.make_wsgi_app()) result = app.get("/").body self.assertEqual(result, b"foo") # need mtime to change and most systems have 1-second resolution time.sleep(1) with open(path, "wb") as fp: fp.write(b"bar") result = app.get("/").body self.assertEqual(result, b"bar") finally: os.close(fd) os.unlink(path) class Test_filters_and_tests(Base, unittest.TestCase): def _set_up_environ(self): self.config.include("pyramid_jinja2") return self.config.get_jinja2_environment() def _assert_has_test(self, test_name, test_obj): environ = self._set_up_environ() self.assertTrue(test_name in environ.tests) self.assertEqual(environ.tests[test_name], test_obj) def _assert_has_filter(self, filter_name, filter_obj): environ = self._set_up_environ() self.assertTrue(filter_name in environ.filters) self.assertEqual(environ.filters[filter_name], filter_obj) def _assert_has_global(self, global_name, global_obj): environ = self._set_up_environ() self.assertTrue(global_name in environ.globals) self.assertEqual(environ.globals[global_name], global_obj) def test_set_single_filter(self): filters = "my_filter = tests.test_it.my_test_func" self.config.registry.settings["jinja2.filters"] = filters self._assert_has_filter("my_filter", my_test_func) def test_set_single_test(self): filters = "my_test = tests.test_it.my_test_func" self.config.registry.settings["jinja2.tests"] = filters self._assert_has_test("my_test", my_test_func) def test_set_single_global(self): filters = "my_test = tests.test_it.my_test_func" self.config.registry.settings["jinja2.globals"] = filters self._assert_has_global("my_test", my_test_func) def test_set_multi_filters(self): self.config.registry.settings["jinja2.filters"] = ( "my_filter1 = tests.test_it.my_test_func\n" "my_filter2 = tests.test_it.my_test_func\n" "my_filter3 = tests.test_it.my_test_func" ) self._assert_has_filter("my_filter1", my_test_func) self._assert_has_filter("my_filter2", my_test_func) self._assert_has_filter("my_filter3", my_test_func) def test_set_multi_tests(self): self.config.registry.settings["jinja2.tests"] = ( "my_test1 = tests.test_it.my_test_func\n" "my_test2 = tests.test_it.my_test_func\n" "my_test3 = tests.test_it.my_test_func" ) self._assert_has_test("my_test1", my_test_func) self._assert_has_test("my_test2", my_test_func) self._assert_has_test("my_test3", my_test_func) def test_set_multi_globals(self): self.config.registry.settings["jinja2.globals"] = ( "my_global1 = tests.test_it.my_test_func\n" "my_global2 = tests.test_it.my_test_func\n" "my_global3 = tests.test_it.my_test_func" ) self._assert_has_global("my_global1", my_test_func) self._assert_has_global("my_global2", my_test_func) self._assert_has_global("my_global3", my_test_func) def test_filter_and_test_and_global_works_in_render(self): from pyramid.renderers import render config = testing.setUp() config.include("pyramid_jinja2") config.add_settings( { "jinja2.directories": "tests:templates", "jinja2.tests": "my_test = tests.test_it.my_test_func", "jinja2.filters": "my_filter = tests.test_it.my_test_func", "jinja2.globals": "my_global = tests.test_it.my_test_func", } ) config.add_jinja2_renderer(".jinja2") result = render("tests_and_filters.jinja2", {}) # my_test_func returns "True" - it will be rendered as True when used # as filter and will pass in tests self.assertEqual(result, "True is not False True") testing.tearDown() class Test_includeme(unittest.TestCase): def test_it(self): from pyramid.interfaces import IRendererFactory from pyramid_jinja2 import Jinja2RendererFactory, includeme config = testing.setUp() config.registry.settings["jinja2.directories"] = "/foobar" includeme(config) utility = config.registry.getUtility(IRendererFactory, name=".jinja2") self.assertTrue(isinstance(utility, Jinja2RendererFactory)) class Test_add_jinja2_searchpath(unittest.TestCase): def test_it_relative_to_package(self): import os from pyramid_jinja2 import includeme import tests config = testing.setUp() # hack because pyramid pre 1.6 doesn't configure testing configurator # with the correct package name config.package = tests config.package_name = "tests" config.add_settings({"jinja2.directories": "foobar"}) includeme(config) env = config.get_jinja2_environment() self.assertEqual(len(env.loader.searchpath), 2) self.assertEqual( [x.split(os.sep)[-3:] for x in env.loader.searchpath][0], ["pyramid_jinja2", "tests", "foobar"], ) self.assertEqual( [x.split(os.sep)[-2:] for x in env.loader.searchpath][1], ["pyramid_jinja2", "tests"], ) config.add_jinja2_search_path("grrr", prepend=True) self.assertEqual(len(env.loader.searchpath), 3) self.assertEqual( [x.split(os.sep)[-3:] for x in env.loader.searchpath][0], ["pyramid_jinja2", "tests", "grrr"], ) self.assertEqual( [x.split(os.sep)[-3:] for x in env.loader.searchpath][1], ["pyramid_jinja2", "tests", "foobar"], ) self.assertEqual( [x.split(os.sep)[-2:] for x in env.loader.searchpath][2], ["pyramid_jinja2", "tests"], ) class Test_get_jinja2_environment(unittest.TestCase): def test_it(self): from pyramid_jinja2 import Environment, includeme config = testing.setUp() includeme(config) self.assertEqual(config.get_jinja2_environment().__class__, Environment) class Test_bytecode_caching(unittest.TestCase): def test_default(self): from pyramid_jinja2 import includeme config = testing.setUp() config.registry.settings = {} includeme(config) env = config.get_jinja2_environment() self.assertTrue(env.bytecode_cache is None) self.assertFalse(env.auto_reload) def test_default_bccache(self): import jinja2.bccache from pyramid_jinja2 import includeme config = testing.setUp() config.registry.settings = {"jinja2.bytecode_caching": "true"} includeme(config) env = config.get_jinja2_environment() self.assertTrue( isinstance(env.bytecode_cache, jinja2.bccache.FileSystemBytecodeCache) ) self.assertTrue(env.bytecode_cache.directory) self.assertFalse(env.auto_reload) def test_directory(self): import tempfile from pyramid_jinja2 import includeme tmpdir = tempfile.mkdtemp() config = testing.setUp() config.registry.settings["jinja2.bytecode_caching"] = "1" config.registry.settings["jinja2.bytecode_caching_directory"] = tmpdir includeme(config) env = config.get_jinja2_environment() self.assertEqual(env.bytecode_cache.directory, tmpdir) # TODO: test tmpdir is deleted when interpreter exits def test_bccache_instance(self): import jinja2.bccache from pyramid_jinja2 import includeme mycache = jinja2.bccache.MemcachedBytecodeCache(DummyMemcachedClient()) config = testing.setUp() config.registry.settings = {"jinja2.bytecode_caching": mycache} includeme(config) env = config.get_jinja2_environment() self.assertTrue(env.bytecode_cache is mycache) self.assertFalse(env.auto_reload) def test_pyramid_reload_templates(self): from pyramid_jinja2 import includeme config = testing.setUp() config.registry.settings = {} config.registry.settings["pyramid.reload_templates"] = "true" includeme(config) env = config.get_jinja2_environment() self.assertTrue(env.auto_reload) class TestSmartAssetSpecLoader(unittest.TestCase): def _makeOne(self, **kw): from pyramid_jinja2 import SmartAssetSpecLoader return SmartAssetSpecLoader(**kw) def test_list_templates(self): loader = self._makeOne() self.assertRaises(TypeError, loader.list_templates) def test_get_source_invalid_spec(self): from jinja2.exceptions import TemplateNotFound loader = self._makeOne() self.assertRaises( TemplateNotFound, loader.get_source, None, "asset:foobar.jinja2" ) def test_get_source_spec(self): loader = self._makeOne() asset = "tests:templates/helloworld.jinja2" self.assertNotEqual(loader.get_source(None, asset), None) def test_get_source_legacy_spec(self): loader = self._makeOne() # make sure legacy prefixed asset spec based loading works asset = "asset:tests:templates/helloworld.jinja2" self.assertNotEqual(loader.get_source(None, asset), None) def test_get_source_from_path(self): import os.path here = os.path.abspath(os.path.dirname(__file__)) loader = self._makeOne(searchpath=[here]) asset = "templates/helloworld.jinja2" self.assertNotEqual(loader.get_source(None, asset), None) class TestFileInfo(unittest.TestCase): def test_mtime(self): from pyramid.asset import abspath_from_asset_spec from pyramid_jinja2 import FileInfo filename = abspath_from_asset_spec("templates/helloworld.jinja2", "tests") fi = FileInfo(filename) assert "_mtime" not in fi.__dict__ assert fi.mtime is not None assert fi.mtime == fi._mtime def test_uptodate(self): from pyramid_jinja2 import FileInfo fi = FileInfo("foobar") assert fi.uptodate() is False def test_notfound(self): from jinja2 import TemplateNotFound from pyramid_jinja2 import FileInfo fi = FileInfo("foobar") self.assertRaises(TemplateNotFound, lambda: fi._delay_init()) def test_delay_init(self): from pyramid_jinja2 import FileInfo class MyFileInfo(FileInfo): filename = "foo.jinja2" def __init__(self, data): self.data = data FileInfo.__init__(self, self.filename) def open_if_exists(self, fname): return StringIO(self.data) def getmtime(self, fname): return 1 mi = MyFileInfo("nothing good here, move along") mi._delay_init() self.assertEqual(mi._contents, mi.data) class TestJinja2SearchPathIntegration(unittest.TestCase): def test_it(self): import os from pyramid.config import Configurator from webtest import TestApp from pyramid_jinja2 import includeme here = os.path.abspath(os.path.dirname(__file__)) templates_dir = os.path.join(here, "templates") def myview(request): return {} config1 = Configurator( settings={"jinja2.directories": os.path.join(templates_dir, "foo")} ) includeme(config1) config1.add_view(view=myview, renderer="mytemplate.jinja2") config2 = Configurator( settings={"jinja2.directories": os.path.join(templates_dir, "bar")} ) includeme(config2) config2.add_view(view=myview, renderer="mytemplate.jinja2") self.assertNotEqual(config1.registry.settings, config2.registry.settings) app1 = config1.make_wsgi_app() testapp = TestApp(app1) self.assertEqual(testapp.get("/").body, b"foo") app2 = config2.make_wsgi_app() testapp = TestApp(app2) self.assertEqual(testapp.get("/").body, b"bar") def test_it_relative_to_template(self): from pyramid.config import Configurator from webtest import TestApp from pyramid_jinja2 import includeme def myview(request): return {} config = Configurator(settings={"jinja2.directories": "templates"}) includeme(config) config.add_view(view=myview, name="baz1", renderer="baz1/mytemplate.jinja2") config.add_view(view=myview, name="baz2", renderer="baz2/mytemplate.jinja2") app1 = config.make_wsgi_app() testapp = TestApp(app1) self.assertEqual(testapp.get("/baz1").body, b"baz1\nbaz1 body") self.assertEqual(testapp.get("/baz2").body, b"baz2\nbaz2 body") class TestPackageFinder(unittest.TestCase): def test_caller_package(self): from pyramid_jinja2 import _PackageFinder pf = _PackageFinder() class MockInspect(object): def __init__(self, items=()): self.items = items def stack(self): return self.items pf.inspect = MockInspect() self.assertEqual(pf.caller_package(), None) import xml # noqa F401 pf.inspect.items = [(Mock(f_globals={"__name__": "xml"}),)] class TestNewstyle(unittest.TestCase): def test_it(self): import os from pyramid.config import Configurator from webtest import TestApp from pyramid_jinja2 import includeme here = os.path.abspath(os.path.dirname(__file__)) templates_dir = os.path.join(here, "templates") def myview(request): return {"what": "eels"} config = Configurator( settings={"jinja2.directories": templates_dir, "jinja2.newstyle": True} ) includeme(config) config.add_view(view=myview, renderer="newstyle.jinja2") app = config.make_wsgi_app() testapp = TestApp(app) self.assertEqual( testapp.get("/").body.decode("utf-8"), "my hovercraft is full of eels!" ) class Test_add_jinja2_extension(Base, unittest.TestCase): def test_it(self): self.config.include("pyramid_jinja2") env_before = self.config.get_jinja2_environment() class MockExt(object): identifier = "foobar" def __init__(self, x): self.x = x self.config.add_jinja2_extension(MockExt) env_after = self.config.get_jinja2_environment() self.assertTrue("foobar" in env_after.extensions) self.assertTrue(env_before is env_after) def test_alternate_renderer_extension(self): self.config.include("pyramid_jinja2") self.config.add_jinja2_renderer(".html") env_before = self.config.get_jinja2_environment(".html") class MockExt(object): identifier = "foobar" def __init__(self, x): self.x = x self.config.add_jinja2_extension(MockExt, ".html") env_after = self.config.get_jinja2_environment(".html") default_env = self.config.get_jinja2_environment() self.assertTrue("foobar" in env_after.extensions) self.assertTrue("foobar" not in default_env.extensions) self.assertTrue(env_before is env_after) def my_test_func(*args, **kwargs): """Used as a fake filter/test function""" return True class DummyMemcachedClient(dict): """A memcached client acceptable to jinja2.MemcachedBytecodeCache.""" def set(self, key, value, timeout): self[key] = value # pragma: no cover class DummyEnviron(dict): def get_template(self, path): # pragma: no cover return path class DummyTemplate(object): def render(self, system): return b"result".decode("utf-8") class DummyRendererInfo(object): def __init__(self, kw): self.__dict__.update(kw) if "registry" in self.__dict__: self.settings = self.registry.settings pyramid_jinja2-2.10.1/tests/test_settings.py000066400000000000000000000165751456106733600211410ustar00rootroot00000000000000import os.path import unittest class Test_parse_named_assetspecs(unittest.TestCase): def _callFUT(self, *args, **kwargs): from pyramid_jinja2.settings import parse_named_assetspecs return parse_named_assetspecs(*args, **kwargs) def test_it_with_strings(self): from pyramid.path import DottedNameResolver import pyramid_jinja2 import tests resolver = DottedNameResolver() result = self._callFUT( """ foo = pyramid_jinja2 bar = tests """, resolver.maybe_resolve, ) self.assertEqual(result["foo"], pyramid_jinja2) self.assertEqual(result["bar"], tests) def test_it_with_dict(self): from pyramid.path import DottedNameResolver import pyramid_jinja2 import tests resolver = DottedNameResolver() result = self._callFUT( { "foo": "pyramid_jinja2", "bar": tests, }, resolver.maybe_resolve, ) self.assertEqual(result["foo"], pyramid_jinja2) self.assertEqual(result["bar"], tests) class Test_parse_loader_options_from_settings(unittest.TestCase): def _callFUT(self, *args, **kwargs): from pyramid_jinja2.settings import parse_loader_options_from_settings return parse_loader_options_from_settings(*args, **kwargs) def test_defaults(self): options = self._callFUT({}, "p.", None, None) self.assertEqual(options["debug"], False) self.assertEqual(options["encoding"], "utf-8") self.assertEqual(len(options["searchpath"]), 0) def test_options(self): options = self._callFUT( { "debug_templates": "false", "p.debug_templates": "true", "p.input_encoding": "ascii", "p.directories": "tests:templates", }, "p.", None, None, ) self.assertEqual(options["debug"], True) self.assertEqual(options["encoding"], "ascii") self.assertEqual(len(options["searchpath"]), 1) self.assertTrue( options["searchpath"][0].endswith( os.path.join("pyramid_jinja2", "tests", "templates") ) ) def test_options_with_spec(self): options = self._callFUT({"p.directories": "pyramid_jinja2:"}, "p.", None, None) self.assertEqual(len(options["searchpath"]), 1) self.assertTrue(options["searchpath"][0].endswith("pyramid_jinja2")) def test_options_with_abspath(self): import os.path here = os.path.dirname(os.path.abspath(__file__)) options = self._callFUT({"p.directories": here}, "p.", None, None) self.assertEqual(len(options["searchpath"]), 1) self.assertEqual(options["searchpath"][0], here) def test_options_with_relpath(self): import os import pyramid_jinja2 options = self._callFUT({"p.directories": "foo"}, "p.", None, pyramid_jinja2) self.assertEqual(len(options["searchpath"]), 1) self.assertEqual( options["searchpath"][0].split(os.sep)[-2:], ["pyramid_jinja2", "foo"] ) def test_debug_fallback(self): options = self._callFUT( { "debug_templates": "true", }, "p.", None, None, ) self.assertEqual(options["debug"], True) class Test_parse_env_options_from_settings(unittest.TestCase): def _callFUT(self, settings, prefix=""): from pyramid.path import DottedNameResolver import pyramid_jinja2 from pyramid_jinja2.settings import parse_env_options_from_settings resolver = DottedNameResolver() return parse_env_options_from_settings( settings, prefix, resolver.maybe_resolve, pyramid_jinja2, ) def test_most_settings(self): from pyramid_jinja2.i18n import GetTextWrapper settings = { "j2.block_start_string": "<<<", "j2.block_end_string": ">>>", "j2.variable_start_string": "<|<", "j2.variable_end_string": ">|>", "j2.comment_start_string": "<+<", "j2.comment_end_string": ">+>", "j2.line_statement_prefix": ">.>", "j2.line_comment_prefix": "^.^", "j2.trim_blocks": "true", "j2.newline_sequence": "\r", "j2.optimized": "true", "j2.autoescape": "false", "j2.cache_size": "300", } opts = self._callFUT(settings, "j2.") # test self.assertEqual(opts["block_start_string"], "<<<") self.assertEqual(opts["block_end_string"], ">>>") self.assertEqual(opts["variable_start_string"], "<|<") self.assertEqual(opts["variable_end_string"], ">|>") self.assertEqual(opts["comment_start_string"], "<+<") self.assertEqual(opts["comment_end_string"], ">+>") self.assertEqual(opts["line_statement_prefix"], ">.>") self.assertEqual(opts["line_comment_prefix"], "^.^") self.assertEqual(opts["trim_blocks"], True) self.assertEqual(opts["newline_sequence"], "\r") self.assertEqual(opts["optimized"], True) self.assertEqual(opts["autoescape"], False) self.assertEqual(opts["cache_size"], 300) self.assertEqual(opts["gettext"].domain, "pyramid_jinja2") self.assertFalse("finalize" in opts) self.assertTrue(isinstance(opts["gettext"], GetTextWrapper)) def test_finalize(self): settings = { "j2.finalize": "tests.test_settings._fake_finalize", } opts = self._callFUT(settings, "j2.") self.assertTrue(opts["finalize"] is _fake_finalize) def test_override_gettext(self): class FakeGettextWrapper(object): def __init__(self, domain): self.domain = domain settings = { "j2.i18n.gettext": FakeGettextWrapper, "j2.i18n.domain": "testdomain", } opts = self._callFUT(settings, "j2.") self.assertTrue(isinstance(opts["gettext"], FakeGettextWrapper)) self.assertEqual(opts["gettext"].domain, "testdomain") def test_strict_undefined(self): from jinja2 import StrictUndefined settings = {"j2.undefined": "strict"} opts = self._callFUT(settings, "j2.") self.assertEqual(opts["undefined"], StrictUndefined) def test_debug_undefined(self): from jinja2 import DebugUndefined settings = {"j2.undefined": "debug"} opts = self._callFUT(settings, "j2.") self.assertEqual(opts["undefined"], DebugUndefined) def test_default_undefined(self): from jinja2 import Undefined settings = {"j2.undefined": ""} opts = self._callFUT(settings, "j2.") self.assertEqual(opts["undefined"], Undefined) def test_default_extensions(self): opts = self._callFUT({}, "j2.") self.assertEqual(opts["extensions"], ["jinja2.ext.i18n"]) def test_override_i18n_extension(self): settings = { "j2.i18n_extension": "test.TestI18NExtension", } opts = self._callFUT(settings, "j2.") self.assertEqual(opts["extensions"], ["test.TestI18NExtension"]) # This is just a fake top level name that we can pass into maybe_dotted that # will resolve. _fake_finalize = object() pyramid_jinja2-2.10.1/tox.ini000066400000000000000000000035501456106733600160260ustar00rootroot00000000000000[tox] envlist = lint, py37,py38,py39,py310,py311,py312,pypy3, py39-pyramid{13,14,15,16,17,18,110,20}, py39-jinja2legacy, coverage, docs [testenv] commands = python --version pytest {posargs:} deps = pyramid13: pyramid <= 1.3.99 pyramid14: pyramid <= 1.4.99 pyramid15: pyramid <= 1.5.99 pyramid16: pyramid <= 1.6.99 pyramid17: pyramid <= 1.7.99 pyramid18: pyramid <= 1.8.99 pyramid19: pyramid <= 1.9.99 pyramid110: pyramid <= 1.10.99 pyramid20: pyramid <= 2.0.99 jinja2legacy: jinja2 < 3.0 jinja2legacy: markupsafe < 2.0 extras = testing setenv = COVERAGE_FILE=.coverage.{envname} [testenv:coverage] commands = coverage combine coverage xml coverage report --fail-under=100 deps = coverage setenv = COVERAGE_FILE=.coverage [testenv:docs] allowlist_externals = make commands = make -C docs html epub BUILDDIR={envdir} extras = docs [testenv:lint] skip_install = True commands = isort --check-only --df src/pyramid_jinja2 tests demo black --check --diff src/pyramid_jinja2 tests demo flake8 src/pyramid_jinja2/ tests demo check-manifest # build sdist/wheel python -m build . twine check dist/* deps = black build check-manifest flake8 flake8-bugbear isort readme_renderer twine [testenv:format] skip_install = true commands = isort src/pyramid_jinja2 tests demo black src/pyramid_jinja2 tests demo deps = black isort [testenv:build] skip_install = true commands = # clean up build/ and dist/ folders python -c 'import shutil; shutil.rmtree("build", ignore_errors=True)' # Make sure we aren't forgetting anything check-manifest # build sdist/wheel python -m build . # Verify all is well twine check dist/* deps = build check-manifest readme_renderer twine