diff options
| author | Michael Merickel <michael@merickel.org> | 2020-01-03 23:14:53 -0600 |
|---|---|---|
| committer | Michael Merickel <michael@merickel.org> | 2020-01-03 23:14:53 -0600 |
| commit | 828e069de5d0c98e6d54cfdbf20b1a8acd1f6b39 (patch) | |
| tree | be692270de956199b4cfb1eda8a9fc24ceb8374e /docs/narr | |
| parent | 7820b922cc1b87147cc60288dff0bbdfd7b5bc8a (diff) | |
| parent | 148cf5138638ce6b1b92b4e13fe1444df9451e34 (diff) | |
| download | pyramid-828e069de5d0c98e6d54cfdbf20b1a8acd1f6b39.tar.gz pyramid-828e069de5d0c98e6d54cfdbf20b1a8acd1f6b39.tar.bz2 pyramid-828e069de5d0c98e6d54cfdbf20b1a8acd1f6b39.zip | |
Merge branch 'master' into security-docs
Diffstat (limited to 'docs/narr')
| -rw-r--r-- | docs/narr/commandline.rst | 2 | ||||
| -rw-r--r-- | docs/narr/myproject/.coveragerc | 1 | ||||
| -rw-r--r-- | docs/narr/myproject/MANIFEST.in | 3 | ||||
| -rw-r--r-- | docs/narr/myproject/README.txt | 4 | ||||
| -rw-r--r-- | docs/narr/myproject/myproject/views/default.py | 2 | ||||
| -rw-r--r-- | docs/narr/myproject/myproject/views/notfound.py | 2 | ||||
| -rw-r--r-- | docs/narr/myproject/pytest.ini | 7 | ||||
| -rw-r--r-- | docs/narr/myproject/setup.py | 4 | ||||
| -rw-r--r-- | docs/narr/myproject/tests/__init__.py | 0 | ||||
| -rw-r--r-- | docs/narr/myproject/tests/test_it.py (renamed from docs/narr/myproject/myproject/tests.py) | 14 | ||||
| -rw-r--r-- | docs/narr/paste.rst | 4 | ||||
| -rw-r--r-- | docs/narr/project.rst | 137 | ||||
| -rw-r--r-- | docs/narr/testing.rst | 19 |
13 files changed, 111 insertions, 88 deletions
diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst index 0c5189903..149488206 100644 --- a/docs/narr/commandline.rst +++ b/docs/narr/commandline.rst @@ -1025,7 +1025,7 @@ top-level directory, your ``setup.py`` file will look something like this: author_email='', url='', keywords='web pyramid pylons', - packages=find_packages(), + packages=find_packages(exclude=['tests']), include_package_data=True, zip_safe=False, install_requires=requires, diff --git a/docs/narr/myproject/.coveragerc b/docs/narr/myproject/.coveragerc index f0c31d6d7..5837f5504 100644 --- a/docs/narr/myproject/.coveragerc +++ b/docs/narr/myproject/.coveragerc @@ -1,3 +1,2 @@ [run] source = myproject -omit = myproject/test* diff --git a/docs/narr/myproject/MANIFEST.in b/docs/narr/myproject/MANIFEST.in index 1c24b8c0c..f516697f5 100644 --- a/docs/narr/myproject/MANIFEST.in +++ b/docs/narr/myproject/MANIFEST.in @@ -1,2 +1,5 @@ include *.txt *.ini *.cfg *.rst recursive-include myproject *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml *.jinja2 +recursive-include tests * +recursive-exclude * __pycache__ +recursive-exclude * *.py[co] diff --git a/docs/narr/myproject/README.txt b/docs/narr/myproject/README.txt index 2ffc0acba..6c5a0fee0 100644 --- a/docs/narr/myproject/README.txt +++ b/docs/narr/myproject/README.txt @@ -1,4 +1,4 @@ -MyProject +myproject ========= Getting Started @@ -6,7 +6,7 @@ Getting Started - Change directory into your newly created project. - cd MyProject + cd myproject - Create a Python virtual environment. diff --git a/docs/narr/myproject/myproject/views/default.py b/docs/narr/myproject/myproject/views/default.py index 8324cfe32..619ce1c0f 100644 --- a/docs/narr/myproject/myproject/views/default.py +++ b/docs/narr/myproject/myproject/views/default.py @@ -1,6 +1,6 @@ from pyramid.view import view_config -@view_config(route_name='home', renderer='../templates/mytemplate.jinja2') +@view_config(route_name='home', renderer='myproject:templates/mytemplate.jinja2') def my_view(request): return {'project': 'myproject'} diff --git a/docs/narr/myproject/myproject/views/notfound.py b/docs/narr/myproject/myproject/views/notfound.py index 69d6e2804..5abebb277 100644 --- a/docs/narr/myproject/myproject/views/notfound.py +++ b/docs/narr/myproject/myproject/views/notfound.py @@ -1,7 +1,7 @@ from pyramid.view import notfound_view_config -@notfound_view_config(renderer='../templates/404.jinja2') +@notfound_view_config(renderer='myproject:templates/404.jinja2') def notfound_view(request): request.response.status = 404 return {} diff --git a/docs/narr/myproject/pytest.ini b/docs/narr/myproject/pytest.ini index b1b5f4c38..5c8c59068 100644 --- a/docs/narr/myproject/pytest.ini +++ b/docs/narr/myproject/pytest.ini @@ -1,3 +1,6 @@ [pytest] -testpaths = myproject -python_files = *.py +addopts = --strict + +testpaths = + myproject + tests diff --git a/docs/narr/myproject/setup.py b/docs/narr/myproject/setup.py index 1ee272270..e5872df29 100644 --- a/docs/narr/myproject/setup.py +++ b/docs/narr/myproject/setup.py @@ -25,7 +25,7 @@ tests_require = [ setup( name='myproject', version='0.0', - description='MyProject', + description='myproject', long_description=README + '\n\n' + CHANGES, classifiers=[ 'Programming Language :: Python', @@ -37,7 +37,7 @@ setup( author_email='', url='', keywords='web pyramid pylons', - packages=find_packages(), + packages=find_packages(exclude=['tests']), include_package_data=True, zip_safe=False, extras_require={ diff --git a/docs/narr/myproject/tests/__init__.py b/docs/narr/myproject/tests/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/docs/narr/myproject/tests/__init__.py diff --git a/docs/narr/myproject/myproject/tests.py b/docs/narr/myproject/tests/test_it.py index 05ccadcfb..b300da34d 100644 --- a/docs/narr/myproject/myproject/tests.py +++ b/docs/narr/myproject/tests/test_it.py @@ -11,10 +11,16 @@ class ViewTests(unittest.TestCase): testing.tearDown() def test_my_view(self): - from .views.default import my_view + from myproject.views.default import my_view request = testing.DummyRequest() info = my_view(request) - self.assertEqual(info['project'], 'MyProject') + self.assertEqual(info['project'], 'myproject') + + def test_notfound_view(self): + from myproject.views.notfound import notfound_view + request = testing.DummyRequest() + info = notfound_view(request) + self.assertEqual(info, {}) class FunctionalTests(unittest.TestCase): @@ -27,3 +33,7 @@ class FunctionalTests(unittest.TestCase): def test_root(self): res = self.testapp.get('/', status=200) self.assertTrue(b'Pyramid' in res.body) + + def test_notfound(self): + res = self.testapp.get('/badurl', status=404) + self.assertTrue(res.status_code == 404) diff --git a/docs/narr/paste.rst b/docs/narr/paste.rst index fe2846dd3..e198176d4 100644 --- a/docs/narr/paste.rst +++ b/docs/narr/paste.rst @@ -95,4 +95,6 @@ application's ``main`` function as ``global_config`` (see the reference to the Alternative Configuration File Formats -------------------------------------- -It is possible to use different file formats with :app:`Pyramid` if you do not like :term:`PasteDeploy`. Under the hood all command-line scripts such as ``pserve`` and ``pshell`` pass the ``config_uri`` (e.g. ``development.ini`` or ``production.ini``) to the :term:`plaster` library which performs a lookup for an appropriate parser. For ``.ini`` files it uses PasteDeploy but you can register your own configuration formats that plaster will find instead. +It is possible to use different file formats with :app:`Pyramid` if you do not like :term:`PasteDeploy`. +Under the hood all command-line scripts such as ``pserve`` and ``pshell`` pass the ``config_uri`` (e.g., ``development.ini`` or ``production.ini``) to the :term:`plaster` library which performs a lookup for an appropriate parser. +For ``.ini`` files it uses PasteDeploy but you can register your own configuration formats that plaster will find instead. diff --git a/docs/narr/project.rst b/docs/narr/project.rst index 58bef5701..043f77754 100644 --- a/docs/narr/project.rst +++ b/docs/narr/project.rst @@ -117,7 +117,7 @@ On Unix: # Create a new virtual environment... python3 -m venv $VENV # ...where we upgrade packaging tools. - env/bin/pip install --upgrade pip setuptools + $VENV/bin/pip install --upgrade pip setuptools Or on Windows: @@ -208,11 +208,12 @@ Elided output from a run of this command on Unix is shown below: .. code-block:: bash Running setup.py develop for myproject - Successfully installed Jinja2-2.8 Mako-1.0.6 MarkupSafe-0.23 \ - PasteDeploy-1.5.2 Pygments-2.1.3 WebOb-1.7.0 myproject pyramid-1.7.3 \ - pyramid-debugtoolbar-3.0.5 pyramid-jinja2-2.7 pyramid-mako-1.0.2 \ - repoze.lru-0.6 translationstring-1.3 venusian-1.0 waitress-1.0.1 \ - zope.deprecation-4.2.0 zope.interface-4.3.3 + Successfully installed Jinja2-2.10.3 Mako-1.1.0 MarkupSafe-1.1.1 \ + PasteDeploy-2.0.1 Pygments-2.5.2 hupper-1.9.1 myproject plaster-1.0 \ + plaster-pastedeploy-0.7 pyramid-1.10.4 pyramid-debugtoolbar-4.5.1 \ + pyramid-jinja2-2.8 pyramid-mako-1.1.0 repoze.lru-0.7 \ + translationstring-1.3 venusian-3.0.0 waitress-1.4.1 webob-1.8.5 \ + zope.deprecation-4.4.0 zope.interface-4.7.1 This will install a :term:`distribution` representing your project into the virtual environment interpreter's library set so it can be found by ``import`` @@ -262,10 +263,11 @@ Here's sample output from a test run on Unix: .. code-block:: bash $VENV/bin/pytest -q - .. - 2 passed in 0.47 seconds + .... + 4 passed in 0.45 seconds -The tests themselves are found in the ``tests.py`` module in your ``cookiecutter``-generated project. Within a project generated by the ``pyramid-cookiecutter-starter`` cookiecutter, only two sample tests exist. +The tests themselves are found in the ``test_it.py`` module in the ``tests`` package in your ``cookiecutter``-generated project. +Within this project generated by the ``pyramid-cookiecutter-starter`` cookiecutter, only a few sample tests exist. .. note:: @@ -287,7 +289,7 @@ path to the module on which we want to run tests and coverage. .. code-block:: bash - $VENV/bin/pytest --cov=myproject myproject/tests.py -q + $VENV/bin/pytest --cov=myproject myproject tests -q .. seealso:: See ``pytest``'s documentation for :ref:`pytest:usage` or invoke ``pytest -h`` to see its full set of options. @@ -402,8 +404,8 @@ For example, on Unix: .. code-block:: text $VENV/bin/pserve development.ini --reload - Starting subprocess with file monitor - Starting server in PID 16601. + Starting monitor for PID 36224. + Starting server in PID 36224. Serving on http://localhost:6543 Serving on http://localhost:6543 @@ -412,9 +414,10 @@ files, you'll see the server restart automatically: .. code-block:: text - development.ini changed; reloading... - -------------------- Restarting -------------------- - Starting server in PID 16602. + /file-path-to/myproject/development.ini changed; reloading ... + Gracefully killing the server. + Starting monitor for PID 36286. + Starting server in PID 36286. Serving on http://localhost:6543 Serving on http://localhost:6543 @@ -462,7 +465,7 @@ browsing from a system that does not have debugging access. By default, for security reasons, only a browser originating from ``localhost`` (``127.0.0.1``) can see the debug toolbar. To allow your browser on a remote system to access the server, add a line within the ``[app:main]`` section of the -``development.ini`` file in the form ``debugtoolbar.hosts = X .X.X.X``. For +``development.ini`` file in the form ``debugtoolbar.hosts = X.X.X.X``. For example, if your Pyramid application is running on a remote system, and you're browsing from a host with the IP address ``192.168.1.1``, you'd add something like this to enable the toolbar when your system contacts Pyramid: @@ -470,7 +473,7 @@ like this to enable the toolbar when your system contacts Pyramid: .. code-block:: ini [app:main] - # .. other settings ... + # ... other settings ... debugtoolbar.hosts = 192.168.1.1 For more information about what the debug toolbar allows you to do, see the @@ -533,6 +536,8 @@ The ``myproject`` project we've generated has the following directory structure: ├── .gitignore ├── CHANGES.txt ├── MANIFEST.in + ├── README.txt + ├── development.ini ├── myproject │ ├── __init__.py │ ├── routes.py @@ -544,16 +549,37 @@ The ``myproject`` project we've generated has the following directory structure: │ │ ├── 404.jinja2 │ │ ├── layout.jinja2 │ │ └── mytemplate.jinja2 - │ ├── tests.py │ └── views │ ├── __init__.py │ ├── default.py │ └── notfound.py - ├── README.txt - ├── development.ini ├── production.ini ├── pytest.ini - └── setup.py + ├── setup.py + └── tests + ├── __init__.py + └── test_it.py + + +.. index:: + single: tests + +``test_it.py`` +~~~~~~~~~~~~~~ + +The ``test_it.py`` module in the ``tests`` package includes tests for your application. + +.. literalinclude:: myproject/tests/test_it.py + :language: python + :linenos: + +This sample ``test_it.py`` file has two unit tests and two functional tests defined within it. +These tests are executed when you run ``pytest -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. The ``myproject`` :term:`Project` @@ -589,6 +615,8 @@ describe, run, and test your application. #. ``setup.py`` is the file you'll use to test and distribute your application. It is a standard :term:`Setuptools` ``setup.py`` file. +#. ``tests`` package which contains unit and functional test code for the application. + .. index:: single: PasteDeploy single: ini file @@ -701,9 +729,8 @@ specifies the non-Python files that should be included when a setup.py sdist``. Due to the information contained in the default ``MANIFEST.in``, an sdist of your Pyramid project will include ``.txt`` files, ``.ini`` files, ``.rst`` files, graphics files, and template files, as well as -``.py`` files. See -https://docs.python.org/2/distutils/sourcedist.html#the-manifest-in-template -for more information about the syntax and usage of ``MANIFEST.in``. +``.py`` files. +See the Python Packaging Authority's Python Packaging User Guide `Including files in source distributions with MANIFEST.in <https://packaging.python.org/guides/using-manifest-in/>`_ for more information about the syntax and usage of ``MANIFEST.in``. Without the presence of a ``MANIFEST.in`` file or without checking your source code into a version control repository, ``setup.py sdist`` places only *Python @@ -720,9 +747,8 @@ like ``*.pt``, ``*.css`` and ``*.js`` in the generated tarball. If you include files with extensions other than the files named in the project's ``MANIFEST.in`` and you don't make use of a Setuptools-compatible version control system, you'll need to edit the ``MANIFEST.in`` file and include the -statements necessary to include your new files. See -https://docs.python.org/2/distutils/sourcedist.html#principle for more -information about how to do this. +statements necessary to include your new files. +In the aforementioned Python Packaging User Guide, see `MANIFEST.in commands <https://packaging.python.org/guides/using-manifest-in/#manifest-in-commands>`_ for more information about how to do this. You can also delete ``MANIFEST.in`` from your project and rely on a :term:`Setuptools` feature which simply causes all files checked into a version control system to @@ -775,15 +801,17 @@ together. The ``classifiers`` field is a list of `Trove classifiers <https://pypi.org/pypi?%3Aaction=list_classifiers>`_ describing your application. ``author`` and ``author_email`` are text fields which probably don't need any description. ``url`` is a field that should point at your -application project's URL (if any). ``packages=find_packages()`` causes all +application project's URL (if any). +``keywords`` are keywords that describe your project. +``packages=find_packages(exclude=['tests'])`` 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=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`` -indicates 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 +always unpack as a directory, which is more convenient. +``extras_require`` is a Python dictionary that defines what is required to be installed for running tests. +``install_requires`` indicates that this package depends on the ``pyramid`` package. +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. @@ -817,8 +845,6 @@ The ``myproject`` :term:`package` lives inside the ``myproject`` #. A ``templates`` directory, which contains :term:`Jinja2` (or other types of) templates. -#. A ``tests.py`` module, which contains unit test code for the application. - #. A ``routes.py`` module, which contains routing code for the application. #. A ``views`` package, which contains view code for the application. @@ -850,7 +876,7 @@ also informs Python that the directory which contains it is a *package*. #. Line 1 imports the :term:`Configurator` class from :mod:`pyramid.config` that we use later. -#. Lines 4-12 define a function named ``main`` that returns a :app:`Pyramid` +#. Lines 4-11 define a function named ``main`` that returns a :app:`Pyramid` WSGI application. This function is meant to be called by the :term:`PasteDeploy` framework as a result of running ``pserve``. @@ -924,11 +950,13 @@ route named ``home`` to the URL pattern ``/``, this route will match when a visitor visits the root URL. The view_config decorator also names a ``renderer``, which in this case is a template that will be used to render the result of the view callable. This particular view declaration points at -``../templates/mytemplate.jinja2``, which is an :term:`asset specification` that +``myproject:templates/mytemplate.jinja2``, which is an :term:`asset specification` that specifies the ``mytemplate.jinja2`` file within the ``templates`` directory of the -``myproject`` package. The asset specification could have also been specified -as ``myproject:templates/mytemplate.jinja2``; the leading package name and colon is -optional. The template file pointed to is a :term:`Jinja2` template +``myproject`` package. +There is a second form of asset specification: a relative asset specification. +Instead of using an "absolute" asset specification which includes the package name, in certain circumstances you can omit the package name from the specification. +For example, you might be able to use ``../templates/mytemplate.jinja2``. +The template file pointed to is a :term:`Jinja2` template file (``templates/mytemplate.jinja2``). This view callable function is handed a single piece of information: the @@ -949,7 +977,7 @@ Now let's look at ``notfound.py``. :linenos: This file is similar to ``default.py``. -It merely returns a ``404`` response status and an empty dictionary to the template at ``../templates/404.jinja2``. +It merely returns a ``404`` response status and an empty dictionary to the template at ``myproject:templates/404.jinja2``. .. note:: When the application is run with the cookiecutter's :ref:`default development.ini <myproject_ini>` configuration, :ref:`logging is set up @@ -1037,27 +1065,6 @@ It inherits the HTML provided by ``layout.jinja2``, replacing the content block .. index:: - single: tests.py - -``tests.py`` -~~~~~~~~~~~~ - -The ``tests.py`` module includes tests for your application. - -.. literalinclude:: myproject/myproject/tests.py - :language: python - :linenos: - -This sample ``tests.py`` file has one unit test and one functional test defined -within it. These tests are executed when you run ``pytest -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. - -.. index:: pair: modifying; package structure .. _modifying_package_structure: @@ -1159,11 +1166,9 @@ inotify support ~~~~~~~~~~~~~~~ By default ``hupper`` will poll the filesystem for changes to all Python -code. This can be pretty inefficient in larger projects. To be nicer to your -hard drive, you should install the -`watchdog <https://pythonhosted.org/watchdog/>`_ package in development. -``hupper`` will automatically use ``watchdog`` to more efficiently poll the -filesystem. +code. This can be pretty inefficient in larger projects. +To be nicer to your hard drive, you should install either the `watchman <https://facebook.github.io/watchman/>`_ or `watchdog <https://pythonhosted.org/watchdog/>`_ package in development. +``hupper`` will use, in order of preference for efficiency, if available, ``watchman``, ``watchdog``, or finally polling to detect changes to the filesystem. Monitoring Custom Files ~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst index 2182082a8..0fa1e98fd 100644 --- a/docs/narr/testing.rst +++ b/docs/narr/testing.rst @@ -403,20 +403,21 @@ function ``my_view`` that returns an HTML body when the root URL is invoked: :linenos: :language: python -The following example functional test demonstrates invoking the above -:term:`view`: +The following example functional tests demonstrate invoking the above :term:`view`: - .. literalinclude:: myproject/myproject/tests.py + .. literalinclude:: myproject/tests/test_it.py :linenos: :pyobject: FunctionalTests :language: python -When this test is run, each test method creates a "real" :term:`WSGI` -application using the ``main`` function in your ``myproject.__init__`` module, -using :term:`WebTest` to wrap that WSGI application. It assigns the result to -``self.testapp``. In the test named ``test_root``, the ``TestApp``'s ``GET`` -method is used to invoke the root URL. Finally, an assertion is made that the -returned HTML contains the text ``Pyramid``. +When these tests are run, each test method creates a "real" :term:`WSGI` application using the ``main`` function in your ``myproject.__init__`` module, using :term:`WebTest` to wrap that WSGI application. +It assigns the result to ``self.testapp``. + +In the test named ``test_root``, the ``TestApp``'s ``GET`` method is used to invoke the root URL. +An assertion is made that the returned HTML contains the text ``Pyramid``. + +In the test named ``test_notfound``, the ``TestApp``'s ``GET`` method is used to invoke a bad URL ``/badurl``. +An assertion is made that the returned status code in the response is ``404``. See the :term:`WebTest` documentation for further information about the methods available to a :class:`webtest.app.TestApp` instance. |
