Bert JW Regeer
2016-04-13 f3420699895969e825913da51dedfa5b880bc7d5
Merge branch 'master' into feature/BeforeTraversal
17 files deleted
37 files added
151 files modified
4745 ■■■■■ changed files
.travis.yml 2 ●●●●● patch | view | raw | blame | history
CHANGES.txt 15 ●●●●● patch | view | raw | blame | history
docs/conf.py 3 ●●●● patch | view | raw | blame | history
docs/conventions.rst 4 ●●●● patch | view | raw | blame | history
docs/glossary.rst 34 ●●●● patch | view | raw | blame | history
docs/narr/MyProject/README.txt 11 ●●●●● patch | view | raw | blame | history
docs/narr/MyProject/development.ini 4 ●●●● patch | view | raw | blame | history
docs/narr/MyProject/myproject/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
docs/narr/MyProject/myproject/templates/mytemplate.pt 6 ●●●● patch | view | raw | blame | history
docs/narr/MyProject/myproject/tests.py 2 ●●● patch | view | raw | blame | history
docs/narr/MyProject/production.ini 4 ●●●● patch | view | raw | blame | history
docs/narr/MyProject/setup.py 21 ●●●●● patch | view | raw | blame | history
docs/narr/commandline.rst 116 ●●●●● patch | view | raw | blame | history
docs/narr/extending.rst 4 ●●●● patch | view | raw | blame | history
docs/narr/i18n.rst 37 ●●●● patch | view | raw | blame | history
docs/narr/install.rst 393 ●●●● patch | view | raw | blame | history
docs/narr/introduction.rst 15 ●●●● patch | view | raw | blame | history
docs/narr/project.rst 178 ●●●●● patch | view | raw | blame | history
docs/narr/testing.rst 47 ●●●●● patch | view | raw | blame | history
docs/narr/upgrading.rst 2 ●●●●● patch | view | raw | blame | history
docs/quick_tour.rst 168 ●●●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/README.txt 2 ●●● patch | view | raw | blame | history
docs/quick_tour/sqla_demo/sqla_demo/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
docs/quick_tutorial/authentication.rst 4 ●●● patch | view | raw | blame | history
docs/quick_tutorial/authorization.rst 4 ●●● patch | view | raw | blame | history
docs/quick_tutorial/conf.py 281 ●●●●● patch | view | raw | blame | history
docs/quick_tutorial/databases.rst 6 ●●●● patch | view | raw | blame | history
docs/quick_tutorial/debugtoolbar.rst 7 ●●●●● patch | view | raw | blame | history
docs/quick_tutorial/forms.rst 2 ●●● patch | view | raw | blame | history
docs/quick_tutorial/functional_testing.rst 4 ●●●● patch | view | raw | blame | history
docs/quick_tutorial/hello_world.rst 2 ●●● patch | view | raw | blame | history
docs/quick_tutorial/ini.rst 2 ●●● patch | view | raw | blame | history
docs/quick_tutorial/jinja2.rst 4 ●●●● patch | view | raw | blame | history
docs/quick_tutorial/json.rst 2 ●●● patch | view | raw | blame | history
docs/quick_tutorial/logging.rst 2 ●●● patch | view | raw | blame | history
docs/quick_tutorial/more_view_classes.rst 2 ●●● patch | view | raw | blame | history
docs/quick_tutorial/package.rst 38 ●●●●● patch | view | raw | blame | history
docs/quick_tutorial/request_response.rst 2 ●●● patch | view | raw | blame | history
docs/quick_tutorial/requirements.rst 137 ●●●●● patch | view | raw | blame | history
docs/quick_tutorial/routing.rst 2 ●●● patch | view | raw | blame | history
docs/quick_tutorial/scaffolds.rst 11 ●●●● patch | view | raw | blame | history
docs/quick_tutorial/sessions.rst 2 ●●● patch | view | raw | blame | history
docs/quick_tutorial/static_assets.rst 2 ●●● patch | view | raw | blame | history
docs/quick_tutorial/templating.rst 2 ●●● patch | view | raw | blame | history
docs/quick_tutorial/tutorial_approach.rst 2 ●●● patch | view | raw | blame | history
docs/quick_tutorial/unit_testing.rst 4 ●●●● patch | view | raw | blame | history
docs/quick_tutorial/view_classes.rst 2 ●●● patch | view | raw | blame | history
docs/quick_tutorial/views.rst 2 ●●● patch | view | raw | blame | history
docs/tutorials/modwsgi/index.rst 29 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/authorization.rst 40 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/background.rst 2 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/basiclayout.rst 33 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/definingmodels.rst 9 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/definingviews.rst 39 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/design.rst 2 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/distributing.rst 19 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/index.rst 1 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/installation.rst 321 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/authorization/CHANGES.txt 3 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/authorization/README.txt 8 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/authorization/development.ini 8 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/authorization/production.ini 6 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/authorization/setup.py 21 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/authorization/tutorial/models.py 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/authorization/tutorial/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt 5 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/authorization/tutorial/tests.py 124 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/authorization/tutorial/views.py 33 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/basiclayout/README.txt 8 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/basiclayout/development.ini 8 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/basiclayout/production.ini 6 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/basiclayout/setup.py 21 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/basiclayout/tutorial/models.py 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/basiclayout/tutorial/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt 5 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/basiclayout/tutorial/tests.py 1 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/installation/CHANGES.txt 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/installation/MANIFEST.in 2 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/installation/README.txt 12 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/installation/development.ini 65 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/installation/production.ini 60 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/installation/setup.py 53 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/installation/tutorial/__init__.py 18 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/installation/tutorial/models.py 14 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/installation/tutorial/static/pyramid-16x16.png patch | view | raw | blame | history
docs/tutorials/wiki/src/installation/tutorial/static/pyramid.png patch | view | raw | blame | history
docs/tutorials/wiki/src/installation/tutorial/static/theme.css 154 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/installation/tutorial/templates/mytemplate.pt 67 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/installation/tutorial/tests.py 17 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/installation/tutorial/views.py 7 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/models/CHANGES.txt 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/models/README.txt 8 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/models/development.ini 8 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/models/production.ini 6 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/models/setup.py 21 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/models/tutorial/models.py 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/models/tutorial/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt 5 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/models/tutorial/tests.py 44 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/tests/CHANGES.txt 3 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/tests/README.txt 8 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/tests/development.ini 8 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/tests/production.ini 6 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/tests/setup.py 22 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/tests/tutorial/__init__.py 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/tests/tutorial/models.py 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/tests/tutorial/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt 5 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/tests/tutorial/tests.py 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/tests/tutorial/views.py 33 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/views/CHANGES.txt 5 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/views/README.txt 8 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/views/development.ini 8 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/views/production.ini 6 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/views/setup.py 21 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/views/tutorial/models.py 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/views/tutorial/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt 5 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/views/tutorial/tests.py 127 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/tests.rst 46 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/authorization.rst 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/background.rst 2 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/basiclayout.rst 2 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/definingmodels.rst 101 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/definingviews.rst 6 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/design.rst 2 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/distributing.rst 2 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/installation.rst 265 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/authentication/README.txt 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/authentication/development.ini 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/authentication/production.ini 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/authentication/setup.py 21 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/authentication/tutorial/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/authentication/tutorial/tests.py 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/authorization/README.txt 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/authorization/development.ini 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/authorization/production.ini 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/authorization/setup.py 21 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/authorization/tutorial/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/authorization/tutorial/tests.py 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/basiclayout/README.txt 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/basiclayout/development.ini 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/basiclayout/production.ini 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/basiclayout/setup.py 21 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/basiclayout/tutorial/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/basiclayout/tutorial/templates/layout.jinja2 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.jinja2 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/CHANGES.txt 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/MANIFEST.in 2 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/README.txt 14 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/development.ini 71 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/production.ini 60 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/setup.py 55 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/__init__.py 12 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py 73 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/models/meta.py 16 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/models/mymodel.py 18 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/routes.py 3 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/scripts/__init__.py 1 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/scripts/initializedb.py 45 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/static/pyramid-16x16.png patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/static/pyramid.png patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/static/theme.css 154 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/templates/404.jinja2 8 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja2 66 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/templates/mytemplate.jinja2 8 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/tests.py 65 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/views/__init__.py patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/views/default.py 33 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/installation/tutorial/views/notfound.py 7 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/models/README.txt 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/models/development.ini 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/models/production.ini 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/models/setup.py 21 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/models/tutorial/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/models/tutorial/templates/layout.jinja2 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.jinja2 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/models/tutorial/tests.py 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/tests/README.txt 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/tests/development.ini 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/tests/production.ini 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/tests/setup.py 21 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/tests/tutorial/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/tests/tutorial/tests/test_functional.py 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/views/README.txt 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/views/development.ini 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/views/production.ini 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/views/setup.py 21 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/views/tutorial/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/views/tutorial/tests.py 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/tests.rst 16 ●●●●● patch | view | raw | blame | history
pyramid/scaffolds/alchemy/+package+/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
pyramid/scaffolds/alchemy/README.txt_tmpl 2 ●●● patch | view | raw | blame | history
pyramid/scaffolds/alchemy/setup.py_tmpl 21 ●●●●● patch | view | raw | blame | history
pyramid/scaffolds/starter/+package+/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
pyramid/scaffolds/starter/+package+/tests.py_tmpl 12 ●●●●● patch | view | raw | blame | history
pyramid/scaffolds/starter/README.txt_tmpl 11 ●●●●● patch | view | raw | blame | history
pyramid/scaffolds/starter/setup.py_tmpl 21 ●●●●● patch | view | raw | blame | history
pyramid/scaffolds/zodb/+package+/static/theme.css 8 ●●●●● patch | view | raw | blame | history
pyramid/scaffolds/zodb/+package+/static/theme.min.css 1 ●●●● patch | view | raw | blame | history
pyramid/scaffolds/zodb/README.txt_tmpl 11 ●●●●● patch | view | raw | blame | history
pyramid/scaffolds/zodb/setup.py_tmpl 21 ●●●●● patch | view | raw | blame | history
setup.py 48 ●●●● patch | view | raw | blame | history
tox.ini 11 ●●●● patch | view | raw | blame | history
.travis.yml
@@ -4,8 +4,6 @@
matrix:
    include:
        - python: 2.6
          env: TOXENV=py26
        - python: 2.7
          env: TOXENV=py27
        - python: 3.3
CHANGES.txt
@@ -1,6 +1,21 @@
unreleased
==========
- Python 2.6 is no longer supported by Pyramid. See
  https://github.com/Pylons/pyramid/issues/2368
- A complete overhaul of the docs:
  - Use pip instead of easy_install.
  - Become opinionated by preferring Python 3.4 or greater to simplify
    installation of Python and its required packaging tools.
  - Use venv for the tool, and virtual environment for the thing created,
    instead of virtualenv.
  - Use py.test and pytest-cov instead of nose and coverage.
  - Further updates to the scaffolds as well as tutorials and their src files.
  See https://github.com/Pylons/pyramid/pull/2468
- A complete overhaul of the ``alchemy`` scaffold as well as the
  Wiki2 SQLAlchemy + URLDispatch tutorial to introduce more modern features
  into the usage of SQLAlchemy with Pyramid and provide a better starting
docs/conf.py
@@ -66,8 +66,7 @@
    'deform': ('http://docs.pylonsproject.org/projects/deform/en/latest', None),
    'jinja2': ('http://docs.pylonsproject.org/projects/pyramid-jinja2/en/latest/', None),
    'pylonswebframework': ('http://docs.pylonsproject.org/projects/pylons-webframework/en/latest/', None),
    'python': ('http://docs.python.org', None),
    'python3': ('http://docs.python.org/3', None),
    'python': ('https://docs.python.org/3', None),
    'sqla': ('http://docs.sqlalchemy.org/en/latest', None),
    'tm': ('http://docs.pylonsproject.org/projects/pyramid-tm/en/latest/', None),
    'toolbar': ('http://docs.pylonsproject.org/projects/pyramid-debugtoolbar/en/latest', None),
docs/conventions.rst
@@ -57,7 +57,7 @@
     $ $VENV/bin/nosetests
(See :term:`virtualenv` for the meaning of ``$VENV``)
(See :term:`venv` for the meaning of ``$VENV``)
Example blocks representing Windows ``cmd.exe`` commands are prefixed with a
drive letter and/or a directory name, e.g.:
@@ -66,7 +66,7 @@
     c:\examples> %VENV%\Scripts\nosetests
(See :term:`virtualenv` for the meaning of ``%VENV%``)
(See :term:`venv` for the meaning of ``%VENV%``)
Sometimes, when it's unknown which directory is current, Windows ``cmd.exe``
example block commands are prefixed only with a ``>`` character, e.g.:
docs/glossary.rst
@@ -155,9 +155,9 @@
     request before it returns a :term:`context` resource.
   virtualenv
     A term referring both to an isolated Python environment,
     or `the leading tool <http://www.virtualenv.org>`_ that allows one to
     create such environments.
     The `virtualenv tool <https://virtualenv.pypa.io/en/latest/>`_ that allows
     one to create virtual environments. In Python 3.3 and greater,
     :term:`venv` is the preferred tool.
     Note: whenever you encounter commands prefixed with ``$VENV`` (Unix)
     or ``%VENV`` (Windows), know that that is the environment variable whose
@@ -1012,8 +1012,8 @@
   console script
     A script written to the ``bin`` (on UNIX, or ``Scripts`` on Windows)
     directory of a Python installation or :term:`virtualenv` as the result of
     running ``setup.py install`` or ``setup.py develop``.
     directory of a Python installation or :term:`virtual environment` as the
     result of running ``pip install`` or ``pip install -e .``.
   introspector
     An object with the methods described by
@@ -1098,3 +1098,27 @@
      implementing the :class:`pyramid.interfaces.IViewDeriver` interface.
      Examples of built-in derivers including view mapper, the permission
      checker, and applying a renderer to a dictionary returned from the view.
   pip
      The `Python Packaging Authority's <https://www.pypa.io/>`_ recommended
      tool for installing Python packages.
   pyvenv
      The Python Packaging Authority formerly recommended using this command
      for `creating virtual environments on Python 3.4 and 3.5
      <https://packaging.python.org/en/latest/installing/#creating-virtual-environments>`_,
      but it is deprecated in 3.6 in favor of ``python3 -m venv`` on UNIX or
      ``python -m venv`` on Windows, which is backward compatible on Python
      3.3 and greater.
   virtual environment
      An isolated Python environment that allows packages to be installed for
      use by a particular application, rather than being installed system wide.
   venv
      The `Python Packaging Authority's <https://www.pypa.io/>`_ recommended
      tool for creating virtual environments on Python 3.3 and greater.
      Note: whenever you encounter commands prefixed with ``$VENV`` (Unix)
      or ``%VENV`` (Windows), know that that is the environment variable whose
      value is the root of the virtual environment in question.
docs/narr/MyProject/README.txt
@@ -1 +1,12 @@
MyProject README
==================
Getting Started
---------------
- cd <directory containing this file>
- $VENV/bin/pip install -e .
- $VENV/bin/pserve development.ini
docs/narr/MyProject/development.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -29,7 +29,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
docs/narr/MyProject/myproject/static/theme.min.css
File was deleted
docs/narr/MyProject/myproject/templates/mytemplate.pt
@@ -34,15 +34,15 @@
          <div class="col-md-10">
            <div class="content">
              <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Starter scaffold</span></h1>
              <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework 1.6b2</span>.</p>
              <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework 1.7</span>.</p>
            </div>
          </div>
        </div>
        <div class="row">
          <div class="links">
            <ul>
              <li class="current-version">Generated by v1.6b2</li>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/1.6-branch/">Docs</a></li>
              <li class="current-version">Generated by v1.7</li>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/">Docs</a></li>
              <li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
              <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="irc://irc.freenode.net#pyramid">IRC Channel</a></li>
              <li><i class="glyphicon glyphicon-home icon-muted"></i><a href="http://pylonsproject.org">Pylons Project</a></li>
docs/narr/MyProject/myproject/tests.py
@@ -26,4 +26,4 @@
    def test_root(self):
        res = self.testapp.get('/', status=200)
        self.assertTrue('Pyramid' in res.body)
        self.assertTrue(b'Pyramid' in res.body)
docs/narr/MyProject/production.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -23,7 +23,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
docs/narr/MyProject/setup.py
@@ -15,16 +15,22 @@
    'waitress',
    ]
tests_require = [
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',  # includes virtualenv
    'pytest-cov',
    ]
setup(name='MyProject',
      version='0.0',
      description='MyProject',
      long_description=README + '\n\n' + CHANGES,
      classifiers=[
        "Programming Language :: Python",
        "Framework :: Pyramid",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
        ],
          "Programming Language :: Python",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
      ],
      author='',
      author_email='',
      url='',
@@ -32,9 +38,10 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      tests_require=requires,
      test_suite="myproject",
      entry_points="""\
      [paste.app_factory]
      main = myproject:main
docs/narr/commandline.rst
@@ -119,7 +119,7 @@
.. seealso:: See also the output of :ref:`pshell --help <pshell_script>`.
Once you've installed your program for development using ``setup.py develop``,
Once you've installed your program for development using ``pip install -e .``,
you can use an interactive Python shell to execute expressions in a Python
environment exactly like the one that will be used when your application runs
"for real".  To do so, use the ``pshell`` command line utility.
@@ -294,7 +294,7 @@
     python
If you want to use a shell that isn't supported out of the box, you can
introduce a new shell by registering an entry point in your setup.py:
introduce a new shell by registering an entry point in your ``setup.py``:
.. code-block:: python
@@ -578,10 +578,10 @@
.. versionadded:: 1.5
Each of Pyramid's console scripts (``pserve``, ``pviews``, etc.) can be run
directly using ``python -m``, allowing custom arguments to be sent to the
directly using ``python3 -m``, allowing custom arguments to be sent to the
Python interpreter at runtime. For example::
      python -3 -m pyramid.scripts.pserve development.ini
      python3 -m pyramid.scripts.pserve development.ini
.. index::
@@ -815,17 +815,17 @@
----------------------------------------
A "console script" is :term:`setuptools` terminology for a script that gets
installed into the ``bin`` directory of a Python :term:`virtualenv` (or "base"
Python environment) when a :term:`distribution` which houses that script is
installed.  Because it's installed into the ``bin`` directory of a virtualenv
when the distribution is installed, it's a convenient way to package and
distribute functionality that you can call from the command-line. It's often
more convenient to create a console script than it is to create a ``.py``
script and instruct people to call it with the "right" Python interpreter.  A
console script generates a file that lives in ``bin``, and when it's invoked it
will always use the "right" Python environment, which means it will always be
invoked in an environment where all the libraries it needs (such as Pyramid)
are available.
installed into the ``bin`` directory of a Python :term:`virtual environment`
(or "base" Python environment) when a :term:`distribution` which houses that
script is installed. Because it's installed into the ``bin`` directory of a
virtual environment when the distribution is installed, it's a convenient way
to package and distribute functionality that you can call from the
command-line. It's often more convenient to create a console script than it is
to create a ``.py`` script and instruct people to call it with the "right"
Python interpreter. A console script generates a file that lives in ``bin``,
and when it's invoked it will always use the "right" Python environment, which
means it will always be invoked in an environment where all the libraries it
needs (such as Pyramid) are available.
In general, you can make your script into a console script by doing the
following:
@@ -840,12 +840,11 @@
  distribution which creates a mapping between a script name and a dotted name
  representing the callable you added to your distribution.
- Run ``setup.py develop``, ``setup.py install``, or ``easy_install`` to get
  your distribution reinstalled.  When you reinstall your distribution, a file
  representing the script that you named in the last step will be in the
  ``bin`` directory of the virtualenv in which you installed the distribution.
  It will be executable.  Invoking it from a terminal will execute your
  callable.
- Run ``pip install -e .`` or ``pip install .`` to get your distribution
  reinstalled. When you reinstall your distribution, a file representing the
  script that you named in the last step will be in the ``bin`` directory of
  the virtual environment in which you installed the distribution. It will be
  executable. Invoking it from a terminal will execute your callable.
As an example, let's create some code that can be invoked by a console script
that prints the deployment settings of a Pyramid application.  To do so, we'll
@@ -927,16 +926,22 @@
   requires = ['pyramid', 'pyramid_debugtoolbar']
   tests_require = [
       'WebTest >= 1.3.1',  # py3 compat
       'pytest',  # includes virtualenv
       'pytest-cov',
       ]
   setup(name='MyProject',
         version='0.0',
         description='My project',
         long_description=README + '\n\n' +  CHANGES,
         classifiers=[
           "Programming Language :: Python",
           "Framework :: Pylons",
           "Topic :: Internet :: WWW/HTTP",
           "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
           ],
             "Programming Language :: Python",
             "Framework :: Pyramid",
             "Topic :: Internet :: WWW/HTTP",
             "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
         ],
         author='',
         author_email='',
         url='',
@@ -945,20 +950,23 @@
         include_package_data=True,
         zip_safe=False,
         install_requires=requires,
         tests_require=requires,
         test_suite="myproject",
         extras_require={
             'testing': tests_require,
         },
         entry_points = """\
         [paste.app_factory]
         main = myproject:main
         """,
         )
We're going to change the setup.py file to add a ``[console_scripts]`` section
within the ``entry_points`` string.  Within this section, you should specify a
``scriptname = dotted.path.to:yourfunction`` line.  For example::
We're going to change the ``setup.py`` file to add a ``[console_scripts]``
section within the ``entry_points`` string. Within this section, you should
specify a ``scriptname = dotted.path.to:yourfunction`` line.  For example:
  [console_scripts]
  show_settings = myproject.scripts:settings_show
.. code-block:: ini
   [console_scripts]
   show_settings = myproject.scripts:settings_show
The ``show_settings`` name will be the name of the script that is installed
into ``bin``.  The colon (``:``) between ``myproject.scripts`` and
@@ -971,6 +979,7 @@
.. code-block:: python
   :linenos:
   :emphasize-lines: 43-44
   import os
@@ -984,16 +993,22 @@
   requires = ['pyramid', 'pyramid_debugtoolbar']
   tests_require = [
       'WebTest >= 1.3.1',  # py3 compat
       'pytest',  # includes virtualenv
       'pytest-cov',
       ]
   setup(name='MyProject',
         version='0.0',
         description='My project',
         long_description=README + '\n\n' +  CHANGES,
         classifiers=[
           "Programming Language :: Python",
           "Framework :: Pylons",
           "Topic :: Internet :: WWW/HTTP",
           "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
           ],
             "Programming Language :: Python",
             "Framework :: Pyramid",
             "Topic :: Internet :: WWW/HTTP",
             "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
         ],
         author='',
         author_email='',
         url='',
@@ -1002,8 +1017,9 @@
         include_package_data=True,
         zip_safe=False,
         install_requires=requires,
         tests_require=requires,
         test_suite="myproject",
         extras_require={
             'testing': tests_require,
         },
         entry_points = """\
         [paste.app_factory]
         main = myproject:main
@@ -1012,15 +1028,17 @@
         """,
         )
Once you've done this, invoking ``$$VENV/bin/python setup.py develop`` will
install a file named ``show_settings`` into the ``$somevirtualenv/bin``
directory with a small bit of Python code that points to your entry point.  It
will be executable.  Running it without any arguments will print an error and
exit.  Running it with a single argument that is the path of a config file will
print the settings.  Running it with an ``--omit=foo`` argument will omit the
settings that have keys that start with ``foo``.  Running it with two "omit"
options (e.g., ``--omit=foo --omit=bar``) will omit all settings that have keys
that start with either ``foo`` or ``bar``::
Once you've done this, invoking ``$VENV/bin/pip install -e .`` will install a
file named ``show_settings`` into the ``$somevenv/bin`` directory with a
small bit of Python code that points to your entry point. It will be
executable. Running it without any arguments will print an error and exit.
Running it with a single argument that is the path of a config file will print
the settings. Running it with an ``--omit=foo`` argument will omit the settings
that have keys that start with ``foo``. Running it with two "omit" options
(e.g., ``--omit=foo --omit=bar``) will omit all settings that have keys that
start with either ``foo`` or ``bar``:
.. code-block:: bash
  $ $VENV/bin/show_settings development.ini --omit=pyramid --omit=debugtoolbar
  debug_routematch                             False
docs/narr/extending.rst
@@ -197,8 +197,8 @@
  elements, such as templates and static assets as necessary.
- Install the new package into the same Python environment as the original
  application (e.g., ``$VENV/bin/python setup.py develop`` or
  ``$VENV/bin/python setup.py install``).
  application (e.g., ``$VENV/bin/pip install -e .`` or ``$VENV/bin/pip install
  .``).
- Change the ``main`` function in the new package's ``__init__.py`` to include
  the original :app:`Pyramid` application's configuration functions via
docs/narr/i18n.rst
@@ -265,18 +265,18 @@
package name is almost always ``gettext``. For example on a Debian or Ubuntu
system run this command:
.. code-block:: text
.. code-block:: bash
   $ sudo apt-get install gettext
Installing Lingua is done with the Python packaging tools. If the
:term:`virtualenv` into which you've installed your :app:`Pyramid` application
lives in ``/my/virtualenv``, you can install Lingua like so:
:term:`virtual environment` into which you've installed your :app:`Pyramid`
application lives at the environment variable ``$VENV``, you can install Lingua
like so:
.. code-block:: text
.. code-block:: bash
   $ cd /my/virtualenv
   $ $VENV/bin/easy_install lingua
   $ $VENV/bin/pip install lingua
Installation on Windows
+++++++++++++++++++++++
@@ -288,12 +288,13 @@
``$PATH``.
Installing Lingua is done with the Python packaging tools. If the
:term:`virtualenv` into which you've installed your :app:`Pyramid` application
lives in ``C:\my\virtualenv``, you can install Lingua like so:
:term:`virtual environment` into which you've installed your :app:`Pyramid`
application lives at the environment variable ``%VENV%``, you can install
Lingua like so:
.. code-block:: text
.. code-block:: ps1con
   C> %VENV%\Scripts\easy_install lingua
   C> %VENV%\Scripts\pip install lingua
.. index::
@@ -308,9 +309,9 @@
code and :term:`Chameleon` templates which reside in your :app:`Pyramid`
application.  You run a ``pot-create`` command to extract the messages:
.. code-block:: text
.. code-block:: bash
   $ cd /place/where/myapplication/setup.py/lives
   $ cd /file/path/to/myapplication_setup.py
   $ mkdir -p myapplication/locale
   $ $VENV/bin/pot-create -o myapplication/locale/myapplication.pot src
@@ -331,9 +332,9 @@
Initialize a ``.po`` file for a specific locale from a pre-generated ``.pot``
template by using the ``msginit`` command from Gettext:
.. code-block:: text
.. code-block:: bash
   $ cd /place/where/myapplication/setup.py/lives
   $ cd /file/path/to/myapplication_setup.py
   $ cd myapplication/locale
   $ mkdir -p es/LC_MESSAGES
   $ msginit -l es -o es/LC_MESSAGES/myapplication.po
@@ -362,9 +363,9 @@
First, regenerate the ``.pot`` file as per :ref:`extracting_messages`. Then use
the ``msgmerge`` command from Gettext.
.. code-block:: text
.. code-block:: bash
   $ cd /place/where/myapplication/setup.py/lives
   $ cd /file/path/to/myapplication_setup.py
   $ cd myapplication/locale
   $ msgmerge --update es/LC_MESSAGES/myapplication.po myapplication.pot
@@ -380,9 +381,9 @@
compile ``.po`` files to ``.mo`` files using the ``msgfmt`` command from
Gettext:
.. code-block:: text
.. code-block:: bash
   $ cd /place/where/myapplication/setup.py/lives
   $ cd /file/path/to/myapplication_setup.py
   $ msgfmt -o myapplication/locale/es/LC_MESSAGES/myapplication.mo \
         myapplication/locale/es/LC_MESSAGES/myapplication.po
docs/narr/install.rst
@@ -3,38 +3,54 @@
Installing :app:`Pyramid`
=========================
.. note::
    This installation guide emphasizes the use of Python 3.4 and greater for
    simplicity.
.. index::
   single: install preparation
Before You Install
------------------
Before You Install Pyramid
--------------------------
You will need `Python <http://python.org>`_ version 2.6 or better to run
:app:`Pyramid`.
Install Python version 3.4 or greater for your operating system, and satisfy
the :ref:`requirements-for-installing-packages`, as described in
the following sections.
.. sidebar:: Python Versions
    As of this writing, :app:`Pyramid` has been tested under Python 2.6, Python
    2.7, Python 3.3, Python 3.4, Python 3.5, PyPy, and PyPy3. :app:`Pyramid`
    does not run under any version of Python before 2.6.
    As of this writing, :app:`Pyramid` has been tested under Python 2.7,
    Python 3.3, Python 3.4, Python 3.5, PyPy, and PyPy3. :app:`Pyramid` does
    not run under any version of Python before 2.7.
:app:`Pyramid` is known to run on all popular UNIX-like systems such as Linux,
Mac OS X, and FreeBSD as well as on Windows platforms.  It is also known to run
on :term:`PyPy` (1.9+).
Mac OS X, and FreeBSD, as well as on Windows platforms.  It is also known to
run on :term:`PyPy` (1.9+).
:app:`Pyramid` installation does not require the compilation of any C code, so
you need only a Python interpreter that meets the requirements mentioned.
:app:`Pyramid` installation does not require the compilation of any C code.
However, some :app:`Pyramid` dependencies may attempt to build binary
extensions from C code for performance speed ups. If a compiler or Python
headers are unavailable, the dependency will fall back to using pure Python
instead.
Some :app:`Pyramid` dependencies may attempt to build C extensions for
performance speedups. If a compiler or Python headers are unavailable the
dependency will fall back to using pure Python instead.
.. note::
   If you see any warnings or errors related to failing to compile the binary
   extensions, in most cases you may safely ignore those errors. If you wish to
   use the binary extensions, please verify that you have a functioning
   compiler and the Python header files installed for your operating system.
.. _for-mac-os-x-users:
For Mac OS X Users
~~~~~~~~~~~~~~~~~~
Python comes pre-installed on Mac OS X, but due to Apple's release cycle, it is
often out of date. Unless you have a need for a specific earlier version, it is
recommended to install the latest 2.x or 3.x version of Python.
recommended to install the latest 3.x version of Python.
You can install the latest verion of Python for Mac OS X from the binaries on
`python.org <https://www.python.org/downloads/mac-osx/>`_.
@@ -43,14 +59,14 @@
.. code-block:: text
   # for python 2.7
   $ brew install python
   # for python 3.5
   # for python 3.x
   $ brew install python3
If you use an installer for your Python, then you can skip to the section
:ref:`installing_unix`.
.. _if-you-don-t-yet-have-a-python-interpreter-unix:
If You Don't Yet Have a Python Interpreter (UNIX)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -60,250 +76,101 @@
can install Python from source fairly easily on any UNIX system that has
development tools.
.. index::
   pair: install; Python (from package, UNIX)
.. seealso:: See the official Python documentation :ref:`Using Python on Unix
   platforms <python:using-on-unix>` for full details.
Package Manager Method
++++++++++++++++++++++
You can use your system's "package manager" to install Python. Each package
manager is slightly different, but the "flavor" of them is usually the same.
For example, on a Debian or Ubuntu system, use the following command:
.. code-block:: text
   $ sudo apt-get install python2.7-dev
This command will install both the Python interpreter and its development
header files.  Note that the headers are required by some (optional) C
extensions in software depended upon by Pyramid, not by Pyramid itself.
Once these steps are performed, the Python interpreter will usually be
invokable via ``python2.7`` from a shell prompt.
.. index::
   pair: install; Python (from source, UNIX)
Source Compile Method
+++++++++++++++++++++
It's useful to use a Python interpreter that *isn't* the "system" Python
interpreter to develop your software.  The authors of :app:`Pyramid` tend not
to use the system Python for development purposes; always a self-compiled one.
Compiling Python is usually easy, and often the "system" Python is compiled
with options that aren't optimal for web development. For an explanation, see
https://github.com/Pylons/pyramid/issues/747.
To compile software on your UNIX system, typically you need development tools.
Often these can be installed via the package manager.  For example, this works
to do so on an Ubuntu Linux system:
.. code-block:: text
   $ sudo apt-get install build-essential
On Mac OS X, installing `XCode <http://developer.apple.com/tools/xcode/>`_ has
much the same effect.
Once you've got development tools installed on your system, you can install a
Python 2.7 interpreter from *source*, on the same system, using the following
commands:
.. code-block:: text
   $ cd ~
   $ mkdir tmp
   $ mkdir opt
   $ cd tmp
   $ wget http://www.python.org/ftp/python/2.7.3/Python-2.7.3.tgz
   $ tar xvzf Python-2.7.3.tgz
   $ cd Python-2.7.3
   $ ./configure --prefix=$HOME/opt/Python-2.7.3
   $ make && make install
Once these steps are performed, the Python interpreter will be invokable via
``$HOME/opt/Python-2.7.3/bin/python`` from a shell prompt.
.. index::
   pair: install; Python (from package, Windows)
.. _if-you-don-t-yet-have-a-python-interpreter-windows:
If You Don't Yet Have a Python Interpreter (Windows)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If your Windows system doesn't have a Python interpreter, you'll need to
install it by downloading a Python 2.7-series interpreter executable from
install it by downloading a Python 3.x-series interpreter executable from
`python.org's download section <http://python.org/download/>`_ (the files
labeled "Windows Installer").  Once you've downloaded it, double click on the
executable and accept the defaults during the installation process. You may
also need to download and install the Python for Windows extensions.
.. seealso:: See the official Python documentation :ref:`Using Python on
   Windows <python:using-on-windows>` for full details.
.. seealso:: Download and install the `Python for Windows extensions
   <http://sourceforge.net/projects/pywin32/files/pywin32/>`_. Carefully read
   the README.txt file at the end of the list of builds, and follow its
   directions. Make sure you get the proper 32- or 64-bit build and Python
   version.
.. warning::
   After you install Python on Windows, you may need to add the ``C:\Python27``
   directory to your environment's ``Path`` in order to make it possible to
   invoke Python from a command prompt by typing ``python``.  To do so, right
   click ``My Computer``, select ``Properties`` --> ``Advanced Tab`` -->
   ``Environment Variables`` and add that directory to the end of the ``Path``
   environment variable.
   After you install Python on Windows, you may need to add the ``C:\Python3x``
   directory to your environment's ``Path``, where ``x`` is the minor version
   of installed Python, in order to make it possible to invoke Python from a
   command prompt by typing ``python``. To do so, right click ``My Computer``,
   select ``Properties`` --> ``Advanced Tab`` --> ``Environment Variables`` and
   add that directory to the end of the ``Path`` environment variable.
   .. seealso:: See `Configuring Python (on Windows)
      <https://docs.python.org/3/using/windows.html#configuring-python>`_ for
      full details.
.. index::
   single: requirements for installing packages
.. _requirements-for-installing-packages:
Requirements for Installing Packages
------------------------------------
Use :term:`pip` for installing packages and ``python3 -m venv env`` for
creating a virtual environment. A virtual environment is a semi-isolated Python
environment that allows packages to be installed for use by a particular
application, rather than being installed system wide.
.. seealso:: See the Python Packaging Authority's (PyPA) documention
   `Requirements for Installing Packages
   <https://packaging.python.org/en/latest/installing/#requirements-for-installing-packages>`_
   for full details.
.. index::
   single: installing on UNIX
   single: installing on Mac OS X
.. _installing_unix:
Installing :app:`Pyramid` on a UNIX System
------------------------------------------
It is best practice to install :app:`Pyramid` into a "virtual" Python
environment in order to obtain isolation from any "system" packages you've got
installed in your Python version.  This can be done by using the
:term:`virtualenv` package.  Using a virtualenv will also prevent
:app:`Pyramid` from globally installing versions of packages that are not
compatible with your system Python.
After installing Python as described previously in :ref:`for-mac-os-x-users` or
:ref:`if-you-don-t-yet-have-a-python-interpreter-unix`, and satisfying the
:ref:`requirements-for-installing-packages`, you can now install Pyramid.
To set up a virtualenv in which to install :app:`Pyramid`, first ensure that
:term:`setuptools` is installed.  To do so, invoke ``import setuptools`` within
the Python interpreter you'd like to run :app:`Pyramid` under.
#. Make a :term:`virtual environment` workspace:
The following command will not display anything if setuptools is already
installed:
   .. code-block:: bash
.. code-block:: text
      $ export VENV=~/env
      $ python3 -m venv $VENV
   $ python2.7 -c 'import setuptools'
   You can either follow the use of the environment variable ``$VENV``, or
   replace it with the root directory of the virtual environment. If you choose
   the former approach, ensure that ``$VENV`` is an absolute path. In the
   latter case, the ``export`` command can be skipped.
Running the same command will yield the following output if setuptools is not
yet installed:
#. (Optional) Consider using ``$VENV/bin/activate`` to make your shell
   environment wired to use the virtual environment.
.. code-block:: text
#. Use ``pip`` to get :app:`Pyramid` and its direct dependencies installed:
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   ImportError: No module named setuptools
   .. parsed-literal::
If ``import setuptools`` raises an :exc:`ImportError` as it does above, you
will need to install setuptools manually.
      $ $VENV/bin/pip install "pyramid==\ |release|\ "
If you are using a "system" Python (one installed by your OS distributor or a
third-party packager such as Fink or MacPorts), you can usually install the
setuptools package by using your system's package manager.  If you cannot do
this, or if you're using a self-installed version of Python, you will need to
install setuptools "by hand".  Installing setuptools "by hand" is always a
reasonable thing to do, even if your package manager already has a pre-chewed
version of setuptools for installation.
Installing Setuptools
~~~~~~~~~~~~~~~~~~~~~
To install setuptools by hand under Python 2, first download `ez_setup.py
<https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py>`_ then invoke
it using the Python interpreter into which you want to install setuptools.
.. code-block:: text
   $ python ez_setup.py
Once this command is invoked, setuptools should be installed on your system.
If the command fails due to permission errors, you may need to be the
administrative user on your system to successfully invoke the script.  To
remediate this, you may need to do:
.. code-block:: text
   $ sudo python ez_setup.py
.. index::
   pair: install; virtualenv
Installing the ``virtualenv`` Package
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Once you've got setuptools installed, you should install the :term:`virtualenv`
package.  To install the :term:`virtualenv` package into your
setuptools-enabled Python interpreter, use the ``easy_install`` command.
.. warning::
   Python 3.3 includes ``pyvenv`` out of the box, which provides similar
   functionality to ``virtualenv``.  We however suggest using ``virtualenv``
   instead, which works well with Python 3.3.  This isn't a recommendation made
   for technical reasons; it's made because it's not feasible for the authors
   of this guide to explain setup using multiple virtual environment systems.
   We are aiming to not need to make the installation documentation
   Turing-complete.
   If you insist on using ``pyvenv``, you'll need to understand how to install
   software such as ``setuptools`` into the virtual environment manually, which
   this guide does not cover.
.. code-block:: text
   $ easy_install virtualenv
This command should succeed, and tell you that the virtualenv package is now
installed.  If it fails due to permission errors, you may need to install it as
your system's administrative user.  For example:
.. code-block:: text
   $ sudo easy_install virtualenv
.. index::
   single: virtualenv
   pair: Python; virtual environment
Creating the Virtual Python Environment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Once the :term:`virtualenv` package is installed in your Python environment,
you can then create a virtual environment.  To do so, invoke the following:
.. code-block:: text
   $ export VENV=~/env
   $ virtualenv $VENV
   New python executable in /home/foo/env/bin/python
   Installing setuptools.............done.
You can either follow the use of the environment variable, ``$VENV``, or
replace it with the root directory of the :term:`virtualenv`. In that case, the
`export` command can be skipped. If you choose the former approach, ensure that
it's an absolute path.
.. warning::
   Avoid using the ``--system-site-packages`` option when creating the
   virtualenv unless you know what you are doing. For versions of virtualenv
   prior to 1.7, make sure to use the ``--no-site-packages`` option, because
   this option was formerly not the default and may produce undesirable
   results.
.. warning::
    *do not* use ``sudo`` to run the ``virtualenv`` script.  It's perfectly
    acceptable (and desirable) to create a virtualenv as a normal user.
Installing :app:`Pyramid` into the Virtual Python Environment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
After you've got your virtualenv installed, you may install :app:`Pyramid`
itself using the following commands:
.. parsed-literal::
   $ $VENV/bin/easy_install "pyramid==\ |release|\ "
The ``easy_install`` command will take longer than the previous ones to
complete, as it downloads and installs a number of dependencies.
.. note::
   If you see any warnings and/or errors related to failing to compile the C
   extensions, in most cases you may safely ignore those errors. If you wish to
   use the C extensions, please verify that you have a functioning compiler and
   the Python header files installed.
.. index::
   single: installing on Windows
@@ -313,72 +180,38 @@
Installing :app:`Pyramid` on a Windows System
---------------------------------------------
You can use Pyramid on Windows under Python 2 or 3.
After installing Python as described previously in
:ref:`if-you-don-t-yet-have-a-python-interpreter-windows`, and satisfying the
:ref:`requirements-for-installing-packages`, you can now install Pyramid.
#. Download and install the most recent `Python 2.7.x or 3.3.x version
   <http://www.python.org/download/>`_ for your system.
#. Make a :term:`virtual environment` workspace:
#. Download and install the `Python for Windows extensions
   <http://sourceforge.net/projects/pywin32/files/pywin32/>`_. Carefully read
   the README.txt file at the end of the list of builds, and follow its
   directions. Make sure you get the proper 32- or 64-bit build and Python
   version.
#. Install latest :term:`setuptools` distribution into the Python from step 1
   above: download `ez_setup.py
   <https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py>`_ and run
   it using the ``python`` interpreter of your Python 2.7 or 3.3 installation
   using a command prompt:
   .. code-block:: text
      # modify the command according to the python version, e.g.:
      # for Python 2.7:
      c:\> c:\Python27\python ez_setup.py
      # for Python 3.3:
      c:\> c:\Python33\python ez_setup.py
#. Install `virtualenv`:
   .. code-block:: text
      # modify the command according to the python version, e.g.:
      # for Python 2.7:
      c:\> c:\Python27\Scripts\easy_install virtualenv
      # for Python 3.3:
      c:\> c:\Python33\Scripts\easy_install virtualenv
#. Make a :term:`virtualenv` workspace:
   .. code-block:: text
   .. code-block:: ps1con
      c:\> set VENV=c:\env
      # modify the command according to the python version, e.g.:
      # for Python 2.7:
      c:\> c:\Python27\Scripts\virtualenv %VENV%
      # for Python 3.3:
      c:\> c:\Python33\Scripts\virtualenv %VENV%
      # replace "x" with your minor version of Python 3
      c:\> c:\Python3x\Scripts\python3 -m venv %VENV%
   You can either follow the use of the environment variable, ``%VENV%``, or
   replace it with the root directory of the :term:`virtualenv`. In that case,
   the `set` command can be skipped. If you choose the former approach, ensure
   that it's an absolute path.
   You can either follow the use of the environment variable ``%VENV%``, or
   replace it with the root directory of the virtual environment. If you choose
   the former approach, ensure that ``%VENV%`` is an absolute path. In the
   latter case, the ``set`` command can be skipped.
#. (Optional) Consider using ``%VENV%\Scripts\activate.bat`` to make your shell
   environment wired to use the virtualenv.
   environment wired to use the virtual environment.
#. Use ``easy_install`` to get :app:`Pyramid` and its direct dependencies
   installed:
#. Use ``pip`` to get :app:`Pyramid` and its direct dependencies installed:
   .. parsed-literal::
      c:\\env> %VENV%\\Scripts\\easy_install "pyramid==\ |release|\ "
      c:\\env> %VENV%\\Scripts\\pip install "pyramid==\ |release|\ "
What Gets Installed
-------------------
When you ``easy_install`` :app:`Pyramid`, various other libraries such as
WebOb, PasteDeploy, and others are installed.
When you install :app:`Pyramid`, various libraries such as WebOb, PasteDeploy,
and others are installed.
Additionally, as chronicled in :ref:`project_narr`, scaffolds will be
registered, which make it easy to start a new :app:`Pyramid` project.
docs/narr/introduction.rst
@@ -859,14 +859,15 @@
Every release of Pyramid has 100% statement coverage via unit and integration
tests, as measured by the ``coverage`` tool available on PyPI.  It also has
greater than 95% decision/condition coverage as measured by the
``instrumental`` tool available on PyPI.  It is automatically tested by the
Jenkins tool on Python 2.6, Python 2.7, Python 3.3, Python 3.4, Python 3.5,
PyPy, and PyPy3 after each commit to its GitHub repository. Official Pyramid
add-ons are held to a similar testing standard.  We still find bugs in Pyramid
and its official add-ons, but we've noticed we find a lot more of them while
working on other projects that don't have a good testing regime.
``instrumental`` tool available on PyPI. It is automatically tested by Travis,
and Jenkins on Python 2.7, Python 3.3, Python 3.4, Python 3.5, PyPy, and PyPy3
after each commit to its GitHub repository. Official Pyramid add-ons are held
to a similar testing standard.  We still find bugs in Pyramid and its official
add-ons, but we've noticed we find a lot more of them while working on other
projects that don't have a good testing regime.
Example: http://jenkins.pylonsproject.org/
Travis: https://travis-ci.org/Pylons/pyramid
Jenkins: http://jenkins.pylonsproject.org/job/pyramid/
Support
~~~~~~~
docs/narr/project.rst
@@ -67,14 +67,14 @@
.. seealso:: See also the output of :ref:`pcreate --help <pcreate_script>`.
In :ref:`installing_chapter`, you created a virtual Python environment via the
``virtualenv`` command.  To start a :app:`Pyramid` :term:`project`, use the
``pcreate`` command installed within the virtualenv.  We'll choose the
``venv`` command.  To start a :app:`Pyramid` :term:`project`, use the
``pcreate`` command installed within the virtual environment.  We'll choose the
``starter`` scaffold for this purpose.  When we invoke ``pcreate``, it will
create a directory that represents our project.
In :ref:`installing_chapter` we called the virtualenv directory ``env``. The
following commands assume that our current working directory is the ``env``
directory.
In :ref:`installing_chapter` we called the virtual environment directory
``env``. The following commands assume that our current working directory is
the ``env`` directory.
The below example uses the ``pcreate`` command to create a project with the
``starter`` scaffold.
@@ -90,24 +90,13 @@
.. code-block:: text
   > %VENV%\Scripts\pcreate -s starter MyProject
Here's sample output from a run of ``pcreate`` on UNIX for a project we name
``MyProject``:
.. code-block:: bash
   $ $VENV/bin/pcreate -s starter MyProject
   Creating template pyramid
   Creating directory ./MyProject
   # ... more output ...
   Running /Users/chrism/projects/pyramid/bin/python setup.py egg_info
As a result of invoking the ``pcreate`` command, a directory named
``MyProject`` is created.  That directory is a :term:`project` directory. The
``setup.py`` file in that directory can be used to distribute your application,
or install your application for deployment or development.
A ``.ini`` file named ``development.ini`` will be created in the project
An ``.ini`` file named ``development.ini`` will be created in the project
directory.  You will use this ``.ini`` file to configure a server, to run your
application, and to debug your application.  It contains configuration that
enables an interactive debugger and settings optimized for development.
@@ -123,16 +112,16 @@
which holds very simple :app:`Pyramid` sample code.  This is where you'll edit
your application's Python code and templates.
We created this project within an ``env`` virtualenv directory.  However, note
that this is not mandatory.  The project directory can go more or less anywhere
on your filesystem.  You don't need to put it in a special "web server"
directory, and you don't need to put it within a virtualenv directory.  The
author uses Linux mainly, and tends to put project directories which he creates
within his ``~/projects`` directory.  On Windows, it's a good idea to put
project directories within a directory that contains no space characters, so
it's wise to *avoid* a path that contains, i.e., ``My Documents``.  As a
result, the author, when he uses Windows, just puts his projects in
``C:\projects``.
We created this project within an ``env`` virtual environment directory.
However, note that this is not mandatory. The project directory can go more or
less anywhere on your filesystem. You don't need to put it in a special "web
server" directory, and you don't need to put it within a virtual environment
directory. The author uses Linux mainly, and tends to put project directories
which he creates within his ``~/projects`` directory. On Windows, it's a good
idea to put project directories within a directory that contains no space
characters, so it's wise to *avoid* a path that contains, i.e., ``My
Documents``. As a result, the author, when he uses Windows, just puts his
projects in ``C:\projects``.
.. warning::
@@ -151,8 +140,9 @@
To install a newly created project for development, you should ``cd`` to the
newly created project directory and use the Python interpreter from the
:term:`virtualenv` you created during :ref:`installing_chapter` to invoke the
command ``python setup.py develop``
:term:`virtual environment` you created during :ref:`installing_chapter` to
invoke the command ``pip install -e .``, which installs the project in
development mode (``-e`` is for "editable") into the current directory (``.``).
The file named ``setup.py`` will be in the root of the pcreate-generated
project directory.  The ``python`` you're invoking should be the one that lives
@@ -165,23 +155,24 @@
.. code-block:: bash
   $ cd MyProject
   $ $VENV/bin/python setup.py develop
   $ $VENV/bin/pip install -e .
Or on Windows:
.. code-block:: text
.. code-block:: ps1con
   > cd MyProject
   > %VENV%\Scripts\python.exe setup.py develop
   > %VENV%\Scripts\pip install -e .
Elided output from a run of this command on UNIX is shown below:
.. code-block:: bash
   $ cd MyProject
   $ $VENV/bin/python setup.py develop
   $ $VENV/bin/pip install -e .
   ...
   Finished processing dependencies for MyProject==0.0
   Successfully installed Chameleon-2.24 Mako-1.0.4 MyProject \
   pyramid-chameleon-0.3 pyramid-debugtoolbar-2.4.2 pyramid-mako-1.0.2
This will install a :term:`distribution` representing your project into the
virtual environment interpreter's library set so it can be found by ``import``
@@ -195,65 +186,54 @@
Running the Tests for Your Application
--------------------------------------
To run unit tests for your application, you should invoke them using the Python
interpreter from the :term:`virtualenv` you created during
:ref:`installing_chapter` (the ``python`` command that lives in the ``bin``
directory of your virtualenv).
To run unit tests for your application, you must first install the testing
dependencies.
On UNIX:
.. code-block:: bash
   $ $VENV/bin/python setup.py test -q
   $ $VENV/bin/pip install -e ".[testing]"
Or on Windows:
On Windows:
.. code-block:: text
.. code-block:: ps1con
   > %VENV%\Scripts\python.exe setup.py test -q
   > %VENV%\Scripts\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.
On UNIX:
.. code-block:: bash
   $ $VENV/bin/py.test myproject/tests.py -q
On Windows:
.. code-block:: ps1con
   > %VENV%\Scripts\py.test myproject\tests.py -q
Here's sample output from a test run on UNIX:
.. code-block:: bash
   $ $VENV/bin/python setup.py test -q
   running test
   running egg_info
   writing requirements to MyProject.egg-info/requires.txt
   writing MyProject.egg-info/PKG-INFO
   writing top-level names to MyProject.egg-info/top_level.txt
   writing dependency_links to MyProject.egg-info/dependency_links.txt
   writing entry points to MyProject.egg-info/entry_points.txt
   reading manifest file 'MyProject.egg-info/SOURCES.txt'
   reading manifest template 'MANIFEST.in'
   warning: no files found matching '*.cfg'
   warning: no files found matching '*.rst'
   warning: no files found matching '*.ico' under directory 'myproject'
   warning: no files found matching '*.gif' under directory 'myproject'
   warning: no files found matching '*.jpg' under directory 'myproject'
   warning: no files found matching '*.txt' under directory 'myproject'
   warning: no files found matching '*.mak' under directory 'myproject'
   warning: no files found matching '*.mako' under directory 'myproject'
   warning: no files found matching '*.js' under directory 'myproject'
   warning: no files found matching '*.html' under directory 'myproject'
   warning: no files found matching '*.xml' under directory 'myproject'
   writing manifest file 'MyProject.egg-info/SOURCES.txt'
   running build_ext
   .
   ----------------------------------------------------------------------
   Ran 1 test in 0.008s
   OK
   $ $VENV/bin/py.test myproject/tests.py -q
   ..
   2 passed in 0.47 seconds
The tests themselves are found in the ``tests.py`` module in your ``pcreate``
generated project.  Within a project generated by the ``starter`` scaffold, a
single sample test exists.
generated project.  Within a project generated by the ``starter`` scaffold,
only two sample tests exist.
.. note::
    The ``-q`` option is passed to the ``setup.py test`` command to limit the
    output to a stream of dots.  If you don't pass ``-q``, you'll see more
    verbose test result output (which normally isn't very useful).
    The ``-q`` option is passed to the ``py.test`` command to limit the output
    to a stream of dots. If you don't pass ``-q``, you'll see verbose test
    result output (which normally isn't very useful).
.. index::
   single: running an application
@@ -432,9 +412,8 @@
   # .. other settings ...
   debugtoolbar.hosts = 192.168.1.1
For more information about what the debug toolbar allows you to do, see `the
documentation for pyramid_debugtoolbar
<http://docs.pylonsproject.org/projects/pyramid_debugtoolbar/en/latest/>`_.
For more information about what the debug toolbar allows you to do, see the
:ref:`documentation for pyramid_debugtoolbar <toolbar:overview>`.
The debug toolbar will not be shown (and all debugging will be turned off) when
you use the ``production.ini`` file instead of the ``development.ini`` ini file
@@ -688,16 +667,16 @@
~~~~~~~~~~~~
The ``setup.py`` file is a :term:`setuptools` setup file.  It is meant to be
run directly from the command line to perform a variety of functions, such as
testing, packaging, and distributing your application.
used to define requirements for installing dependencies for your package and
testing, as well as distributing your application.
.. note::
   ``setup.py`` is the de facto standard which Python developers use to
   distribute their reusable code.  You can read more about ``setup.py`` files
   and their usage in the `Setuptools documentation
   <http://peak.telecommunity.com/DevCenter/setuptools>`_ and `Python Packaging
   User Guide <https://packaging.python.org/en/latest/>`_.
   and their usage in the `Python Packaging User Guide
   <https://packaging.python.org/en/latest/>`_ and `Setuptools documentation
   <http://pythonhosted.org/setuptools/>`_.
Our generated ``setup.py`` looks like this:
@@ -706,7 +685,7 @@
   :linenos:
The ``setup.py`` file calls the setuptools ``setup`` function, which does
various things depending on the arguments passed to ``setup.py`` on the command
various things depending on the arguments passed to ``pip`` on the command
line.
Within the arguments to this function call, information about your application
@@ -717,8 +696,8 @@
Your application's name can be any string; it is specified in the ``name``
field.  The version number is specified in the ``version`` value.  A short
description is provided in the ``description`` field.  The ``long_description``
is conventionally the content of the README and CHANGES file appended together.
The ``classifiers`` field is a list of `Trove
is conventionally the content of the ``README`` and ``CHANGES`` files appended
together. The ``classifiers`` field is a list of `Trove
<http://pypi.python.org/pypi?%3Aaction=list_classifiers>`_ classifiers
describing your application.  ``author`` and ``author_email`` are text fields
which probably don't need any description.  ``url`` is a field that should
@@ -726,14 +705,13 @@
causes all packages within the project to be found when packaging the
application.  ``include_package_data`` will include non-Python files when the
application is packaged if those files are checked into version control. 
``zip_safe`` indicates that this package is not safe to use as a zipped egg;
instead it will always unpack as a directory, which is more convenient.
``install_requires`` and ``tests_require`` indicate that this package depends
on the ``pyramid`` package.  ``test_suite`` points at the package for our
application, which means all tests found in the package will be run when
``setup.py test`` is invoked.  We examined ``entry_points`` in our discussion
of the ``development.ini`` file; this file defines the ``main`` entry point
that represents our project's application.
``zip_safe=False`` indicates that this package is not safe to use as a zipped
egg; instead it will always unpack as a directory, which is more convenient.
``install_requires`` indicate that this package depends on the ``pyramid``
package. ``extras_require`` is a Python dictionary that defines what is
required to be installed for running tests. We examined ``entry_points`` in our
discussion of the ``development.ini`` file; this file defines the ``main``
entry point that represents our project's application.
Usually you only need to think about the contents of the ``setup.py`` file when
distributing your application to other people, when adding Python package
@@ -745,7 +723,7 @@
   $ $VENV/bin/python setup.py sdist
This will create a tarball of your application in a ``dist`` subdirectory named
``MyProject-0.1.tar.gz``.  You can send this tarball to other people who want
``MyProject-0.0.tar.gz``.  You can send this tarball to other people who want
to install and use your application.
.. index::
@@ -928,13 +906,13 @@
.. literalinclude:: MyProject/myproject/tests.py
   :language: python
   :lines: 1-17
   :linenos:
This sample ``tests.py`` file has a single unit test defined within it.  This
test is executed when you run ``python setup.py test``.  You may add more tests
here as you build your application.  You are not required to write tests to use
:app:`Pyramid`. This file is simply provided for convenience and example.
This sample ``tests.py`` file has one unit test and one functional test defined
within it. These tests are executed when you run ``py.test myproject/tests.py
-q``. You may add more tests here as you build your application. You are not
required to write tests to use :app:`Pyramid`. This file is simply provided for
convenience and example.
See :ref:`testing_chapter` for more information about writing :app:`Pyramid`
unit tests.
docs/narr/testing.rst
@@ -275,7 +275,7 @@
           
In the above example, we create a ``MyTest`` test case that inherits from
:class:`unittest.TestCase`.  If it's in our :app:`Pyramid` application, it will
be found when ``setup.py test`` is run.  It has two test methods.
be found when ``py.test`` is run.  It has two test methods.
The first test method, ``test_view_fn_forbidden`` tests the ``view_fn`` when
the authentication policy forbids the current user the ``edit`` permission. Its
@@ -365,46 +365,37 @@
In Pyramid, functional tests are typically written using the :term:`WebTest`
package, which provides APIs for invoking HTTP(S) requests to your application.
We also like ``py.test`` and ``pytest-cov`` to provide simple testing and
coverage reports.
Regardless of which testing :term:`package` you use, ensure to add a
``tests_require`` dependency on that package to your application's
``setup.py`` file.  Using the project ``MyProject`` generated by the starter
scaffold as described in :doc:`project`, we would insert the following code immediately following the
``requires`` block in the file ``MyProject/setup.py``.
Regardless of which testing :term:`package` you use, be sure to add a
``tests_require`` dependency on that package to your application's ``setup.py``
file. Using the project ``MyProject`` generated by the starter scaffold as
described in :doc:`project`, we would insert the following code immediately
following the ``requires`` block in the file ``MyProject/setup.py``.
.. code-block:: ini
.. literalinclude:: MyProject/setup.py
    :language: python
    :linenos:
    :lines: 11-22
    :lineno-start: 11
    :emphasize-lines: 8-
    requires = [
        'pyramid',
        'pyramid_chameleon',
        'pyramid_debugtoolbar',
        'waitress',
        ]
    test_requires = [
        'webtest',
        ]
Remember to change the dependency.
.. code-block:: ini
.. literalinclude:: MyProject/setup.py
    :language: python
    :linenos:
    :lineno-start: 39
    :emphasize-lines: 2
    :lines: 40-44
    :lineno-start: 40
    :emphasize-lines: 2-4
      install_requires=requires,
      tests_require=test_requires,
      test_suite="myproject",
As always, whenever you change your dependencies, make sure to run the
following command.
As always, whenever you change your dependencies, make sure to run the correct
``pip install -e`` command.
.. code-block:: bash
    $VENV/bin/python setup.py develop
    $VENV/bin/pip install -e ".[testing]"
In your ``MyPackage`` project, your :term:`package` is named ``myproject``
which contains a ``views`` module, which in turn contains a :term:`view`
docs/narr/upgrading.rst
@@ -127,8 +127,6 @@
   $ python -Wd setup.py test -q
The ``-Wd`` argument tells Python to print deprecation warnings to the console.
Note that the ``-Wd`` flag is only required for Python 2.7 and better: Python
versions 2.6 and older print deprecation warnings to the console by default.
See `the Python -W flag documentation
<http://docs.python.org/using/cmdline.html#cmdoption-W>`_ for more information.
docs/quick_tour.rst
@@ -15,43 +15,46 @@
Once you have a standard Python environment setup, getting started with Pyramid
is a breeze. Unfortunately "standard" is not so simple in Python. For this
Quick Tour, it means `Python <https://www.python.org/downloads/>`_, a `virtual
environment <http://docs.python.org/dev/library/venv.html>`_ (or `virtualenv
for Python 2.7 <https://pypi.python.org/pypi/virtualenv>`_), and `setuptools
<https://pypi.python.org/pypi/setuptools/>`_.
Quick Tour, it means `Python <https://www.python.org/downloads/>`_, `venv
<https://packaging.python.org/en/latest/projects/#venv>`_ (or `virtualenv for
Python 2.7 <https://packaging.python.org/en/latest/projects/#virtualenv>`_),
`pip <https://packaging.python.org/en/latest/projects/#pip>`_, and `setuptools
<https://packaging.python.org/en/latest/projects/#easy-install>`_.
As an example, for Python 3.3+ on Linux:
To save a little bit of typing and to be certain that we use the modules,
scripts, and packages installed in our virtual environment, we'll set an
environment variable, too.
As an example, for Python 3.5+ on Linux:
.. parsed-literal::
  $ pyvenv env33
  $ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | env33/bin/python
  $ env33/bin/easy_install "pyramid==\ |release|\ "
    # set an environment variable to where you want your virtual environment
    $ export VENV=~/env
    # create the virtual environment
    $ python3 -m venv $VENV
    # install pyramid
    $ $VENV/bin/pip install pyramid
    # or for a specific released version
    $ $VENV/bin/pip install "pyramid==\ |release|\ "
For Windows:
.. parsed-literal::
    # Use your browser to download:
    #   https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
    c:\\> c:\\Python33\\python -m venv env33
    c:\\> env33\\Scripts\\python ez_setup.py
    c:\\> env33\\Scripts\\easy_install "pyramid==\ |release|\ "
    # set an environment variable to where you want your virtual environment
    c:\> set VENV=c:\env
    # create the virtual environment
    c:\\> c:\\Python35\\python3 -m venv %VENV%
    # install pyramid
    c:\\> %VENV%\\Scripts\\pip install pyramid
    # or for a specific released version
    c:\\> %VENV%\\Scripts\\pip install "pyramid==\ |release|\ "
Of course Pyramid runs fine on Python 2.6+, as do the examples in this *Quick
Tour*. We're just showing Python 3 a little love (Pyramid had production
support for Python 3 in October 2011).
.. note::
    Why ``easy_install`` and not ``pip``?  Some distributions upon which
    Pyramid depends have optional C extensions for performance. ``pip`` cannot
    install some binary Python distributions.  With ``easy_install``, Windows
    users are able to obtain binary Python distributions, so they get the
    benefit of the C extensions without needing a C compiler.  Also there can
    be issues when ``pip`` and ``easy_install`` are used side-by-side in the
    same environment, so we chose to recommend ``easy_install`` for the sake of
    reducing the complexity of these instructions.
Tour*. We're showing Python 3 for simplicity. (Pyramid had production support
for Python 3 in October 2011.) Also for simplicity, the remaining examples will
show only UNIX commands.
.. seealso:: See also:
    :ref:`Quick Tutorial section on Requirements <qtut_requirements>`,
@@ -72,7 +75,7 @@
.. code-block:: bash
    $ python ./app.py
    $ $VENV/bin/python ./app.py
Next open http://localhost:6543/ in a browser, and you will see the ``Hello
World!`` message.
@@ -121,7 +124,9 @@
In this Pyramid view, we get the URL being visited from ``request.url``. Also
if you visited http://localhost:6543/?name=alice in a browser, the name is
included in the body of the response::
included in the body of the response:
.. code-block:: text
  URL http://localhost:6543/?name=alice with name: alice
@@ -249,7 +254,7 @@
.. code-block:: bash
    $ easy_install pyramid_chameleon
    $ $VENV/bin/pip install pyramid_chameleon
With the package installed, we can include the template bindings into our
configuration in ``app.py``:
@@ -293,7 +298,7 @@
.. code-block:: bash
    $ easy_install pyramid_jinja2
    $ $VENV/bin/pip install pyramid_jinja2
With the package installed, we can include the template bindings into our
configuration:
@@ -502,7 +507,7 @@
.. code-block:: bash
    $ cd hello_world
    $ python ./setup.py develop
    $ $VENV/bin/pip install -e .
We are moving in the direction of a full-featured Pyramid project, with a
proper setup for Python standards (packaging) and Pyramid configuration. This
@@ -510,7 +515,7 @@
.. code-block:: bash
    $ pserve development.ini
    $ $VENV/bin/pserve development.ini
Let's look at ``pserve`` and configuration in more depth.
@@ -537,7 +542,7 @@
.. code-block:: bash
    $ pserve development.ini --reload
    $ $VENV/bin/pserve development.ini --reload
The ``pserve`` command has a number of other options and operations. Most of
the work, though, comes from your project's wiring, as expressed in the
@@ -617,7 +622,7 @@
.. code-block:: bash
    $ python ./setup.py develop
    $ $VENV/bin/pip install -e .
The ``pyramid_debugtoolbar`` package is a Pyramid add-on, which means we need
to include its configuration into our web application. The ``pyramid_jinja2``
@@ -648,48 +653,79 @@
    :ref:`Quick Tutorial pyramid_debugtoolbar <qtut_debugtoolbar>` and
    :ref:`pyramid_debugtoolbar <toolbar:overview>`
Unit tests and ``nose``
=======================
Unit tests and ``py.test``
==========================
Yikes! We got this far and we haven't yet discussed tests. This is particularly
egregious, as Pyramid has had a deep commitment to full test coverage since
before its release.
Our ``pyramid_jinja2_starter`` scaffold generated a ``tests.py`` module with
one unit test in it. To run it, let's install the handy ``nose`` test runner by
editing ``setup.py``. While we're at it, we'll throw in the ``coverage`` tool
which yells at us for code that isn't tested. Edit line 36 so it becomes the
following:
one unit test in it. To run it, let's install the handy ``pytest`` test runner
by editing ``setup.py``. While we're at it, we'll throw in the ``pytest-cov``
tool which yells at us for code that isn't tested. Insert and edit the
following lines as shown:
.. code-block:: python
    :linenos:
    :lineno-start: 36
    :lineno-start: 11
    :emphasize-lines: 8-12
          tests_require={
              'testing': ['nose', 'coverage'],
          },
    requires = [
        'pyramid',
        'pyramid_jinja2',
        'pyramid_debugtoolbar',
        'waitress',
    ]
We changed ``setup.py`` which means we need to rerun
``python ./setup.py develop``. We can now run all our tests:
    tests_require = [
        'WebTest >= 1.3.1',  # py3 compat
        'pytest',  # includes virtualenv
        'pytest-cov',
        ]
.. code-block:: python
    :linenos:
    :lineno-start: 34
    :emphasize-lines: 2-4
        zip_safe=False,
        extras_require={
          'testing': tests_require,
        },
We changed ``setup.py`` which means we need to rerun ``$VENV/bin/pip install -e
".[testing]"``. We can now run all our tests:
.. code-block:: bash
    $ nosetests hello_world/tests.py
    .
    Name                  Stmts   Miss  Cover   Missing
    ---------------------------------------------------
    hello_world              11      8    27%   11-23
    hello_world.models        5      1    80%   8
    hello_world.tests        14      0   100%
    hello_world.views         4      0   100%
    ---------------------------------------------------
    TOTAL                    34      9    74%
    ----------------------------------------------------------------------
    Ran 1 test in 0.009s
    $ $VENV/bin/py.test --cov=hello_world --cov-report=term-missing hello_world/tests.py
    OK
This yields the following output.
Our unit test passed. What did our test look like?
.. code-block:: text
    =========================== test session starts ===========================
    platform darwin -- Python 3.5.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
    rootdir: /Users/stevepiercy/projects/hack-on-pyramid/hello_world, inifile:
    plugins: cov-2.2.1
    collected 1 items
    hello_world/tests.py .
    ------------- coverage: platform darwin, python 3.5.0-final-0 -------------
    Name                       Stmts   Miss  Cover   Missing
    --------------------------------------------------------
    hello_world/__init__.py       11      8    27%   11-23
    hello_world/resources.py       5      1    80%   8
    hello_world/tests.py          14      0   100%
    hello_world/views.py           4      0   100%
    --------------------------------------------------------
    TOTAL                         34      9    74%
    ========================= 1 passed in 0.22 seconds =========================
Our unit test passed, although its coverage is incomplete. What did our test
look like?
.. literalinclude:: quick_tour/package/hello_world/tests.py
    :linenos:
@@ -746,7 +782,9 @@
Our application, a package named ``hello_world``, is set up as a logger and
configured to log messages at a ``DEBUG`` or higher level. When you visit
http://localhost:6543, your console will now show::
http://localhost:6543, your console will now show:
.. code-block:: text
    2016-01-18 13:55:55,040 DEBUG [hello_world.views:10][waitress] Some Message
@@ -825,9 +863,9 @@
.. code-block:: bash
  $ pcreate --scaffold alchemy sqla_demo
  $ $VENV/bin/pcreate --scaffold alchemy sqla_demo
  $ cd sqla_demo
  $ python setup.py develop
  $ $VENV/bin/pip install -e .
We now have a working sample SQLAlchemy application with all dependencies
installed. The sample project provides a console script to initialize a SQLite
@@ -835,8 +873,8 @@
.. code-block:: bash
  $ initialize_sqla_demo_db development.ini
  $ pserve development.ini
  $ $VENV/bin/initialize_sqla_demo_db development.ini
  $ $VENV/bin/pserve development.ini
The ORM eases the mapping of database structures into a programming language.
SQLAlchemy uses "models" for this mapping. The scaffold generated a sample
docs/quick_tour/sqla_demo/README.txt
@@ -6,7 +6,7 @@
- cd <directory containing this file>
- $VENV/bin/python setup.py develop
- $VENV/bin/pip install -e .
- $VENV/bin/initialize_sqla_demo_db development.ini
docs/quick_tour/sqla_demo/sqla_demo/static/theme.min.css
File was deleted
docs/quick_tutorial/authentication.rst
@@ -1,3 +1,5 @@
.. _qtut_authentication:
==============================
20: Logins With Authentication
==============================
@@ -33,7 +35,7 @@
   .. code-block:: bash
    $ cd ..; cp -r view_classes authentication; cd authentication
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/pip install -e .
#. Put the security hash in the ``authentication/development.ini``
   configuration file as ``tutorial.secret`` instead of putting it in
docs/quick_tutorial/authorization.rst
@@ -1,3 +1,5 @@
.. _qtut_authorization:
===========================================
21: Protecting Resources With Authorization
===========================================
@@ -38,7 +40,7 @@
   .. code-block:: bash
    $ cd ..; cp -r authentication authorization; cd authorization
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/pip install -e .
#. Start by changing ``authorization/tutorial/__init__.py`` to
   specify a root factory to the :term:`configurator`:
docs/quick_tutorial/conf.py
File was deleted
docs/quick_tutorial/databases.rst
@@ -53,7 +53,7 @@
   .. note::
     We aren't yet doing ``$VENV/bin/python setup.py develop`` as we
     We aren't yet doing ``$VENV/bin/pip install -e .`` as we
     will change it later.
#. Our configuration file at ``databases/development.ini`` wires
@@ -78,7 +78,7 @@
   .. code-block:: bash
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/pip install -e .
#. The script references some models in ``databases/tutorial/models.py``:
@@ -176,7 +176,7 @@
The ``initialize_tutorial_db`` is a nice example of framework support.
You point your setup at the location of some ``[console_scripts]`` and
these get generated into your virtualenv's ``bin`` directory. Our
these get generated into your virtual environment's ``bin`` directory. Our
console script follows the pattern of being fed a configuration file
with all the bootstrapping. It then opens SQLAlchemy and creates the
root of the wiki, which also makes the SQLite file. Note the
docs/quick_tutorial/debugtoolbar.rst
@@ -4,8 +4,7 @@
04: Easier Development with ``debugtoolbar``
============================================
Error-handling and introspection using the ``pyramid_debugtoolbar``
add-on.
Error handling and introspection using the ``pyramid_debugtoolbar`` add-on.
Background
==========
@@ -36,8 +35,8 @@
   .. code-block:: bash
    $ cd ..; cp -r ini debugtoolbar; cd debugtoolbar
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/easy_install pyramid_debugtoolbar
    $ $VENV/bin/pip install -e .
    $ $VENV/bin/pip install pyramid_debugtoolbar
#. Our ``debugtoolbar/development.ini`` gets a configuration entry for
   ``pyramid.includes``:
docs/quick_tutorial/forms.rst
@@ -50,7 +50,7 @@
   .. code-block:: bash
      $ $VENV/bin/python setup.py develop
      $ $VENV/bin/pip install -e .
#. Register a static view in ``forms/tutorial/__init__.py`` for
   Deform's CSS/JS etc. as well as our demo wikipage scenario's
docs/quick_tutorial/functional_testing.rst
@@ -34,8 +34,8 @@
   .. code-block:: bash
    $ cd ..; cp -r unit_testing functional_testing; cd functional_testing
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/easy_install webtest
    $ $VENV/bin/pip install -e .
    $ $VENV/bin/pip install webtest
#. Let's extend ``functional_testing/tutorial/tests.py`` to include a
   functional test:
docs/quick_tutorial/hello_world.rst
@@ -5,7 +5,7 @@
================================
What's the simplest way to get started in Pyramid? A single-file module.
No Python packages, no ``setup.py``, no other machinery.
No Python packages, no ``pip install -e .``, no other machinery.
Background
==========
docs/quick_tutorial/ini.rst
@@ -50,7 +50,7 @@
   .. code-block:: bash
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/pip install -e .
#. Let's make a file ``ini/development.ini`` for our configuration:
docs/quick_tutorial/jinja2.rst
@@ -26,8 +26,8 @@
   .. code-block:: bash
    $ cd ..; cp -r view_classes jinja2; cd jinja2
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/easy_install pyramid_jinja2
    $ $VENV/bin/pip install -e .
    $ $VENV/bin/pip install pyramid_jinja2
#. We need to include ``pyramid_jinja2`` in
   ``jinja2/tutorial/__init__.py``:
docs/quick_tutorial/json.rst
@@ -31,7 +31,7 @@
   .. code-block:: bash
    $ cd ..; cp -r view_classes json; cd json
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/pip install -e .
#. We add a new route for ``hello_json`` in
   ``json/tutorial/__init__.py``:
docs/quick_tutorial/logging.rst
@@ -35,7 +35,7 @@
   .. code-block:: bash
    $ cd ..; cp -r view_classes logging; cd logging
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/pip install -e .
#. Extend ``logging/tutorial/views.py`` to log a message:
docs/quick_tutorial/more_view_classes.rst
@@ -57,7 +57,7 @@
   .. code-block:: bash
    $ cd ..; cp -r templating more_view_classes; cd more_view_classes
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/pip install -e .
#. Our route in ``more_view_classes/tutorial/__init__.py`` needs some
   replacement patterns:
docs/quick_tutorial/package.rst
@@ -14,39 +14,34 @@
directory is on ``sys.path`` and has a special file named
``__init__.py``, it is treated as a Python package.
Packages can be bundled up, made available for installation,
and installed through a (muddled, but improving) toolchain oriented
around a ``setup.py`` file for a
`setuptools project <http://pythonhosted.org/setuptools/setuptools.html>`_.
Explaining it all in this
tutorial will induce madness. For this tutorial, this is all you need to
know:
Packages can be bundled up, made available for installation, and installed
through a toolchain oriented around a ``setup.py`` file. For this tutorial,
this is all you need to know:
- We will have a directory for each tutorial step as a setuptools *project*
- We will have a directory for each tutorial step as a *project*.
- This project will contain a ``setup.py`` which injects the features
  of the setuptool's project machinery into the directory
- This project will contain a ``setup.py`` which injects the features of the
  project machinery into the directory.
- In this project we will make a ``tutorial`` subdirectory into a Python
  *package* using an ``__init__.py`` Python module file
  *package* using an ``__init__.py`` Python module file.
- We will run ``python setup.py develop`` to install our project in
  development mode
- We will run ``pip install -e .`` to install our project in development mode.
In summary:
- You'll do your development in a Python *package*
- You'll do your development in a Python *package*.
- That package will be part of a setuptools *project*
- That package will be part of a *project*.
Objectives
==========
- Make a Python "package" directory with an ``__init__.py``
- Make a Python "package" directory with an ``__init__.py``.
- Get a minimum Python "project" in place by making a ``setup.py``
- Get a minimum Python "project" in place by making a ``setup.py``.
- Install our ``tutorial`` project in development mode
- Install our ``tutorial`` project in development mode.
Steps
=====
@@ -66,7 +61,7 @@
   .. code-block:: bash
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/pip install -e .
    $ mkdir tutorial
#. Enter the following into ``package/tutorial/__init__.py``:
@@ -107,5 +102,6 @@
tries to capture how this stuff works a step at a time.  It's generally a bad
idea to run a Python module inside a package directly as a script.
.. seealso:: :ref:`Python Packages <python:tut-packages>`,
   `setuptools Entry Points <http://pythonhosted.org/setuptools/pkg_resources.html#entry-points>`_
.. seealso:: :ref:`Python Packages <python:tut-packages>` and `Working in
   "Development Mode"
   <https://packaging.python.org/en/latest/distributing/#working-in-development-mode>`_.
docs/quick_tutorial/request_response.rst
@@ -41,7 +41,7 @@
   .. code-block:: bash
    $ cd ..; cp -r view_classes request_response; cd request_response
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/pip install -e .
#. Simplify the routes in ``request_response/tutorial/__init__.py``:
docs/quick_tutorial/requirements.rst
@@ -4,9 +4,9 @@
Requirements
============
Let's get our tutorial environment setup. Most of the setup work is in
standard Python development practices (install Python,
make an isolated environment, and setup packaging tools.)
Let's get our tutorial environment set up. Most of the set up work is in
standard Python development practices (install Python and make an isolated
environment.)
.. note::
@@ -19,16 +19,14 @@
This *Quick Tutorial* is based on:
* **Python 3.3**. Pyramid fully supports Python 3.3+ and Python 2.6+.
  This tutorial uses **Python 3.3** but runs fine under Python 2.7.
* **Python 3.5**. Pyramid fully supports Python 3.3+ and Python 2.6+. This
  tutorial uses **Python 3.5** but runs fine under Python 2.7.
* **pyvenv**. We believe in virtual environments. For this tutorial,
  we use Python 3.3's built-in solution, the ``pyvenv`` command.
  For Python 2.7, you can install ``virtualenv``.
* **venv**. We believe in virtual environments. For this tutorial, we use
  Python 3.5's built-in solution ``venv``. For Python 2.7, you can install
  ``virtualenv``.
* **setuptools and easy_install**. We use
  `setuptools <https://pypi.python.org/pypi/setuptools/>`_
  and its ``easy_install`` for package management.
* **pip**. We use ``pip`` for package management.
* **Workspaces, projects, and packages.** Our home directory
  will contain a *tutorial workspace* with our Python virtual
@@ -46,22 +44,22 @@
Steps
=====
#. :ref:`install-python-3.3-or-greater`
#. :ref:`install-python-3`
#. :ref:`create-a-project-directory-structure`
#. :ref:`set-an-environment-variable`
#. :ref:`create-a-virtual-environment`
#. :ref:`install-setuptools-(python-packaging-tools)`
#. :ref:`install-pyramid`
.. _install-python-3.3-or-greater:
Install Python 3.3 or greater
-----------------------------
.. _install-python-3:
Download the latest standard Python 3.3+ release (not development release)
from `python.org <https://www.python.org/downloads/>`_.
Install Python 3
----------------
Windows and Mac OS X users can download and run an installer.
Download the latest standard Python 3 release (not development release) from
`python.org <https://www.python.org/downloads/>`_.
Windows users should also install the `Python for Windows extensions
<http://sourceforge.net/projects/pywin32/files/pywin32/>`_. Carefully read the
@@ -69,10 +67,16 @@
directions. Make sure you get the proper 32- or 64-bit build and Python
version.
Linux users can either use their package manager to install Python 3.3
or may `build Python 3.3 from source
Linux users can either use their package manager to install Python 3
or may `build Python 3 from source
<http://pyramid.readthedocs.org/en/master/narr/install.html#package-manager-
method>`_.
.. seealso:: See also :ref:`For Mac OS X Users <for-mac-os-x-users>`, :ref:`If
   You Don't Yet Have a Python Interpreter (UNIX)
   <if-you-don-t-yet-have-a-python-interpreter-unix>`, and :ref:`If You Don't
   Yet Have a Python Interpreter (Windows)
   <if-you-don-t-yet-have-a-python-interpreter-windows>`.
.. _create-a-project-directory-structure:
@@ -125,7 +129,7 @@
Next within ``projects`` is your workspace directory, here named
``quick_tutorial``. A workspace is a common term used by integrated
development environments (IDE) like PyCharm and PyDev that stores
isolated Python environments (virtualenvs) and specific project files
isolated Python environments (virtual environments) and specific project files
and repositories.
@@ -142,6 +146,8 @@
    # Mac and Linux
    $ export VENV=~/projects/quick_tutorial/env
.. code-block:: ps1con
    # Windows
    # TODO: This command does not work
    c:\> set VENV=c:\projects\quick_tutorial\env
@@ -152,62 +158,23 @@
Create a Virtual Environment
----------------------------
.. warning:: The current state of isolated Python environments using
    ``pyvenv`` on Windows is suboptimal in comparison to Mac and Linux.  See
    http://stackoverflow.com/q/15981111/95735 for a discussion of the issue
    and `PEP 453 <http://www.python.org/dev/peps/pep-0453/>`_ for a proposed
    resolution.
``pyvenv`` is a tool to create isolated Python 3.3 environments, each
with its own Python binary and independent set of installed Python
packages in its site directories. Let's create one, using the location
we just specified in the environment variable.
``venv`` is a tool to create isolated Python 3 environments, each with its own
Python binary and independent set of installed Python packages in its site
directories. Let's create one, using the location we just specified in the
environment variable.
.. code-block:: bash
    # Mac and Linux
    $ pyvenv $VENV
    $ python3 -m venv $VENV
.. code-block:: ps1con
    # Windows
    c:\> c:\Python33\python -m venv %VENV%
    c:\> c:\Python35\python3 -m venv %VENV%
.. seealso:: See also Python 3's :mod:`venv module <python3:venv>`,
   Python 2's `virtualenv <http://www.virtualenv.org/en/latest/>`_
   package,
   :ref:`Installing Pyramid on a Windows System <installing_windows>`
.. _install-setuptools-(python-packaging-tools):
Install ``setuptools`` (Python packaging tools)
-----------------------------------------------
The following command will download a script to install ``setuptools``, then
pipe it to your environment's version of Python.
.. code-block:: bash
    # Mac and Linux
    $ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | $VENV/bin/python
    # Windows
    #
    # Use your web browser to download this file:
    #   https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
    #
    # ...and save it to:
    # c:\projects\quick_tutorial\ez_setup.py
    #
    # Then run the following command:
    c:\> %VENV%\Scripts\python ez_setup.py
If ``wget`` complains with a certificate error, then run this command instead:
.. code-block:: bash
    # Mac and Linux
    $ wget --no-check-certificate https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | $VENV/bin/python
.. seealso:: See also Python 3's :mod:`venv module <python:venv>` and Python
   2's `virtualenv <https://virtualenv.pypa.io/en/latest/>`_ package.
.. _install-pyramid:
@@ -221,10 +188,10 @@
.. parsed-literal::
    # Mac and Linux
    $ $VENV/bin/easy_install "pyramid==\ |release|\ "
    $ $VENV/bin/pip install "pyramid==\ |release|\ "
    # Windows
    c:\\> %VENV%\\Scripts\\easy_install "pyramid==\ |release|\ "
    c:\\> %VENV%\\Scripts\\pip install "pyramid==\ |release|\ "
Our Python virtual environment now has the Pyramid software available.
@@ -234,30 +201,12 @@
.. code-block:: bash
    # Mac and Linux
    $ $VENV/bin/easy_install nose webtest deform sqlalchemy \
    $ $VENV/bin/pip install nose webtest deform sqlalchemy \
       pyramid_chameleon pyramid_debugtoolbar waitress \
       pyramid_tm zope.sqlalchemy
.. code-block:: ps1con
    # Windows
    c:\> %VENV%\Scripts\easy_install nose webtest deform sqlalchemy pyramid_chameleon pyramid_debugtoolbar waitress pyramid_tm zope.sqlalchemy
.. note::
    Why ``easy_install`` and not ``pip``? Pyramid encourages use of namespace
    packages, for which ``pip``'s support is less-than-optimal. Also, Pyramid's
    dependencies use some optional C extensions for performance:   with
    ``easy_install``, Windows users can get these extensions without needing
    a C compiler (``pip`` does not support installing binary Windows
    distributions, except for ``wheels``, which are not yet available for
    all dependencies).
.. seealso:: See also :ref:`installing_unix`. For instructions to set up your
    Python environment for development using Windows or Python 2, see Pyramid's
    :ref:`Before You Install <installing_chapter>`.
    See also Python 3's :mod:`venv module <python3:venv>`, the `setuptools
    installation instructions
    <https://pypi.python.org/pypi/setuptools/0.9.8#installation-instructions>`_,
    and `easy_install help <https://pypi.python.org/pypi/setuptools/0.9.8#using-setuptools-and-easyinstall>`_.
    c:\> %VENV%\Scripts\pip install nose webtest deform sqlalchemy pyramid_chameleon pyramid_debugtoolbar waitress pyramid_tm zope.sqlalchemy
docs/quick_tutorial/routing.rst
@@ -48,7 +48,7 @@
   .. code-block:: bash
    $ cd ..; cp -r view_classes routing; cd routing
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/pip install -e .
#. Our ``routing/tutorial/__init__.py`` needs a route with a replacement
   pattern:
docs/quick_tutorial/scaffolds.rst
@@ -12,7 +12,7 @@
==========
We're going to cover a lot in this tutorial, focusing on one topic at a
time and writing everything from scratch. As a warmup, though,
time and writing everything from scratch. As a warm up, though,
it sure would be nice to see some pixels on a screen.
Like other web development frameworks, Pyramid provides a number of
@@ -47,21 +47,22 @@
        $ $VENV/bin/pcreate --scaffold starter scaffolds
#. Use normal Python development to setup our project for development:
#. Install our project in editable mode for development in the current
   directory:
    .. code-block:: bash
        $ cd scaffolds
        $ $VENV/bin/python setup.py develop
        $ $VENV/bin/pip install -e .
#. Startup the application by pointing Pyramid's ``pserve`` command at
#. Start up the application by pointing Pyramid's ``pserve`` command at
   the project's (generated) configuration file:
    .. code-block:: bash
        $ $VENV/bin/pserve development.ini --reload
   On startup, ``pserve`` logs some output:
   On start up, ``pserve`` logs some output:
    .. code-block:: bash
docs/quick_tutorial/sessions.rst
@@ -34,7 +34,7 @@
   .. code-block:: bash
    $ cd ..; cp -r view_classes sessions; cd sessions
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/pip install -e .
#. Our ``sessions/tutorial/__init__.py`` needs a choice of session
   factory to get registered with the :term:`configurator`:
docs/quick_tutorial/static_assets.rst
@@ -23,7 +23,7 @@
   .. code-block:: bash
    $ cd ..; cp -r view_classes static_assets; cd static_assets
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/pip install -e .
#. We add a call ``config.add_static_view`` in
   ``static_assets/tutorial/__init__.py``:
docs/quick_tutorial/templating.rst
@@ -56,7 +56,7 @@
   .. code-block:: bash
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/pip install -e .
#. We need to connect ``pyramid_chameleon`` as a renderer by making a
   call in the setup of ``templating/tutorial/__init__.py``:
docs/quick_tutorial/tutorial_approach.rst
@@ -17,7 +17,7 @@
To successfully run each step::
  $ cd request_response
  $ $VENV/bin/python setup.py develop
  $ $VENV/bin/pip install -e .
...and repeat for each step you would like to work on. In most cases we
will start with the results of an earlier step.
docs/quick_tutorial/unit_testing.rst
@@ -48,8 +48,8 @@
   .. code-block:: bash
    $ cd ..; cp -r debugtoolbar unit_testing; cd unit_testing
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/easy_install nose
    $ $VENV/bin/pip install -e .
    $ $VENV/bin/pip install nose
#. Now we write a simple unit test in ``unit_testing/tutorial/tests.py``:
docs/quick_tutorial/view_classes.rst
@@ -41,7 +41,7 @@
   .. code-block:: bash
    $ cd ..; cp -r templating view_classes; cd view_classes
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/pip install -e .
#. Our ``view_classes/tutorial/views.py`` now has a view class with
   our two views:
docs/quick_tutorial/views.rst
@@ -43,7 +43,7 @@
   .. code-block:: bash
    $ cd ..; cp -r functional_testing views; cd views
    $ $VENV/bin/python setup.py develop
    $ $VENV/bin/pip install -e .
#. Our ``views/tutorial/__init__.py`` gets a lot shorter:
docs/tutorials/modwsgi/index.rst
@@ -1,7 +1,7 @@
.. _modwsgi_tutorial:
Running a :app:`Pyramid` Application under ``mod_wsgi``
==========================================================
=======================================================
:term:`mod_wsgi` is an Apache module developed by Graham Dumpleton.
It allows :term:`WSGI` programs to be served using the Apache web
@@ -24,21 +24,15 @@
    system.  If you do not, install Apache 2.X for your platform in
    whatever manner makes sense.
#.  It is also assumed that you have satisfied the
    :ref:`requirements-for-installing-packages`.
#.  Once you have Apache installed, install ``mod_wsgi``.  Use the
    (excellent) `installation instructions
    <http://code.google.com/p/modwsgi/wiki/InstallationInstructions>`_
    for your platform into your system's Apache installation.
#.  Install :term:`virtualenv` into the Python which mod_wsgi will
    run using the ``easy_install`` program.
    .. code-block:: text
       $ sudo /usr/bin/easy_install-2.6 virtualenv
    This command may need to be performed as the root user.
#.  Create a :term:`virtualenv` which we'll use to install our
#.  Create a :term:`virtual environment` which we'll use to install our
    application.
    .. code-block:: text
@@ -46,14 +40,14 @@
       $ cd ~
       $ mkdir modwsgi
       $ cd modwsgi
       $ /usr/local/bin/virtualenv env
       $ python3 -m venv env
#.  Install :app:`Pyramid` into the newly created virtualenv:
#.  Install :app:`Pyramid` into the newly created virtual environment:
    .. code-block:: text
       $ cd ~/modwsgi/env
       $ $VENV/bin/easy_install pyramid
       $ $VENV/bin/pip install pyramid
    
#.  Create and install your :app:`Pyramid` application.  For the purposes of
    this tutorial, we'll just be using the ``pyramid_starter`` application as
@@ -65,9 +59,9 @@
       $ cd ~/modwsgi/env
       $ $VENV/bin/pcreate -s starter myapp
       $ cd myapp
       $ $VENV/bin/python setup.py install
       $ $VENV/bin/pip install -e .
#.  Within the virtualenv directory (``~/modwsgi/env``), create a
#.  Within the virtual environment directory (``~/modwsgi/env``), create a
    script named ``pyramid.wsgi``.  Give it these contents:
    .. code-block:: python
@@ -107,7 +101,7 @@
       WSGIApplicationGroup %{GLOBAL}
       WSGIPassAuthorization On
       WSGIDaemonProcess pyramid user=chrism group=staff threads=4 \
          python-path=/Users/chrism/modwsgi/env/lib/python2.6/site-packages
          python-path=/Users/chrism/modwsgi/env/lib/python2.7/site-packages
       WSGIScriptAlias /myapp /Users/chrism/modwsgi/env/pyramid.wsgi
       <Directory /Users/chrism/modwsgi/env>
@@ -131,4 +125,3 @@
configuration documentation
<http://code.google.com/p/modwsgi/wiki/ConfigurationGuidelines>`_ for
more in-depth configuration information.
docs/tutorials/wiki/authorization.rst
@@ -5,12 +5,12 @@
====================
:app:`Pyramid` provides facilities for :term:`authentication` and
::term:`authorization`.  We'll make use of both features to provide security
:to our application.  Our application currently allows anyone with access to
:the server to view, edit, and add pages to our wiki.  We'll change that to
:allow only people who are members of a *group* named ``group:editors`` to add
:and edit wiki pages but we'll continue allowing anyone with access to the
:server to view pages.
:term:`authorization`. We'll make use of both features to provide security to
our application. Our application currently allows anyone with access to the
server to view, edit, and add pages to our wiki. We'll change that to allow
only people who are members of a *group* named ``group:editors`` to add and
edit wiki pages, but we'll continue allowing anyone with access to the server
to view pages.
We will also add a login page and a logout link on all the pages.  The login
page will be shown when a user is denied access to any of the views that
@@ -41,7 +41,7 @@
Add users and groups
~~~~~~~~~~~~~~~~~~~~
Create a new ``tutorial/tutorial/security.py`` module with the
Create a new ``tutorial/security.py`` module with the
following content:
.. literalinclude:: src/authorization/tutorial/security.py
@@ -67,7 +67,7 @@
Add an ACL
~~~~~~~~~~
Open ``tutorial/tutorial/models.py`` and add the following import
Open ``tutorial/models.py`` and add the following import
statement at the head:
.. literalinclude:: src/authorization/tutorial/models.py
@@ -109,7 +109,7 @@
Add authentication and authorization policies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Open ``tutorial/tutorial/__init__.py`` and add the highlighted import
Open ``tutorial/__init__.py`` and add the highlighted import
statements:
.. literalinclude:: src/authorization/tutorial/__init__.py
@@ -142,7 +142,7 @@
Add permission declarations
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Open ``tutorial/tutorial/views.py`` and add a ``permission='edit'`` parameter
Open ``tutorial/views.py`` and add a ``permission='edit'`` parameter
to the ``@view_config`` decorators for ``add_page()`` and ``edit_page()``:
.. literalinclude:: src/authorization/tutorial/views.py
@@ -196,7 +196,7 @@
redirect back to the front page.
Add the following import statements to the head of
``tutorial/tutorial/views.py``:
``tutorial/views.py``:
.. literalinclude:: src/authorization/tutorial/views.py
   :lines: 6-17
@@ -236,7 +236,7 @@
Add the ``login.pt`` Template
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Create ``tutorial/tutorial/templates/login.pt`` with the following content:
Create ``tutorial/templates/login.pt`` with the following content:
.. literalinclude:: src/authorization/tutorial/templates/login.pt
   :language: html
@@ -247,7 +247,7 @@
Return a ``logged_in`` flag to the renderer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Open ``tutorial/tutorial/views.py`` again. Add a ``logged_in`` parameter to
Open ``tutorial/views.py`` again. Add a ``logged_in`` parameter to
the return value of ``view_page()``, ``add_page()``, and ``edit_page()`` as
follows:
@@ -274,8 +274,8 @@
Add a "Logout" link when logged in
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Open ``tutorial/tutorial/templates/edit.pt`` and
``tutorial/tutorial/templates/view.pt`` and add the following code as
Open ``tutorial/templates/edit.pt`` and
``tutorial/templates/view.pt`` and add the following code as
indicated by the highlighted lines.
.. literalinclude:: src/authorization/tutorial/templates/edit.pt
@@ -291,7 +291,7 @@
Reviewing our changes
---------------------
Our ``tutorial/tutorial/__init__.py`` will look like this when we're done:
Our ``tutorial/__init__.py`` will look like this when we're done:
.. literalinclude:: src/authorization/tutorial/__init__.py
   :linenos:
@@ -300,7 +300,7 @@
Only the highlighted lines need to be added or edited.
Our ``tutorial/tutorial/models.py`` will look like this when we're done:
Our ``tutorial/models.py`` will look like this when we're done:
.. literalinclude:: src/authorization/tutorial/models.py
   :linenos:
@@ -309,7 +309,7 @@
Only the highlighted lines need to be added or edited.
Our ``tutorial/tutorial/views.py`` will look like this when we're done:
Our ``tutorial/views.py`` will look like this when we're done:
.. literalinclude:: src/authorization/tutorial/views.py
   :linenos:
@@ -318,7 +318,7 @@
Only the highlighted lines need to be added or edited.
Our ``tutorial/tutorial/templates/edit.pt`` template will look like this when
Our ``tutorial/templates/edit.pt`` template will look like this when
we're done:
.. literalinclude:: src/authorization/tutorial/templates/edit.pt
@@ -328,7 +328,7 @@
Only the highlighted lines need to be added or edited.
Our ``tutorial/tutorial/templates/view.pt`` template will look like this when
Our ``tutorial/templates/view.pt`` template will look like this when
we're done:
.. literalinclude:: src/authorization/tutorial/templates/view.pt
docs/tutorials/wiki/background.rst
@@ -1,3 +1,5 @@
.. _wiki_background:
==========
Background
==========
docs/tutorials/wiki/basiclayout.rst
@@ -1,3 +1,5 @@
.. _wiki_basic_layout:
============
Basic Layout
============
@@ -12,21 +14,22 @@
A directory on disk can be turned into a Python :term:`package` by containing
an ``__init__.py`` file.  Even if empty, this marks a directory as a Python
package.  We use ``__init__.py`` both as a marker, indicating the directory
in which it's contained is a package, and to contain application configuration
package.  We use ``__init__.py`` both as a marker, indicating the directory in
which it's contained is a package, and to contain application configuration
code.
When you run the application using the ``pserve`` command using the
``development.ini`` generated configuration file, the application
configuration points at a Setuptools *entry point* described as
configuration points at a setuptools *entry point* described as
``egg:tutorial``.  In our application, because the application's ``setup.py``
file says so, this entry point happens to be the ``main`` function within the
file named ``__init__.py``. Let's take a look at the code and describe what
it does:
file named ``__init__.py``.
   .. literalinclude:: src/basiclayout/tutorial/__init__.py
      :linenos:
      :language: py
Open ``tutorial/__init__.py``.  It should already contain the following:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
  :linenos:
  :language: py
#. *Lines 1-3*.  Perform some dependency imports.
@@ -81,9 +84,9 @@
Here is the source for ``models.py``:
   .. literalinclude:: src/basiclayout/tutorial/models.py
      :linenos:
      :language: py
.. literalinclude:: src/basiclayout/tutorial/models.py
  :linenos:
  :language: python
#. *Lines 4-5*.  The ``MyModel`` :term:`resource` class is implemented here.
   Instances of this class are capable of being persisted in :term:`ZODB`
@@ -113,9 +116,9 @@
Here is the source for ``views.py``:
   .. literalinclude:: src/basiclayout/tutorial/views.py
      :linenos:
      :language: py
.. literalinclude:: src/basiclayout/tutorial/views.py
  :linenos:
  :language: python
Let's try to understand the components in this module:
@@ -169,7 +172,7 @@
opposed to the tutorial :term:`package` directory) looks like this:
.. literalinclude:: src/basiclayout/development.ini
   :language: ini
  :language: ini
Note the existence of a ``[app:main]`` section which specifies our WSGI
application.  Our ZODB database settings are specified as the
docs/tutorials/wiki/definingmodels.rst
@@ -1,9 +1,11 @@
.. _wiki_defining_the_domain_model:
=========================
Defining the Domain Model
=========================
The first change we'll make to our stock pcreate-generated application will be
to define two :term:`resource` constructors, one representing a wiki page,
The first change we'll make to our stock ``pcreate``-generated application will
be to define two :term:`resource` constructors, one representing a wiki page,
and another representing the wiki as a mapping of wiki page names to page
objects.  We'll do this inside our ``models.py`` file.
@@ -38,8 +40,7 @@
  or they may live in a Python subpackage of your application package named
  ``models``, but this is only by convention.
Open ``tutorial/tutorial/models.py`` file and edit it to look like the
following:
Open ``tutorial/models.py`` file and edit it to look like the following:
.. literalinclude:: src/models/tutorial/models.py
   :linenos:
docs/tutorials/wiki/definingviews.rst
@@ -1,3 +1,5 @@
.. _wiki_defining_views:
==============
Defining Views
==============
@@ -41,7 +43,7 @@
package's ``setup.py`` file by assigning this dependency to the ``requires``
parameter in the ``setup()`` function.
Open ``tutorial/setup.py`` and edit it to look like the following:
Open ``setup.py`` and edit it to look like the following:
.. literalinclude:: src/views/setup.py
   :linenos:
@@ -50,40 +52,44 @@
Only the highlighted line needs to be added.
Running ``setup.py develop``
Running ``pip install -e .``
============================
Since a new software dependency was added, you will need to run ``python
setup.py develop`` again inside the root of the ``tutorial`` package to obtain
and register the newly added dependency distribution.
Since a new software dependency was added, you will need to run ``pip install
-e .`` again inside the root of the ``tutorial`` package to obtain and register
the newly added dependency distribution.
Make sure your current working directory is the root of the project (the
directory in which ``setup.py`` lives) and execute the following command.
On UNIX:
.. code-block:: text
.. code-block:: bash
   $ cd tutorial
   $ $VENV/bin/python setup.py develop
   $ $VENV/bin/pip install -e .
On Windows:
.. code-block:: text
.. code-block:: ps1con
   c:\pyramidtut> cd tutorial
   c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
   c:\pyramidtut\tutorial> %VENV%\Scripts\pip install -e .
Success executing this command will end with a line to the console something
like::
like:
   Finished processing dependencies for tutorial==0.0
.. code-block:: text
   Successfully installed docutils-0.12 tutorial-0.0
Adding view functions in ``views.py``
=====================================
It's time for a major change.  Open ``tutorial/tutorial/views.py`` and edit it
to look like the following:
It's time for a major change.  Open ``tutorial/views.py`` and edit it to look
like the following:
.. literalinclude:: src/views/tutorial/views.py
   :linenos:
@@ -310,7 +316,7 @@
The ``view.pt`` template
------------------------
Create ``tutorial/tutorial/templates/view.pt`` and add the following
Create ``tutorial/templates/view.pt`` and add the following
content:
.. literalinclude:: src/views/tutorial/templates/view.pt
@@ -329,8 +335,7 @@
The ``edit.pt`` template
------------------------
Create ``tutorial/tutorial/templates/edit.pt`` and add the following
content:
Create ``tutorial/templates/edit.pt`` and add the following content:
.. literalinclude:: src/views/tutorial/templates/edit.pt
   :linenos:
@@ -352,6 +357,7 @@
   See :ref:`renderer_system_values` for information about other names that
   are available by default when a template is used as a renderer.
Static assets
-------------
@@ -367,6 +373,7 @@
method ``static_url``, e.g.,
``request.static_url('<package>:static/foo.css')`` within templates.
Viewing the application in a browser
====================================
docs/tutorials/wiki/design.rst
@@ -1,3 +1,5 @@
.. _wiki_design:
======
Design
======
docs/tutorials/wiki/distributing.rst
@@ -1,3 +1,5 @@
.. _wiki_distributing_your_application:
=============================
Distributing Your Application
=============================
@@ -5,18 +7,18 @@
Once your application works properly, you can create a "tarball" from it by
using the ``setup.py sdist`` command.  The following commands assume your
current working directory is the ``tutorial`` package we've created and that
the parent directory of the ``tutorial`` package is a virtualenv representing
a :app:`Pyramid` environment.
the parent directory of the ``tutorial`` package is a virtual environment
representing a :app:`Pyramid` environment.
On UNIX:
.. code-block:: text
.. code-block:: bash
   $ $VENV/bin/python setup.py sdist
On Windows:
.. code-block:: text
.. code-block:: ps1con
   c:\pyramidtut> %VENV%\Scripts\python setup.py sdist
@@ -25,16 +27,15 @@
.. code-block:: text
   running sdist
   # .. more output ..
   # more output
   creating dist
   tar -cf dist/tutorial-0.0.tar tutorial-0.0
   gzip -f9 dist/tutorial-0.0.tar
   Creating tar archive
   removing 'tutorial-0.0' (and everything under it)
Note that this command creates a tarball in the "dist" subdirectory named
``tutorial-0.0.tar.gz``.  You can send this file to your friends to show them
your cool new application.  They should be able to install it by pointing the
``easy_install`` command directly at it. Or you can upload it to `PyPI
``pip install .`` command directly at it. Or you can upload it to `PyPI
<http://pypi.python.org>`_ and share it with the rest of the world, where it
can be downloaded via ``easy_install`` remotely like any other package people
can be downloaded via ``pip install`` remotely like any other package people
download from PyPI.
docs/tutorials/wiki/index.rst
@@ -26,4 +26,3 @@
   authorization
   tests
   distributing
docs/tutorials/wiki/installation.rst
@@ -1,17 +1,19 @@
.. _wiki_installation:
============
Installation
============
Before you begin
================
----------------
This tutorial assumes that you have already followed the steps in
:ref:`installing_chapter`, except **do not create a virtualenv or install
Pyramid**.  Thereby you will satisfy the following requirements.
:ref:`installing_chapter`, except **do not create a virtual environment or
install Pyramid**.  Thereby you will satisfy the following requirements.
* Python interpreter is installed on your operating system
* :term:`setuptools` or :term:`distribute` is installed
* :term:`virtualenv` is installed
* A Python interpreter is installed on your operating system.
* You've satisfied the :ref:`requirements-for-installing-packages`.
Create directory to contain the project
---------------------------------------
@@ -21,257 +23,328 @@
On UNIX
^^^^^^^
.. code-block:: text
.. code-block:: bash
    $ mkdir ~/pyramidtut
On Windows
^^^^^^^^^^
.. code-block:: text
.. code-block:: ps1con
   c:\> mkdir pyramidtut
Create and use a virtual Python environment
-------------------------------------------
Next let's create a `virtualenv` workspace for our project.  We will
use the `VENV` environment variable instead of the absolute path of the
virtual environment.
Next let's create a virtual environment workspace for our project.  We will use
the ``VENV`` environment variable instead of the absolute path of the virtual
environment.
On UNIX
^^^^^^^
.. code-block:: text
.. code-block:: bash
   $ export VENV=~/pyramidtut
   $ virtualenv $VENV
   New python executable in /home/foo/env/bin/python
   Installing setuptools.............done.
   $ python3 -m venv $VENV
On Windows
^^^^^^^^^^
.. code-block:: text
.. code-block:: ps1con
   c:\> set VENV=c:\pyramidtut
Versions of Python use different paths, so you will need to adjust the
Each version of Python uses different paths, so you will need to adjust the
path to the command for your Python version.
Python 2.7:
.. code-block:: text
.. code-block:: ps1con
   c:\> c:\Python27\Scripts\virtualenv %VENV%
Python 3.3:
Python 3.5:
.. code-block:: text
.. code-block:: ps1con
   c:\> c:\Python33\Scripts\virtualenv %VENV%
   c:\> c:\Python35\Scripts\python -m venv %VENV%
Install Pyramid and tutorial dependencies into the virtual Python environment
-----------------------------------------------------------------------------
Upgrade ``pip`` and ``setuptools`` in the virtual environment
-------------------------------------------------------------
On UNIX
^^^^^^^
.. code-block:: text
.. code-block:: bash
    $ $VENV/bin/easy_install docutils pyramid_tm pyramid_zodbconn \
            pyramid_debugtoolbar nose coverage
    $ $VENV/bin/pip install --upgrade pip setuptools
On Windows
^^^^^^^^^^
.. code-block:: text
.. code-block:: ps1con
     c:\> %VENV%\Scripts\easy_install docutils pyramid_tm pyramid_zodbconn \
            pyramid_debugtoolbar nose coverage
   c:\> %VENV%\Scripts\pip install --upgrade pip setuptools
Change Directory to Your Virtual Python Environment
Install Pyramid into the virtual Python environment
---------------------------------------------------
Change directory to the ``pyramidtut`` directory.
On UNIX
^^^^^^^
.. code-block:: text
.. code-block:: bash
   $ $VENV/bin/pip install pyramid
On Windows
^^^^^^^^^^
.. code-block:: ps1con
   c:\> %VENV%\Scripts\pip install pyramid
Change directory to your virtual Python environment
---------------------------------------------------
Change directory to the ``pyramidtut`` directory, which is both your workspace
and your virtual environment.
On UNIX
^^^^^^^
.. code-block:: bash
   $ cd pyramidtut
On Windows
^^^^^^^^^^
.. code-block:: text
.. code-block:: ps1con
   c:\> cd pyramidtut
.. _making_a_project:
Making a project
================
----------------
Your next step is to create a project.  For this tutorial, we will use
the :term:`scaffold` named ``zodb``, which generates an application
that uses :term:`ZODB` and :term:`traversal`.
:app:`Pyramid` supplies a variety of scaffolds to generate sample
projects. We will use `pcreate`—a script that comes with Pyramid to
quickly and easily generate scaffolds, usually with a single command—to
create the scaffold for our project.
:app:`Pyramid` supplies a variety of scaffolds to generate sample projects. We
will use ``pcreate``, a script that comes with Pyramid, to create our project
using a scaffold.
By passing `zodb` into the `pcreate` command, the script creates
the files needed to use ZODB. By passing in our application name
`tutorial`, the script inserts that application name into all the
required files.
By passing ``zodb`` into the ``pcreate`` command, the script creates the files
needed to use ZODB. By passing in our application name ``tutorial``, the script
inserts that application name into all the required files.
The below instructions assume your current working directory is "pyramidtut".
On UNIX
-------
^^^^^^^
.. code-block:: text
.. code-block:: bash
   $ $VENV/bin/pcreate -s zodb tutorial
On Windows
----------
^^^^^^^^^^
.. code-block:: text
.. code-block:: ps1con
   c:\pyramidtut> %VENV%\Scripts\pcreate -s zodb tutorial
.. note:: If you are using Windows, the ``zodb``
   scaffold may not deal gracefully with installation into a
   location that contains spaces in the path.  If you experience
   startup problems, try putting both the virtualenv and the project
   into directories that do not contain spaces in their paths.
.. note:: If you are using Windows, the ``zodb`` scaffold may not deal
   gracefully with installation into a location that contains spaces in the
   path. If you experience startup problems, try putting both the virtual
   environment and the project into directories that do not contain spaces in
   their paths.
.. _installing_project_in_dev_mode_zodb:
Installing the project in development mode
==========================================
------------------------------------------
In order to do development on the project easily, you must "register"
the project as a development egg in your workspace using the
``setup.py develop`` command.  In order to do so, cd to the `tutorial`
directory you created in :ref:`making_a_project`, and run the
``setup.py develop`` command using the virtualenv Python interpreter.
In order to do development on the project easily, you must "register" the
project as a development egg in your workspace using the ``pip install -e .``
command. In order to do so, change directory to the ``tutorial`` directory that
you created in :ref:`making_a_project`, and run the ``pip install -e .``
command using the virtual environment Python interpreter.
On UNIX
-------
^^^^^^^
.. code-block:: text
.. code-block:: bash
   $ cd tutorial
   $ $VENV/bin/python setup.py develop
   $ $VENV/bin/pip install -e .
On Windows
----------
^^^^^^^^^^
.. code-block:: text
.. code-block:: ps1con
   c:\pyramidtut> cd tutorial
   c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
   c:\pyramidtut\tutorial> %VENV%\Scripts\pip install -e .
The console will show `setup.py` checking for packages and installing
missing packages. Success executing this command will show a line like
the following::
The console will show ``pip`` checking for packages and installing missing
packages. Success executing this command will show a line like the following:
   Finished processing dependencies for tutorial==0.0
.. code-block:: bash
   Successfully installed BTrees-4.2.0 Chameleon-2.24 Mako-1.0.4 \
   MarkupSafe-0.23 Pygments-2.1.3 ZConfig-3.1.0 ZEO-4.2.0b1 ZODB-4.2.0 \
   ZODB3-3.11.0 mock-2.0.0 pbr-1.8.1 persistent-4.1.1 pyramid-chameleon-0.3 \
   pyramid-debugtoolbar-2.4.2 pyramid-mako-1.0.2 pyramid-tm-0.12.1 \
   pyramid-zodbconn-0.7 six-1.10.0 transaction-1.4.4 tutorial waitress-0.8.10 \
   zc.lockfile-1.1.0 zdaemon-4.1.0 zodbpickle-0.6.0 zodburi-2.0
.. _install-testing-requirements_zodb:
Install testing requirements
----------------------------
In order to run tests, we need to install the testing requirements. This is
done through our project's ``setup.py`` file, in the ``tests_require`` and
``extras_require`` stanzas, and by issuing the command below for your
operating system.
.. literalinclude:: src/installation/setup.py
   :language: python
   :linenos:
   :lineno-start: 22
   :lines: 22-26
.. literalinclude:: src/installation/setup.py
   :language: python
   :linenos:
   :lineno-start: 45
   :lines: 45-47
On UNIX
^^^^^^^
.. code-block:: bash
   $ $VENV/bin/pip install -e ".[testing]"
On Windows
^^^^^^^^^^
.. code-block:: ps1con
   c:\pyramidtut\tutorial> %VENV%\Scripts\pip install -e ".[testing]"
.. _running_tests:
Run the tests
=============
-------------
After you've installed the project in development mode, you may run
the tests for the project.
After you've installed the project in development mode as well as the testing
requirements, you may run the tests for the project.
On UNIX
-------
^^^^^^^
.. code-block:: text
.. code-block:: bash
   $ $VENV/bin/python setup.py test -q
   $ $VENV/bin/py.test tutorial/tests.py -q
On Windows
----------
^^^^^^^^^^
.. code-block:: text
.. code-block:: ps1con
   c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py test -q
   c:\pyramidtut\tutorial> %VENV%\Scripts\py.test tutorial\tests.py -q
For a successful test run, you should see output that ends like this::
For a successful test run, you should see output that ends like this:
  .
  ----------------------------------------------------------------------
  Ran 1 test in 0.094s
  OK
.. code-block:: bash
   .
   1 passed in 0.24 seconds
Expose test coverage information
================================
--------------------------------
You can run the ``nosetests`` command to see test coverage
information.  This runs the tests in the same way that ``setup.py
test`` does but provides additional "coverage" information, exposing
which lines of your project are "covered" (or not covered) by the
You can run the ``py.test`` command to see test coverage information. This
runs the tests in the same way that ``py.test`` does, but provides additional
"coverage" information, exposing which lines of your project are covered by the
tests.
We've already installed the ``pytest-cov`` package into our virtual
environment, so we can run the tests with coverage.
On UNIX
-------
^^^^^^^
.. code-block:: text
.. code-block:: bash
   $ $VENV/bin/nosetests --cover-package=tutorial --cover-erase --with-coverage
   $ $VENV/bin/py.test --cov=tutorial --cov-report=term-missing tutorial/tests.py
On Windows
----------
^^^^^^^^^^
.. code-block:: text
.. code-block:: ps1con
   c:\pyramidtut\tutorial> %VENV%\Scripts\nosetests --cover-package=tutorial \
         --cover-erase --with-coverage
   c:\pyramidtut\tutorial> %VENV%\Scripts\py.test --cov=tutorial \
       --cov-report=term-missing tutorial\tests.py
If successful, you will see output something like this::
If successful, you will see output something like this:
    .
    Name                 Stmts   Miss  Cover   Missing
    --------------------------------------------------
    tutorial.py             12      7    42%   7-8, 14-18
    tutorial/models.py      10      6    40%   9-14
    tutorial/views.py        4      0   100%
    --------------------------------------------------
    TOTAL                   26     13    50%
    ----------------------------------------------------------------------
    Ran 1 test in 0.392s
.. code-block:: bash
    OK
   ======================== test session starts ========================
   platform Python 3.5.1, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
   rootdir: /Users/stevepiercy/projects/pyramidtut/tutorial, inifile:
   plugins: cov-2.2.1
   collected 1 items
Looks like our package doesn't quite have 100% test coverage.
   tutorial/tests.py .
   ------------------ coverage: platform Python 3.5.1 ------------------
   Name                   Stmts   Miss  Cover   Missing
   ----------------------------------------------------
   tutorial/__init__.py      12      7    42%   7-8, 14-18
   tutorial/models.py        10      6    40%   9-14
   tutorial/tests.py         12      0   100%
   tutorial/views.py          4      0   100%
   ----------------------------------------------------
   TOTAL                     38     13    66%
   ===================== 1 passed in 0.31 seconds ======================
Our package doesn't quite have 100% test coverage.
.. _wiki-start-the-application:
Start the application
=====================
---------------------
Start the application.
On UNIX
-------
^^^^^^^
.. code-block:: text
.. code-block:: bash
   $ $VENV/bin/pserve development.ini --reload
On Windows
----------
^^^^^^^^^^
.. code-block:: text
.. code-block:: ps1con
   c:\pyramidtut\tutorial> %VENV%\Scripts\pserve development.ini --reload
@@ -280,34 +353,38 @@
   Your OS firewall, if any, may pop up a dialog asking for authorization
   to allow python to accept incoming network connections.
If successful, you will see something like this on your console::
If successful, you will see something like this on your console:
.. code-block:: text
    Starting subprocess with file monitor
    Starting server in PID 95736.
    serving on http://0.0.0.0:6543
    serving on http://127.0.0.1:6543
This means the server is ready to accept requests.
Visit the application in a browser
==================================
In a browser, visit `http://localhost:6543/ <http://localhost:6543>`_.  You
will see the generated application's default page.
Visit the application in a browser
----------------------------------
In a browser, visit http://localhost:6543/. You will see the generated
application's default page.
One thing you'll notice is the "debug toolbar" icon on right hand side of the
page.  You can read more about the purpose of the icon at
:ref:`debug_toolbar`.  It allows you to get information about your
application while you develop.
Decisions the ``zodb`` scaffold has made for you
================================================
------------------------------------------------
Creating a project using the ``zodb`` scaffold makes the following
assumptions:
- you are willing to use :term:`ZODB` as persistent storage
- You are willing to use :term:`ZODB` as persistent storage.
- you are willing to use :term:`traversal` to map URLs to code
- You are willing to use :term:`traversal` to map URLs to code.
.. note::
docs/tutorials/wiki/src/authorization/CHANGES.txt
@@ -1,5 +1,4 @@
0.0
---
- Initial version
-  Initial version
docs/tutorials/wiki/src/authorization/README.txt
@@ -1,4 +1,12 @@
tutorial README
==================
Getting Started
---------------
- cd <directory containing this file>
- $VENV/bin/pip install -e .
- $VENV/bin/pserve development.ini
docs/tutorials/wiki/src/authorization/development.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -29,12 +29,12 @@
[server:main]
use = egg:waitress#main
host = 0.0.0.0
host = 127.0.0.1
port = 6543
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
@@ -62,4 +62,4 @@
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
docs/tutorials/wiki/src/authorization/production.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -29,7 +29,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
@@ -57,4 +57,4 @@
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
docs/tutorials/wiki/src/authorization/setup.py
@@ -20,16 +20,22 @@
    'docutils',
    ]
tests_require = [
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',  # includes virtualenv
    'pytest-cov',
    ]
setup(name='tutorial',
      version='0.0',
      description='tutorial',
      long_description=README + '\n\n' + CHANGES,
      classifiers=[
        "Programming Language :: Python",
        "Framework :: Pyramid",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
        ],
          "Programming Language :: Python",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
      ],
      author='',
      author_email='',
      url='',
@@ -37,9 +43,10 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      tests_require=requires,
      test_suite="tutorial",
      entry_points="""\
      [paste.app_factory]
      main = tutorial:main
docs/tutorials/wiki/src/authorization/tutorial/models.py
@@ -17,7 +17,7 @@
        self.data = data
def appmaker(zodb_root):
    if not 'app_root' in zodb_root:
    if 'app_root' not in zodb_root:
        app_root = Wiki()
        frontpage = Page('This is the front page')
        app_root['FrontPage'] = frontpage
docs/tutorials/wiki/src/authorization/tutorial/static/theme.min.css
File was deleted
docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt
@@ -34,14 +34,15 @@
          <div class="col-md-10">
            <div class="content">
              <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">ZODB scaffold</span></h1>
              <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework</span>.</p>
              <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework 1.7</span>.</p>
            </div>
          </div>
        </div>
        <div class="row">
          <div class="links">
            <ul>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/latest/">Docs</a></li>
              <li class="current-version">Generated by v1.7</li>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/">Docs</a></li>
              <li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
              <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="irc://irc.freenode.net#pyramid">IRC Channel</a></li>
              <li><i class="glyphicon glyphicon-home icon-muted"></i><a href="http://pylonsproject.org">Pylons Project</a></li>
docs/tutorials/wiki/src/authorization/tutorial/tests.py
@@ -2,122 +2,16 @@
from pyramid import testing
class PageModelTests(unittest.TestCase):
    def _getTargetClass(self):
        from .models import Page
        return Page
class ViewTests(unittest.TestCase):
    def setUp(self):
        self.config = testing.setUp()
    def _makeOne(self, data=u'some data'):
        return self._getTargetClass()(data=data)
    def tearDown(self):
        testing.tearDown()
    def test_constructor(self):
        instance = self._makeOne()
        self.assertEqual(instance.data, u'some data')
class WikiModelTests(unittest.TestCase):
    def _getTargetClass(self):
        from .models import Wiki
        return Wiki
    def _makeOne(self):
        return self._getTargetClass()()
    def test_it(self):
        wiki = self._makeOne()
        self.assertEqual(wiki.__parent__, None)
        self.assertEqual(wiki.__name__, None)
class AppmakerTests(unittest.TestCase):
    def _callFUT(self, zodb_root):
        from .models import appmaker
        return appmaker(zodb_root)
    def test_it(self):
        root = {}
        self._callFUT(root)
        self.assertEqual(root['app_root']['FrontPage'].data,
                         'This is the front page')
class ViewWikiTests(unittest.TestCase):
    def test_it(self):
        from .views import view_wiki
        context = testing.DummyResource()
    def test_my_view(self):
        from .views import my_view
        request = testing.DummyRequest()
        response = view_wiki(context, request)
        self.assertEqual(response.location, 'http://example.com/FrontPage')
class ViewPageTests(unittest.TestCase):
    def _callFUT(self, context, request):
        from .views import view_page
        return view_page(context, request)
    def test_it(self):
        wiki = testing.DummyResource()
        wiki['IDoExist'] = testing.DummyResource()
        context = testing.DummyResource(data='Hello CruelWorld IDoExist')
        context.__parent__ = wiki
        context.__name__ = 'thepage'
        request = testing.DummyRequest()
        info = self._callFUT(context, request)
        self.assertEqual(info['page'], context)
        self.assertEqual(
            info['content'],
            '<div class="document">\n'
            '<p>Hello <a href="http://example.com/add_page/CruelWorld">'
            'CruelWorld</a> '
            '<a href="http://example.com/IDoExist/">'
            'IDoExist</a>'
            '</p>\n</div>\n')
        self.assertEqual(info['edit_url'],
                         'http://example.com/thepage/edit_page')
class AddPageTests(unittest.TestCase):
    def _callFUT(self, context, request):
        from .views import add_page
        return add_page(context, request)
    def test_it_notsubmitted(self):
        context = testing.DummyResource()
        request = testing.DummyRequest()
        request.subpath = ['AnotherPage']
        info = self._callFUT(context, request)
        self.assertEqual(info['page'].data,'')
        self.assertEqual(
            info['save_url'],
            request.resource_url(context, 'add_page', 'AnotherPage'))
    def test_it_submitted(self):
        context = testing.DummyResource()
        request = testing.DummyRequest({'form.submitted':True,
                                        'body':'Hello yo!'})
        request.subpath = ['AnotherPage']
        self._callFUT(context, request)
        page = context['AnotherPage']
        self.assertEqual(page.data, 'Hello yo!')
        self.assertEqual(page.__name__, 'AnotherPage')
        self.assertEqual(page.__parent__, context)
class EditPageTests(unittest.TestCase):
    def _callFUT(self, context, request):
        from .views import edit_page
        return edit_page(context, request)
    def test_it_notsubmitted(self):
        context = testing.DummyResource()
        request = testing.DummyRequest()
        info = self._callFUT(context, request)
        self.assertEqual(info['page'], context)
        self.assertEqual(info['save_url'],
                         request.resource_url(context, 'edit_page'))
    def test_it_submitted(self):
        context = testing.DummyResource()
        request = testing.DummyRequest({'form.submitted':True,
                                        'body':'Hello yo!'})
        response = self._callFUT(context, request)
        self.assertEqual(response.location, 'http://example.com/')
        self.assertEqual(context.data, 'Hello yo!')
        info = my_view(request)
        self.assertEqual(info['project'], 'tutorial')
docs/tutorials/wiki/src/authorization/tutorial/views.py
@@ -37,15 +37,15 @@
            view_url = request.resource_url(page)
            return '<a href="%s">%s</a>' % (view_url, word)
        else:
            add_url = request.application_url + '/add_page/' + word
            add_url = request.application_url + '/add_page/' + word
            return '<a href="%s">%s</a>' % (add_url, word)
    content = publish_parts(context.data, writer_name='html')['html_body']
    content = wikiwords.sub(check, content)
    edit_url = request.resource_url(context, 'edit_page')
    return dict(page = context, content = content, edit_url = edit_url,
                logged_in = request.authenticated_userid)
    return dict(page=context, content=content, edit_url=edit_url,
                logged_in=request.authenticated_userid)
@view_config(name='add_page', context='.models.Wiki',
             renderer='templates/edit.pt',
@@ -58,7 +58,7 @@
        page.__name__ = pagename
        page.__parent__ = context
        context[pagename] = page
        return HTTPFound(location = request.resource_url(page))
        return HTTPFound(location=request.resource_url(page))
    save_url = request.resource_url(context, 'add_page', pagename)
    page = Page('')
    page.__name__ = pagename
@@ -73,7 +73,7 @@
def edit_page(context, request):
    if 'form.submitted' in request.params:
        context.data = request.params['body']
        return HTTPFound(location = request.resource_url(context))
        return HTTPFound(location=request.resource_url(context))
    return dict(page=context,
                save_url=request.resource_url(context, 'edit_page'),
@@ -86,7 +86,7 @@
    login_url = request.resource_url(request.context, 'login')
    referrer = request.url
    if referrer == login_url:
        referrer = '/' # never use the login form itself as came_from
        referrer = '/'  # never use the login form itself as came_from
    came_from = request.params.get('came_from', referrer)
    message = ''
    login = ''
@@ -96,20 +96,21 @@
        password = request.params['password']
        if USERS.get(login) == password:
            headers = remember(request, login)
            return HTTPFound(location = came_from,
                             headers = headers)
            return HTTPFound(location=came_from,
                             headers=headers)
        message = 'Failed login'
    return dict(
        message = message,
        url = request.application_url + '/login',
        came_from = came_from,
        login = login,
        password = password,
        )
        message=message,
        url=request.application_url + '/login',
        came_from=came_from,
        login=login,
        password=password,
    )
@view_config(context='.models.Wiki', name='logout')
def logout(request):
    headers = forget(request)
    return HTTPFound(location = request.resource_url(request.context),
                     headers = headers)
    return HTTPFound(location=request.resource_url(request.context),
                     headers=headers)
docs/tutorials/wiki/src/basiclayout/README.txt
@@ -1,4 +1,12 @@
tutorial README
==================
Getting Started
---------------
- cd <directory containing this file>
- $VENV/bin/pip install -e .
- $VENV/bin/pserve development.ini
docs/tutorials/wiki/src/basiclayout/development.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -29,12 +29,12 @@
[server:main]
use = egg:waitress#main
host = 0.0.0.0
host = 127.0.0.1
port = 6543
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
@@ -62,4 +62,4 @@
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
docs/tutorials/wiki/src/basiclayout/production.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -29,7 +29,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
@@ -57,4 +57,4 @@
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
docs/tutorials/wiki/src/basiclayout/setup.py
@@ -19,16 +19,22 @@
    'waitress',
    ]
tests_require = [
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',  # includes virtualenv
    'pytest-cov',
    ]
setup(name='tutorial',
      version='0.0',
      description='tutorial',
      long_description=README + '\n\n' + CHANGES,
      classifiers=[
        "Programming Language :: Python",
        "Framework :: Pyramid",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
        ],
          "Programming Language :: Python",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
      ],
      author='',
      author_email='',
      url='',
@@ -36,9 +42,10 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      tests_require=requires,
      test_suite="tutorial",
      entry_points="""\
      [paste.app_factory]
      main = tutorial:main
docs/tutorials/wiki/src/basiclayout/tutorial/models.py
@@ -6,7 +6,7 @@
def appmaker(zodb_root):
    if not 'app_root' in zodb_root:
    if 'app_root' not in zodb_root:
        app_root = MyModel()
        zodb_root['app_root'] = app_root
        import transaction
docs/tutorials/wiki/src/basiclayout/tutorial/static/theme.min.css
File was deleted
docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt
@@ -34,14 +34,15 @@
          <div class="col-md-10">
            <div class="content">
              <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">ZODB scaffold</span></h1>
              <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework</span>.</p>
              <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework 1.7</span>.</p>
            </div>
          </div>
        </div>
        <div class="row">
          <div class="links">
            <ul>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/latest/">Docs</a></li>
              <li class="current-version">Generated by v1.7</li>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/">Docs</a></li>
              <li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
              <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="irc://irc.freenode.net#pyramid">IRC Channel</a></li>
              <li><i class="glyphicon glyphicon-home icon-muted"></i><a href="http://pylonsproject.org">Pylons Project</a></li>
docs/tutorials/wiki/src/basiclayout/tutorial/tests.py
@@ -2,6 +2,7 @@
from pyramid import testing
class ViewTests(unittest.TestCase):
    def setUp(self):
        self.config = testing.setUp()
docs/tutorials/wiki/src/installation/CHANGES.txt
New file
@@ -0,0 +1,4 @@
0.0
---
-  Initial version
docs/tutorials/wiki/src/installation/MANIFEST.in
New file
@@ -0,0 +1,2 @@
include *.txt *.ini *.cfg *.rst
recursive-include tutorial *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml
docs/tutorials/wiki/src/installation/README.txt
New file
@@ -0,0 +1,12 @@
tutorial README
==================
Getting Started
---------------
- cd <directory containing this file>
- $VENV/bin/pip install -e .
- $VENV/bin/pserve development.ini
docs/tutorials/wiki/src/installation/development.ini
New file
@@ -0,0 +1,65 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
use = egg:tutorial
pyramid.reload_templates = true
pyramid.debug_authorization = false
pyramid.debug_notfound = false
pyramid.debug_routematch = false
pyramid.default_locale_name = en
pyramid.includes =
    pyramid_debugtoolbar
    pyramid_zodbconn
    pyramid_tm
tm.attempts = 3
zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000
# 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/1.7-branch/narr/logging.html
###
[loggers]
keys = root, tutorial
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = INFO
handlers = console
[logger_tutorial]
level = DEBUG
handlers =
qualname = tutorial
[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
docs/tutorials/wiki/src/installation/production.ini
New file
@@ -0,0 +1,60 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
use = egg:tutorial
pyramid.reload_templates = false
pyramid.debug_authorization = false
pyramid.debug_notfound = false
pyramid.debug_routematch = false
pyramid.default_locale_name = en
pyramid.includes =
    pyramid_tm
    pyramid_zodbconn
tm.attempts = 3
zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000
###
# wsgi server configuration
###
[server:main]
use = egg:waitress#main
host = 0.0.0.0
port = 6543
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
keys = root, tutorial
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = WARN
handlers = console
[logger_tutorial]
level = WARN
handlers =
qualname = tutorial
[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
docs/tutorials/wiki/src/installation/setup.py
New file
@@ -0,0 +1,53 @@
import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(here, 'README.txt')) as f:
    README = f.read()
with open(os.path.join(here, 'CHANGES.txt')) as f:
    CHANGES = f.read()
requires = [
    'pyramid',
    'pyramid_chameleon',
    'pyramid_debugtoolbar',
    'pyramid_tm',
    'pyramid_zodbconn',
    'transaction',
    'ZODB3',
    'waitress',
    ]
tests_require = [
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',  # includes virtualenv
    'pytest-cov',
    ]
setup(name='tutorial',
      version='0.0',
      description='tutorial',
      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 pylons pyramid',
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      entry_points="""\
      [paste.app_factory]
      main = tutorial:main
      """,
      )
docs/tutorials/wiki/src/installation/tutorial/__init__.py
New file
@@ -0,0 +1,18 @@
from pyramid.config import Configurator
from pyramid_zodbconn import get_connection
from .models import appmaker
def root_factory(request):
    conn = get_connection(request)
    return appmaker(conn.root())
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = Configurator(root_factory=root_factory, settings=settings)
    config.include('pyramid_chameleon')
    config.add_static_view('static', 'static', cache_max_age=3600)
    config.scan()
    return config.make_wsgi_app()
docs/tutorials/wiki/src/installation/tutorial/models.py
New file
@@ -0,0 +1,14 @@
from persistent.mapping import PersistentMapping
class MyModel(PersistentMapping):
    __parent__ = __name__ = None
def appmaker(zodb_root):
    if 'app_root' not in zodb_root:
        app_root = MyModel()
        zodb_root['app_root'] = app_root
        import transaction
        transaction.commit()
    return zodb_root['app_root']
docs/tutorials/wiki/src/installation/tutorial/static/pyramid-16x16.png
docs/tutorials/wiki/src/installation/tutorial/static/pyramid.png
docs/tutorials/wiki/src/installation/tutorial/static/theme.css
New file
@@ -0,0 +1,154 @@
@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, a {
  color: #f2b7bd;
  text-decoration: underline;
}
.starter-template .links ul li a:hover, a:hover {
  color: #ffffff;
  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;
  }
}
docs/tutorials/wiki/src/installation/tutorial/templates/mytemplate.pt
New file
@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html lang="${request.locale_name}">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="pyramid web application">
    <meta name="author" content="Pylons Project">
    <link rel="shortcut icon" href="${request.static_url('tutorial:static/pyramid-16x16.png')}">
    <title>ZODB Scaffold for The Pyramid Web Framework</title>
    <!-- Bootstrap core CSS -->
    <link href="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
    <!-- Custom styles for this scaffold -->
    <link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!--[if lt IE 9]>
      <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
      <script src="//oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <div class="starter-template">
      <div class="container">
        <div class="row">
          <div class="col-md-2">
            <img class="logo img-responsive" src="${request.static_url('tutorial:static/pyramid.png')}" alt="pyramid web framework">
          </div>
          <div class="col-md-10">
            <div class="content">
              <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">ZODB scaffold</span></h1>
              <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework 1.7</span>.</p>
            </div>
          </div>
        </div>
        <div class="row">
          <div class="links">
            <ul>
              <li class="current-version">Generated by v1.7</li>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/">Docs</a></li>
              <li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
              <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="irc://irc.freenode.net#pyramid">IRC Channel</a></li>
              <li><i class="glyphicon glyphicon-home icon-muted"></i><a href="http://pylonsproject.org">Pylons Project</a></li>
            </ul>
          </div>
        </div>
        <div class="row">
          <div class="copyright">
            Copyright &copy; Pylons Project
          </div>
        </div>
      </div>
    </div>
    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="//oss.maxcdn.com/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/js/bootstrap.min.js"></script>
  </body>
</html>
docs/tutorials/wiki/src/installation/tutorial/tests.py
New file
@@ -0,0 +1,17 @@
import unittest
from pyramid import testing
class ViewTests(unittest.TestCase):
    def setUp(self):
        self.config = testing.setUp()
    def tearDown(self):
        testing.tearDown()
    def test_my_view(self):
        from .views import my_view
        request = testing.DummyRequest()
        info = my_view(request)
        self.assertEqual(info['project'], 'tutorial')
docs/tutorials/wiki/src/installation/tutorial/views.py
New file
@@ -0,0 +1,7 @@
from pyramid.view import view_config
from .models import MyModel
@view_config(context=MyModel, renderer='templates/mytemplate.pt')
def my_view(request):
    return {'project': 'tutorial'}
docs/tutorials/wiki/src/models/CHANGES.txt
@@ -1,4 +1,4 @@
0.0
---
- Initial version
-  Initial version
docs/tutorials/wiki/src/models/README.txt
@@ -1,4 +1,12 @@
tutorial README
==================
Getting Started
---------------
- cd <directory containing this file>
- $VENV/bin/pip install -e .
- $VENV/bin/pserve development.ini
docs/tutorials/wiki/src/models/development.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -29,12 +29,12 @@
[server:main]
use = egg:waitress#main
host = 0.0.0.0
host = 127.0.0.1
port = 6543
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
@@ -62,4 +62,4 @@
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
docs/tutorials/wiki/src/models/production.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -29,7 +29,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
@@ -57,4 +57,4 @@
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
docs/tutorials/wiki/src/models/setup.py
@@ -19,16 +19,22 @@
    'waitress',
    ]
tests_require = [
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',  # includes virtualenv
    'pytest-cov',
    ]
setup(name='tutorial',
      version='0.0',
      description='tutorial',
      long_description=README + '\n\n' + CHANGES,
      classifiers=[
        "Programming Language :: Python",
        "Framework :: Pyramid",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
        ],
          "Programming Language :: Python",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
      ],
      author='',
      author_email='',
      url='',
@@ -36,9 +42,10 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      tests_require=requires,
      test_suite="tutorial",
      entry_points="""\
      [paste.app_factory]
      main = tutorial:main
docs/tutorials/wiki/src/models/tutorial/models.py
@@ -10,7 +10,7 @@
        self.data = data
def appmaker(zodb_root):
    if not 'app_root' in zodb_root:
    if 'app_root' not in zodb_root:
        app_root = Wiki()
        frontpage = Page('This is the front page')
        app_root['FrontPage'] = frontpage
docs/tutorials/wiki/src/models/tutorial/static/theme.min.css
File was deleted
docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt
@@ -34,14 +34,15 @@
          <div class="col-md-10">
            <div class="content">
              <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">ZODB scaffold</span></h1>
              <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework</span>.</p>
              <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework 1.7</span>.</p>
            </div>
          </div>
        </div>
        <div class="row">
          <div class="links">
            <ul>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/latest/">Docs</a></li>
              <li class="current-version">Generated by v1.7</li>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/">Docs</a></li>
              <li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
              <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="irc://irc.freenode.net#pyramid">IRC Channel</a></li>
              <li><i class="glyphicon glyphicon-home icon-muted"></i><a href="http://pylonsproject.org">Pylons Project</a></li>
docs/tutorials/wiki/src/models/tutorial/tests.py
@@ -2,50 +2,6 @@
from pyramid import testing
class PageModelTests(unittest.TestCase):
    def _getTargetClass(self):
        from .models import Page
        return Page
    def _makeOne(self, data=u'some data'):
        return self._getTargetClass()(data=data)
    def test_constructor(self):
        instance = self._makeOne()
        self.assertEqual(instance.data, u'some data')
class WikiModelTests(unittest.TestCase):
    def _getTargetClass(self):
        from .models import Wiki
        return Wiki
    def _makeOne(self):
        return self._getTargetClass()()
    def test_it(self):
        wiki = self._makeOne()
        self.assertEqual(wiki.__parent__, None)
        self.assertEqual(wiki.__name__, None)
class AppmakerTests(unittest.TestCase):
    def _callFUT(self, zodb_root):
        from .models import appmaker
        return appmaker(zodb_root)
    def test_no_app_root(self):
        root = {}
        self._callFUT(root)
        self.assertEqual(root['app_root']['FrontPage'].data,
                         'This is the front page')
    def test_w_app_root(self):
        app_root = object()
        root = {'app_root': app_root}
        self._callFUT(root)
        self.assertTrue(root['app_root'] is app_root)
class ViewTests(unittest.TestCase):
    def setUp(self):
docs/tutorials/wiki/src/tests/CHANGES.txt
@@ -1,5 +1,4 @@
0.0
---
- Initial version
-  Initial version
docs/tutorials/wiki/src/tests/README.txt
@@ -1,4 +1,12 @@
tutorial README
==================
Getting Started
---------------
- cd <directory containing this file>
- $VENV/bin/pip install -e .
- $VENV/bin/pserve development.ini
docs/tutorials/wiki/src/tests/development.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -29,12 +29,12 @@
[server:main]
use = egg:waitress#main
host = 0.0.0.0
host = 127.0.0.1
port = 6543
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
@@ -62,4 +62,4 @@
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
docs/tutorials/wiki/src/tests/production.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -29,7 +29,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
@@ -57,4 +57,4 @@
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
docs/tutorials/wiki/src/tests/setup.py
@@ -18,7 +18,12 @@
    'ZODB3',
    'waitress',
    'docutils',
    'WebTest', # add this
    ]
tests_require = [
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',  # includes virtualenv
    'pytest-cov',
    ]
setup(name='tutorial',
@@ -26,11 +31,11 @@
      description='tutorial',
      long_description=README + '\n\n' + CHANGES,
      classifiers=[
        "Programming Language :: Python",
        "Framework :: Pyramid",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
        ],
          "Programming Language :: Python",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
      ],
      author='',
      author_email='',
      url='',
@@ -38,9 +43,10 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      tests_require=requires,
      test_suite="tutorial",
      entry_points="""\
      [paste.app_factory]
      main = tutorial:main
docs/tutorials/wiki/src/tests/tutorial/__init__.py
@@ -19,9 +19,9 @@
        'sosecret', callback=groupfinder, hashalg='sha512')
    authz_policy = ACLAuthorizationPolicy()
    config = Configurator(root_factory=root_factory, settings=settings)
    config.include('pyramid_chameleon')
    config.set_authentication_policy(authn_policy)
    config.set_authorization_policy(authz_policy)
    config.include('pyramid_chameleon')
    config.add_static_view('static', 'static', cache_max_age=3600)
    config.scan()
    return config.make_wsgi_app()
docs/tutorials/wiki/src/tests/tutorial/models.py
@@ -17,7 +17,7 @@
        self.data = data
def appmaker(zodb_root):
    if not 'app_root' in zodb_root:
    if 'app_root' not in zodb_root:
        app_root = Wiki()
        frontpage = Page('This is the front page')
        app_root['FrontPage'] = frontpage
docs/tutorials/wiki/src/tests/tutorial/static/theme.min.css
File was deleted
docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt
@@ -34,14 +34,15 @@
          <div class="col-md-10">
            <div class="content">
              <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">ZODB scaffold</span></h1>
              <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework</span>.</p>
              <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework 1.7</span>.</p>
            </div>
          </div>
        </div>
        <div class="row">
          <div class="links">
            <ul>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/latest/">Docs</a></li>
              <li class="current-version">Generated by v1.7</li>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/">Docs</a></li>
              <li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
              <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="irc://irc.freenode.net#pyramid">IRC Channel</a></li>
              <li><i class="glyphicon glyphicon-home icon-muted"></i><a href="http://pylonsproject.org">Pylons Project</a></li>
docs/tutorials/wiki/src/tests/tutorial/tests.py
@@ -164,6 +164,10 @@
        res = self.testapp.get('/SomePage', status=404)
        self.assertTrue(b'Not Found' in res.body)
    def test_referrer_is_login(self):
        res = self.testapp.get('/login', status=200)
        self.assertTrue(b'name="came_from" value="/"' in res.body)
    def test_successful_log_in(self):
        res = self.testapp.get( self.viewer_login, status=302)
        self.assertEqual(res.location, 'http://localhost/FrontPage')
docs/tutorials/wiki/src/tests/tutorial/views.py
@@ -37,15 +37,15 @@
            view_url = request.resource_url(page)
            return '<a href="%s">%s</a>' % (view_url, word)
        else:
            add_url = request.application_url + '/add_page/' + word
            add_url = request.application_url + '/add_page/' + word
            return '<a href="%s">%s</a>' % (add_url, word)
    content = publish_parts(context.data, writer_name='html')['html_body']
    content = wikiwords.sub(check, content)
    edit_url = request.resource_url(context, 'edit_page')
    return dict(page = context, content = content, edit_url = edit_url,
                logged_in = request.authenticated_userid)
    return dict(page=context, content=content, edit_url=edit_url,
                logged_in=request.authenticated_userid)
@view_config(name='add_page', context='.models.Wiki',
             renderer='templates/edit.pt',
@@ -58,7 +58,7 @@
        page.__name__ = pagename
        page.__parent__ = context
        context[pagename] = page
        return HTTPFound(location = request.resource_url(page))
        return HTTPFound(location=request.resource_url(page))
    save_url = request.resource_url(context, 'add_page', pagename)
    page = Page('')
    page.__name__ = pagename
@@ -73,7 +73,7 @@
def edit_page(context, request):
    if 'form.submitted' in request.params:
        context.data = request.params['body']
        return HTTPFound(location = request.resource_url(context))
        return HTTPFound(location=request.resource_url(context))
    return dict(page=context,
                save_url=request.resource_url(context, 'edit_page'),
@@ -86,7 +86,7 @@
    login_url = request.resource_url(request.context, 'login')
    referrer = request.url
    if referrer == login_url:
        referrer = '/' # never use the login form itself as came_from
        referrer = '/'  # never use the login form itself as came_from
    came_from = request.params.get('came_from', referrer)
    message = ''
    login = ''
@@ -96,20 +96,21 @@
        password = request.params['password']
        if USERS.get(login) == password:
            headers = remember(request, login)
            return HTTPFound(location = came_from,
                             headers = headers)
            return HTTPFound(location=came_from,
                             headers=headers)
        message = 'Failed login'
    return dict(
        message = message,
        url = request.application_url + '/login',
        came_from = came_from,
        login = login,
        password = password,
        )
        message=message,
        url=request.application_url + '/login',
        came_from=came_from,
        login=login,
        password=password,
    )
@view_config(context='.models.Wiki', name='logout')
def logout(request):
    headers = forget(request)
    return HTTPFound(location = request.resource_url(request.context),
                     headers = headers)
    return HTTPFound(location=request.resource_url(request.context),
                     headers=headers)
docs/tutorials/wiki/src/views/CHANGES.txt
@@ -1,3 +1,4 @@
0.1
0.0
---
  Initial version
-  Initial version
docs/tutorials/wiki/src/views/README.txt
@@ -1,4 +1,12 @@
tutorial README
==================
Getting Started
---------------
- cd <directory containing this file>
- $VENV/bin/pip install -e .
- $VENV/bin/pserve development.ini
docs/tutorials/wiki/src/views/development.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -29,12 +29,12 @@
[server:main]
use = egg:waitress#main
host = 0.0.0.0
host = 127.0.0.1
port = 6543
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
@@ -62,4 +62,4 @@
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
docs/tutorials/wiki/src/views/production.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -29,7 +29,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
@@ -57,4 +57,4 @@
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
docs/tutorials/wiki/src/views/setup.py
@@ -20,16 +20,22 @@
    'docutils',
    ]
tests_require = [
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',  # includes virtualenv
    'pytest-cov',
    ]
setup(name='tutorial',
      version='0.0',
      description='tutorial',
      long_description=README + '\n\n' + CHANGES,
      classifiers=[
        "Programming Language :: Python",
        "Framework :: Pyramid",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
        ],
          "Programming Language :: Python",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
      ],
      author='',
      author_email='',
      url='',
@@ -37,9 +43,10 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      tests_require=requires,
      test_suite="tutorial",
      entry_points="""\
      [paste.app_factory]
      main = tutorial:main
docs/tutorials/wiki/src/views/tutorial/models.py
@@ -10,7 +10,7 @@
        self.data = data
def appmaker(zodb_root):
    if not 'app_root' in zodb_root:
    if 'app_root' not in zodb_root:
        app_root = Wiki()
        frontpage = Page('This is the front page')
        app_root['FrontPage'] = frontpage
docs/tutorials/wiki/src/views/tutorial/static/theme.min.css
File was deleted
docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt
@@ -34,14 +34,15 @@
          <div class="col-md-10">
            <div class="content">
              <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">ZODB scaffold</span></h1>
              <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework</span>.</p>
              <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework 1.7</span>.</p>
            </div>
          </div>
        </div>
        <div class="row">
          <div class="links">
            <ul>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/latest/">Docs</a></li>
              <li class="current-version">Generated by v1.7</li>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/">Docs</a></li>
              <li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
              <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="irc://irc.freenode.net#pyramid">IRC Channel</a></li>
              <li><i class="glyphicon glyphicon-home icon-muted"></i><a href="http://pylonsproject.org">Pylons Project</a></li>
docs/tutorials/wiki/src/views/tutorial/tests.py
@@ -2,125 +2,16 @@
from pyramid import testing
class PageModelTests(unittest.TestCase):
    def _getTargetClass(self):
        from .models import Page
        return Page
class ViewTests(unittest.TestCase):
    def setUp(self):
        self.config = testing.setUp()
    def _makeOne(self, data=u'some data'):
        return self._getTargetClass()(data=data)
    def tearDown(self):
        testing.tearDown()
    def test_constructor(self):
        instance = self._makeOne()
        self.assertEqual(instance.data, u'some data')
class WikiModelTests(unittest.TestCase):
    def _getTargetClass(self):
        from .models import Wiki
        return Wiki
    def _makeOne(self):
        return self._getTargetClass()()
    def test_it(self):
        wiki = self._makeOne()
        self.assertEqual(wiki.__parent__, None)
        self.assertEqual(wiki.__name__, None)
class AppmakerTests(unittest.TestCase):
    def _callFUT(self, zodb_root):
        from .models import appmaker
        return appmaker(zodb_root)
    def test_it(self):
        root = {}
        self._callFUT(root)
        self.assertEqual(root['app_root']['FrontPage'].data,
                         'This is the front page')
class ViewWikiTests(unittest.TestCase):
    def test_it(self):
        from .views import view_wiki
        context = testing.DummyResource()
    def test_my_view(self):
        from .views import my_view
        request = testing.DummyRequest()
        response = view_wiki(context, request)
        self.assertEqual(response.location, 'http://example.com/FrontPage')
class ViewPageTests(unittest.TestCase):
    def _callFUT(self, context, request):
        from .views import view_page
        return view_page(context, request)
    def test_it(self):
        wiki = testing.DummyResource()
        wiki['IDoExist'] = testing.DummyResource()
        context = testing.DummyResource(data='Hello CruelWorld IDoExist')
        context.__parent__ = wiki
        context.__name__ = 'thepage'
        request = testing.DummyRequest()
        info = self._callFUT(context, request)
        self.assertEqual(info['page'], context)
        self.assertEqual(
            info['content'],
            '<div class="document">\n'
            '<p>Hello <a href="http://example.com/add_page/CruelWorld">'
            'CruelWorld</a> '
            '<a href="http://example.com/IDoExist/">'
            'IDoExist</a>'
            '</p>\n</div>\n')
        self.assertEqual(info['edit_url'],
                         'http://example.com/thepage/edit_page')
class AddPageTests(unittest.TestCase):
    def _callFUT(self, context, request):
        from .views import add_page
        return add_page(context, request)
    def test_it_notsubmitted(self):
        context = testing.DummyResource()
        request = testing.DummyRequest()
        request.subpath = ['AnotherPage']
        info = self._callFUT(context, request)
        self.assertEqual(info['page'].data,'')
        self.assertEqual(
            info['save_url'],
            request.resource_url(context, 'add_page', 'AnotherPage'))
    def test_it_submitted(self):
        context = testing.DummyResource()
        request = testing.DummyRequest({'form.submitted':True,
                                        'body':'Hello yo!'})
        request.subpath = ['AnotherPage']
        self._callFUT(context, request)
        page = context['AnotherPage']
        self.assertEqual(page.data, 'Hello yo!')
        self.assertEqual(page.__name__, 'AnotherPage')
        self.assertEqual(page.__parent__, context)
class EditPageTests(unittest.TestCase):
    def _callFUT(self, context, request):
        from .views import edit_page
        return edit_page(context, request)
    def test_it_notsubmitted(self):
        context = testing.DummyResource()
        request = testing.DummyRequest()
        info = self._callFUT(context, request)
        self.assertEqual(info['page'], context)
        self.assertEqual(info['save_url'],
                         request.resource_url(context, 'edit_page'))
    def test_it_submitted(self):
        context = testing.DummyResource()
        request = testing.DummyRequest({'form.submitted':True,
                                        'body':'Hello yo!'})
        response = self._callFUT(context, request)
        self.assertEqual(response.location, 'http://example.com/')
        self.assertEqual(context.data, 'Hello yo!')
        info = my_view(request)
        self.assertEqual(info['project'], 'tutorial')
docs/tutorials/wiki/tests.rst
@@ -1,3 +1,5 @@
.. _wiki_adding_tests:
============
Adding Tests
============
@@ -49,55 +51,25 @@
Running the tests
=================
We can run these tests by using ``setup.py test`` in the same way we did in
:ref:`running_tests`.  However, first we must edit our ``setup.py`` to
include a dependency on WebTest, which we've used in our ``tests.py``.
Change the ``requires`` list in ``setup.py`` to include ``WebTest``.
.. literalinclude:: src/tests/setup.py
   :linenos:
   :language: python
   :lines: 11-22
   :emphasize-lines: 11
After we've added a dependency on WebTest in ``setup.py``, we need to run
``setup.py develop`` to get WebTest installed into our virtualenv.  Assuming
our shell's current working directory is the "tutorial" distribution
directory:
We can run these tests by using ``py.test`` similarly to how we did in
:ref:`running_tests`. Our testing dependencies have already been satisfied,
courtesy of the scaffold, so we can jump right to running tests.
On UNIX:
.. code-block:: text
   $ $VENV/bin/python setup.py develop
   $ $VENV/bin/py.test tutorial/tests.py -q
On Windows:
.. code-block:: text
   c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
Once that command has completed successfully, we can run the tests
themselves:
On UNIX:
.. code-block:: text
   $ $VENV/bin/python setup.py test -q
On Windows:
.. code-block:: text
   c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py test -q
   c:\pyramidtut\tutorial> %VENV%\Scripts\py.test tutorial/tests.py -q
The expected result should look like the following:
.. code-block:: text
   .........
   ----------------------------------------------------------------------
   Ran 23 tests in 1.653s
   OK
   ........................
   24 passed in 2.46 seconds
docs/tutorials/wiki2/authorization.rst
@@ -4,7 +4,7 @@
Adding authorization
====================
In the last chapter we built :term:`authentication` into our wiki2. We also
In the last chapter we built :term:`authentication` into our wiki. We also
went one step further and used the ``request.user`` object to perform some
explicit :term:`authorization` checks. This is fine for a lot of applications,
but :app:`Pyramid` provides some facilities for cleaning this up and decoupling
docs/tutorials/wiki2/background.rst
@@ -1,3 +1,5 @@
.. _wiki2_background:
==========
Background
==========
docs/tutorials/wiki2/basiclayout.rst
@@ -1,3 +1,5 @@
.. _wiki2_basic_layout:
============
Basic Layout
============
docs/tutorials/wiki2/definingmodels.rst
@@ -1,3 +1,5 @@
.. _wiki2_defining_the_domain_model:
=========================
Defining the Domain Model
=========================
@@ -37,12 +39,12 @@
Only the highlighted line needs to be added.
Running ``setup.py develop``
Running ``pip install -e .``
============================
Since a new software dependency was added, you will need to run ``python
setup.py develop`` again inside the root of the ``tutorial`` package to obtain
and register the newly added dependency distribution.
Since a new software dependency was added, you will need to run ``pip install
-e .`` again inside the root of the ``tutorial`` package to obtain and register
the newly added dependency distribution.
Make sure your current working directory is the root of the project (the
directory in which ``setup.py`` lives) and execute the following command.
@@ -52,19 +54,19 @@
.. code-block:: bash
   $ cd tutorial
   $ $VENV/bin/python setup.py develop
   $ $VENV/bin/pip install -e .
On Windows:
.. code-block:: ps1con
   c:\pyramidtut> cd tutorial
   c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
   c:\pyramidtut\tutorial> %VENV%\Scripts\pip install -e .
Success executing this command will end with a line to the console something
like this::
   Finished processing dependencies for tutorial==0.0
   Successfully installed bcrypt-2.0.0 cffi-1.5.2 pycparser-2.14 tutorial-0.0
Remove ``mymodel.py``
@@ -149,7 +151,7 @@
   :language: py
   :emphasize-lines: 8,9
Here we align our imports with the names of the models, ``User`` and ``Page``.
Here we align our imports with the names of the models, ``Page`` and ``User``.
Edit ``scripts/initializedb.py``
@@ -185,51 +187,54 @@
we've made to both the models.py file and to the initializedb.py file. See
:ref:`initialize_db_wiki2` for instructions.
Success will look something like this::
Success will look something like this:
  2016-02-12 01:06:35,855 INFO  [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
  2016-02-12 01:06:35,855 INFO  [sqlalchemy.engine.base.Engine:1193][MainThread] ()
  2016-02-12 01:06:35,855 INFO  [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
  2016-02-12 01:06:35,855 INFO  [sqlalchemy.engine.base.Engine:1193][MainThread] ()
  2016-02-12 01:06:35,856 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] PRAGMA table_info("pages")
  2016-02-12 01:06:35,856 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ()
  2016-02-12 01:06:35,856 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] PRAGMA table_info("users")
  2016-02-12 01:06:35,856 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ()
  2016-02-12 01:06:35,857 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread]
  CREATE TABLE users (
    id INTEGER NOT NULL,
    name TEXT NOT NULL,
    role TEXT NOT NULL,
    password_hash TEXT,
    CONSTRAINT pk_users PRIMARY KEY (id),
    CONSTRAINT uq_users_name UNIQUE (name)
  )
.. code-block:: bash
   2016-04-09 02:49:51,711 INFO  [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
   2016-04-09 02:49:51,711 INFO  [sqlalchemy.engine.base.Engine:1193][MainThread] ()
   2016-04-09 02:49:51,712 INFO  [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
   2016-04-09 02:49:51,712 INFO  [sqlalchemy.engine.base.Engine:1193][MainThread] ()
   2016-04-09 02:49:51,713 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] PRAGMA table_info("pages")
   2016-04-09 02:49:51,714 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ()
   2016-04-09 02:49:51,714 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] PRAGMA table_info("users")
   2016-04-09 02:49:51,714 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ()
   2016-04-09 02:49:51,715 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread]
   CREATE TABLE users (
           id INTEGER NOT NULL,
           name TEXT NOT NULL,
           role TEXT NOT NULL,
           password_hash TEXT,
           CONSTRAINT pk_users PRIMARY KEY (id),
           CONSTRAINT uq_users_name UNIQUE (name)
   )
  2016-02-12 01:06:35,857 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ()
  2016-02-12 01:06:35,858 INFO  [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
  2016-02-12 01:06:35,858 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread]
  CREATE TABLE pages (
    id INTEGER NOT NULL,
    name TEXT NOT NULL,
    data INTEGER NOT NULL,
    creator_id INTEGER NOT NULL,
    CONSTRAINT pk_pages PRIMARY KEY (id),
    CONSTRAINT uq_pages_name UNIQUE (name),
    CONSTRAINT fk_pages_creator_id_users FOREIGN KEY(creator_id) REFERENCES users (id)
  )
   2016-04-09 02:49:51,715 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ()
   2016-04-09 02:49:51,716 INFO  [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
   2016-04-09 02:49:51,716 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread]
   CREATE TABLE pages (
           id INTEGER NOT NULL,
           name TEXT NOT NULL,
           data INTEGER NOT NULL,
           creator_id INTEGER NOT NULL,
           CONSTRAINT pk_pages PRIMARY KEY (id),
           CONSTRAINT uq_pages_name UNIQUE (name),
           CONSTRAINT fk_pages_creator_id_users FOREIGN KEY(creator_id) REFERENCES users (id)
   )
  2016-02-12 01:06:35,859 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ()
  2016-02-12 01:06:35,859 INFO  [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
  2016-02-12 01:06:36,383 INFO  [sqlalchemy.engine.base.Engine:646][MainThread] BEGIN (implicit)
  2016-02-12 01:06:36,384 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO users (name, role, password_hash) VALUES (?, ?, ?)
  2016-02-12 01:06:36,384 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ('editor', 'editor', '$2b$12$bSr5QR3wFs1LAnld7R94e.TXPj7DVoTxu2hA1kY6rm.Q3cAhD.AQO')
  2016-02-12 01:06:36,384 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO users (name, role, password_hash) VALUES (?, ?, ?)
  2016-02-12 01:06:36,384 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ('basic', 'basic', '$2b$12$.v0BQK2xWEQOnywbX2BFs.qzXo5Qf9oZohGWux/MOSj6Z.pVaY2Z6')
  2016-02-12 01:06:36,385 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO pages (name, data, creator_id) VALUES (?, ?, ?)
  2016-02-12 01:06:36,385 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ('FrontPage', 'This is the front page', 1)
  2016-02-12 01:06:36,385 INFO  [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
   2016-04-09 02:49:51,716 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ()
   2016-04-09 02:49:51,717 INFO  [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
   2016-04-09 02:49:52,256 INFO  [sqlalchemy.engine.base.Engine:646][MainThread] BEGIN (implicit)
   2016-04-09 02:49:52,257 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO users (name, role, password_hash) VALUES (?, ?, ?)
   2016-04-09 02:49:52,257 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ('editor', 'editor', b'$2b$12$APUPJvI/kKxrbQPyQehkR.ggoOM6fFYCZ07SFCkWGltl1wJsKB98y')
   2016-04-09 02:49:52,258 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO users (name, role, password_hash) VALUES (?, ?, ?)
   2016-04-09 02:49:52,258 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ('basic', 'basic', b'$2b$12$GeFnypuQpZyxZLH.sN0akOrPdZMcQjqVTCim67u6f89lOFH/0ddc6')
   2016-04-09 02:49:52,259 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO pages (name, data, creator_id) VALUES (?, ?, ?)
   2016-04-09 02:49:52,259 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ('FrontPage', 'This is the front page', 1)
   2016-04-09 02:49:52,259 INFO  [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
View the application in a browser
---------------------------------
docs/tutorials/wiki2/definingviews.rst
@@ -1,3 +1,5 @@
.. _wiki2_defining_views:
==============
Defining Views
==============
@@ -36,7 +38,7 @@
Only the highlighted line needs to be added.
Again, as we did in the previous chapter, the dependency now needs to be
installed, so re-run the ``python setup.py develop`` command.
installed, so re-run the ``$VENV/bin/pip install -e .`` command.
Static assets
@@ -338,7 +340,7 @@
.. literalinclude:: src/views/tutorial/templates/layout.jinja2
   :linenos:
   :emphasize-lines: 11,36
   :emphasize-lines: 11,35-36
   :language: html
Since we're using a templating engine, we can factor common boilerplate out of
docs/tutorials/wiki2/design.rst
@@ -1,3 +1,5 @@
.. _wiki2_design:
======
Design
======
docs/tutorials/wiki2/distributing.rst
@@ -1,3 +1,5 @@
.. _wiki2_distributing_your_application:
=============================
Distributing Your Application
=============================
docs/tutorials/wiki2/installation.rst
@@ -1,3 +1,5 @@
.. _wiki2_installation:
============
Installation
============
@@ -6,12 +8,11 @@
----------------
This tutorial assumes that you have already followed the steps in
:ref:`installing_chapter`, except **do not create a virtualenv or install
Pyramid**.  Thereby you will satisfy the following requirements.
:ref:`installing_chapter`, except **do not create a virtual environment or
install Pyramid**.  Thereby you will satisfy the following requirements.
* Python interpreter is installed on your operating system
* :term:`setuptools` or :term:`distribute` is installed
* :term:`virtualenv` is installed
* A Python interpreter is installed on your operating system.
* You've satisfied the :ref:`requirements-for-installing-packages`.
Create directory to contain the project
@@ -37,8 +38,8 @@
Create and use a virtual Python environment
-------------------------------------------
Next let's create a ``virtualenv`` workspace for our project.  We will use the
``VENV`` environment variable instead of the absolute path of the virtual
Next let's create a virtual environment workspace for our project.  We will use
the ``VENV`` environment variable instead of the absolute path of the virtual
environment.
On UNIX
@@ -47,7 +48,7 @@
.. code-block:: bash
   $ export VENV=~/pyramidtut
   $ virtualenv $VENV
   $ python3 -m venv $VENV
On Windows
^^^^^^^^^^
@@ -69,7 +70,25 @@
.. code-block:: ps1con
   c:\> c:\Python35\Scripts\virtualenv %VENV%
   c:\> c:\Python35\Scripts\python -m venv %VENV%
Upgrade ``pip`` and ``setuptools`` in the virtual environment
-------------------------------------------------------------
On UNIX
^^^^^^^
.. code-block:: bash
    $ $VENV/bin/pip install --upgrade pip setuptools
On Windows
^^^^^^^^^^
.. code-block:: ps1con
   c:\> %VENV%\Scripts\pip install --upgrade pip setuptools
Install Pyramid into the virtual Python environment
@@ -80,26 +99,27 @@
.. code-block:: bash
   $ $VENV/bin/easy_install pyramid
   $ $VENV/bin/pip install pyramid
On Windows
^^^^^^^^^^
.. code-block:: ps1con
   c:\> %VENV%\Scripts\easy_install pyramid
   c:\> %VENV%\Scripts\pip install pyramid
Install SQLite3 and its development packages
--------------------------------------------
If you used a package manager to install your Python or if you compiled your
Python from source, then you must install SQLite3 and its development packages.
If you downloaded your Python as an installer from https://www.python.org, then
you already have it installed and can skip this step.
If you used a package manager to install your Python or if you compiled
your Python from source, then you must install SQLite3 and its
development packages.  If you downloaded your Python as an installer
from https://www.python.org, then you already have it installed and can skip
this step.
If you need to install the SQLite3 packages, then, for example, using the
Debian system and ``apt-get``, the command would be the following:
If you need to install the SQLite3 packages, then, for example, using
the Debian system and ``apt-get``, the command would be the following:
.. code-block:: bash
@@ -164,8 +184,9 @@
.. note:: If you are using Windows, the ``alchemy`` scaffold may not deal
   gracefully with installation into a location that contains spaces in the
   path. If you experience startup problems, try putting both the virtualenv
   and the project into directories that do not contain spaces in their paths.
   path. If you experience startup problems, try putting both the virtual
   environment and the project into directories that do not contain spaces in
   their paths.
.. _installing_project_in_dev_mode:
@@ -174,10 +195,10 @@
------------------------------------------
In order to do development on the project easily, you must "register" the
project as a development egg in your workspace using the ``setup.py develop``
project as a development egg in your workspace using the ``pip install -e .``
command. In order to do so, change directory to the ``tutorial`` directory that
you created in :ref:`sql_making_a_project`, and run the ``setup.py develop``
command using the virtualenv Python interpreter.
you created in :ref:`sql_making_a_project`, and run the ``pip install -e .``
command using the virtual environment Python interpreter.
On UNIX
^^^^^^^
@@ -185,7 +206,7 @@
.. code-block:: bash
   $ cd tutorial
   $ $VENV/bin/python setup.py develop
   $ $VENV/bin/pip install -e .
On Windows
^^^^^^^^^^
@@ -193,104 +214,141 @@
.. code-block:: ps1con
   c:\pyramidtut> cd tutorial
   c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
   c:\pyramidtut\tutorial> %VENV%\Scripts\pip install -e .
The console will show ``setup.py`` checking for packages and installing missing
packages. Success executing this command will show a line like the following::
The console will show ``pip`` checking for packages and installing missing
packages. Success executing this command will show a line like the following:
   Finished processing dependencies for tutorial==0.0
.. code-block:: bash
   Successfully installed Chameleon-2.24 Mako-1.0.4 MarkupSafe-0.23 \
   Pygments-2.1.3 SQLAlchemy-1.0.12 pyramid-chameleon-0.3 \
   pyramid-debugtoolbar-2.4.2 pyramid-mako-1.0.2 pyramid-tm-0.12.1 \
   transaction-1.4.4 tutorial waitress-0.8.10 zope.sqlalchemy-0.7.6
.. _install-testing-requirements:
Install testing requirements
----------------------------
In order to run tests, we need to install the testing requirements. This is
done through our project's ``setup.py`` file, in the ``tests_require`` and
``extras_require`` stanzas, and by issuing the command below for your
operating system.
.. literalinclude:: src/installation/setup.py
   :language: python
   :linenos:
   :lineno-start: 22
   :lines: 22-26
.. literalinclude:: src/installation/setup.py
   :language: python
   :linenos:
   :lineno-start: 45
   :lines: 45-47
On UNIX
^^^^^^^
.. code-block:: bash
   $ $VENV/bin/pip install -e ".[testing]"
On Windows
^^^^^^^^^^
.. code-block:: ps1con
   c:\pyramidtut\tutorial> %VENV%\Scripts\pip install -e ".[testing]"
.. _sql_running_tests:
Run the tests
-------------
After you've installed the project in development mode, you may run the tests
for the project.
After you've installed the project in development mode as well as the testing
requirements, you may run the tests for the project.
On UNIX
^^^^^^^
.. code-block:: bash
   $ $VENV/bin/python setup.py test -q
   $ $VENV/bin/py.test tutorial/tests.py -q
On Windows
^^^^^^^^^^
.. code-block:: ps1con
   c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py test -q
   c:\pyramidtut\tutorial> %VENV%\Scripts\py.test tutorial\tests.py -q
For a successful test run, you should see output that ends like this::
For a successful test run, you should see output that ends like this:
.. code-block:: bash
   ..
   ----------------------------------------------------------------------
   Ran 2 tests in 0.053s
   2 passed in 0.44 seconds
   OK
Expose test coverage information
--------------------------------
You can run the ``nosetests`` command to see test coverage information. This
runs the tests in the same way that ``setup.py test`` does, but provides
additional "coverage" information, exposing which lines of your project are
covered by the tests.
You can run the ``py.test`` command to see test coverage information. This
runs the tests in the same way that ``py.test`` does, but provides additional
"coverage" information, exposing which lines of your project are covered by the
tests.
To get this functionality working, we'll need to install the ``nose`` and
``coverage`` packages into our ``virtualenv``:
We've already installed the ``pytest-cov`` package into our virtual
environment, so we can run the tests with coverage.
On UNIX
^^^^^^^
.. code-block:: bash
   $ $VENV/bin/easy_install nose coverage
   $ $VENV/bin/py.test --cov=tutorial --cov-report=term-missing tutorial/tests.py
On Windows
^^^^^^^^^^
.. code-block:: ps1con
   c:\pyramidtut\tutorial> %VENV%\Scripts\easy_install nose coverage
   c:\pyramidtut\tutorial> %VENV%\Scripts\py.test --cov=tutorial \
       --cov-report=term-missing tutorial\tests.py
Once ``nose`` and ``coverage`` are installed, we can run the tests with
coverage.
On UNIX
^^^^^^^
If successful, you will see output something like this:
.. code-block:: bash
   $ $VENV/bin/nosetests --cover-package=tutorial --cover-erase --with-coverage
   ======================== test session starts ========================
   platform Python 3.5.1, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
   rootdir: /Users/stevepiercy/projects/pyramidtut/tutorial, inifile:
   plugins: cov-2.2.1
   collected 2 items
On Windows
^^^^^^^^^^
   tutorial/tests.py ..
   ------------------ coverage: platform Python 3.5.1 ------------------
   Name                               Stmts   Miss  Cover   Missing
   ----------------------------------------------------------------
   tutorial/__init__.py                   8      6    25%   7-12
   tutorial/models/__init__.py           22      0   100%
   tutorial/models/meta.py                5      0   100%
   tutorial/models/mymodel.py             8      0   100%
   tutorial/routes.py                     3      3     0%   1-3
   tutorial/scripts/__init__.py           0      0   100%
   tutorial/scripts/initializedb.py      26     26     0%   1-45
   tutorial/tests.py                     39      0   100%
   tutorial/views/__init__.py             0      0   100%
   tutorial/views/default.py             12      0   100%
   tutorial/views/notfound.py             4      4     0%   1-7
   ----------------------------------------------------------------
   TOTAL                                127     39    69%
.. code-block:: ps1con
   c:\pyramidtut\tutorial> %VENV%\Scripts\nosetests --cover-package=tutorial \
         --cover-erase --with-coverage
If successful, you will see output something like this::
   ..
   Name                         Stmts   Miss  Cover   Missing
   ----------------------------------------------------------
   tutorial.py                      8      6    25%   7-12
   tutorial/models.py              22      0   100%
   tutorial/models/meta.py          5      0   100%
   tutorial/models/mymodel.py       8      0   100%
   tutorial/scripts.py              0      0   100%
   tutorial/views.py                0      0   100%
   tutorial/views/default.py       12      0   100%
   ----------------------------------------------------------
   TOTAL                           55      6    89%
   ----------------------------------------------------------------------
   Ran 2 tests in 0.579s
   OK
   ===================== 2 passed in 0.57 seconds ======================
Our package doesn't quite have 100% test coverage.
@@ -307,6 +365,13 @@
   The ``initialize_tutorial_db`` command does not perform a migration, but
   rather it simply creates missing tables and adds some dummy data. If you
   already have a database, you should delete it before running
   ``initialize_tutorial_db`` again.
.. note::
   The ``initialize_tutorial_db`` command is not performing a migration but
   rather simply creating missing tables and adding some dummy data. If you
   already have a database, you should delete it before running
   ``initialize_tutorial_db`` again.
@@ -327,15 +392,17 @@
   c:\pyramidtut\tutorial> %VENV%\Scripts\initialize_tutorial_db development.ini
The output to your console should be something like this::
The output to your console should be something like this:
   2016-02-21 23:57:41,793 INFO  [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
   2016-02-21 23:57:41,793 INFO  [sqlalchemy.engine.base.Engine:1193][MainThread] ()
   2016-02-21 23:57:41,794 INFO  [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
   2016-02-21 23:57:41,794 INFO  [sqlalchemy.engine.base.Engine:1193][MainThread] ()
   2016-02-21 23:57:41,796 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] PRAGMA table_info("models")
   2016-02-21 23:57:41,796 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ()
   2016-02-21 23:57:41,798 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread]
.. code-block:: bash
   2016-04-09 00:53:37,801 INFO  [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
   2016-04-09 00:53:37,801 INFO  [sqlalchemy.engine.base.Engine:1193][MainThread] ()
   2016-04-09 00:53:37,802 INFO  [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
   2016-04-09 00:53:37,802 INFO  [sqlalchemy.engine.base.Engine:1193][MainThread] ()
   2016-04-09 00:53:37,802 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] PRAGMA table_info("models")
   2016-04-09 00:53:37,803 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ()
   2016-04-09 00:53:37,803 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread]
   CREATE TABLE models (
           id INTEGER NOT NULL,
           name TEXT,
@@ -344,15 +411,15 @@
   )
   2016-02-21 23:57:41,798 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ()
   2016-02-21 23:57:41,798 INFO  [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
   2016-02-21 23:57:41,799 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] CREATE UNIQUE INDEX my_index ON models (name)
   2016-02-21 23:57:41,799 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ()
   2016-02-21 23:57:41,799 INFO  [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
   2016-02-21 23:57:41,801 INFO  [sqlalchemy.engine.base.Engine:646][MainThread] BEGIN (implicit)
   2016-02-21 23:57:41,802 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO models (name, value) VALUES (?, ?)
   2016-02-21 23:57:41,802 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ('one', 1)
   2016-02-21 23:57:41,821 INFO  [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
   2016-04-09 00:53:37,803 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ()
   2016-04-09 00:53:37,804 INFO  [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
   2016-04-09 00:53:37,805 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] CREATE UNIQUE INDEX my_index ON models (name)
   2016-04-09 00:53:37,805 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ()
   2016-04-09 00:53:37,806 INFO  [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
   2016-04-09 00:53:37,807 INFO  [sqlalchemy.engine.base.Engine:646][MainThread] BEGIN (implicit)
   2016-04-09 00:53:37,808 INFO  [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO models (name, value) VALUES (?, ?)
   2016-04-09 00:53:37,808 INFO  [sqlalchemy.engine.base.Engine:1100][MainThread] ('one', 1)
   2016-04-09 00:53:37,809 INFO  [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
Success!  You should now have a ``tutorial.sqlite`` file in your current
working directory. This is an SQLite database with a single table defined in it
@@ -415,8 +482,8 @@
- You are willing to use :term:`URL dispatch` to map URLs to code.
- You want to use zope.sqlalchemy_, pyramid_tm_ and the transaction_ package to
  scope sessions to requests.
- You want to use zope.sqlalchemy_, pyramid_tm_, and the transaction_ packages
  to scope sessions to requests.
- You want to use pyramid_jinja2_ to render your templates. Different
  templating engines can be used, but we had to choose one to make this
@@ -440,3 +507,15 @@
.. _transaction:
   http://zodb.readthedocs.org/en/latest/transactions.html
.. _pyramid_jinja2:
   http://docs.pylonsproject.org/projects/pyramid-jinja2/en/latest/
.. _pyramid_tm:
   http://docs.pylonsproject.org/projects/pyramid-tm/en/latest/
.. _zope.sqlalchemy:
   https://pypi.python.org/pypi/zope.sqlalchemy
.. _transaction:
   http://zodb.readthedocs.org/en/latest/transactions.html
docs/tutorials/wiki2/src/authentication/README.txt
@@ -6,7 +6,7 @@
- cd <directory containing this file>
- $VENV/bin/python setup.py develop
- $VENV/bin/pip install -e .
- $VENV/bin/initialize_tutorial_db development.ini
docs/tutorials/wiki2/src/authentication/development.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -34,7 +34,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
docs/tutorials/wiki2/src/authentication/production.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -23,7 +23,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
docs/tutorials/wiki2/src/authentication/setup.py
@@ -22,19 +22,21 @@
    ]
tests_require = [
    'WebTest',
]
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',  # includes virtualenv
    'pytest-cov',
    ]
setup(name='tutorial',
      version='0.0',
      description='tutorial',
      long_description=README + '\n\n' + CHANGES,
      classifiers=[
        "Programming Language :: Python",
        "Framework :: Pyramid",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
        ],
          "Programming Language :: Python",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
      ],
      author='',
      author_email='',
      url='',
@@ -42,8 +44,9 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      test_suite='tutorial',
      tests_require=tests_require,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      entry_points="""\
      [paste.app_factory]
docs/tutorials/wiki2/src/authentication/tutorial/static/theme.min.css
File was deleted
docs/tutorials/wiki2/src/authentication/tutorial/tests.py
@@ -28,7 +28,7 @@
        self.session = get_tm_session(session_factory, transaction.manager)
    def init_database(self):
        from .models import Base
        from .models.meta import Base
        Base.metadata.create_all(self.engine)
    def tearDown(self):
docs/tutorials/wiki2/src/authorization/README.txt
@@ -6,7 +6,7 @@
- cd <directory containing this file>
- $VENV/bin/python setup.py develop
- $VENV/bin/pip install -e .
- $VENV/bin/initialize_tutorial_db development.ini
docs/tutorials/wiki2/src/authorization/development.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -34,7 +34,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
docs/tutorials/wiki2/src/authorization/production.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -23,7 +23,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
docs/tutorials/wiki2/src/authorization/setup.py
@@ -22,19 +22,21 @@
    ]
tests_require = [
    'WebTest',
]
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',  # includes virtualenv
    'pytest-cov',
    ]
setup(name='tutorial',
      version='0.0',
      description='tutorial',
      long_description=README + '\n\n' + CHANGES,
      classifiers=[
        "Programming Language :: Python",
        "Framework :: Pyramid",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
        ],
          "Programming Language :: Python",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
      ],
      author='',
      author_email='',
      url='',
@@ -42,8 +44,9 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      test_suite='tutorial',
      tests_require=tests_require,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      entry_points="""\
      [paste.app_factory]
docs/tutorials/wiki2/src/authorization/tutorial/static/theme.min.css
File was deleted
docs/tutorials/wiki2/src/authorization/tutorial/tests.py
@@ -28,7 +28,7 @@
        self.session = get_tm_session(session_factory, transaction.manager)
    def init_database(self):
        from .models import Base
        from .models.meta import Base
        Base.metadata.create_all(self.engine)
    def tearDown(self):
docs/tutorials/wiki2/src/basiclayout/README.txt
@@ -6,7 +6,7 @@
- cd <directory containing this file>
- $VENV/bin/python setup.py develop
- $VENV/bin/pip install -e .
- $VENV/bin/initialize_tutorial_db development.ini
docs/tutorials/wiki2/src/basiclayout/development.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -32,7 +32,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
docs/tutorials/wiki2/src/basiclayout/production.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -21,7 +21,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
docs/tutorials/wiki2/src/basiclayout/setup.py
@@ -20,19 +20,21 @@
    ]
tests_require = [
    'WebTest',
]
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',  # includes virtualenv
    'pytest-cov',
    ]
setup(name='tutorial',
      version='0.0',
      description='tutorial',
      long_description=README + '\n\n' + CHANGES,
      classifiers=[
        "Programming Language :: Python",
        "Framework :: Pyramid",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
        ],
          "Programming Language :: Python",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
      ],
      author='',
      author_email='',
      url='',
@@ -40,8 +42,9 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      test_suite='tutorial',
      tests_require=tests_require,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      entry_points="""\
      [paste.app_factory]
docs/tutorials/wiki2/src/basiclayout/tutorial/static/theme.min.css
File was deleted
docs/tutorials/wiki2/src/basiclayout/tutorial/templates/layout.jinja2
@@ -40,7 +40,7 @@
        <div class="row">
          <div class="links">
            <ul>
              <li class="current-version">Generated by v1.7.dev0</li>
              <li class="current-version">Generated by v1.7</li>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/">Docs</a></li>
              <li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
              <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="irc://irc.freenode.net#pyramid">IRC Channel</a></li>
docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.jinja2
@@ -3,6 +3,6 @@
{% block content %}
<div class="content">
  <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Alchemy scaffold</span></h1>
  <p class="lead">Welcome to <span class="font-normal">{{project}}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework 1.7.dev0</span>.</p>
  <p class="lead">Welcome to <span class="font-normal">{{project}}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework 1.7</span>.</p>
</div>
{% endblock content %}
docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py
@@ -28,7 +28,7 @@
        self.session = get_tm_session(session_factory, transaction.manager)
    def init_database(self):
        from .models import Base
        from .models.meta import Base
        Base.metadata.create_all(self.engine)
    def tearDown(self):
docs/tutorials/wiki2/src/installation/CHANGES.txt
New file
@@ -0,0 +1,4 @@
0.0
---
-  Initial version
docs/tutorials/wiki2/src/installation/MANIFEST.in
New file
@@ -0,0 +1,2 @@
include *.txt *.ini *.cfg *.rst
recursive-include tutorial *.ico *.png *.css *.gif *.jpg *.jinja2 *.pt *.txt *.mak *.mako *.js *.html *.xml
docs/tutorials/wiki2/src/installation/README.txt
New file
@@ -0,0 +1,14 @@
tutorial README
==================
Getting Started
---------------
- cd <directory containing this file>
- $VENV/bin/pip install -e .
- $VENV/bin/initialize_tutorial_db development.ini
- $VENV/bin/pserve development.ini
docs/tutorials/wiki2/src/installation/development.ini
New file
@@ -0,0 +1,71 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
use = egg:tutorial
pyramid.reload_templates = true
pyramid.debug_authorization = false
pyramid.debug_notfound = false
pyramid.debug_routematch = false
pyramid.default_locale_name = en
pyramid.includes =
    pyramid_debugtoolbar
    pyramid_tm
sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
# 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/1.7-branch/narr/logging.html
###
[loggers]
keys = root, tutorial, sqlalchemy
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = INFO
handlers = console
[logger_tutorial]
level = DEBUG
handlers =
qualname = tutorial
[logger_sqlalchemy]
level = INFO
handlers =
qualname = sqlalchemy.engine
# "level = INFO" logs SQL queries.
# "level = DEBUG" logs SQL queries and results.
# "level = WARN" logs neither.  (Recommended for production systems.)
[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
docs/tutorials/wiki2/src/installation/production.ini
New file
@@ -0,0 +1,60 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
use = egg:tutorial
pyramid.reload_templates = false
pyramid.debug_authorization = false
pyramid.debug_notfound = false
pyramid.debug_routematch = false
pyramid.default_locale_name = en
sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
[server:main]
use = egg:waitress#main
host = 0.0.0.0
port = 6543
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
keys = root, tutorial, sqlalchemy
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = WARN
handlers = console
[logger_tutorial]
level = WARN
handlers =
qualname = tutorial
[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine
# "level = INFO" logs SQL queries.
# "level = DEBUG" logs SQL queries and results.
# "level = WARN" logs neither.  (Recommended for production systems.)
[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
docs/tutorials/wiki2/src/installation/setup.py
New file
@@ -0,0 +1,55 @@
import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(here, 'README.txt')) as f:
    README = f.read()
with open(os.path.join(here, 'CHANGES.txt')) as f:
    CHANGES = f.read()
requires = [
    'pyramid',
    'pyramid_jinja2',
    'pyramid_debugtoolbar',
    'pyramid_tm',
    'SQLAlchemy',
    'transaction',
    'zope.sqlalchemy',
    'waitress',
    ]
tests_require = [
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',  # includes virtualenv
    'pytest-cov',
    ]
setup(name='tutorial',
      version='0.0',
      description='tutorial',
      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 wsgi bfg pylons pyramid',
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      entry_points="""\
      [paste.app_factory]
      main = tutorial:main
      [console_scripts]
      initialize_tutorial_db = tutorial.scripts.initializedb:main
      """,
      )
docs/tutorials/wiki2/src/installation/tutorial/__init__.py
New file
@@ -0,0 +1,12 @@
from pyramid.config import Configurator
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = Configurator(settings=settings)
    config.include('pyramid_jinja2')
    config.include('.models')
    config.include('.routes')
    config.scan()
    return config.make_wsgi_app()
docs/tutorials/wiki2/src/installation/tutorial/models/__init__.py
New file
@@ -0,0 +1,73 @@
from sqlalchemy import engine_from_config
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import configure_mappers
import zope.sqlalchemy
# import or define all models here to ensure they are attached to the
# Base.metadata prior to any initialization routines
from .mymodel import MyModel # flake8: noqa
# run configure_mappers after defining all of the models to ensure
# all relationships can be setup
configure_mappers()
def get_engine(settings, prefix='sqlalchemy.'):
    return engine_from_config(settings, prefix)
def get_session_factory(engine):
    factory = sessionmaker()
    factory.configure(bind=engine)
    return factory
def get_tm_session(session_factory, transaction_manager):
    """
    Get a ``sqlalchemy.orm.Session`` instance backed by a transaction.
    This function will hook the session to the transaction manager which
    will take care of committing any changes.
    - When using pyramid_tm it will automatically be committed or aborted
      depending on whether an exception is raised.
    - When using scripts you should wrap the session in a manager yourself.
      For example::
          import transaction
          engine = get_engine(settings)
          session_factory = get_session_factory(engine)
          with transaction.manager:
              dbsession = get_tm_session(session_factory, transaction.manager)
    """
    dbsession = session_factory()
    zope.sqlalchemy.register(
        dbsession, transaction_manager=transaction_manager)
    return dbsession
def includeme(config):
    """
    Initialize the model for a Pyramid app.
    Activate this setup using ``config.include('tutorial.models')``.
    """
    settings = config.get_settings()
    # use pyramid_tm to hook the transaction lifecycle to the request
    config.include('pyramid_tm')
    session_factory = get_session_factory(get_engine(settings))
    config.registry['dbsession_factory'] = session_factory
    # make request.dbsession available for use in Pyramid
    config.add_request_method(
        # r.tm is the transaction manager used by pyramid_tm
        lambda r: get_tm_session(session_factory, r.tm),
        'dbsession',
        reify=True
    )
docs/tutorials/wiki2/src/installation/tutorial/models/meta.py
New file
@@ -0,0 +1,16 @@
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.schema import MetaData
# Recommended naming convention used by Alembic, as various different database
# providers will autogenerate vastly different names making migrations more
# difficult. See: http://alembic.readthedocs.org/en/latest/naming.html
NAMING_CONVENTION = {
    "ix": 'ix_%(column_0_label)s',
    "uq": "uq_%(table_name)s_%(column_0_name)s",
    "ck": "ck_%(table_name)s_%(constraint_name)s",
    "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
    "pk": "pk_%(table_name)s"
}
metadata = MetaData(naming_convention=NAMING_CONVENTION)
Base = declarative_base(metadata=metadata)
docs/tutorials/wiki2/src/installation/tutorial/models/mymodel.py
New file
@@ -0,0 +1,18 @@
from sqlalchemy import (
    Column,
    Index,
    Integer,
    Text,
)
from .meta import Base
class MyModel(Base):
    __tablename__ = 'models'
    id = Column(Integer, primary_key=True)
    name = Column(Text)
    value = Column(Integer)
Index('my_index', MyModel.name, unique=True, mysql_length=255)
docs/tutorials/wiki2/src/installation/tutorial/routes.py
New file
@@ -0,0 +1,3 @@
def includeme(config):
    config.add_static_view('static', 'static', cache_max_age=3600)
    config.add_route('home', '/')
docs/tutorials/wiki2/src/installation/tutorial/scripts/__init__.py
New file
@@ -0,0 +1 @@
# package
docs/tutorials/wiki2/src/installation/tutorial/scripts/initializedb.py
New file
@@ -0,0 +1,45 @@
import os
import sys
import transaction
from pyramid.paster import (
    get_appsettings,
    setup_logging,
    )
from pyramid.scripts.common import parse_vars
from ..models.meta import Base
from ..models import (
    get_engine,
    get_session_factory,
    get_tm_session,
    )
from ..models import MyModel
def usage(argv):
    cmd = os.path.basename(argv[0])
    print('usage: %s <config_uri> [var=value]\n'
          '(example: "%s development.ini")' % (cmd, cmd))
    sys.exit(1)
def main(argv=sys.argv):
    if len(argv) < 2:
        usage(argv)
    config_uri = argv[1]
    options = parse_vars(argv[2:])
    setup_logging(config_uri)
    settings = get_appsettings(config_uri, options=options)
    engine = get_engine(settings)
    Base.metadata.create_all(engine)
    session_factory = get_session_factory(engine)
    with transaction.manager:
        dbsession = get_tm_session(session_factory, transaction.manager)
        model = MyModel(name='one', value=1)
        dbsession.add(model)
docs/tutorials/wiki2/src/installation/tutorial/static/pyramid-16x16.png
docs/tutorials/wiki2/src/installation/tutorial/static/pyramid.png
docs/tutorials/wiki2/src/installation/tutorial/static/theme.css
New file
@@ -0,0 +1,154 @@
@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, a {
  color: #f2b7bd;
  text-decoration: underline;
}
.starter-template .links ul li a:hover, a:hover {
  color: #ffffff;
  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;
  }
}
docs/tutorials/wiki2/src/installation/tutorial/templates/404.jinja2
New file
@@ -0,0 +1,8 @@
{% extends "layout.jinja2" %}
{% block content %}
<div class="content">
  <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Alchemy scaffold</span></h1>
  <p class="lead"><span class="font-semi-bold">404</span> Page Not Found</p>
</div>
{% endblock content %}
docs/tutorials/wiki2/src/installation/tutorial/templates/layout.jinja2
New file
@@ -0,0 +1,66 @@
<!DOCTYPE html>
<html lang="{{request.locale_name}}">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="pyramid web application">
    <meta name="author" content="Pylons Project">
    <link rel="shortcut icon" href="{{request.static_url('tutorial:static/pyramid-16x16.png')}}">
    <title>Alchemy Scaffold for The Pyramid Web Framework</title>
    <!-- Bootstrap core CSS -->
    <link href="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
    <!-- Custom styles for this scaffold -->
    <link href="{{request.static_url('tutorial:static/theme.css')}}" rel="stylesheet">
    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!--[if lt IE 9]>
      <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
      <script src="//oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <div class="starter-template">
      <div class="container">
        <div class="row">
          <div class="col-md-2">
            <img class="logo img-responsive" src="{{request.static_url('tutorial:static/pyramid.png')}}" alt="pyramid web framework">
          </div>
          <div class="col-md-10">
            {% block content %}
                <p>No content</p>
            {% endblock content %}
          </div>
        </div>
        <div class="row">
          <div class="links">
            <ul>
              <li class="current-version">Generated by v1.7</li>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/">Docs</a></li>
              <li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
              <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="irc://irc.freenode.net#pyramid">IRC Channel</a></li>
              <li><i class="glyphicon glyphicon-home icon-muted"></i><a href="http://pylonsproject.org">Pylons Project</a></li>
            </ul>
          </div>
        </div>
        <div class="row">
          <div class="copyright">
            Copyright &copy; Pylons Project
          </div>
        </div>
      </div>
    </div>
    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="//oss.maxcdn.com/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/js/bootstrap.min.js"></script>
  </body>
</html>
docs/tutorials/wiki2/src/installation/tutorial/templates/mytemplate.jinja2
New file
@@ -0,0 +1,8 @@
{% extends "layout.jinja2" %}
{% block content %}
<div class="content">
  <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Alchemy scaffold</span></h1>
  <p class="lead">Welcome to <span class="font-normal">{{project}}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework 1.7</span>.</p>
</div>
{% endblock content %}
docs/tutorials/wiki2/src/installation/tutorial/tests.py
New file
@@ -0,0 +1,65 @@
import unittest
import transaction
from pyramid import testing
def dummy_request(dbsession):
    return testing.DummyRequest(dbsession=dbsession)
class BaseTest(unittest.TestCase):
    def setUp(self):
        self.config = testing.setUp(settings={
            'sqlalchemy.url': 'sqlite:///:memory:'
        })
        self.config.include('.models')
        settings = self.config.get_settings()
        from .models import (
            get_engine,
            get_session_factory,
            get_tm_session,
            )
        self.engine = get_engine(settings)
        session_factory = get_session_factory(self.engine)
        self.session = get_tm_session(session_factory, transaction.manager)
    def init_database(self):
        from .models.meta import Base
        Base.metadata.create_all(self.engine)
    def tearDown(self):
        from .models.meta import Base
        testing.tearDown()
        transaction.abort()
        Base.metadata.drop_all(self.engine)
class TestMyViewSuccessCondition(BaseTest):
    def setUp(self):
        super(TestMyViewSuccessCondition, self).setUp()
        self.init_database()
        from .models import MyModel
        model = MyModel(name='one', value=55)
        self.session.add(model)
    def test_passing_view(self):
        from .views.default import my_view
        info = my_view(dummy_request(self.session))
        self.assertEqual(info['one'].name, 'one')
        self.assertEqual(info['project'], 'tutorial')
class TestMyViewFailureCondition(BaseTest):
    def test_failing_view(self):
        from .views.default import my_view
        info = my_view(dummy_request(self.session))
        self.assertEqual(info.status_int, 500)
docs/tutorials/wiki2/src/installation/tutorial/views/__init__.py
docs/tutorials/wiki2/src/installation/tutorial/views/default.py
New file
@@ -0,0 +1,33 @@
from pyramid.response import Response
from pyramid.view import view_config
from sqlalchemy.exc import DBAPIError
from ..models import MyModel
@view_config(route_name='home', renderer='../templates/mytemplate.jinja2')
def my_view(request):
    try:
        query = request.dbsession.query(MyModel)
        one = query.filter(MyModel.name == 'one').first()
    except DBAPIError:
        return Response(db_err_msg, content_type='text/plain', status=500)
    return {'one': one, 'project': 'tutorial'}
db_err_msg = """\
Pyramid is having a problem using your SQL database.  The problem
might be caused by one of the following things:
1.  You may need to run the "initialize_tutorial_db" script
    to initialize your database tables.  Check your virtual
    environment's "bin" directory for this script and try to run it.
2.  Your database server may not be running.  Check that the
    database server referred to by the "sqlalchemy.url" setting in
    your "development.ini" file is running.
After you fix the problem, please restart the Pyramid application to
try it again.
"""
docs/tutorials/wiki2/src/installation/tutorial/views/notfound.py
New file
@@ -0,0 +1,7 @@
from pyramid.view import notfound_view_config
@notfound_view_config(renderer='../templates/404.jinja2')
def notfound_view(request):
    request.response.status = 404
    return {}
docs/tutorials/wiki2/src/models/README.txt
@@ -6,7 +6,7 @@
- cd <directory containing this file>
- $VENV/bin/python setup.py develop
- $VENV/bin/pip install -e .
- $VENV/bin/initialize_tutorial_db development.ini
docs/tutorials/wiki2/src/models/development.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -32,7 +32,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
docs/tutorials/wiki2/src/models/production.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -21,7 +21,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
docs/tutorials/wiki2/src/models/setup.py
@@ -21,19 +21,21 @@
    ]
tests_require = [
    'WebTest',
]
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',  # includes virtualenv
    'pytest-cov',
    ]
setup(name='tutorial',
      version='0.0',
      description='tutorial',
      long_description=README + '\n\n' + CHANGES,
      classifiers=[
        "Programming Language :: Python",
        "Framework :: Pyramid",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
        ],
          "Programming Language :: Python",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
      ],
      author='',
      author_email='',
      url='',
@@ -41,8 +43,9 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      test_suite='tutorial',
      tests_require=tests_require,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      entry_points="""\
      [paste.app_factory]
docs/tutorials/wiki2/src/models/tutorial/static/theme.min.css
File was deleted
docs/tutorials/wiki2/src/models/tutorial/templates/layout.jinja2
@@ -40,7 +40,7 @@
        <div class="row">
          <div class="links">
            <ul>
              <li class="current-version">Generated by v1.7.dev0</li>
              <li class="current-version">Generated by v1.7</li>
              <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/">Docs</a></li>
              <li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
              <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="irc://irc.freenode.net#pyramid">IRC Channel</a></li>
docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.jinja2
@@ -3,6 +3,6 @@
{% block content %}
<div class="content">
  <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Alchemy scaffold</span></h1>
  <p class="lead">Welcome to <span class="font-normal">{{project}}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework 1.7.dev0</span>.</p>
  <p class="lead">Welcome to <span class="font-normal">{{project}}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework 1.7</span>.</p>
</div>
{% endblock content %}
docs/tutorials/wiki2/src/models/tutorial/tests.py
@@ -28,7 +28,7 @@
        self.session = get_tm_session(session_factory, transaction.manager)
    def init_database(self):
        from .models import Base
        from .models.meta import Base
        Base.metadata.create_all(self.engine)
    def tearDown(self):
docs/tutorials/wiki2/src/tests/README.txt
@@ -6,7 +6,7 @@
- cd <directory containing this file>
- $VENV/bin/python setup.py develop
- $VENV/bin/pip install -e .
- $VENV/bin/initialize_tutorial_db development.ini
docs/tutorials/wiki2/src/tests/development.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -34,7 +34,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
docs/tutorials/wiki2/src/tests/production.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -23,7 +23,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
docs/tutorials/wiki2/src/tests/setup.py
@@ -22,19 +22,21 @@
    ]
tests_require = [
    'WebTest',
]
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',  # includes virtualenv
    'pytest-cov',
    ]
setup(name='tutorial',
      version='0.0',
      description='tutorial',
      long_description=README + '\n\n' + CHANGES,
      classifiers=[
        "Programming Language :: Python",
        "Framework :: Pyramid",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
        ],
          "Programming Language :: Python",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
      ],
      author='',
      author_email='',
      url='',
@@ -42,8 +44,9 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      test_suite='tutorial',
      tests_require=tests_require,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      entry_points="""\
      [paste.app_factory]
docs/tutorials/wiki2/src/tests/tutorial/static/theme.min.css
File was deleted
docs/tutorials/wiki2/src/tests/tutorial/tests/test_functional.py
@@ -1,6 +1,6 @@
import transaction
import unittest
from webtest import TestApp
import webtest
class FunctionalTests(unittest.TestCase):
@@ -30,7 +30,7 @@
            'auth.secret': 'seekrit',
        }
        app = main({}, **settings)
        cls.testapp = TestApp(app)
        cls.testapp = webtest.TestApp(app)
        session_factory = app.registry['dbsession_factory']
        cls.engine = session_factory.kw['bind']
docs/tutorials/wiki2/src/views/README.txt
@@ -6,7 +6,7 @@
- cd <directory containing this file>
- $VENV/bin/python setup.py develop
- $VENV/bin/pip install -e .
- $VENV/bin/initialize_tutorial_db development.ini
docs/tutorials/wiki2/src/views/development.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -32,7 +32,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
docs/tutorials/wiki2/src/views/production.ini
@@ -1,6 +1,6 @@
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
###
[app:main]
@@ -21,7 +21,7 @@
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
###
[loggers]
docs/tutorials/wiki2/src/views/setup.py
@@ -22,19 +22,21 @@
    ]
tests_require = [
    'WebTest',
]
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',  # includes virtualenv
    'pytest-cov',
    ]
setup(name='tutorial',
      version='0.0',
      description='tutorial',
      long_description=README + '\n\n' + CHANGES,
      classifiers=[
        "Programming Language :: Python",
        "Framework :: Pyramid",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
        ],
          "Programming Language :: Python",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
      ],
      author='',
      author_email='',
      url='',
@@ -42,8 +44,9 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      test_suite='tutorial',
      tests_require=tests_require,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      entry_points="""\
      [paste.app_factory]
docs/tutorials/wiki2/src/views/tutorial/static/theme.min.css
File was deleted
docs/tutorials/wiki2/src/views/tutorial/tests.py
@@ -28,7 +28,7 @@
        self.session = get_tm_session(session_factory, transaction.manager)
    def init_database(self):
        from .models import Base
        from .models.meta import Base
        Base.metadata.create_all(self.engine)
    def tearDown(self):
docs/tutorials/wiki2/tests.rst
@@ -1,3 +1,5 @@
.. _wiki2_adding_tests:
============
Adding Tests
============
@@ -75,30 +77,26 @@
Running the tests
=================
We can run these tests by using ``setup.py test`` in the same way we did in
:ref:`running_tests`:
We can run these tests similarly to how we did in :ref:`running_tests`:
On UNIX:
.. code-block:: bash
   $ $VENV/bin/python setup.py test -q
   $ $VENV/bin/py.test -q
On Windows:
.. code-block:: ps1con
   c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py test -q
   c:\pyramidtut\tutorial> %VENV%\Scripts\py.test -q
The expected result should look like the following:
.. code-block:: text
   .....................
   ----------------------------------------------------------------------
   Ran 22 tests in 5.320s
   OK
   ......................
   22 passed, 1 pytest-warnings in 5.81 seconds
.. note:: If you use Python 3 during this tutorial, you will see deprecation
   warnings in the output, which we will choose to ignore. In making this
pyramid/scaffolds/alchemy/+package+/static/theme.min.css
File was deleted
pyramid/scaffolds/alchemy/README.txt_tmpl
@@ -6,7 +6,7 @@
- cd <directory containing this file>
- $VENV/bin/python setup.py develop
- $VENV/bin/pip install -e .
- $VENV/bin/initialize_{{project}}_db development.ini
pyramid/scaffolds/alchemy/setup.py_tmpl
@@ -20,19 +20,21 @@
    ]
tests_require = [
    'WebTest',
]
    '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",
        ],
          "Programming Language :: Python",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
      ],
      author='',
      author_email='',
      url='',
@@ -40,8 +42,9 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      test_suite='{{package}}',
      tests_require=tests_require,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      entry_points="""\
      [paste.app_factory]
pyramid/scaffolds/starter/+package+/static/theme.min.css
File was deleted
pyramid/scaffolds/starter/+package+/tests.py_tmpl
@@ -15,3 +15,15 @@
        request = testing.DummyRequest()
        info = my_view(request)
        self.assertEqual(info['project'], '{{project}}')
class FunctionalTests(unittest.TestCase):
    def setUp(self):
        from {{package}} import main
        app = main({})
        from webtest import TestApp
        self.testapp = TestApp(app)
    def test_root(self):
        res = self.testapp.get('/', status=200)
        self.assertTrue(b'Pyramid' in res.body)
pyramid/scaffolds/starter/README.txt_tmpl
@@ -1 +1,12 @@
{{project}} README
==================
Getting Started
---------------
- cd <directory containing this file>
- $VENV/bin/pip install -e .
- $VENV/bin/pserve development.ini
pyramid/scaffolds/starter/setup.py_tmpl
@@ -15,16 +15,22 @@
    '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",
        ],
          "Programming Language :: Python",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
      ],
      author='',
      author_email='',
      url='',
@@ -32,9 +38,10 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      tests_require=requires,
      test_suite="{{package}}",
      entry_points="""\
      [paste.app_factory]
      main = {{package}}:main
pyramid/scaffolds/zodb/+package+/static/theme.css
@@ -72,10 +72,12 @@
  color: #f2b7bd;
  font-weight: 400;
}
.starter-template .links ul li a {
  color: #ffffff;
.starter-template .links ul li a, a {
  color: #f2b7bd;
  text-decoration: underline;
}
.starter-template .links ul li a:hover {
.starter-template .links ul li a:hover, a:hover {
  color: #ffffff;
  text-decoration: underline;
}
.starter-template .links ul li .icon-muted {
pyramid/scaffolds/zodb/+package+/static/theme.min.css
File was deleted
pyramid/scaffolds/zodb/README.txt_tmpl
@@ -1 +1,12 @@
{{project}} README
==================
Getting Started
---------------
- cd <directory containing this file>
- $VENV/bin/pip install -e .
- $VENV/bin/pserve development.ini
pyramid/scaffolds/zodb/setup.py_tmpl
@@ -19,16 +19,22 @@
    '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",
        ],
          "Programming Language :: Python",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
      ],
      author='',
      author_email='',
      url='',
@@ -36,9 +42,10 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      extras_require={
          'testing': tests_require,
      },
      install_requires=requires,
      tests_require=requires,
      test_suite="{{package}}",
      entry_points="""\
      [paste.app_factory]
      main = {{package}}:main
setup.py
@@ -38,7 +38,7 @@
except IOError:
    README = CHANGES = ''
install_requires=[
install_requires = [
    'setuptools',
    'WebOb >= 1.3.1', # request.domain and CookieProfile
    'repoze.lru >= 0.4', # py3 compat
@@ -74,24 +74,23 @@
setup(name='pyramid',
      version='1.7.dev0',
      description='The Pyramid Web Framework, a Pylons project',
      long_description=README + '\n\n' +  CHANGES,
      long_description=README + '\n\n' + CHANGES,
      classifiers=[
        "Development Status :: 6 - Mature",
        "Intended Audience :: Developers",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2.6",
        "Programming Language :: Python :: 2.7",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.3",
        "Programming Language :: Python :: 3.4",
        "Programming Language :: Python :: 3.5",
        "Programming Language :: Python :: Implementation :: CPython",
        "Programming Language :: Python :: Implementation :: PyPy",
        "Framework :: Pyramid",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: WSGI",
        "License :: Repoze Public License",
        ],
          "Development Status :: 6 - Mature",
          "Intended Audience :: Developers",
          "Programming Language :: Python",
          "Programming Language :: Python :: 2.7",
          "Programming Language :: Python :: 3",
          "Programming Language :: Python :: 3.3",
          "Programming Language :: Python :: 3.4",
          "Programming Language :: Python :: 3.5",
          "Programming Language :: Python :: Implementation :: CPython",
          "Programming Language :: Python :: Implementation :: PyPy",
          "Framework :: Pyramid",
          "Topic :: Internet :: WWW/HTTP",
          "Topic :: Internet :: WWW/HTTP :: WSGI",
          "License :: Repoze Public License",
      ],
      keywords='web wsgi pylons pyramid',
      author="Chris McDonough, Agendaless Consulting",
      author_email="pylons-discuss@googlegroups.com",
@@ -100,14 +99,14 @@
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      install_requires = install_requires,
      extras_require = {
          'testing':testing_extras,
          'docs':docs_extras,
      install_requires=install_requires,
      extras_require={
          'testing': testing_extras,
          'docs': docs_extras,
          },
      tests_require = tests_require,
      tests_require=tests_require,
      test_suite="pyramid.tests",
      entry_points = """\
      entry_points="""\
        [pyramid.scaffold]
        starter=pyramid.scaffolds:StarterProjectTemplate
        zodb=pyramid.scaffolds:ZODBProjectTemplate
@@ -128,4 +127,3 @@
        cherrypy = pyramid.scripts.pserve:cherrypy_server_runner
      """
      )
tox.ini
@@ -1,6 +1,6 @@
[tox]
envlist =
    py26,py27,py33,py34,py35,pypy,pypy3,
    py27,py33,py34,py35,pypy,pypy3,
    docs,pep8,
    {py2,py3}-cover,coverage,
@@ -8,7 +8,6 @@
# Most of these are defaults but if you specify any you can't fall back
# to defaults for others.
basepython =
    py26: python2.6
    py27: python2.7
    py33: python3.3
    py34: python3.4
@@ -22,14 +21,8 @@
    pip install pyramid[testing]
    nosetests --with-xunit --xunit-file=nosetests-{envname}.xml {posargs:}
[testenv:py26-scaffolds]
basepython = python2.6
commands =
    python pyramid/scaffolds/tests.py
deps = virtualenv
[testenv:py27-scaffolds]
basepython = python2.6
basepython = python2.7
commands =
    python pyramid/scaffolds/tests.py
deps = virtualenv