docs/tutorials/wiki/authorization.rst | ●●●●● patch | view | raw | blame | history | |
docs/tutorials/wiki/background.rst | ●●●●● patch | view | raw | blame | history | |
docs/tutorials/wiki/basiclayout.rst | ●●●●● patch | view | raw | blame | history | |
docs/tutorials/wiki/definingmodels.rst | ●●●●● patch | view | raw | blame | history | |
docs/tutorials/wiki/definingviews.rst | ●●●●● patch | view | raw | blame | history | |
docs/tutorials/wiki/design.rst | ●●●●● patch | view | raw | blame | history | |
docs/tutorials/wiki/distributing.rst | ●●●●● patch | view | raw | blame | history | |
docs/tutorials/wiki/index.rst | ●●●●● patch | view | raw | blame | history | |
docs/tutorials/wiki/installation.rst | ●●●●● patch | view | raw | blame | history | |
docs/tutorials/wiki/tests.rst | ●●●●● patch | view | raw | blame | history |
docs/tutorials/wiki/authorization.rst
@@ -26,7 +26,7 @@ * Add :term:`permission` declarations to the ``edit_page`` and ``add_page`` views (``views.py``). Then we will add the login and logout feature: Then we will add the login and logout features: * Add ``login`` and ``logout`` views (``views.py``). * Add a login template (``login.pt``). @@ -73,7 +73,7 @@ The ``groupfinder`` function accepts a userid and a request and returns one of these values: - If the userid exists in the system, it will return a sequence of group - If ``userid`` exists in the system, it will return a sequence of group identifiers (or an empty sequence if the user isn't a member of any groups). - If the userid *does not* exist in the system, it will return ``None``. @@ -103,19 +103,18 @@ ~~~~~~~~~~ Open ``tutorial/models.py`` and add the following import statement at the head: statement near the top: .. literalinclude:: src/authorization/tutorial/models.py :lines: 4-7 :linenos: :lines: 4-8 :lineno-match: :language: python Add the following lines to the ``Wiki`` class: .. literalinclude:: src/authorization/tutorial/models.py :lines: 9-13 :linenos: :lineno-start: 9 :lineno-match: :emphasize-lines: 4-5 :language: python @@ -124,10 +123,10 @@ :term:`principal` that is associated to all requests. Both are used in the :term:`ACE` entries that make up the ACL. The ACL is a list that needs to be named `__acl__` and be an attribute of a The ACL is a list that needs to be named ``__acl__`` and be an attribute of a class. We define an :term:`ACL` with two :term:`ACE` entries: the first entry allows any user the `view` permission. The second entry allows the ``group:editors`` principal the `edit` permission. allows any user the ``view`` permission. The second entry allows the ``group:editors`` principal the ``edit`` permission. The ``Wiki`` class that contains the ACL is the :term:`resource` constructor for the :term:`root` resource, which is a ``Wiki`` instance. The ACL is @@ -150,15 +149,14 @@ .. literalinclude:: src/authorization/tutorial/__init__.py :lines: 1-8 :linenos: :emphasize-lines: 4-5,8 :emphasize-lines: 3-6,8 :language: python Now add those policies to the configuration: .. literalinclude:: src/authorization/tutorial/__init__.py :lines: 18-23 :linenos: :lineno-start: 18 :lineno-match: :emphasize-lines: 1-3,5-6 :language: python @@ -181,12 +179,12 @@ to the ``@view_config`` decorators for ``add_page()`` and ``edit_page()``: .. literalinclude:: src/authorization/tutorial/views.py :lines: 50-52 :lines: 49-51 :emphasize-lines: 2-3 :language: python .. literalinclude:: src/authorization/tutorial/views.py :lines: 70-72 :lines: 68-70 :emphasize-lines: 2-3 :language: python @@ -234,8 +232,8 @@ ``tutorial/views.py``: .. literalinclude:: src/authorization/tutorial/views.py :lines: 6-17 :emphasize-lines: 1-12 :lines: 5-18 :emphasize-lines: 1-14 :language: python All the highlighted lines need to be added or edited. @@ -248,9 +246,8 @@ Now add the ``login`` and ``logout`` views at the end of the file: .. literalinclude:: src/authorization/tutorial/views.py :lines: 82-116 :linenos: :lineno-start: 82 :lines: 80- :lineno-match: :language: python ``login()`` has two decorators: @@ -287,17 +284,17 @@ follows: .. literalinclude:: src/authorization/tutorial/views.py :lines: 47-48 :lines: 46-47 :emphasize-lines: 1-2 :language: python .. literalinclude:: src/authorization/tutorial/views.py :lines: 67-68 :lines: 65-66 :emphasize-lines: 1-2 :language: python .. literalinclude:: src/authorization/tutorial/views.py :lines: 78-80 :lines: 76-78 :emphasize-lines: 2-3 :language: python @@ -348,7 +345,7 @@ .. literalinclude:: src/authorization/tutorial/views.py :linenos: :emphasize-lines: 8,11-15,17,24,29,48,52,68,72,80,82-120 :emphasize-lines: 8,11-15,17,24,29,47,51,66,70,78,80- :language: python Only the highlighted lines need to be added or edited. @@ -358,7 +355,7 @@ .. literalinclude:: src/authorization/tutorial/templates/edit.pt :linenos: :emphasize-lines: 36-38 :emphasize-lines: 37-39 :language: html Only the highlighted lines need to be added or edited. @@ -368,7 +365,7 @@ .. literalinclude:: src/authorization/tutorial/templates/view.pt :linenos: :emphasize-lines: 36-38 :emphasize-lines: 37-39 :language: html Only the highlighted lines need to be added or edited. docs/tutorials/wiki/background.rst
@@ -13,7 +13,7 @@ To code along with this tutorial, the developer will need a UNIX machine with development tools (Mac OS X with XCode, any Linux or BSD variant, etc.) *or* a Windows system of any kind. variant, and so on) *or* a Windows system of any kind. .. warning:: docs/tutorials/wiki/basiclayout.rst
@@ -4,7 +4,7 @@ Basic Layout ============ The starter files generated by the ``zodb`` scaffold are very basic, but The starter files generated by the ``zodb`` cookiecutter are very basic, but they provide a good orientation for the high-level patterns common to most :term:`traversal`-based (and :term:`ZODB`-based) :app:`Pyramid` projects. @@ -44,7 +44,11 @@ #. *Line 15*. Include support for the :term:`Chameleon` template rendering bindings, allowing us to use the ``.pt`` templates. #. *Line 16*. Register a "static view", which answers requests whose URL #. *Line 16*. Include support for ``pyramid_tm``, allowing Pyramid requests to join the active transaction as provided by the `transaction <https://pypi.python.org/pypi/transaction>`_ package. #. *Line 17*. Include support for ``pyramid_zodbconn``, providing integration between :term:`ZODB` and a Pyramid application. #. *Line 18*. Register a "static view", which answers requests whose URL paths start with ``/static``, using the :meth:`pyramid.config.Configurator.add_static_view` method. This statement registers a view that will serve up static assets, such as CSS @@ -54,19 +58,19 @@ will be ``/static``. The second argument of this tag is the "path", which is a relative :term:`asset specification`, so it finds the resources it should serve within the ``static`` directory inside the ``tutorial`` package. Alternatively the scaffold could have used an *absolute* asset package. Alternatively the cookiecutter could have used an *absolute* asset specification as the path (``tutorial:static``). #. *Line 17*. Perform a :term:`scan`. A scan will find :term:`configuration #. *Line 19*. Perform a :term:`scan`. A scan will find :term:`configuration decoration`, such as view configuration decorators (e.g., ``@view_config``) in the source code of the ``tutorial`` package and will take actions based on these decorators. We don't pass any arguments to :meth:`~pyramid.config.Configurator.scan`, which implies that the scan should take place in the current package (in this case, ``tutorial``). The scaffold could have equivalently said ``config.scan('tutorial')``, but The cookiecutter could have equivalently said ``config.scan('tutorial')``, but it chose to omit the package name argument. #. *Line 18*. Use the #. *Line 20*. Use the :meth:`pyramid.config.Configurator.make_wsgi_app` method to return a :term:`WSGI` application. @@ -79,7 +83,7 @@ tree represents the site structure, but it *also* represents the :term:`domain model` of the application, because each resource is a node stored persistently in a :term:`ZODB` database. The ``models.py`` file is where the ``zodb`` scaffold put the classes that implement our where the ``zodb`` cookiecutter put the classes that implement our resource objects, each of which also happens to be a domain model object. Here is the source for ``models.py``: @@ -93,7 +97,7 @@ because the class inherits from the :class:`persistent.mapping.PersistentMapping` class. The ``__parent__`` and ``__name__`` are important parts of the :term:`traversal` protocol. By default, have these as ``None`` indicating that this is the By default, set these to ``None`` to indicate that this is the :term:`root` object. #. *Lines 8-14*. ``appmaker`` is used to return the *application @@ -110,7 +114,7 @@ Views With ``views.py`` ----------------------- Our scaffold generated a default ``views.py`` on our behalf. It Our cookiecutter generated a default ``views.py`` on our behalf. It contains a single view, which is used to render the page shown when you visit the URL ``http://localhost:6543/``. @@ -156,7 +160,7 @@ #. *Lines 6-7*. We define a :term:`view callable` named ``my_view``, which we decorated in the step above. This view callable is a *function* we write generated by the ``zodb`` scaffold that is given a write generated by the ``zodb`` cookiecutter that is given a ``request`` and which returns a dictionary. The ``mytemplate.pt`` :term:`renderer` named by the asset specification in the step above will convert this dictionary to a :term:`response` on our behalf. @@ -168,8 +172,8 @@ Configuration in ``development.ini`` ------------------------------------ The ``development.ini`` (in the tutorial :term:`project` directory, as opposed to the tutorial :term:`package` directory) looks like this: The ``development.ini`` (in the ``tutorial`` :term:`project` directory, as opposed to the ``tutorial`` :term:`package` directory) looks like this: .. literalinclude:: src/basiclayout/development.ini :language: ini docs/tutorials/wiki/definingmodels.rst
@@ -4,7 +4,7 @@ Defining the Domain Model ========================= The first change we'll make to our stock ``pcreate``-generated application will The first change we'll make to our stock cookiecutter-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. @@ -50,7 +50,9 @@ generated ``models.py`` file. The ``MyModel`` class is only a sample and we're not going to use it. Then, we'll add a ``Wiki`` class. We want it to inherit from the Then we'll add an import at the top for the :class:`persistent.Persistent` class. We'll use this for a new ``Page`` class in a moment. Then we'll add a ``Wiki`` class. We want it to inherit from the :class:`persistent.mapping.PersistentMapping` class because it provides mapping behavior, and it makes sure that our Wiki page is stored as a "first-class" persistent object in our ZODB database. docs/tutorials/wiki/definingviews.rst
@@ -4,7 +4,7 @@ Defining Views ============== A :term:`view callable` in a :term:`traversal` -based :app:`Pyramid` A :term:`view callable` in a :term:`traversal`-based :app:`Pyramid` application is typically a simple Python function that accepts two parameters: :term:`context` and :term:`request`. A view callable is assumed to return a :term:`response` object. @@ -16,7 +16,7 @@ this one-argument pattern used in other :app:`Pyramid` tutorials and applications. Either calling convention will work in any :app:`Pyramid` application; the calling conventions can be used interchangeably as necessary. In :term:`traversal` based applications, interchangeably as necessary. In :term:`traversal`-based applications, URLs are mapped to a context :term:`resource`, and since our :term:`resource tree` also represents our application's "domain model", we're often interested in the context because @@ -75,15 +75,15 @@ .. code-block:: doscon c:\pyramidtut> cd tutorial c:\pyramidtut\tutorial> %VENV%\Scripts\pip install -e . c:\> cd tutorial c:\tutorial> %VENV%\Scripts\pip install -e . Success executing this command will end with a line to the console something like: .. code-block:: text Successfully installed docutils-0.12 tutorial-0.0 Successfully installed docutils-0.13.1 tutorial Adding view functions in ``views.py`` @@ -99,11 +99,11 @@ We added some imports and created a regular expression to find "WikiWords". We got rid of the ``my_view`` view function and its decorator that was added when we originally rendered the ``zodb`` scaffold. It was only an example and when we originally rendered the ``zodb`` cookiecutter. It was only an example and isn't relevant to our application. Then we added four :term:`view callable` functions to our ``views.py`` module: module: * ``view_wiki()`` - Displays the wiki itself. It will answer on the root URL. * ``view_page()`` - Displays an individual page. @@ -127,8 +127,7 @@ .. literalinclude:: src/views/tutorial/views.py :lines: 12-14 :lineno-start: 12 :linenos: :lineno-match: :language: python .. note:: In our code, we use an *import* that is *relative* to our package @@ -166,8 +165,7 @@ .. literalinclude:: src/views/tutorial/views.py :lines: 16-33 :lineno-start: 16 :linenos: :lineno-match: :language: python The ``view_page`` function is configured to respond as the default view @@ -220,8 +218,7 @@ .. literalinclude:: src/views/tutorial/views.py :lines: 35-50 :lineno-start: 35 :linenos: :lineno-match: :language: python The ``add_page`` function is configured to respond when the context resource @@ -248,7 +245,7 @@ add view is invoked via, e.g., ``http://localhost:6543/add_page/SomeName``, the :term:`subpath` will be a tuple: ``('SomeName',)``. The add view takes the zeroth element of the subpath (the wiki page name), The add view takes the zero\ :sup:`th` element of the subpath (the wiki page name), and aliases it to the name attribute in order to know the name of the page we're trying to add. @@ -275,8 +272,7 @@ .. literalinclude:: src/views/tutorial/views.py :lines: 52-60 :lineno-start: 52 :linenos: :lineno-match: :language: python The ``edit_page`` function is configured to respond when the context is @@ -317,26 +313,26 @@ The ``view.pt`` template ------------------------ Create ``tutorial/templates/view.pt`` and add the following content: Rename ``tutorial/templates/mytemplate.pt`` to ``tutorial/templates/view.pt`` and edit the emphasized lines to look like the following: .. literalinclude:: src/views/tutorial/templates/view.pt :linenos: :language: html :emphasize-lines: 11-12,37-52 This template is used by ``view_page()`` for displaying a single wiki page. It includes: - A ``div`` element that is replaced with the ``content`` value provided by the view (lines 36-38). ``content`` contains HTML, so the ``structure`` the view (lines 37-39). ``content`` contains HTML, so the ``structure`` keyword is used to prevent escaping it (i.e., changing ">" to ">", etc.) - A link that points at the "edit" URL which invokes the ``edit_page`` view for the page being viewed (lines 40-42). for the page being viewed (lines 41-43). The ``edit.pt`` template ------------------------ Create ``tutorial/templates/edit.pt`` and add the following content: Copy ``tutorial/templates/view.pt`` to ``tutorial/templates/edit.pt`` and edit the emphasized lines to look like the following: .. literalinclude:: src/views/tutorial/templates/edit.pt :linenos: @@ -345,12 +341,12 @@ This template is used by ``add_page()`` and ``edit_page()`` for adding and editing a wiki page. It displays a page containing a form that includes: - A 10 row by 60 column ``textarea`` field named ``body`` that is filled with any existing page data when it is rendered (line 45). - A submit button that has the name ``form.submitted`` (line 48). - A 10-row by 60-column ``textarea`` field named ``body`` that is filled with any existing page data when it is rendered (line 46). - A submit button that has the name ``form.submitted`` (line 49). The form POSTs back to the ``save_url`` argument supplied by the view (line 43). The view will use the ``body`` and ``form.submitted`` values. 44). The view will use the ``body`` and ``form.submitted`` values. .. note:: Our templates use a ``request`` object that none of our tutorial views return in their dictionary. ``request`` is one of several names that docs/tutorials/wiki/design.rst
@@ -43,11 +43,8 @@ Two templates will be used, one for viewing, and one for both adding and editing wiki pages. The default templating systems in :app:`Pyramid` are :term:`Chameleon` and :term:`Mako`. Chameleon is a variant of :term:`ZPT`, which is an XML-based templating language. Mako is a non-XML-based templating language. Because we had to pick one, we chose Chameleon for this tutorial. As of version 1.5 :app:`Pyramid` no longer ships with templating systems. In this tutorial, we will use :term:`Chameleon`. Chameleon is a variant of :term:`ZPT`, which is an XML-based templating language. Security -------- docs/tutorials/wiki/distributing.rst
@@ -20,7 +20,7 @@ .. code-block:: doscon c:\pyramidtut> %VENV%\Scripts\python setup.py sdist c:\tutorial> %VENV%\Scripts\python setup.py sdist The output of such a command will be something like: docs/tutorials/wiki/index.rst
@@ -5,13 +5,12 @@ This tutorial introduces a :term:`ZODB` and :term:`traversal`-based :app:`Pyramid` application to a developer familiar with Python. It will be most familiar to developers with previous :term:`Zope` experience. When the is finished, the developer will have created a basic Wiki application with most familiar to developers with previous :term:`Zope` experience. When finished, the developer will have created a basic Wiki application with authentication. For cut and paste purposes, the source code for all stages of this tutorial can be browsed on GitHub at `docs/tutorials/wiki/src <https://github.com/Pylons/pyramid/tree/master/docs/tutorials/wiki/src>`_, tutorial can be browsed on GitHub at `GitHub <https://github.com/Pylons/pyramid/>`_ for a specific branch or version under ``docs/tutorials/wiki/src``, which corresponds to the same location if you have Pyramid sources. .. toctree:: docs/tutorials/wiki/installation.rst
@@ -15,66 +15,114 @@ * You've satisfied the :ref:`requirements-for-installing-packages`. Create directory to contain the project --------------------------------------- Install cookiecutter -------------------- We will use a :term:`cookiecutter` to create a Python package project from a Python package project template. See `Cookiecutter Installation <https://cookiecutter.readthedocs.io/en/latest/installation.html>`_ for instructions. We need a workspace for our project files. .. note:: At the time of writing, the installation instructions for Cookiecutter suggest the optional use of ``sudo``, implying to install it in the system Python. We suggest that you install it in a virtual environment instead. Generate a Pyramid project from a cookiecutter ---------------------------------------------- We will create a Pyramid project in your home directory for UNIX or at the root for Windows. It is assumed you know the path to where you installed ``cookiecutter``. Issue the following commands and override the defaults in the prompts as follows. On UNIX ^^^^^^^ .. code-block:: bash $ mkdir ~/pyramidtut $ cd ~ $ cookiecutter https://github.com/Pylons/pyramid-cookiecutter-zodb On Windows ^^^^^^^^^^ .. code-block:: doscon c:\> mkdir pyramidtut c:\> cd \ c:\> cookiecutter https://github.com/Pylons/pyramid-cookiecutter-zodb On all operating systems ^^^^^^^^^^^^^^^^^^^^^^^^ If prompted for the first item, accept the default ``yes`` by hitting return. #. ``You've cloned ~/.cookiecutters/pyramid-cookiecutter-zodb before. Is it okay to delete and re-clone it? [yes]:`` #. ``project_name [Pyramid Scaffold]: myproj`` #. ``repo_name [scaffold]: tutorial`` Create and use a virtual Python environment Change directory into your newly created project ------------------------------------------------ On UNIX ^^^^^^^ .. code-block:: bash $ cd tutorial On Windows ^^^^^^^^^^ .. code-block:: doscon c:\> cd tutorial Set and use a ``VENV`` environment variable ------------------------------------------- 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. We will set the ``VENV`` environment variable to the absolute path of the virtual environment, and use it going forward. On UNIX ^^^^^^^ .. code-block:: bash $ export VENV=~/pyramidtut $ python3 -m venv $VENV $ export VENV=~/tutorial On Windows ^^^^^^^^^^ .. code-block:: doscon c:\> set VENV=c:\pyramidtut c:\tutorial\> set VENV=c:\tutorial Each version of Python uses different paths, so you will need to adjust the path to the command for your Python version. Create a virtual environment ---------------------------- On UNIX ^^^^^^^ .. code-block:: bash $ python3 -m venv $VENV On Windows ^^^^^^^^^^ 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:: doscon c:\> c:\Python27\Scripts\virtualenv %VENV% c:\tutorial\> c:\Python27\Scripts\virtualenv %VENV% Python 3.6: .. code-block:: doscon c:\> c:\Python35\Scripts\python -m venv %VENV% c:\tutorial\> c:\Python36\Scripts\python -m venv %VENV% Upgrade ``pip`` and ``setuptools`` in the virtual environment ------------------------------------------------------------- Upgrade packaging tools in the virtual environment -------------------------------------------------- On UNIX ^^^^^^^ @@ -88,86 +136,7 @@ .. code-block:: doscon c:\> %VENV%\Scripts\pip install --upgrade pip setuptools Install Pyramid into the virtual Python environment --------------------------------------------------- On UNIX ^^^^^^^ .. parsed-literal:: $ $VENV/bin/pip install "pyramid==\ |release|\ " On Windows ^^^^^^^^^^ .. parsed-literal:: c:\\> %VENV%\\Scripts\\pip install "pyramid==\ |release|\ " 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:: doscon 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 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. The below instructions assume your current working directory is "pyramidtut". On UNIX ^^^^^^^ .. code-block:: bash $ $VENV/bin/pcreate -s zodb tutorial On Windows ^^^^^^^^^^ .. code-block:: doscon 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 virtual environment and the project into directories that do not contain spaces in their paths. c:\tutorial\> %VENV%\Scripts\pip install --upgrade pip setuptools .. _installing_project_in_dev_mode_zodb: @@ -175,76 +144,51 @@ 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 ``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. In order to do development on the project easily, you must "register" the project as a development egg in your workspace. We will install testing requirements at the same time. We do so with the following command. On UNIX ^^^^^^^ .. code-block:: bash $ cd tutorial $ $VENV/bin/pip install -e . $ $VENV/bin/pip install -e ".[testing]" On Windows ^^^^^^^^^^ .. code-block:: doscon c:\pyramidtut> cd tutorial c:\pyramidtut\tutorial> %VENV%\Scripts\pip install -e . c:\tutorial\> %VENV%\Scripts\pip install -e ".[testing]" The console will show ``pip`` checking for packages and installing missing packages. Success executing this command will show a line like the following: On all operating systems ^^^^^^^^^^^^^^^^^^^^^^^^ The console will show ``pip`` checking for packages and installing missing packages. Success executing this command will show a line like the following: .. 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 Successfully installed BTrees-4.3.1 Chameleon-3.0 Mako-1.0.6 \ MarkupSafe-0.23 PasteDeploy-1.5.2 Pygments-2.1.3 WebOb-1.6.3 \ WebTest-2.0.23 ZConfig-3.1.0 ZEO-5.0.4 ZODB-5.1.1 ZODB3-3.11.0 \ beautifulsoup4-4.5.1 coverage-4.2 mock-2.0.0 pbr-1.10.0 persistent-4.2.2 \ py-1.4.31 pyramid-1.7.3 pyramid-chameleon-0.3 pyramid-debugtoolbar-3.0.5 \ pyramid-mako-1.0.2 pyramid-tm-1.1.1 pyramid-zodbconn-0.7 pyramidtut \ pytest-3.0.5 pytest-cov-2.4.0 repoze.lru-0.6 six-1.10.0 transaction-2.0.3 \ translationstring-1.3 venusian-1.0 waitress-1.0.1 zc.lockfile-1.2.1 \ zdaemon-4.2.0 zodbpickle-0.6.0 zodburi-2.0 zope.deprecation-4.2.0 \ zope.interface-4.3.3 .. _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. Testing requirements are defined in our project's ``setup.py`` file, in the ``tests_require`` and ``extras_require`` stanzas. .. literalinclude:: src/installation/setup.py :language: python :linenos: :lineno-start: 22 :lines: 22-26 :language: python :lineno-match: :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:: doscon c:\pyramidtut\tutorial> %VENV%\Scripts\pip install -e ".[testing]" :language: python :lineno-match: :lines: 46-48 .. _running_tests: @@ -269,7 +213,7 @@ .. code-block:: doscon c:\pyramidtut\tutorial> %VENV%\Scripts\py.test -q c:\tutorial\> %VENV%\Scripts\py.test -q For a successful test run, you should see output that ends like this: @@ -284,7 +228,7 @@ 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 :term:`coverage` information, exposing which lines of your project are covered by the tests. We've already installed the ``pytest-cov`` package into our virtual @@ -302,41 +246,40 @@ .. code-block:: doscon c:\pyramidtut\tutorial> %VENV%\Scripts\py.test --cov \ c:\tutorial\> %VENV%\Scripts\py.test --cov \ --cov-report=term-missing If successful, you will see output something like this: .. code-block:: bash ======================== test session starts ======================== platform Python 3.6.0, 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 ======================== test session starts ======================== platform Python 3.6.0, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: /Users/stevepiercy/tutorial, inifile: plugins: cov-2.4.0 collected 1 items tutorial/tests.py . ------------------ coverage: platform Python 3.6.0 ------------------ Name Stmts Miss Cover Missing ---------------------------------------------------- tutorial/__init__.py 12 7 42% 7-8, 14-18 ------------------------------------------------------- tutorial/__init__.py 14 9 36% 7-8, 14-20 tutorial/models.py 10 6 40% 9-14 tutorial/tests.py 12 0 100% tutorial/views.py 4 0 100% ---------------------------------------------------- TOTAL 38 13 66% ------------------------------------------------------- TOTAL 28 15 46% ===================== 1 passed in 0.31 seconds ====================== Our package doesn't quite have 100% test coverage. .. _test_and_coverage_scaffold_defaults_zodb: .. _test_and_coverage_cookiecutter_defaults_zodb: Test and coverage scaffold defaults ----------------------------------- Test and coverage cookiecutter defaults --------------------------------------- Scaffolds include configuration defaults for ``py.test`` and test coverage. Cookiecutters include configuration defaults for ``py.test`` and test coverage. These configuration files are ``pytest.ini`` and ``.coveragerc``, located at the root of your package. Without these defaults, we would need to specify the path to the module on which we want to run tests and coverage. @@ -353,11 +296,10 @@ .. code-block:: doscon c:\pyramidtut\tutorial> %VENV%\Scripts\py.test --cov=tutorial \ --cov-report=term-missing tutorial\tests.py -q c:\tutorial\> %VENV%\Scripts\py.test --cov=tutorial tutorial\tests.py -q py.test follows :ref:`conventions for Python test discovery <pytest:test discovery>`, and the configuration defaults from the scaffold <pytest:test discovery>`, and the configuration defaults from the cookiecutter tell ``py.test`` where to find the module on which we want to run tests and coverage. @@ -385,7 +327,7 @@ .. code-block:: doscon c:\pyramidtut\tutorial> %VENV%\Scripts\pserve development.ini --reload c:\tutorial\> %VENV%\Scripts\pserve development.ini --reload .. note:: @@ -396,9 +338,10 @@ .. code-block:: text Starting subprocess with file monitor Starting server in PID 82349. serving on http://127.0.0.1:6543 Starting subprocess with file monitor Starting server in PID 44078. Serving on http://localhost:6543 Serving on http://localhost:6543 This means the server is ready to accept requests. @@ -415,13 +358,13 @@ application while you develop. Decisions the ``zodb`` scaffold has made for you ------------------------------------------------ Decisions the ``zodb`` cookiecutter has made for you ---------------------------------------------------- Creating a project using the ``zodb`` scaffold makes the following Creating a project using the ``zodb`` cookiecutter makes the following assumptions: - You are willing to use :term:`ZODB` as persistent storage. - You are willing to use :term:`ZODB` for persistent storage. - You are willing to use :term:`traversal` to map URLs to code. docs/tutorials/wiki/tests.rst
@@ -16,7 +16,7 @@ we'll write a test class for the ``appmaker``. To do so, we'll retain the ``tutorial.tests.ViewTests`` class that was generated as part of the ``zodb`` scaffold. We'll add three test classes: one generated as part of the ``zodb`` cookiecutter. We'll add three test classes: one for the ``Page`` model named ``PageModelTests``, one for the ``Wiki`` model named ``WikiModelTests``, and one for the appmaker named ``AppmakerTests``. @@ -24,8 +24,8 @@ ============== We'll modify our ``tests.py`` file, adding tests for each view function we added previously. As a result, we'll *delete* the ``ViewTests`` class that the ``zodb`` scaffold provided, and add four other test classes: added previously. As a result, we'll delete the ``ViewTests`` class that the ``zodb`` cookiecutter provided, and add four other test classes: ``ViewWikiTests``, ``ViewPageTests``, ``AddPageTests``, and ``EditPageTests``. These test the ``view_wiki``, ``view_page``, ``add_page``, and ``edit_page`` views. @@ -52,7 +52,7 @@ ================= We can run these tests by using ``py.test`` similarly to how we did in :ref:`running_tests`. Courtesy of the scaffold, our testing dependencies have :ref:`running_tests`. Courtesy of the cookiecutter, our testing dependencies have already been satisfied and ``py.test`` and coverage have already been configured, so we can jump right to running tests. @@ -66,11 +66,11 @@ .. code-block:: text c:\pyramidtut\tutorial> %VENV%\Scripts\py.test -q c:\tutorial\> %VENV%\Scripts\py.test -q The expected result should look like the following: .. code-block:: text ........................ 24 passed in 2.46 seconds ......................... 25 passed in 6.87 seconds