From a155b4be97de8955ba753220984287e82853e35f Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Mon, 27 Aug 2018 14:38:02 -0700 Subject: Improve instructions of how to run p-scripts - add link in each script usage to the instructions --- docs/narr/commandline.rst | 165 ++++++++++++++++++++++++++++-------------- docs/pscripts/pcreate.rst | 2 +- docs/pscripts/pdistreport.rst | 2 +- docs/pscripts/prequest.rst | 2 +- docs/pscripts/proutes.rst | 2 +- docs/pscripts/pserve.rst | 2 +- docs/pscripts/pshell.rst | 2 +- docs/pscripts/ptweens.rst | 2 +- docs/pscripts/pviews.rst | 2 +- 9 files changed, 118 insertions(+), 63 deletions(-) diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst index 9e0310c29..107f35914 100644 --- a/docs/narr/commandline.rst +++ b/docs/narr/commandline.rst @@ -6,6 +6,63 @@ Command-Line Pyramid Your :app:`Pyramid` application can be controlled and inspected using a variety of command-line utilities. These utilities are documented in this chapter. +We commonly refer to this collection of utilities as "p-scripts", which is short for "Pyramid console scripts". + +Each p-script's command line usage details is available in the :ref:`pscripts_documentation`. + + +.. index:: + single: running p-scripts + pair: running; p-scripts + +.. _running-pscripts: + +Running p-scripts +----------------- + +All of the Pyramid console scripts may be run either: + +* by its name +* through a Python interpreter + + +.. index:: + single: running p-script by name + triple: p-script; running; name + +.. _running-pscripts-by-name: + +Running by ``p*`` script name +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each of Pyramid's console scripts may be run by its name. For example: + +.. code-block:: bash + + $VENV/bin/pserve development.ini --reload + +.. note:: ``$VENV/bin/`` represents the ``bin`` directory in a virtual environment, where ``$VENV`` is an environment variable representing its path. + + +.. index:: + single: running p-scripts via Python + triple: p-script; running; Python + +.. _custom-arguments-to-python: + +Using Custom Arguments to Python when Running ``p*`` Scripts +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 1.5 + +Each of Pyramid's console scripts (``pserve``, ``pviews``, etc.) can be run +using ``python3 -m``, allowing custom arguments to be sent to the +Python interpreter at runtime. For example: + +.. code-block:: bash + + python3 -m pyramid.scripts.pserve development.ini --reload + .. index:: pair: matching views; printing @@ -13,8 +70,8 @@ of command-line utilities. These utilities are documented in this chapter. .. _displaying_matching_views: -Displaying Matching Views for a Given URL ------------------------------------------ +``pviews``: Displaying Matching Views for a Given URL +----------------------------------------------------- .. seealso:: See also the output of :ref:`pviews --help `. @@ -31,7 +88,7 @@ to be ``main``. Here is an example for a simple view configuration using :term:`traversal`: -.. code-block:: text +.. code-block:: bash :linenos: $VENV/bin/pviews development.ini#tutorial /FrontPage @@ -54,7 +111,7 @@ permissions and predicates that are part of that view configuration. A more complex configuration might generate something like this: -.. code-block:: text +.. code-block:: bash :linenos: $VENV/bin/pviews development.ini#shootout /about @@ -114,8 +171,8 @@ found* message. .. _interactive_shell: -The Interactive Shell ---------------------- +``pshell``: The Interactive Shell +--------------------------------- .. seealso:: See also the output of :ref:`pshell --help `. @@ -144,7 +201,7 @@ have an ``[app:main]`` section that looks like so: If so, you can use the following command to invoke a debug shell using the name ``main`` as a section name: -.. code-block:: text +.. code-block:: bash $VENV/bin/pshell starter/development.ini#main Python 2.6.5 (r265:79063, Apr 29 2010, 00:31:32) @@ -178,7 +235,7 @@ default :term:`root factory`, ``registry``, and ``request`` will be available. You can also simply rely on the ``main`` default section name by omitting any hash after the filename: -.. code-block:: text +.. code-block:: bash $VENV/bin/pshell starter/development.ini @@ -252,7 +309,7 @@ By defining the ``setup`` callable, we will create the module ``myapp.lib.pshell When this ``.ini`` file is loaded, the extra variable ``models`` will be available for use immediately. Since a ``setup`` callable was also specified, it is executed and new variables ``testapp``, ``tm``, and ``dbsession`` are exposed, and the request is configured to generate URLs from the host ``http://www.example.com``. For example: -.. code-block:: text +.. code-block:: bash $VENV/bin/pshell starter/development.ini Python 2.6.5 (r265:79063, Apr 29 2010, 00:31:32) @@ -296,13 +353,13 @@ installed such as ``pyramid_ipython`` it will normally be auto-selected and used. You may also specifically invoke your choice with the ``-p choice`` or ``--python-shell choice`` option. -.. code-block:: text +.. code-block:: bash $VENV/bin/pshell -p ipython development.ini#MyProject You may use the ``--list-shells`` option to see the available shells. -.. code-block:: text +.. code-block:: bash $VENV/bin/pshell --list-shells Available shells: @@ -363,8 +420,8 @@ specify a list of preferred shells. .. _displaying_application_routes: -Displaying All Application Routes ---------------------------------- +``proutes``: Displaying All Application Routes +---------------------------------------------- .. seealso:: See also the output of :ref:`proutes --help `. @@ -378,7 +435,7 @@ the ``section_name`` is ``main`` and can be omitted. For example: -.. code-block:: text +.. code-block:: bash :linenos: $VENV/bin/proutes development.ini @@ -415,7 +472,7 @@ and use those as defaults. For example you may remove the request method and place the view first: -.. code-block:: text +.. code-block:: ini :linenos: [proutes] @@ -425,7 +482,7 @@ For example you may remove the request method and place the view first: You can also separate the formats with commas or spaces: -.. code-block:: text +.. code-block:: ini :linenos: [proutes] @@ -446,8 +503,8 @@ include. The current available formats are ``name``, ``pattern``, ``view``, and .. _displaying_tweens: -Displaying "Tweens" -------------------- +``ptweens``: Displaying "Tweens" +-------------------------------- .. seealso:: See also the output of :ref:`ptweens --help `. @@ -462,7 +519,7 @@ standard Python dotted name in the ``ptweens`` output. For example, here's the ``ptweens`` command run against a system configured without any explicit tweens: -.. code-block:: text +.. code-block:: bash :linenos: $VENV/bin/ptweens development.ini @@ -480,10 +537,10 @@ without any explicit tweens: Here's the ``ptweens`` command run against a system configured *with* explicit tweens defined in its ``development.ini`` file: -.. code-block:: text +.. code-block:: bash :linenos: - ptweens development.ini + $VENV/bin/ptweens development.ini "pyramid.tweens" config value set (explicitly ordered tweens used) Explicit Tween Chain (used) @@ -534,8 +591,8 @@ See :ref:`registering_tweens` for more information about tweens. .. _invoking_a_request: -Invoking a Request ------------------- +``prequest``: Invoking a Request +-------------------------------- .. seealso:: See also the output of :ref:`prequest --help `. @@ -553,9 +610,11 @@ There are two required arguments to ``prequest``: - The path: this should be the non-URL-quoted path element of the URL to the resource you'd like to be rendered on the server. For example, ``/``. -For example:: +For example: + +.. code-block:: bash - $ $VENV/bin/prequest development.ini / + $VENV/bin/prequest development.ini / This will print the body of the response to the console on which it was invoked. @@ -564,16 +623,20 @@ Several options are supported by ``prequest``. These should precede any config file name or URL. ``prequest`` has a ``-d`` (i.e., ``--display-headers``) option which prints the -status and headers returned by the server before the output:: +status and headers returned by the server before the output: + +.. code-block:: bash - $ $VENV/bin/prequest -d development.ini / + $VENV/bin/prequest -d development.ini / This will print the status, headers, and the body of the response to the console. -You can add request header values by using the ``--header`` option:: +You can add request header values by using the ``--header`` option: + +.. code-block:: bash - $ $VENV/bin/prequest --header=Host:example.com development.ini / + $VENV/bin/prequest --header=Host:example.com development.ini / Headers are added to the WSGI environment by converting them to their CGI/WSGI equivalents (e.g., ``Host=example.com`` will insert the ``HTTP_HOST`` header @@ -584,21 +647,11 @@ in the WSGI environment. By default, ``prequest`` sends a ``GET`` request. You can change this by using the ``-m`` (aka ``--method``) option. ``GET``, ``HEAD``, ``POST``, and ``DELETE`` are currently supported. When you use ``POST``, the standard input -of the ``prequest`` process is used as the ``POST`` body:: - - $ $VENV/bin/prequest -mPOST development.ini / < somefile - - -Using Custom Arguments to Python when Running ``p*`` Scripts ------------------------------------------------------------- - -.. versionadded:: 1.5 +of the ``prequest`` process is used as the ``POST`` body: -Each of Pyramid's console scripts (``pserve``, ``pviews``, etc.) can be run -directly using ``python3 -m``, allowing custom arguments to be sent to the -Python interpreter at runtime. For example:: +.. code-block:: bash - python3 -m pyramid.scripts.pserve development.ini + $VENV/bin/prequest -mPOST development.ini / < somefile .. index:: @@ -608,8 +661,8 @@ Python interpreter at runtime. For example:: .. _showing_distributions: -Showing All Installed Distributions and Their Versions ------------------------------------------------------- +``pdistreport``: Showing All Installed Distributions and Their Versions +----------------------------------------------------------------------- .. versionadded:: 1.5 @@ -618,17 +671,19 @@ Showing All Installed Distributions and Their Versions You can use the ``pdistreport`` command to show the :app:`Pyramid` version in use, the Python version in use, and all installed versions of Python -distributions in your Python environment:: - - $ $VENV/bin/pdistreport - Pyramid version: 1.5dev - Platform Linux-3.2.0-51-generic-x86_64-with-debian-wheezy-sid - Packages: - authapp 0.0 - /home/chrism/projects/foo/src/authapp - beautifulsoup4 4.1.3 - /home/chrism/projects/foo/lib/python2.7/site-packages/beautifulsoup4-4.1.3-py2.7.egg - ... more output ... +distributions in your Python environment: + +.. code-block:: bash + + $VENV/bin/pdistreport + Pyramid version: 1.5dev + Platform Linux-3.2.0-51-generic-x86_64-with-debian-wheezy-sid + Packages: + authapp 0.0 + /home/chrism/projects/foo/src/authapp + beautifulsoup4 4.1.3 + /home/chrism/projects/foo/lib/python2.7/site-packages/beautifulsoup4-4.1.3-py2.7.egg + # ... more output ... ``pdistreport`` takes no options. Its output is useful to paste into a pastebin when you are having problems and need someone with more familiarity diff --git a/docs/pscripts/pcreate.rst b/docs/pscripts/pcreate.rst index c48a70acd..e2c45626a 100644 --- a/docs/pscripts/pcreate.rst +++ b/docs/pscripts/pcreate.rst @@ -6,4 +6,4 @@ .. autoprogram:: pyramid.scripts.pcreate:PCreateCommand.parser :prog: pcreate -.. seealso:: :ref:`creating_a_project` +.. seealso:: :ref:`creating_a_project` and :ref:`running-pscripts`. diff --git a/docs/pscripts/pdistreport.rst b/docs/pscripts/pdistreport.rst index b3c9dffd8..fa07f53ad 100644 --- a/docs/pscripts/pdistreport.rst +++ b/docs/pscripts/pdistreport.rst @@ -6,4 +6,4 @@ .. autoprogram:: pyramid.scripts.pdistreport:get_parser() :prog: pdistreport -.. seealso:: :ref:`showing_distributions` +.. seealso:: :ref:`showing_distributions` and :ref:`running-pscripts`. diff --git a/docs/pscripts/prequest.rst b/docs/pscripts/prequest.rst index 64ed01739..3767506fb 100644 --- a/docs/pscripts/prequest.rst +++ b/docs/pscripts/prequest.rst @@ -6,4 +6,4 @@ .. autoprogram:: pyramid.scripts.prequest:PRequestCommand.parser :prog: prequest -.. seealso:: :ref:`invoking_a_request` +.. seealso:: :ref:`invoking_a_request` and :ref:`running-pscripts`. diff --git a/docs/pscripts/proutes.rst b/docs/pscripts/proutes.rst index ee7c209e3..282ef327f 100644 --- a/docs/pscripts/proutes.rst +++ b/docs/pscripts/proutes.rst @@ -6,4 +6,4 @@ .. autoprogram:: pyramid.scripts.proutes:PRoutesCommand.parser :prog: proutes -.. seealso:: :ref:`displaying_application_routes` +.. seealso:: :ref:`displaying_application_routes` and :ref:`running-pscripts`. diff --git a/docs/pscripts/pserve.rst b/docs/pscripts/pserve.rst index 991976aea..cc3c80c91 100644 --- a/docs/pscripts/pserve.rst +++ b/docs/pscripts/pserve.rst @@ -6,4 +6,4 @@ .. autoprogram:: pyramid.scripts.pserve:PServeCommand.parser :prog: pserve -.. seealso:: :ref:`running_the_project_application` +.. seealso:: :ref:`running_the_project_application` and :ref:`running-pscripts`. diff --git a/docs/pscripts/pshell.rst b/docs/pscripts/pshell.rst index 4e2ce74cb..7c9050826 100644 --- a/docs/pscripts/pshell.rst +++ b/docs/pscripts/pshell.rst @@ -6,4 +6,4 @@ .. autoprogram:: pyramid.scripts.pshell:PShellCommand.parser :prog: pshell -.. seealso:: :ref:`interactive_shell` +.. seealso:: :ref:`interactive_shell` and :ref:`running-pscripts`. diff --git a/docs/pscripts/ptweens.rst b/docs/pscripts/ptweens.rst index f586e1467..fe9c27abd 100644 --- a/docs/pscripts/ptweens.rst +++ b/docs/pscripts/ptweens.rst @@ -6,4 +6,4 @@ .. autoprogram:: pyramid.scripts.ptweens:PTweensCommand.parser :prog: ptweens -.. seealso:: :ref:`displaying_tweens` +.. seealso:: :ref:`displaying_tweens` and :ref:`running-pscripts`. diff --git a/docs/pscripts/pviews.rst b/docs/pscripts/pviews.rst index da4660779..0726cb6aa 100644 --- a/docs/pscripts/pviews.rst +++ b/docs/pscripts/pviews.rst @@ -6,4 +6,4 @@ .. autoprogram:: pyramid.scripts.pviews:PViewsCommand.parser :prog: pviews -.. seealso:: :ref:`displaying_matching_views` +.. seealso:: :ref:`displaying_matching_views` and :ref:`running-pscripts`. -- cgit v1.2.3 From d7dfe77e5fa8f0aa1ae75ae076ce160661376172 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Mon, 27 Aug 2018 23:57:42 -0700 Subject: Use correct terminology for running p-scripts in Python --- docs/narr/commandline.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst index 107f35914..3cc7b9653 100644 --- a/docs/narr/commandline.rst +++ b/docs/narr/commandline.rst @@ -23,7 +23,7 @@ Running p-scripts All of the Pyramid console scripts may be run either: * by its name -* through a Python interpreter +* as a Python module .. index:: -- cgit v1.2.3 From cbab50f10ffcb12d094aafc0afacc5601838e56c Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Tue, 28 Aug 2018 13:47:24 -0700 Subject: Clarify $VENV convention with references. --- docs/narr/commandline.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst index 3cc7b9653..53e4ee31c 100644 --- a/docs/narr/commandline.rst +++ b/docs/narr/commandline.rst @@ -41,7 +41,9 @@ Each of Pyramid's console scripts may be run by its name. For example: $VENV/bin/pserve development.ini --reload -.. note:: ``$VENV/bin/`` represents the ``bin`` directory in a virtual environment, where ``$VENV`` is an environment variable representing its path. +.. note:: ``$VENV/bin/`` is a convention we use to simplify Pyramid documentation. + It represents the ``bin`` directory in a virtual environment, where ``$VENV`` is an environment variable representing its path. + See :ref:`installing_unix` and :ref:`venv-bin-pip-vs-source-bin-activate` for more information. .. index:: -- cgit v1.2.3 From 8ffc520f8f49397861899599c3ec9edf3ba79853 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Tue, 28 Aug 2018 13:57:58 -0700 Subject: Add label to :ref: to make Sphinx happy --- docs/narr/commandline.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst index 53e4ee31c..98e34fea2 100644 --- a/docs/narr/commandline.rst +++ b/docs/narr/commandline.rst @@ -43,7 +43,7 @@ Each of Pyramid's console scripts may be run by its name. For example: .. note:: ``$VENV/bin/`` is a convention we use to simplify Pyramid documentation. It represents the ``bin`` directory in a virtual environment, where ``$VENV`` is an environment variable representing its path. - See :ref:`installing_unix` and :ref:`venv-bin-pip-vs-source-bin-activate` for more information. + See :ref:`installing_unix` and :ref:`Why use $VENV/bin/pip instead of source bin/activate, then pip ` for more information. .. index:: -- cgit v1.2.3 From b14adf400cb70e02b7a4f3602cb2b6ca272ca40e Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Tue, 28 Aug 2018 17:13:05 -0700 Subject: Attempt to get Python 3.8 to build on Travis-CI --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 30e7e5b79..dcbd37294 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,8 +26,10 @@ matrix: env: TOXENV=py37 dist: xenial sudo: true - - python: nightly + - python: 3.8-dev env: TOXENV=py38 + dist: xenial + sudo: true allow_failures: - env: TOXENV=py38 -- cgit v1.2.3 From 61adead5482cdb6fc07921e8bff787b99c980e52 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 30 Aug 2018 02:11:38 -0700 Subject: Update wiki with zodb cookiecutter source files --- docs/tutorials/wiki/src/authorization/README.txt | 2 +- .../wiki/src/authorization/development.ini | 3 +++ .../tutorials/wiki/src/authorization/production.ini | 3 +++ docs/tutorials/wiki/src/authorization/setup.py | 2 +- .../src/authorization/tutorial/templates/edit.pt | 1 - docs/tutorials/wiki/src/basiclayout/development.ini | 3 +++ docs/tutorials/wiki/src/basiclayout/production.ini | 3 +++ docs/tutorials/wiki/src/basiclayout/setup.py | 2 +- docs/tutorials/wiki/src/installation/.gitignore | 21 +++++++++++++++++++++ .../tutorials/wiki/src/installation/development.ini | 3 +++ docs/tutorials/wiki/src/installation/production.ini | 3 +++ docs/tutorials/wiki/src/installation/setup.py | 2 +- .../wiki/src/installation/tutorial/pshell.py | 11 +++++++++++ docs/tutorials/wiki/src/models/development.ini | 3 +++ docs/tutorials/wiki/src/models/production.ini | 3 +++ docs/tutorials/wiki/src/models/setup.py | 2 +- docs/tutorials/wiki/src/tests/README.txt | 2 +- docs/tutorials/wiki/src/tests/development.ini | 3 +++ docs/tutorials/wiki/src/tests/production.ini | 3 +++ docs/tutorials/wiki/src/tests/setup.py | 2 +- docs/tutorials/wiki/src/views/README.txt | 2 +- docs/tutorials/wiki/src/views/development.ini | 3 +++ docs/tutorials/wiki/src/views/production.ini | 3 +++ docs/tutorials/wiki/src/views/setup.py | 2 +- 24 files changed, 77 insertions(+), 10 deletions(-) create mode 100644 docs/tutorials/wiki/src/installation/.gitignore create mode 100644 docs/tutorials/wiki/src/installation/tutorial/pshell.py diff --git a/docs/tutorials/wiki/src/authorization/README.txt b/docs/tutorials/wiki/src/authorization/README.txt index 5ec53bf9d..8a56d14af 100644 --- a/docs/tutorials/wiki/src/authorization/README.txt +++ b/docs/tutorials/wiki/src/authorization/README.txt @@ -14,7 +14,7 @@ Getting Started - Upgrade packaging tools. - env/bin/pip install --upgrade pip setuptools wheel + env/bin/pip install --upgrade pip setuptools - Install the project in editable mode with its testing requirements. diff --git a/docs/tutorials/wiki/src/authorization/development.ini b/docs/tutorials/wiki/src/authorization/development.ini index fec08941d..228f18f36 100644 --- a/docs/tutorials/wiki/src/authorization/development.ini +++ b/docs/tutorials/wiki/src/authorization/development.ini @@ -22,6 +22,9 @@ retry.attempts = 3 # '127.0.0.1' and '::1'. # debugtoolbar.hosts = 127.0.0.1 ::1 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki/src/authorization/production.ini b/docs/tutorials/wiki/src/authorization/production.ini index f2fa8d6d5..46b1e331b 100644 --- a/docs/tutorials/wiki/src/authorization/production.ini +++ b/docs/tutorials/wiki/src/authorization/production.ini @@ -16,6 +16,9 @@ zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 retry.attempts = 3 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki/src/authorization/setup.py b/docs/tutorials/wiki/src/authorization/setup.py index 3f0b1317c..7011387f6 100644 --- a/docs/tutorials/wiki/src/authorization/setup.py +++ b/docs/tutorials/wiki/src/authorization/setup.py @@ -25,7 +25,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt index 3ef0c7e0e..eedb83da4 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt +++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt @@ -23,7 +23,6 @@ -
diff --git a/docs/tutorials/wiki/src/basiclayout/development.ini b/docs/tutorials/wiki/src/basiclayout/development.ini index fec08941d..228f18f36 100644 --- a/docs/tutorials/wiki/src/basiclayout/development.ini +++ b/docs/tutorials/wiki/src/basiclayout/development.ini @@ -22,6 +22,9 @@ retry.attempts = 3 # '127.0.0.1' and '::1'. # debugtoolbar.hosts = 127.0.0.1 ::1 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki/src/basiclayout/production.ini b/docs/tutorials/wiki/src/basiclayout/production.ini index f2fa8d6d5..46b1e331b 100644 --- a/docs/tutorials/wiki/src/basiclayout/production.ini +++ b/docs/tutorials/wiki/src/basiclayout/production.ini @@ -16,6 +16,9 @@ zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 retry.attempts = 3 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki/src/basiclayout/setup.py b/docs/tutorials/wiki/src/basiclayout/setup.py index d743c984f..e05e279e2 100644 --- a/docs/tutorials/wiki/src/basiclayout/setup.py +++ b/docs/tutorials/wiki/src/basiclayout/setup.py @@ -23,7 +23,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/tutorials/wiki/src/installation/.gitignore b/docs/tutorials/wiki/src/installation/.gitignore new file mode 100644 index 000000000..1853d983c --- /dev/null +++ b/docs/tutorials/wiki/src/installation/.gitignore @@ -0,0 +1,21 @@ +*.egg +*.egg-info +*.pyc +*$py.class +*~ +.coverage +coverage.xml +build/ +dist/ +.tox/ +nosetests.xml +env*/ +tmp/ +Data.fs* +*.sublime-project +*.sublime-workspace +.*.sw? +.sw? +.DS_Store +coverage +test diff --git a/docs/tutorials/wiki/src/installation/development.ini b/docs/tutorials/wiki/src/installation/development.ini index fec08941d..228f18f36 100644 --- a/docs/tutorials/wiki/src/installation/development.ini +++ b/docs/tutorials/wiki/src/installation/development.ini @@ -22,6 +22,9 @@ retry.attempts = 3 # '127.0.0.1' and '::1'. # debugtoolbar.hosts = 127.0.0.1 ::1 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki/src/installation/production.ini b/docs/tutorials/wiki/src/installation/production.ini index f2fa8d6d5..46b1e331b 100644 --- a/docs/tutorials/wiki/src/installation/production.ini +++ b/docs/tutorials/wiki/src/installation/production.ini @@ -16,6 +16,9 @@ zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 retry.attempts = 3 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki/src/installation/setup.py b/docs/tutorials/wiki/src/installation/setup.py index d743c984f..e05e279e2 100644 --- a/docs/tutorials/wiki/src/installation/setup.py +++ b/docs/tutorials/wiki/src/installation/setup.py @@ -23,7 +23,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/tutorials/wiki/src/installation/tutorial/pshell.py b/docs/tutorials/wiki/src/installation/tutorial/pshell.py new file mode 100644 index 000000000..3d026291b --- /dev/null +++ b/docs/tutorials/wiki/src/installation/tutorial/pshell.py @@ -0,0 +1,11 @@ +from . import models + +def setup(env): + request = env['request'] + + # start a transaction + request.tm.begin() + + # inject some vars into the shell builtins + env['tm'] = request.tm + env['models'] = models diff --git a/docs/tutorials/wiki/src/models/development.ini b/docs/tutorials/wiki/src/models/development.ini index fec08941d..228f18f36 100644 --- a/docs/tutorials/wiki/src/models/development.ini +++ b/docs/tutorials/wiki/src/models/development.ini @@ -22,6 +22,9 @@ retry.attempts = 3 # '127.0.0.1' and '::1'. # debugtoolbar.hosts = 127.0.0.1 ::1 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki/src/models/production.ini b/docs/tutorials/wiki/src/models/production.ini index f2fa8d6d5..46b1e331b 100644 --- a/docs/tutorials/wiki/src/models/production.ini +++ b/docs/tutorials/wiki/src/models/production.ini @@ -16,6 +16,9 @@ zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 retry.attempts = 3 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki/src/models/setup.py b/docs/tutorials/wiki/src/models/setup.py index d743c984f..e05e279e2 100644 --- a/docs/tutorials/wiki/src/models/setup.py +++ b/docs/tutorials/wiki/src/models/setup.py @@ -23,7 +23,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/tutorials/wiki/src/tests/README.txt b/docs/tutorials/wiki/src/tests/README.txt index 5ec53bf9d..8a56d14af 100644 --- a/docs/tutorials/wiki/src/tests/README.txt +++ b/docs/tutorials/wiki/src/tests/README.txt @@ -14,7 +14,7 @@ Getting Started - Upgrade packaging tools. - env/bin/pip install --upgrade pip setuptools wheel + env/bin/pip install --upgrade pip setuptools - Install the project in editable mode with its testing requirements. diff --git a/docs/tutorials/wiki/src/tests/development.ini b/docs/tutorials/wiki/src/tests/development.ini index fec08941d..228f18f36 100644 --- a/docs/tutorials/wiki/src/tests/development.ini +++ b/docs/tutorials/wiki/src/tests/development.ini @@ -22,6 +22,9 @@ retry.attempts = 3 # '127.0.0.1' and '::1'. # debugtoolbar.hosts = 127.0.0.1 ::1 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki/src/tests/production.ini b/docs/tutorials/wiki/src/tests/production.ini index f2fa8d6d5..46b1e331b 100644 --- a/docs/tutorials/wiki/src/tests/production.ini +++ b/docs/tutorials/wiki/src/tests/production.ini @@ -16,6 +16,9 @@ zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 retry.attempts = 3 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki/src/tests/setup.py b/docs/tutorials/wiki/src/tests/setup.py index 3f0b1317c..7011387f6 100644 --- a/docs/tutorials/wiki/src/tests/setup.py +++ b/docs/tutorials/wiki/src/tests/setup.py @@ -25,7 +25,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/tutorials/wiki/src/views/README.txt b/docs/tutorials/wiki/src/views/README.txt index 5ec53bf9d..8a56d14af 100644 --- a/docs/tutorials/wiki/src/views/README.txt +++ b/docs/tutorials/wiki/src/views/README.txt @@ -14,7 +14,7 @@ Getting Started - Upgrade packaging tools. - env/bin/pip install --upgrade pip setuptools wheel + env/bin/pip install --upgrade pip setuptools - Install the project in editable mode with its testing requirements. diff --git a/docs/tutorials/wiki/src/views/development.ini b/docs/tutorials/wiki/src/views/development.ini index fec08941d..228f18f36 100644 --- a/docs/tutorials/wiki/src/views/development.ini +++ b/docs/tutorials/wiki/src/views/development.ini @@ -22,6 +22,9 @@ retry.attempts = 3 # '127.0.0.1' and '::1'. # debugtoolbar.hosts = 127.0.0.1 ::1 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki/src/views/production.ini b/docs/tutorials/wiki/src/views/production.ini index f2fa8d6d5..46b1e331b 100644 --- a/docs/tutorials/wiki/src/views/production.ini +++ b/docs/tutorials/wiki/src/views/production.ini @@ -16,6 +16,9 @@ zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 retry.attempts = 3 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki/src/views/setup.py b/docs/tutorials/wiki/src/views/setup.py index bd3d15af1..a11ae6c8f 100644 --- a/docs/tutorials/wiki/src/views/setup.py +++ b/docs/tutorials/wiki/src/views/setup.py @@ -24,7 +24,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] -- cgit v1.2.3 From 160e802545a3f42134fbd88f1d71dd7c15fd3ba7 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 30 Aug 2018 02:17:37 -0700 Subject: Update wiki with zodb cookiecutter source files --- docs/tutorials/wiki/authorization.rst | 6 +++--- docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt | 1 - docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt | 1 - docs/tutorials/wiki/src/tests/tutorial/templates/view.pt | 1 - 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/docs/tutorials/wiki/authorization.rst b/docs/tutorials/wiki/authorization.rst index a2e61e632..b7eeb19ae 100644 --- a/docs/tutorials/wiki/authorization.rst +++ b/docs/tutorials/wiki/authorization.rst @@ -312,7 +312,7 @@ indicated by the highlighted lines. .. literalinclude:: src/authorization/tutorial/templates/edit.pt :lines: 35-39 - :emphasize-lines: 3-5 + :emphasize-lines: 2-4 :language: html The attribute ``tal:condition="logged_in"`` will make the element be included @@ -355,7 +355,7 @@ we're done: .. literalinclude:: src/authorization/tutorial/templates/edit.pt :linenos: - :emphasize-lines: 37-39 + :emphasize-lines: 36-38 :language: html Only the highlighted lines need to be added or edited. @@ -365,7 +365,7 @@ we're done: .. literalinclude:: src/authorization/tutorial/templates/view.pt :linenos: - :emphasize-lines: 37-39 + :emphasize-lines: 36-38 :language: html Only the highlighted lines need to be added or edited. diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt index 5d9478fb9..f2a9249ef 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt +++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt @@ -23,7 +23,6 @@ -
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt index 3ef0c7e0e..eedb83da4 100644 --- a/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt +++ b/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt @@ -23,7 +23,6 @@ -
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt index 5d9478fb9..f2a9249ef 100644 --- a/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt +++ b/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt @@ -23,7 +23,6 @@ -
-- cgit v1.2.3 From 6cadff5aca91a799e69d641625d16280791653f6 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 30 Aug 2018 02:18:47 -0700 Subject: Update wiki with zodb cookiecutter source files --- docs/tutorials/wiki/src/authorization/.gitignore | 21 +++++++++++++++++++++ .../wiki/src/authorization/tutorial/pshell.py | 11 +++++++++++ docs/tutorials/wiki/src/basiclayout/.gitignore | 21 +++++++++++++++++++++ .../wiki/src/basiclayout/tutorial/pshell.py | 11 +++++++++++ docs/tutorials/wiki/src/models/.gitignore | 21 +++++++++++++++++++++ docs/tutorials/wiki/src/models/tutorial/pshell.py | 11 +++++++++++ docs/tutorials/wiki/src/tests/.gitignore | 21 +++++++++++++++++++++ docs/tutorials/wiki/src/tests/tutorial/pshell.py | 11 +++++++++++ docs/tutorials/wiki/src/views/.gitignore | 21 +++++++++++++++++++++ docs/tutorials/wiki/src/views/tutorial/pshell.py | 11 +++++++++++ 10 files changed, 160 insertions(+) create mode 100644 docs/tutorials/wiki/src/authorization/.gitignore create mode 100644 docs/tutorials/wiki/src/authorization/tutorial/pshell.py create mode 100644 docs/tutorials/wiki/src/basiclayout/.gitignore create mode 100644 docs/tutorials/wiki/src/basiclayout/tutorial/pshell.py create mode 100644 docs/tutorials/wiki/src/models/.gitignore create mode 100644 docs/tutorials/wiki/src/models/tutorial/pshell.py create mode 100644 docs/tutorials/wiki/src/tests/.gitignore create mode 100644 docs/tutorials/wiki/src/tests/tutorial/pshell.py create mode 100644 docs/tutorials/wiki/src/views/.gitignore create mode 100644 docs/tutorials/wiki/src/views/tutorial/pshell.py diff --git a/docs/tutorials/wiki/src/authorization/.gitignore b/docs/tutorials/wiki/src/authorization/.gitignore new file mode 100644 index 000000000..1853d983c --- /dev/null +++ b/docs/tutorials/wiki/src/authorization/.gitignore @@ -0,0 +1,21 @@ +*.egg +*.egg-info +*.pyc +*$py.class +*~ +.coverage +coverage.xml +build/ +dist/ +.tox/ +nosetests.xml +env*/ +tmp/ +Data.fs* +*.sublime-project +*.sublime-workspace +.*.sw? +.sw? +.DS_Store +coverage +test diff --git a/docs/tutorials/wiki/src/authorization/tutorial/pshell.py b/docs/tutorials/wiki/src/authorization/tutorial/pshell.py new file mode 100644 index 000000000..3d026291b --- /dev/null +++ b/docs/tutorials/wiki/src/authorization/tutorial/pshell.py @@ -0,0 +1,11 @@ +from . import models + +def setup(env): + request = env['request'] + + # start a transaction + request.tm.begin() + + # inject some vars into the shell builtins + env['tm'] = request.tm + env['models'] = models diff --git a/docs/tutorials/wiki/src/basiclayout/.gitignore b/docs/tutorials/wiki/src/basiclayout/.gitignore new file mode 100644 index 000000000..1853d983c --- /dev/null +++ b/docs/tutorials/wiki/src/basiclayout/.gitignore @@ -0,0 +1,21 @@ +*.egg +*.egg-info +*.pyc +*$py.class +*~ +.coverage +coverage.xml +build/ +dist/ +.tox/ +nosetests.xml +env*/ +tmp/ +Data.fs* +*.sublime-project +*.sublime-workspace +.*.sw? +.sw? +.DS_Store +coverage +test diff --git a/docs/tutorials/wiki/src/basiclayout/tutorial/pshell.py b/docs/tutorials/wiki/src/basiclayout/tutorial/pshell.py new file mode 100644 index 000000000..3d026291b --- /dev/null +++ b/docs/tutorials/wiki/src/basiclayout/tutorial/pshell.py @@ -0,0 +1,11 @@ +from . import models + +def setup(env): + request = env['request'] + + # start a transaction + request.tm.begin() + + # inject some vars into the shell builtins + env['tm'] = request.tm + env['models'] = models diff --git a/docs/tutorials/wiki/src/models/.gitignore b/docs/tutorials/wiki/src/models/.gitignore new file mode 100644 index 000000000..1853d983c --- /dev/null +++ b/docs/tutorials/wiki/src/models/.gitignore @@ -0,0 +1,21 @@ +*.egg +*.egg-info +*.pyc +*$py.class +*~ +.coverage +coverage.xml +build/ +dist/ +.tox/ +nosetests.xml +env*/ +tmp/ +Data.fs* +*.sublime-project +*.sublime-workspace +.*.sw? +.sw? +.DS_Store +coverage +test diff --git a/docs/tutorials/wiki/src/models/tutorial/pshell.py b/docs/tutorials/wiki/src/models/tutorial/pshell.py new file mode 100644 index 000000000..3d026291b --- /dev/null +++ b/docs/tutorials/wiki/src/models/tutorial/pshell.py @@ -0,0 +1,11 @@ +from . import models + +def setup(env): + request = env['request'] + + # start a transaction + request.tm.begin() + + # inject some vars into the shell builtins + env['tm'] = request.tm + env['models'] = models diff --git a/docs/tutorials/wiki/src/tests/.gitignore b/docs/tutorials/wiki/src/tests/.gitignore new file mode 100644 index 000000000..1853d983c --- /dev/null +++ b/docs/tutorials/wiki/src/tests/.gitignore @@ -0,0 +1,21 @@ +*.egg +*.egg-info +*.pyc +*$py.class +*~ +.coverage +coverage.xml +build/ +dist/ +.tox/ +nosetests.xml +env*/ +tmp/ +Data.fs* +*.sublime-project +*.sublime-workspace +.*.sw? +.sw? +.DS_Store +coverage +test diff --git a/docs/tutorials/wiki/src/tests/tutorial/pshell.py b/docs/tutorials/wiki/src/tests/tutorial/pshell.py new file mode 100644 index 000000000..3d026291b --- /dev/null +++ b/docs/tutorials/wiki/src/tests/tutorial/pshell.py @@ -0,0 +1,11 @@ +from . import models + +def setup(env): + request = env['request'] + + # start a transaction + request.tm.begin() + + # inject some vars into the shell builtins + env['tm'] = request.tm + env['models'] = models diff --git a/docs/tutorials/wiki/src/views/.gitignore b/docs/tutorials/wiki/src/views/.gitignore new file mode 100644 index 000000000..1853d983c --- /dev/null +++ b/docs/tutorials/wiki/src/views/.gitignore @@ -0,0 +1,21 @@ +*.egg +*.egg-info +*.pyc +*$py.class +*~ +.coverage +coverage.xml +build/ +dist/ +.tox/ +nosetests.xml +env*/ +tmp/ +Data.fs* +*.sublime-project +*.sublime-workspace +.*.sw? +.sw? +.DS_Store +coverage +test diff --git a/docs/tutorials/wiki/src/views/tutorial/pshell.py b/docs/tutorials/wiki/src/views/tutorial/pshell.py new file mode 100644 index 000000000..3d026291b --- /dev/null +++ b/docs/tutorials/wiki/src/views/tutorial/pshell.py @@ -0,0 +1,11 @@ +from . import models + +def setup(env): + request = env['request'] + + # start a transaction + request.tm.begin() + + # inject some vars into the shell builtins + env['tm'] = request.tm + env['models'] = models -- cgit v1.2.3 From 7633490dd5c70ce93c94c62e08b1a80f8cc2bf6f Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 30 Aug 2018 02:30:59 -0700 Subject: Remove unused template --- .../src/tests/tutorial/templates/mytemplate.pt | 67 ---------------------- 1 file changed, 67 deletions(-) delete mode 100644 docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt deleted file mode 100644 index 1d33787d9..000000000 --- a/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - ZODB Scaffold for The Pyramid Web Framework - - - - - - - - - - - - - -
-
-
-
- -
-
-
-

Pyramid ZODB scaffold

-

Welcome to ${project}, an application generated by
the Pyramid Web Framework 1.7.

-
-
-
-
- -
-
- -
-
-
- - - - - - - - -- cgit v1.2.3 From 9a9ea6a2c050c1ad5044df34b49026af016c463a Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 30 Aug 2018 02:51:26 -0700 Subject: Update wiki2 with alchemy cookiecutter source files --- docs/tutorials/wiki2/basiclayout.rst | 2 +- .../wiki2/src/authentication/development.ini | 5 ++++- .../wiki2/src/authentication/production.ini | 3 +++ docs/tutorials/wiki2/src/authentication/setup.py | 2 +- .../wiki2/src/authentication/tutorial/__init__.py | 12 +++++----- .../wiki2/src/authentication/tutorial/pshell.py | 12 ++++++++++ .../tutorial/scripts/initialize_db.py | 22 +++++++++--------- .../wiki2/src/authorization/development.ini | 5 ++++- .../wiki2/src/authorization/production.ini | 3 +++ docs/tutorials/wiki2/src/authorization/setup.py | 2 +- .../wiki2/src/authorization/tutorial/__init__.py | 12 +++++----- .../wiki2/src/authorization/tutorial/pshell.py | 12 ++++++++++ .../tutorial/scripts/initialize_db.py | 22 +++++++++--------- .../wiki2/src/basiclayout/development.ini | 5 ++++- .../tutorials/wiki2/src/basiclayout/production.ini | 3 +++ docs/tutorials/wiki2/src/basiclayout/setup.py | 2 +- .../wiki2/src/basiclayout/tutorial/__init__.py | 10 ++++----- .../wiki2/src/basiclayout/tutorial/pshell.py | 12 ++++++++++ .../basiclayout/tutorial/scripts/initialize_db.py | 26 +++++++++++++--------- .../wiki2/src/installation/development.ini | 5 ++++- .../wiki2/src/installation/production.ini | 3 +++ docs/tutorials/wiki2/src/installation/setup.py | 2 +- .../wiki2/src/installation/tutorial/__init__.py | 10 ++++----- .../wiki2/src/installation/tutorial/pshell.py | 12 ++++++++++ .../installation/tutorial/scripts/initialize_db.py | 26 +++++++++++++--------- docs/tutorials/wiki2/src/models/development.ini | 5 ++++- docs/tutorials/wiki2/src/models/production.ini | 3 +++ docs/tutorials/wiki2/src/models/setup.py | 2 +- .../wiki2/src/models/tutorial/__init__.py | 10 ++++----- docs/tutorials/wiki2/src/models/tutorial/pshell.py | 12 ++++++++++ .../src/models/tutorial/scripts/initialize_db.py | 22 +++++++++--------- docs/tutorials/wiki2/src/tests/development.ini | 5 ++++- docs/tutorials/wiki2/src/tests/production.ini | 3 +++ docs/tutorials/wiki2/src/tests/setup.py | 2 +- .../tutorials/wiki2/src/tests/tutorial/__init__.py | 12 +++++----- docs/tutorials/wiki2/src/tests/tutorial/pshell.py | 12 ++++++++++ .../src/tests/tutorial/scripts/initialize_db.py | 22 +++++++++--------- docs/tutorials/wiki2/src/views/development.ini | 5 ++++- docs/tutorials/wiki2/src/views/production.ini | 3 +++ docs/tutorials/wiki2/src/views/setup.py | 2 +- .../tutorials/wiki2/src/views/tutorial/__init__.py | 10 ++++----- docs/tutorials/wiki2/src/views/tutorial/pshell.py | 12 ++++++++++ .../src/views/tutorial/scripts/initialize_db.py | 22 +++++++++--------- 43 files changed, 264 insertions(+), 130 deletions(-) create mode 100644 docs/tutorials/wiki2/src/authentication/tutorial/pshell.py create mode 100644 docs/tutorials/wiki2/src/authorization/tutorial/pshell.py create mode 100644 docs/tutorials/wiki2/src/basiclayout/tutorial/pshell.py create mode 100644 docs/tutorials/wiki2/src/installation/tutorial/pshell.py create mode 100644 docs/tutorials/wiki2/src/models/tutorial/pshell.py create mode 100644 docs/tutorials/wiki2/src/tests/tutorial/pshell.py create mode 100644 docs/tutorials/wiki2/src/views/tutorial/pshell.py diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst index 313b5998e..671893b5f 100644 --- a/docs/tutorials/wiki2/basiclayout.rst +++ b/docs/tutorials/wiki2/basiclayout.rst @@ -44,7 +44,7 @@ When you invoke the ``pserve development.ini`` command, the ``main`` function above is executed. It accepts some settings and returns a :term:`WSGI` application. (See :ref:`startup_chapter` for more about ``pserve``.) -Next in ``main``, construct a :term:`Configurator` object: +Next in ``main``, construct a :term:`Configurator` object using a context manager: .. literalinclude:: src/basiclayout/tutorial/__init__.py :lines: 7 diff --git a/docs/tutorials/wiki2/src/authentication/development.ini b/docs/tutorials/wiki2/src/authentication/development.ini index d76a6cd72..8fbb5fd38 100644 --- a/docs/tutorials/wiki2/src/authentication/development.ini +++ b/docs/tutorials/wiki2/src/authentication/development.ini @@ -24,6 +24,9 @@ auth.secret = seekrit # '127.0.0.1' and '::1'. # debugtoolbar.hosts = 127.0.0.1 ::1 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### @@ -62,7 +65,7 @@ handlers = qualname = tutorial [logger_sqlalchemy] -level = INFO +level = WARN handlers = qualname = sqlalchemy.engine # "level = INFO" logs SQL queries. diff --git a/docs/tutorials/wiki2/src/authentication/production.ini b/docs/tutorials/wiki2/src/authentication/production.ini index c46adb7b5..9fef64f83 100644 --- a/docs/tutorials/wiki2/src/authentication/production.ini +++ b/docs/tutorials/wiki2/src/authentication/production.ini @@ -18,6 +18,9 @@ retry.attempts = 3 auth.secret = real-seekrit +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki2/src/authentication/setup.py b/docs/tutorials/wiki2/src/authentication/setup.py index 28b766cbe..e2a30c0e7 100644 --- a/docs/tutorials/wiki2/src/authentication/setup.py +++ b/docs/tutorials/wiki2/src/authentication/setup.py @@ -26,7 +26,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/tutorials/wiki2/src/authentication/tutorial/__init__.py b/docs/tutorials/wiki2/src/authentication/tutorial/__init__.py index f5c033b8b..5d4bae3d7 100644 --- a/docs/tutorials/wiki2/src/authentication/tutorial/__init__.py +++ b/docs/tutorials/wiki2/src/authentication/tutorial/__init__.py @@ -4,10 +4,10 @@ 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.include('.security') - config.scan() + with Configurator(settings=settings) as config: + config.include('pyramid_jinja2') + config.include('.models') + config.include('.routes') + config.include('.security') + config.scan() return config.make_wsgi_app() diff --git a/docs/tutorials/wiki2/src/authentication/tutorial/pshell.py b/docs/tutorials/wiki2/src/authentication/tutorial/pshell.py new file mode 100644 index 000000000..108c04d5e --- /dev/null +++ b/docs/tutorials/wiki2/src/authentication/tutorial/pshell.py @@ -0,0 +1,12 @@ +from . import models + +def setup(env): + request = env['request'] + + # start a transaction + request.tm.begin() + + # inject some vars into the shell builtins + env['tm'] = request.tm + env['dbsession'] = request.dbsession + env['models'] = models diff --git a/docs/tutorials/wiki2/src/authentication/tutorial/scripts/initialize_db.py b/docs/tutorials/wiki2/src/authentication/tutorial/scripts/initialize_db.py index 231d5d44b..e6350fb36 100644 --- a/docs/tutorials/wiki2/src/authentication/tutorial/scripts/initialize_db.py +++ b/docs/tutorials/wiki2/src/authentication/tutorial/scripts/initialize_db.py @@ -1,4 +1,4 @@ -import os +import argparse import sys from pyramid.paster import bootstrap, setup_logging @@ -24,19 +24,19 @@ def setup_models(dbsession): dbsession.add(page) -def usage(argv): - cmd = os.path.basename(argv[0]) - print('usage: %s \n' - '(example: "%s development.ini")' % (cmd, cmd)) - sys.exit(1) +def parse_args(argv): + parser = argparse.ArgumentParser() + parser.add_argument( + 'config_uri', + help='Configuration file, e.g., development.ini', + ) + return parser.parse_args(argv[1:]) def main(argv=sys.argv): - if len(argv) != 2: - usage(argv) - config_uri = argv[1] - setup_logging(config_uri) - env = bootstrap(config_uri) + args = parse_args(argv) + setup_logging(args.config_uri) + env = bootstrap(args.config_uri) try: with env['request'].tm: diff --git a/docs/tutorials/wiki2/src/authorization/development.ini b/docs/tutorials/wiki2/src/authorization/development.ini index d76a6cd72..8fbb5fd38 100644 --- a/docs/tutorials/wiki2/src/authorization/development.ini +++ b/docs/tutorials/wiki2/src/authorization/development.ini @@ -24,6 +24,9 @@ auth.secret = seekrit # '127.0.0.1' and '::1'. # debugtoolbar.hosts = 127.0.0.1 ::1 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### @@ -62,7 +65,7 @@ handlers = qualname = tutorial [logger_sqlalchemy] -level = INFO +level = WARN handlers = qualname = sqlalchemy.engine # "level = INFO" logs SQL queries. diff --git a/docs/tutorials/wiki2/src/authorization/production.ini b/docs/tutorials/wiki2/src/authorization/production.ini index c46adb7b5..9fef64f83 100644 --- a/docs/tutorials/wiki2/src/authorization/production.ini +++ b/docs/tutorials/wiki2/src/authorization/production.ini @@ -18,6 +18,9 @@ retry.attempts = 3 auth.secret = real-seekrit +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki2/src/authorization/setup.py b/docs/tutorials/wiki2/src/authorization/setup.py index 28b766cbe..e2a30c0e7 100644 --- a/docs/tutorials/wiki2/src/authorization/setup.py +++ b/docs/tutorials/wiki2/src/authorization/setup.py @@ -26,7 +26,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py b/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py index f5c033b8b..5d4bae3d7 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py +++ b/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py @@ -4,10 +4,10 @@ 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.include('.security') - config.scan() + with Configurator(settings=settings) as config: + config.include('pyramid_jinja2') + config.include('.models') + config.include('.routes') + config.include('.security') + config.scan() return config.make_wsgi_app() diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/pshell.py b/docs/tutorials/wiki2/src/authorization/tutorial/pshell.py new file mode 100644 index 000000000..108c04d5e --- /dev/null +++ b/docs/tutorials/wiki2/src/authorization/tutorial/pshell.py @@ -0,0 +1,12 @@ +from . import models + +def setup(env): + request = env['request'] + + # start a transaction + request.tm.begin() + + # inject some vars into the shell builtins + env['tm'] = request.tm + env['dbsession'] = request.dbsession + env['models'] = models diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initialize_db.py b/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initialize_db.py index 231d5d44b..e6350fb36 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initialize_db.py +++ b/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initialize_db.py @@ -1,4 +1,4 @@ -import os +import argparse import sys from pyramid.paster import bootstrap, setup_logging @@ -24,19 +24,19 @@ def setup_models(dbsession): dbsession.add(page) -def usage(argv): - cmd = os.path.basename(argv[0]) - print('usage: %s \n' - '(example: "%s development.ini")' % (cmd, cmd)) - sys.exit(1) +def parse_args(argv): + parser = argparse.ArgumentParser() + parser.add_argument( + 'config_uri', + help='Configuration file, e.g., development.ini', + ) + return parser.parse_args(argv[1:]) def main(argv=sys.argv): - if len(argv) != 2: - usage(argv) - config_uri = argv[1] - setup_logging(config_uri) - env = bootstrap(config_uri) + args = parse_args(argv) + setup_logging(args.config_uri) + env = bootstrap(args.config_uri) try: with env['request'].tm: diff --git a/docs/tutorials/wiki2/src/basiclayout/development.ini b/docs/tutorials/wiki2/src/basiclayout/development.ini index ee050c0ea..564aefb56 100644 --- a/docs/tutorials/wiki2/src/basiclayout/development.ini +++ b/docs/tutorials/wiki2/src/basiclayout/development.ini @@ -22,6 +22,9 @@ retry.attempts = 3 # '127.0.0.1' and '::1'. # debugtoolbar.hosts = 127.0.0.1 ::1 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### @@ -60,7 +63,7 @@ handlers = qualname = tutorial [logger_sqlalchemy] -level = INFO +level = WARN handlers = qualname = sqlalchemy.engine # "level = INFO" logs SQL queries. diff --git a/docs/tutorials/wiki2/src/basiclayout/production.ini b/docs/tutorials/wiki2/src/basiclayout/production.ini index 91d0f5ddb..29cdda1e1 100644 --- a/docs/tutorials/wiki2/src/basiclayout/production.ini +++ b/docs/tutorials/wiki2/src/basiclayout/production.ini @@ -16,6 +16,9 @@ sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite retry.attempts = 3 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki2/src/basiclayout/setup.py b/docs/tutorials/wiki2/src/basiclayout/setup.py index e0cc964fe..11725dd51 100644 --- a/docs/tutorials/wiki2/src/basiclayout/setup.py +++ b/docs/tutorials/wiki2/src/basiclayout/setup.py @@ -24,7 +24,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py index 4dab44823..28bd1f80d 100644 --- a/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py +++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py @@ -4,9 +4,9 @@ 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() + with Configurator(settings=settings) as config: + config.include('pyramid_jinja2') + config.include('.models') + config.include('.routes') + config.scan() return config.make_wsgi_app() diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/pshell.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/pshell.py new file mode 100644 index 000000000..108c04d5e --- /dev/null +++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/pshell.py @@ -0,0 +1,12 @@ +from . import models + +def setup(env): + request = env['request'] + + # start a transaction + request.tm.begin() + + # inject some vars into the shell builtins + env['tm'] = request.tm + env['dbsession'] = request.dbsession + env['models'] = models diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initialize_db.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initialize_db.py index b882f9bf7..c629d1780 100644 --- a/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initialize_db.py +++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initialize_db.py @@ -1,4 +1,4 @@ -import os +import argparse import sys from pyramid.paster import bootstrap, setup_logging @@ -8,23 +8,27 @@ from .. import models def setup_models(dbsession): + """ + Add or update models / fixtures in the database. + + """ model = models.mymodel.MyModel(name='one', value=1) dbsession.add(model) -def usage(argv): - cmd = os.path.basename(argv[0]) - print('usage: %s \n' - '(example: "%s development.ini")' % (cmd, cmd)) - sys.exit(1) +def parse_args(argv): + parser = argparse.ArgumentParser() + parser.add_argument( + 'config_uri', + help='Configuration file, e.g., development.ini', + ) + return parser.parse_args(argv[1:]) def main(argv=sys.argv): - if len(argv) != 2: - usage(argv) - config_uri = argv[1] - setup_logging(config_uri) - env = bootstrap(config_uri) + args = parse_args(argv) + setup_logging(args.config_uri) + env = bootstrap(args.config_uri) try: with env['request'].tm: diff --git a/docs/tutorials/wiki2/src/installation/development.ini b/docs/tutorials/wiki2/src/installation/development.ini index ee050c0ea..564aefb56 100644 --- a/docs/tutorials/wiki2/src/installation/development.ini +++ b/docs/tutorials/wiki2/src/installation/development.ini @@ -22,6 +22,9 @@ retry.attempts = 3 # '127.0.0.1' and '::1'. # debugtoolbar.hosts = 127.0.0.1 ::1 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### @@ -60,7 +63,7 @@ handlers = qualname = tutorial [logger_sqlalchemy] -level = INFO +level = WARN handlers = qualname = sqlalchemy.engine # "level = INFO" logs SQL queries. diff --git a/docs/tutorials/wiki2/src/installation/production.ini b/docs/tutorials/wiki2/src/installation/production.ini index 91d0f5ddb..29cdda1e1 100644 --- a/docs/tutorials/wiki2/src/installation/production.ini +++ b/docs/tutorials/wiki2/src/installation/production.ini @@ -16,6 +16,9 @@ sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite retry.attempts = 3 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki2/src/installation/setup.py b/docs/tutorials/wiki2/src/installation/setup.py index e0cc964fe..11725dd51 100644 --- a/docs/tutorials/wiki2/src/installation/setup.py +++ b/docs/tutorials/wiki2/src/installation/setup.py @@ -24,7 +24,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/tutorials/wiki2/src/installation/tutorial/__init__.py b/docs/tutorials/wiki2/src/installation/tutorial/__init__.py index 4dab44823..28bd1f80d 100644 --- a/docs/tutorials/wiki2/src/installation/tutorial/__init__.py +++ b/docs/tutorials/wiki2/src/installation/tutorial/__init__.py @@ -4,9 +4,9 @@ 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() + with Configurator(settings=settings) as config: + config.include('pyramid_jinja2') + config.include('.models') + config.include('.routes') + config.scan() return config.make_wsgi_app() diff --git a/docs/tutorials/wiki2/src/installation/tutorial/pshell.py b/docs/tutorials/wiki2/src/installation/tutorial/pshell.py new file mode 100644 index 000000000..108c04d5e --- /dev/null +++ b/docs/tutorials/wiki2/src/installation/tutorial/pshell.py @@ -0,0 +1,12 @@ +from . import models + +def setup(env): + request = env['request'] + + # start a transaction + request.tm.begin() + + # inject some vars into the shell builtins + env['tm'] = request.tm + env['dbsession'] = request.dbsession + env['models'] = models diff --git a/docs/tutorials/wiki2/src/installation/tutorial/scripts/initialize_db.py b/docs/tutorials/wiki2/src/installation/tutorial/scripts/initialize_db.py index b882f9bf7..c629d1780 100644 --- a/docs/tutorials/wiki2/src/installation/tutorial/scripts/initialize_db.py +++ b/docs/tutorials/wiki2/src/installation/tutorial/scripts/initialize_db.py @@ -1,4 +1,4 @@ -import os +import argparse import sys from pyramid.paster import bootstrap, setup_logging @@ -8,23 +8,27 @@ from .. import models def setup_models(dbsession): + """ + Add or update models / fixtures in the database. + + """ model = models.mymodel.MyModel(name='one', value=1) dbsession.add(model) -def usage(argv): - cmd = os.path.basename(argv[0]) - print('usage: %s \n' - '(example: "%s development.ini")' % (cmd, cmd)) - sys.exit(1) +def parse_args(argv): + parser = argparse.ArgumentParser() + parser.add_argument( + 'config_uri', + help='Configuration file, e.g., development.ini', + ) + return parser.parse_args(argv[1:]) def main(argv=sys.argv): - if len(argv) != 2: - usage(argv) - config_uri = argv[1] - setup_logging(config_uri) - env = bootstrap(config_uri) + args = parse_args(argv) + setup_logging(args.config_uri) + env = bootstrap(args.config_uri) try: with env['request'].tm: diff --git a/docs/tutorials/wiki2/src/models/development.ini b/docs/tutorials/wiki2/src/models/development.ini index ee050c0ea..564aefb56 100644 --- a/docs/tutorials/wiki2/src/models/development.ini +++ b/docs/tutorials/wiki2/src/models/development.ini @@ -22,6 +22,9 @@ retry.attempts = 3 # '127.0.0.1' and '::1'. # debugtoolbar.hosts = 127.0.0.1 ::1 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### @@ -60,7 +63,7 @@ handlers = qualname = tutorial [logger_sqlalchemy] -level = INFO +level = WARN handlers = qualname = sqlalchemy.engine # "level = INFO" logs SQL queries. diff --git a/docs/tutorials/wiki2/src/models/production.ini b/docs/tutorials/wiki2/src/models/production.ini index 91d0f5ddb..29cdda1e1 100644 --- a/docs/tutorials/wiki2/src/models/production.ini +++ b/docs/tutorials/wiki2/src/models/production.ini @@ -16,6 +16,9 @@ sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite retry.attempts = 3 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki2/src/models/setup.py b/docs/tutorials/wiki2/src/models/setup.py index 2576cc848..09e3126ea 100644 --- a/docs/tutorials/wiki2/src/models/setup.py +++ b/docs/tutorials/wiki2/src/models/setup.py @@ -25,7 +25,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/tutorials/wiki2/src/models/tutorial/__init__.py b/docs/tutorials/wiki2/src/models/tutorial/__init__.py index 4dab44823..28bd1f80d 100644 --- a/docs/tutorials/wiki2/src/models/tutorial/__init__.py +++ b/docs/tutorials/wiki2/src/models/tutorial/__init__.py @@ -4,9 +4,9 @@ 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() + with Configurator(settings=settings) as config: + config.include('pyramid_jinja2') + config.include('.models') + config.include('.routes') + config.scan() return config.make_wsgi_app() diff --git a/docs/tutorials/wiki2/src/models/tutorial/pshell.py b/docs/tutorials/wiki2/src/models/tutorial/pshell.py new file mode 100644 index 000000000..108c04d5e --- /dev/null +++ b/docs/tutorials/wiki2/src/models/tutorial/pshell.py @@ -0,0 +1,12 @@ +from . import models + +def setup(env): + request = env['request'] + + # start a transaction + request.tm.begin() + + # inject some vars into the shell builtins + env['tm'] = request.tm + env['dbsession'] = request.dbsession + env['models'] = models diff --git a/docs/tutorials/wiki2/src/models/tutorial/scripts/initialize_db.py b/docs/tutorials/wiki2/src/models/tutorial/scripts/initialize_db.py index 231d5d44b..e6350fb36 100644 --- a/docs/tutorials/wiki2/src/models/tutorial/scripts/initialize_db.py +++ b/docs/tutorials/wiki2/src/models/tutorial/scripts/initialize_db.py @@ -1,4 +1,4 @@ -import os +import argparse import sys from pyramid.paster import bootstrap, setup_logging @@ -24,19 +24,19 @@ def setup_models(dbsession): dbsession.add(page) -def usage(argv): - cmd = os.path.basename(argv[0]) - print('usage: %s \n' - '(example: "%s development.ini")' % (cmd, cmd)) - sys.exit(1) +def parse_args(argv): + parser = argparse.ArgumentParser() + parser.add_argument( + 'config_uri', + help='Configuration file, e.g., development.ini', + ) + return parser.parse_args(argv[1:]) def main(argv=sys.argv): - if len(argv) != 2: - usage(argv) - config_uri = argv[1] - setup_logging(config_uri) - env = bootstrap(config_uri) + args = parse_args(argv) + setup_logging(args.config_uri) + env = bootstrap(args.config_uri) try: with env['request'].tm: diff --git a/docs/tutorials/wiki2/src/tests/development.ini b/docs/tutorials/wiki2/src/tests/development.ini index d76a6cd72..8fbb5fd38 100644 --- a/docs/tutorials/wiki2/src/tests/development.ini +++ b/docs/tutorials/wiki2/src/tests/development.ini @@ -24,6 +24,9 @@ auth.secret = seekrit # '127.0.0.1' and '::1'. # debugtoolbar.hosts = 127.0.0.1 ::1 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### @@ -62,7 +65,7 @@ handlers = qualname = tutorial [logger_sqlalchemy] -level = INFO +level = WARN handlers = qualname = sqlalchemy.engine # "level = INFO" logs SQL queries. diff --git a/docs/tutorials/wiki2/src/tests/production.ini b/docs/tutorials/wiki2/src/tests/production.ini index c46adb7b5..9fef64f83 100644 --- a/docs/tutorials/wiki2/src/tests/production.ini +++ b/docs/tutorials/wiki2/src/tests/production.ini @@ -18,6 +18,9 @@ retry.attempts = 3 auth.secret = real-seekrit +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki2/src/tests/setup.py b/docs/tutorials/wiki2/src/tests/setup.py index 28b766cbe..e2a30c0e7 100644 --- a/docs/tutorials/wiki2/src/tests/setup.py +++ b/docs/tutorials/wiki2/src/tests/setup.py @@ -26,7 +26,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/tutorials/wiki2/src/tests/tutorial/__init__.py b/docs/tutorials/wiki2/src/tests/tutorial/__init__.py index f5c033b8b..5d4bae3d7 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/__init__.py +++ b/docs/tutorials/wiki2/src/tests/tutorial/__init__.py @@ -4,10 +4,10 @@ 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.include('.security') - config.scan() + with Configurator(settings=settings) as config: + config.include('pyramid_jinja2') + config.include('.models') + config.include('.routes') + config.include('.security') + config.scan() return config.make_wsgi_app() diff --git a/docs/tutorials/wiki2/src/tests/tutorial/pshell.py b/docs/tutorials/wiki2/src/tests/tutorial/pshell.py new file mode 100644 index 000000000..108c04d5e --- /dev/null +++ b/docs/tutorials/wiki2/src/tests/tutorial/pshell.py @@ -0,0 +1,12 @@ +from . import models + +def setup(env): + request = env['request'] + + # start a transaction + request.tm.begin() + + # inject some vars into the shell builtins + env['tm'] = request.tm + env['dbsession'] = request.dbsession + env['models'] = models diff --git a/docs/tutorials/wiki2/src/tests/tutorial/scripts/initialize_db.py b/docs/tutorials/wiki2/src/tests/tutorial/scripts/initialize_db.py index 231d5d44b..e6350fb36 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/scripts/initialize_db.py +++ b/docs/tutorials/wiki2/src/tests/tutorial/scripts/initialize_db.py @@ -1,4 +1,4 @@ -import os +import argparse import sys from pyramid.paster import bootstrap, setup_logging @@ -24,19 +24,19 @@ def setup_models(dbsession): dbsession.add(page) -def usage(argv): - cmd = os.path.basename(argv[0]) - print('usage: %s \n' - '(example: "%s development.ini")' % (cmd, cmd)) - sys.exit(1) +def parse_args(argv): + parser = argparse.ArgumentParser() + parser.add_argument( + 'config_uri', + help='Configuration file, e.g., development.ini', + ) + return parser.parse_args(argv[1:]) def main(argv=sys.argv): - if len(argv) != 2: - usage(argv) - config_uri = argv[1] - setup_logging(config_uri) - env = bootstrap(config_uri) + args = parse_args(argv) + setup_logging(args.config_uri) + env = bootstrap(args.config_uri) try: with env['request'].tm: diff --git a/docs/tutorials/wiki2/src/views/development.ini b/docs/tutorials/wiki2/src/views/development.ini index ee050c0ea..564aefb56 100644 --- a/docs/tutorials/wiki2/src/views/development.ini +++ b/docs/tutorials/wiki2/src/views/development.ini @@ -22,6 +22,9 @@ retry.attempts = 3 # '127.0.0.1' and '::1'. # debugtoolbar.hosts = 127.0.0.1 ::1 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### @@ -60,7 +63,7 @@ handlers = qualname = tutorial [logger_sqlalchemy] -level = INFO +level = WARN handlers = qualname = sqlalchemy.engine # "level = INFO" logs SQL queries. diff --git a/docs/tutorials/wiki2/src/views/production.ini b/docs/tutorials/wiki2/src/views/production.ini index 91d0f5ddb..29cdda1e1 100644 --- a/docs/tutorials/wiki2/src/views/production.ini +++ b/docs/tutorials/wiki2/src/views/production.ini @@ -16,6 +16,9 @@ sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite retry.attempts = 3 +[pshell] +setup = tutorial.pshell.setup + ### # wsgi server configuration ### diff --git a/docs/tutorials/wiki2/src/views/setup.py b/docs/tutorials/wiki2/src/views/setup.py index 28b766cbe..e2a30c0e7 100644 --- a/docs/tutorials/wiki2/src/views/setup.py +++ b/docs/tutorials/wiki2/src/views/setup.py @@ -26,7 +26,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/tutorials/wiki2/src/views/tutorial/__init__.py b/docs/tutorials/wiki2/src/views/tutorial/__init__.py index 4dab44823..28bd1f80d 100644 --- a/docs/tutorials/wiki2/src/views/tutorial/__init__.py +++ b/docs/tutorials/wiki2/src/views/tutorial/__init__.py @@ -4,9 +4,9 @@ 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() + with Configurator(settings=settings) as config: + config.include('pyramid_jinja2') + config.include('.models') + config.include('.routes') + config.scan() return config.make_wsgi_app() diff --git a/docs/tutorials/wiki2/src/views/tutorial/pshell.py b/docs/tutorials/wiki2/src/views/tutorial/pshell.py new file mode 100644 index 000000000..108c04d5e --- /dev/null +++ b/docs/tutorials/wiki2/src/views/tutorial/pshell.py @@ -0,0 +1,12 @@ +from . import models + +def setup(env): + request = env['request'] + + # start a transaction + request.tm.begin() + + # inject some vars into the shell builtins + env['tm'] = request.tm + env['dbsession'] = request.dbsession + env['models'] = models diff --git a/docs/tutorials/wiki2/src/views/tutorial/scripts/initialize_db.py b/docs/tutorials/wiki2/src/views/tutorial/scripts/initialize_db.py index 231d5d44b..e6350fb36 100644 --- a/docs/tutorials/wiki2/src/views/tutorial/scripts/initialize_db.py +++ b/docs/tutorials/wiki2/src/views/tutorial/scripts/initialize_db.py @@ -1,4 +1,4 @@ -import os +import argparse import sys from pyramid.paster import bootstrap, setup_logging @@ -24,19 +24,19 @@ def setup_models(dbsession): dbsession.add(page) -def usage(argv): - cmd = os.path.basename(argv[0]) - print('usage: %s \n' - '(example: "%s development.ini")' % (cmd, cmd)) - sys.exit(1) +def parse_args(argv): + parser = argparse.ArgumentParser() + parser.add_argument( + 'config_uri', + help='Configuration file, e.g., development.ini', + ) + return parser.parse_args(argv[1:]) def main(argv=sys.argv): - if len(argv) != 2: - usage(argv) - config_uri = argv[1] - setup_logging(config_uri) - env = bootstrap(config_uri) + args = parse_args(argv) + setup_logging(args.config_uri) + env = bootstrap(args.config_uri) try: with env['request'].tm: -- cgit v1.2.3 From 8f30e87698ea2041d3baec080417167c3d2f3674 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 30 Aug 2018 03:40:56 -0700 Subject: Update quick_tour with starter and alchemy cookiecutters source files --- docs/quick_tour.rst | 8 +-- docs/quick_tour/logging/.gitignore | 21 ++++++++ docs/quick_tour/logging/hello_world/__init__.py | 9 ++-- docs/quick_tour/logging/hello_world/routes.py | 3 ++ .../logging/hello_world/templates/404.jinja2 | 8 +++ docs/quick_tour/logging/hello_world/tests.py | 2 +- docs/quick_tour/logging/hello_world/views.py | 9 ---- .../logging/hello_world/views/__init__.py | 0 .../logging/hello_world/views/default.py | 9 ++++ .../logging/hello_world/views/notfound.py | 7 +++ docs/quick_tour/logging/setup.py | 2 +- docs/quick_tour/package/.gitignore | 21 ++++++++ docs/quick_tour/package/hello_world/__init__.py | 9 ++-- docs/quick_tour/package/hello_world/routes.py | 3 ++ .../package/hello_world/templates/404.jinja2 | 8 +++ docs/quick_tour/package/hello_world/tests.py | 2 +- docs/quick_tour/package/hello_world/views.py | 6 --- .../package/hello_world/views/__init__.py | 0 .../package/hello_world/views/default.py | 6 +++ .../package/hello_world/views/notfound.py | 7 +++ docs/quick_tour/package/setup.py | 2 +- docs/quick_tour/sessions/.gitignore | 21 ++++++++ docs/quick_tour/sessions/hello_world/__init__.py | 13 +++-- docs/quick_tour/sessions/hello_world/routes.py | 3 ++ .../sessions/hello_world/templates/404.jinja2 | 8 +++ docs/quick_tour/sessions/hello_world/tests.py | 2 +- docs/quick_tour/sessions/hello_world/views.py | 14 ------ .../sessions/hello_world/views/__init__.py | 0 .../sessions/hello_world/views/default.py | 14 ++++++ .../sessions/hello_world/views/notfound.py | 7 +++ docs/quick_tour/sessions/setup.py | 2 +- docs/quick_tour/sqla_demo/.gitignore | 21 ++++++++ docs/quick_tour/sqla_demo/README.txt | 12 ++++- docs/quick_tour/sqla_demo/development.ini | 11 +++- docs/quick_tour/sqla_demo/production.ini | 9 ++++ docs/quick_tour/sqla_demo/pytest.ini | 2 +- docs/quick_tour/sqla_demo/setup.py | 7 +-- docs/quick_tour/sqla_demo/sqla_demo/__init__.py | 10 ++-- docs/quick_tour/sqla_demo/sqla_demo/alembic/env.py | 58 ++++++++++++++++++++++ .../sqla_demo/sqla_demo/alembic/script.py.mako | 24 +++++++++ .../sqla_demo/alembic/versions/README.txt | 1 + docs/quick_tour/sqla_demo/sqla_demo/pshell.py | 12 +++++ .../sqla_demo/sqla_demo/scripts/initialize_db.py | 48 ++++++++++++++++++ .../sqla_demo/sqla_demo/scripts/initializedb.py | 45 ----------------- .../sqla_demo/templates/mytemplate.jinja2 | 2 +- .../sqla_demo/sqla_demo/views/default.py | 11 ++-- 46 files changed, 380 insertions(+), 119 deletions(-) create mode 100644 docs/quick_tour/logging/.gitignore create mode 100644 docs/quick_tour/logging/hello_world/routes.py create mode 100644 docs/quick_tour/logging/hello_world/templates/404.jinja2 delete mode 100644 docs/quick_tour/logging/hello_world/views.py create mode 100644 docs/quick_tour/logging/hello_world/views/__init__.py create mode 100644 docs/quick_tour/logging/hello_world/views/default.py create mode 100644 docs/quick_tour/logging/hello_world/views/notfound.py create mode 100644 docs/quick_tour/package/.gitignore create mode 100644 docs/quick_tour/package/hello_world/routes.py create mode 100644 docs/quick_tour/package/hello_world/templates/404.jinja2 delete mode 100644 docs/quick_tour/package/hello_world/views.py create mode 100644 docs/quick_tour/package/hello_world/views/__init__.py create mode 100644 docs/quick_tour/package/hello_world/views/default.py create mode 100644 docs/quick_tour/package/hello_world/views/notfound.py create mode 100644 docs/quick_tour/sessions/.gitignore create mode 100644 docs/quick_tour/sessions/hello_world/routes.py create mode 100644 docs/quick_tour/sessions/hello_world/templates/404.jinja2 delete mode 100644 docs/quick_tour/sessions/hello_world/views.py create mode 100644 docs/quick_tour/sessions/hello_world/views/__init__.py create mode 100644 docs/quick_tour/sessions/hello_world/views/default.py create mode 100644 docs/quick_tour/sessions/hello_world/views/notfound.py create mode 100644 docs/quick_tour/sqla_demo/.gitignore create mode 100644 docs/quick_tour/sqla_demo/sqla_demo/alembic/env.py create mode 100644 docs/quick_tour/sqla_demo/sqla_demo/alembic/script.py.mako create mode 100644 docs/quick_tour/sqla_demo/sqla_demo/alembic/versions/README.txt create mode 100644 docs/quick_tour/sqla_demo/sqla_demo/pshell.py create mode 100644 docs/quick_tour/sqla_demo/sqla_demo/scripts/initialize_db.py delete mode 100644 docs/quick_tour/sqla_demo/sqla_demo/scripts/initializedb.py diff --git a/docs/quick_tour.rst b/docs/quick_tour.rst index c61cbfdfd..26195a701 100644 --- a/docs/quick_tour.rst +++ b/docs/quick_tour.rst @@ -755,14 +755,14 @@ Pyramid (for example, when a new request comes in). Maybe you would like to log messages in your code? In your Python module, import and set up the logging in your ``views.py``: -.. literalinclude:: quick_tour/logging/hello_world/views.py +.. literalinclude:: quick_tour/logging/hello_world/views/default.py :language: python :lineno-match: :lines: 3-4 You can now, in your code, log messages: -.. literalinclude:: quick_tour/logging/hello_world/views.py +.. literalinclude:: quick_tour/logging/hello_world/views/default.py :language: python :lineno-match: :lines: 7-8 @@ -819,13 +819,13 @@ Now make a "factory" and pass it to the :term:`configurator`'s .. literalinclude:: quick_tour/sessions/hello_world/__init__.py :language: python :lineno-match: - :lines: 10-13 + :lines: 9-12 :emphasize-lines: 2-3 Pyramid's :term:`request` object now has a ``session`` attribute that we can use in our view code in ``views.py``: -.. literalinclude:: quick_tour/sessions/hello_world/views.py +.. literalinclude:: quick_tour/sessions/hello_world/views/default.py :language: python :lineno-match: :lines: 7- diff --git a/docs/quick_tour/logging/.gitignore b/docs/quick_tour/logging/.gitignore new file mode 100644 index 000000000..1853d983c --- /dev/null +++ b/docs/quick_tour/logging/.gitignore @@ -0,0 +1,21 @@ +*.egg +*.egg-info +*.pyc +*$py.class +*~ +.coverage +coverage.xml +build/ +dist/ +.tox/ +nosetests.xml +env*/ +tmp/ +Data.fs* +*.sublime-project +*.sublime-workspace +.*.sw? +.sw? +.DS_Store +coverage +test diff --git a/docs/quick_tour/logging/hello_world/__init__.py b/docs/quick_tour/logging/hello_world/__init__.py index 49dde36d4..a3d5a6469 100644 --- a/docs/quick_tour/logging/hello_world/__init__.py +++ b/docs/quick_tour/logging/hello_world/__init__.py @@ -4,9 +4,8 @@ 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.add_static_view('static', 'static', cache_max_age=3600) - config.add_route('home', '/') - config.scan() + with Configurator(settings=settings) as config: + config.include('pyramid_jinja2') + config.include('.routes') + config.scan() return config.make_wsgi_app() diff --git a/docs/quick_tour/logging/hello_world/routes.py b/docs/quick_tour/logging/hello_world/routes.py new file mode 100644 index 000000000..25504ad4d --- /dev/null +++ b/docs/quick_tour/logging/hello_world/routes.py @@ -0,0 +1,3 @@ +def includeme(config): + config.add_static_view('static', 'static', cache_max_age=3600) + config.add_route('home', '/') diff --git a/docs/quick_tour/logging/hello_world/templates/404.jinja2 b/docs/quick_tour/logging/hello_world/templates/404.jinja2 new file mode 100644 index 000000000..aaf12413f --- /dev/null +++ b/docs/quick_tour/logging/hello_world/templates/404.jinja2 @@ -0,0 +1,8 @@ +{% extends "layout.jinja2" %} + +{% block content %} +
+

Pyramid Starter project

+

404 Page Not Found

+
+{% endblock content %} diff --git a/docs/quick_tour/logging/hello_world/tests.py b/docs/quick_tour/logging/hello_world/tests.py index ee9745685..f01ae2a3c 100644 --- a/docs/quick_tour/logging/hello_world/tests.py +++ b/docs/quick_tour/logging/hello_world/tests.py @@ -11,7 +11,7 @@ class ViewTests(unittest.TestCase): testing.tearDown() def test_my_view(self): - from .views import my_view + from .views.default import my_view request = testing.DummyRequest() info = my_view(request) self.assertEqual(info['project'], 'hello_world') diff --git a/docs/quick_tour/logging/hello_world/views.py b/docs/quick_tour/logging/hello_world/views.py deleted file mode 100644 index a648d6ba3..000000000 --- a/docs/quick_tour/logging/hello_world/views.py +++ /dev/null @@ -1,9 +0,0 @@ -from pyramid.view import view_config - -import logging -log = logging.getLogger(__name__) - -@view_config(route_name='home', renderer='templates/mytemplate.jinja2') -def my_view(request): - log.debug('Some Message') - return {'project': 'hello_world'} diff --git a/docs/quick_tour/logging/hello_world/views/__init__.py b/docs/quick_tour/logging/hello_world/views/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/docs/quick_tour/logging/hello_world/views/default.py b/docs/quick_tour/logging/hello_world/views/default.py new file mode 100644 index 000000000..bbb99d78c --- /dev/null +++ b/docs/quick_tour/logging/hello_world/views/default.py @@ -0,0 +1,9 @@ +from pyramid.view import view_config + +import logging +log = logging.getLogger(__name__) + +@view_config(route_name='home', renderer='../templates/mytemplate.jinja2') +def my_view(request): + log.debug('Some Message') + return {'project': 'hello_world'} diff --git a/docs/quick_tour/logging/hello_world/views/notfound.py b/docs/quick_tour/logging/hello_world/views/notfound.py new file mode 100644 index 000000000..69d6e2804 --- /dev/null +++ b/docs/quick_tour/logging/hello_world/views/notfound.py @@ -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 {} diff --git a/docs/quick_tour/logging/setup.py b/docs/quick_tour/logging/setup.py index 44d90b990..27b025384 100644 --- a/docs/quick_tour/logging/setup.py +++ b/docs/quick_tour/logging/setup.py @@ -18,7 +18,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/quick_tour/package/.gitignore b/docs/quick_tour/package/.gitignore new file mode 100644 index 000000000..1853d983c --- /dev/null +++ b/docs/quick_tour/package/.gitignore @@ -0,0 +1,21 @@ +*.egg +*.egg-info +*.pyc +*$py.class +*~ +.coverage +coverage.xml +build/ +dist/ +.tox/ +nosetests.xml +env*/ +tmp/ +Data.fs* +*.sublime-project +*.sublime-workspace +.*.sw? +.sw? +.DS_Store +coverage +test diff --git a/docs/quick_tour/package/hello_world/__init__.py b/docs/quick_tour/package/hello_world/__init__.py index 49dde36d4..a3d5a6469 100644 --- a/docs/quick_tour/package/hello_world/__init__.py +++ b/docs/quick_tour/package/hello_world/__init__.py @@ -4,9 +4,8 @@ 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.add_static_view('static', 'static', cache_max_age=3600) - config.add_route('home', '/') - config.scan() + with Configurator(settings=settings) as config: + config.include('pyramid_jinja2') + config.include('.routes') + config.scan() return config.make_wsgi_app() diff --git a/docs/quick_tour/package/hello_world/routes.py b/docs/quick_tour/package/hello_world/routes.py new file mode 100644 index 000000000..25504ad4d --- /dev/null +++ b/docs/quick_tour/package/hello_world/routes.py @@ -0,0 +1,3 @@ +def includeme(config): + config.add_static_view('static', 'static', cache_max_age=3600) + config.add_route('home', '/') diff --git a/docs/quick_tour/package/hello_world/templates/404.jinja2 b/docs/quick_tour/package/hello_world/templates/404.jinja2 new file mode 100644 index 000000000..aaf12413f --- /dev/null +++ b/docs/quick_tour/package/hello_world/templates/404.jinja2 @@ -0,0 +1,8 @@ +{% extends "layout.jinja2" %} + +{% block content %} +
+

Pyramid Starter project

+

404 Page Not Found

+
+{% endblock content %} diff --git a/docs/quick_tour/package/hello_world/tests.py b/docs/quick_tour/package/hello_world/tests.py index ee9745685..f01ae2a3c 100644 --- a/docs/quick_tour/package/hello_world/tests.py +++ b/docs/quick_tour/package/hello_world/tests.py @@ -11,7 +11,7 @@ class ViewTests(unittest.TestCase): testing.tearDown() def test_my_view(self): - from .views import my_view + from .views.default import my_view request = testing.DummyRequest() info = my_view(request) self.assertEqual(info['project'], 'hello_world') diff --git a/docs/quick_tour/package/hello_world/views.py b/docs/quick_tour/package/hello_world/views.py deleted file mode 100644 index 67f78dad7..000000000 --- a/docs/quick_tour/package/hello_world/views.py +++ /dev/null @@ -1,6 +0,0 @@ -from pyramid.view import view_config - - -@view_config(route_name='home', renderer='templates/mytemplate.jinja2') -def my_view(request): - return {'project': 'hello_world'} diff --git a/docs/quick_tour/package/hello_world/views/__init__.py b/docs/quick_tour/package/hello_world/views/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/docs/quick_tour/package/hello_world/views/default.py b/docs/quick_tour/package/hello_world/views/default.py new file mode 100644 index 000000000..7458da006 --- /dev/null +++ b/docs/quick_tour/package/hello_world/views/default.py @@ -0,0 +1,6 @@ +from pyramid.view import view_config + + +@view_config(route_name='home', renderer='../templates/mytemplate.jinja2') +def my_view(request): + return {'project': 'hello_world'} diff --git a/docs/quick_tour/package/hello_world/views/notfound.py b/docs/quick_tour/package/hello_world/views/notfound.py new file mode 100644 index 000000000..69d6e2804 --- /dev/null +++ b/docs/quick_tour/package/hello_world/views/notfound.py @@ -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 {} diff --git a/docs/quick_tour/package/setup.py b/docs/quick_tour/package/setup.py index 44d90b990..27b025384 100644 --- a/docs/quick_tour/package/setup.py +++ b/docs/quick_tour/package/setup.py @@ -18,7 +18,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/quick_tour/sessions/.gitignore b/docs/quick_tour/sessions/.gitignore new file mode 100644 index 000000000..1853d983c --- /dev/null +++ b/docs/quick_tour/sessions/.gitignore @@ -0,0 +1,21 @@ +*.egg +*.egg-info +*.pyc +*$py.class +*~ +.coverage +coverage.xml +build/ +dist/ +.tox/ +nosetests.xml +env*/ +tmp/ +Data.fs* +*.sublime-project +*.sublime-workspace +.*.sw? +.sw? +.DS_Store +coverage +test diff --git a/docs/quick_tour/sessions/hello_world/__init__.py b/docs/quick_tour/sessions/hello_world/__init__.py index 7cdc55ebe..c2b9f68c7 100644 --- a/docs/quick_tour/sessions/hello_world/__init__.py +++ b/docs/quick_tour/sessions/hello_world/__init__.py @@ -4,11 +4,10 @@ from pyramid.session import SignedCookieSessionFactory def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ - config = Configurator(settings=settings) - config.include('pyramid_jinja2') - config.add_static_view('static', 'static', cache_max_age=3600) - config.add_route('home', '/') - my_session_factory = SignedCookieSessionFactory('itsaseekreet') - config.set_session_factory(my_session_factory) - config.scan() + with Configurator(settings=settings) as config: + config.include('pyramid_jinja2') + config.include('.routes') + my_session_factory = SignedCookieSessionFactory('itsaseekreet') + config.set_session_factory(my_session_factory) + config.scan() return config.make_wsgi_app() diff --git a/docs/quick_tour/sessions/hello_world/routes.py b/docs/quick_tour/sessions/hello_world/routes.py new file mode 100644 index 000000000..25504ad4d --- /dev/null +++ b/docs/quick_tour/sessions/hello_world/routes.py @@ -0,0 +1,3 @@ +def includeme(config): + config.add_static_view('static', 'static', cache_max_age=3600) + config.add_route('home', '/') diff --git a/docs/quick_tour/sessions/hello_world/templates/404.jinja2 b/docs/quick_tour/sessions/hello_world/templates/404.jinja2 new file mode 100644 index 000000000..aaf12413f --- /dev/null +++ b/docs/quick_tour/sessions/hello_world/templates/404.jinja2 @@ -0,0 +1,8 @@ +{% extends "layout.jinja2" %} + +{% block content %} +
+

Pyramid Starter project

+

404 Page Not Found

+
+{% endblock content %} diff --git a/docs/quick_tour/sessions/hello_world/tests.py b/docs/quick_tour/sessions/hello_world/tests.py index ee9745685..f01ae2a3c 100644 --- a/docs/quick_tour/sessions/hello_world/tests.py +++ b/docs/quick_tour/sessions/hello_world/tests.py @@ -11,7 +11,7 @@ class ViewTests(unittest.TestCase): testing.tearDown() def test_my_view(self): - from .views import my_view + from .views.default import my_view request = testing.DummyRequest() info = my_view(request) self.assertEqual(info['project'], 'hello_world') diff --git a/docs/quick_tour/sessions/hello_world/views.py b/docs/quick_tour/sessions/hello_world/views.py deleted file mode 100644 index 9716f854e..000000000 --- a/docs/quick_tour/sessions/hello_world/views.py +++ /dev/null @@ -1,14 +0,0 @@ -from pyramid.view import view_config - -import logging -log = logging.getLogger(__name__) - -@view_config(route_name='home', renderer='templates/mytemplate.jinja2') -def my_view(request): - log.debug('Some Message') - session = request.session - if 'counter' in session: - session['counter'] += 1 - else: - session['counter'] = 0 - return {'project': 'hello_world'} diff --git a/docs/quick_tour/sessions/hello_world/views/__init__.py b/docs/quick_tour/sessions/hello_world/views/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/docs/quick_tour/sessions/hello_world/views/default.py b/docs/quick_tour/sessions/hello_world/views/default.py new file mode 100644 index 000000000..33b8d8ded --- /dev/null +++ b/docs/quick_tour/sessions/hello_world/views/default.py @@ -0,0 +1,14 @@ +from pyramid.view import view_config + +import logging +log = logging.getLogger(__name__) + +@view_config(route_name='home', renderer='../templates/mytemplate.jinja2') +def my_view(request): + log.debug('Some Message') + session = request.session + if 'counter' in session: + session['counter'] += 1 + else: + session['counter'] = 0 + return {'project': 'hello_world'} diff --git a/docs/quick_tour/sessions/hello_world/views/notfound.py b/docs/quick_tour/sessions/hello_world/views/notfound.py new file mode 100644 index 000000000..69d6e2804 --- /dev/null +++ b/docs/quick_tour/sessions/hello_world/views/notfound.py @@ -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 {} diff --git a/docs/quick_tour/sessions/setup.py b/docs/quick_tour/sessions/setup.py index 44d90b990..27b025384 100644 --- a/docs/quick_tour/sessions/setup.py +++ b/docs/quick_tour/sessions/setup.py @@ -18,7 +18,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/quick_tour/sqla_demo/.gitignore b/docs/quick_tour/sqla_demo/.gitignore new file mode 100644 index 000000000..1853d983c --- /dev/null +++ b/docs/quick_tour/sqla_demo/.gitignore @@ -0,0 +1,21 @@ +*.egg +*.egg-info +*.pyc +*$py.class +*~ +.coverage +coverage.xml +build/ +dist/ +.tox/ +nosetests.xml +env*/ +tmp/ +Data.fs* +*.sublime-project +*.sublime-workspace +.*.sw? +.sw? +.DS_Store +coverage +test diff --git a/docs/quick_tour/sqla_demo/README.txt b/docs/quick_tour/sqla_demo/README.txt index 27bbff5a7..d00790492 100644 --- a/docs/quick_tour/sqla_demo/README.txt +++ b/docs/quick_tour/sqla_demo/README.txt @@ -20,7 +20,17 @@ Getting Started env/bin/pip install -e ".[testing]" -- Configure the database. +- Initialize and upgrade the database using Alembic. + + - Generate your first revision. + + env/bin/alembic -c development.ini revision --autogenerate -m "init" + + - Upgrade to that revision. + + env/bin/alembic -c development.ini upgrade head + +- Load default data into the database using a script. env/bin/initialize_sqla_demo_db development.ini diff --git a/docs/quick_tour/sqla_demo/development.ini b/docs/quick_tour/sqla_demo/development.ini index 8836a846e..056a672e4 100644 --- a/docs/quick_tour/sqla_demo/development.ini +++ b/docs/quick_tour/sqla_demo/development.ini @@ -22,10 +22,19 @@ retry.attempts = 3 # '127.0.0.1' and '::1'. # debugtoolbar.hosts = 127.0.0.1 ::1 +[pshell] +setup = sqla_demo.pshell.setup + ### # wsgi server configuration ### +[alembic] +# path to migration scripts +script_location = sqla_demo/alembic +file_template = %%(year)d%%(month).2d%%(day).2d_%%(rev)s +# file_template = %%(rev)s_%%(slug)s + [server:main] use = egg:waitress#main listen = localhost:6543 @@ -54,7 +63,7 @@ handlers = qualname = sqla_demo [logger_sqlalchemy] -level = INFO +level = WARN handlers = qualname = sqlalchemy.engine # "level = INFO" logs SQL queries. diff --git a/docs/quick_tour/sqla_demo/production.ini b/docs/quick_tour/sqla_demo/production.ini index 4566e02a0..fe7f946bd 100644 --- a/docs/quick_tour/sqla_demo/production.ini +++ b/docs/quick_tour/sqla_demo/production.ini @@ -16,10 +16,19 @@ sqlalchemy.url = sqlite:///%(here)s/sqla_demo.sqlite retry.attempts = 3 +[pshell] +setup = sqla_demo.pshell.setup + ### # wsgi server configuration ### +[alembic] +# path to migration scripts +script_location = sqla_demo/alembic +file_template = %%(year)d%%(month).2d%%(day).2d_%%(rev)s +# file_template = %%(rev)s_%%(slug)s + [server:main] use = egg:waitress#main listen = *:6543 diff --git a/docs/quick_tour/sqla_demo/pytest.ini b/docs/quick_tour/sqla_demo/pytest.ini index 2d7535841..b4b690a0f 100644 --- a/docs/quick_tour/sqla_demo/pytest.ini +++ b/docs/quick_tour/sqla_demo/pytest.ini @@ -1,3 +1,3 @@ [pytest] testpaths = sqla_demo -python_files = *.py +python_files = test*.py diff --git a/docs/quick_tour/sqla_demo/setup.py b/docs/quick_tour/sqla_demo/setup.py index 855a15d58..76cd518ca 100644 --- a/docs/quick_tour/sqla_demo/setup.py +++ b/docs/quick_tour/sqla_demo/setup.py @@ -9,8 +9,9 @@ with open(os.path.join(here, 'CHANGES.txt')) as f: CHANGES = f.read() requires = [ + 'alembic', 'plaster_pastedeploy', - 'pyramid >= 1.9a', + 'pyramid >= 1.9', 'pyramid_debugtoolbar', 'pyramid_jinja2', 'pyramid_retry', @@ -23,7 +24,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] @@ -54,7 +55,7 @@ setup( 'main = sqla_demo:main', ], 'console_scripts': [ - 'initialize_sqla_demo_db = sqla_demo.scripts.initializedb:main', + 'initialize_sqla_demo_db = sqla_demo.scripts.initialize_db:main', ], }, ) diff --git a/docs/quick_tour/sqla_demo/sqla_demo/__init__.py b/docs/quick_tour/sqla_demo/sqla_demo/__init__.py index 4dab44823..28bd1f80d 100644 --- a/docs/quick_tour/sqla_demo/sqla_demo/__init__.py +++ b/docs/quick_tour/sqla_demo/sqla_demo/__init__.py @@ -4,9 +4,9 @@ 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() + with Configurator(settings=settings) as config: + config.include('pyramid_jinja2') + config.include('.models') + config.include('.routes') + config.scan() return config.make_wsgi_app() diff --git a/docs/quick_tour/sqla_demo/sqla_demo/alembic/env.py b/docs/quick_tour/sqla_demo/sqla_demo/alembic/env.py new file mode 100644 index 000000000..46ce86a4e --- /dev/null +++ b/docs/quick_tour/sqla_demo/sqla_demo/alembic/env.py @@ -0,0 +1,58 @@ +"""Pyramid bootstrap environment. """ +from alembic import context +from pyramid.paster import get_appsettings, setup_logging +from sqlalchemy import engine_from_config + +from sqla_demo.models.meta import Base + +config = context.config + +setup_logging(config.config_file_name) + +settings = get_appsettings(config.config_file_name) +target_metadata = Base.metadata + + +def run_migrations_offline(): + """Run migrations in 'offline' mode. + + This configures the context with just a URL + and not an Engine, though an Engine is acceptable + here as well. By skipping the Engine creation + we don't even need a DBAPI to be available. + + Calls to context.execute() here emit the given string to the + script output. + + """ + context.configure(url=settings['sqlalchemy.url']) + with context.begin_transaction(): + context.run_migrations() + + +def run_migrations_online(): + """Run migrations in 'online' mode. + + In this scenario we need to create an Engine + and associate a connection with the context. + + """ + engine = engine_from_config(settings, prefix='sqlalchemy.') + + connection = engine.connect() + context.configure( + connection=connection, + target_metadata=target_metadata + ) + + try: + with context.begin_transaction(): + context.run_migrations() + finally: + connection.close() + + +if context.is_offline_mode(): + run_migrations_offline() +else: + run_migrations_online() diff --git a/docs/quick_tour/sqla_demo/sqla_demo/alembic/script.py.mako b/docs/quick_tour/sqla_demo/sqla_demo/alembic/script.py.mako new file mode 100644 index 000000000..2c0156303 --- /dev/null +++ b/docs/quick_tour/sqla_demo/sqla_demo/alembic/script.py.mako @@ -0,0 +1,24 @@ +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision | comma,n} +Create Date: ${create_date} + +""" +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +# revision identifiers, used by Alembic. +revision = ${repr(up_revision)} +down_revision = ${repr(down_revision)} +branch_labels = ${repr(branch_labels)} +depends_on = ${repr(depends_on)} + + +def upgrade(): + ${upgrades if upgrades else "pass"} + + +def downgrade(): + ${downgrades if downgrades else "pass"} diff --git a/docs/quick_tour/sqla_demo/sqla_demo/alembic/versions/README.txt b/docs/quick_tour/sqla_demo/sqla_demo/alembic/versions/README.txt new file mode 100644 index 000000000..09ed32c8d --- /dev/null +++ b/docs/quick_tour/sqla_demo/sqla_demo/alembic/versions/README.txt @@ -0,0 +1 @@ +Placeholder for alembic versions \ No newline at end of file diff --git a/docs/quick_tour/sqla_demo/sqla_demo/pshell.py b/docs/quick_tour/sqla_demo/sqla_demo/pshell.py new file mode 100644 index 000000000..108c04d5e --- /dev/null +++ b/docs/quick_tour/sqla_demo/sqla_demo/pshell.py @@ -0,0 +1,12 @@ +from . import models + +def setup(env): + request = env['request'] + + # start a transaction + request.tm.begin() + + # inject some vars into the shell builtins + env['tm'] = request.tm + env['dbsession'] = request.dbsession + env['models'] = models diff --git a/docs/quick_tour/sqla_demo/sqla_demo/scripts/initialize_db.py b/docs/quick_tour/sqla_demo/sqla_demo/scripts/initialize_db.py new file mode 100644 index 000000000..c629d1780 --- /dev/null +++ b/docs/quick_tour/sqla_demo/sqla_demo/scripts/initialize_db.py @@ -0,0 +1,48 @@ +import argparse +import sys + +from pyramid.paster import bootstrap, setup_logging +from sqlalchemy.exc import OperationalError + +from .. import models + + +def setup_models(dbsession): + """ + Add or update models / fixtures in the database. + + """ + model = models.mymodel.MyModel(name='one', value=1) + dbsession.add(model) + + +def parse_args(argv): + parser = argparse.ArgumentParser() + parser.add_argument( + 'config_uri', + help='Configuration file, e.g., development.ini', + ) + return parser.parse_args(argv[1:]) + + +def main(argv=sys.argv): + args = parse_args(argv) + setup_logging(args.config_uri) + env = bootstrap(args.config_uri) + + try: + with env['request'].tm: + dbsession = env['request'].dbsession + setup_models(dbsession) + except OperationalError: + print(''' +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 initialize your database tables with `alembic`. + Check your README.txt for description 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. + ''') diff --git a/docs/quick_tour/sqla_demo/sqla_demo/scripts/initializedb.py b/docs/quick_tour/sqla_demo/sqla_demo/scripts/initializedb.py deleted file mode 100644 index 7307ecc5c..000000000 --- a/docs/quick_tour/sqla_demo/sqla_demo/scripts/initializedb.py +++ /dev/null @@ -1,45 +0,0 @@ -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 [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) diff --git a/docs/quick_tour/sqla_demo/sqla_demo/templates/mytemplate.jinja2 b/docs/quick_tour/sqla_demo/sqla_demo/templates/mytemplate.jinja2 index 26d72c0a6..d8b0a4232 100644 --- a/docs/quick_tour/sqla_demo/sqla_demo/templates/mytemplate.jinja2 +++ b/docs/quick_tour/sqla_demo/sqla_demo/templates/mytemplate.jinja2 @@ -5,4 +5,4 @@

Pyramid Alchemy project

Welcome to {{project}}, a Pyramid application generated by
Cookiecutter.

-{% endblock content %} +{% endblock content %} \ No newline at end of file diff --git a/docs/quick_tour/sqla_demo/sqla_demo/views/default.py b/docs/quick_tour/sqla_demo/sqla_demo/views/default.py index d4afb1b0b..f7ad4c8f2 100644 --- a/docs/quick_tour/sqla_demo/sqla_demo/views/default.py +++ b/docs/quick_tour/sqla_demo/sqla_demo/views/default.py @@ -3,14 +3,14 @@ from pyramid.view import view_config from sqlalchemy.exc import DBAPIError -from ..models import MyModel +from .. import models @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() + query = request.dbsession.query(models.MyModel) + one = query.filter(models.MyModel.name == 'one').first() except DBAPIError: return Response(db_err_msg, content_type='text/plain', status=500) return {'one': one, 'project': 'sqla_demo'} @@ -20,9 +20,8 @@ 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_sqla_demo_db" script - to initialize your database tables. Check your virtual - environment's "bin" directory for this script and try to run it. +1. You may need to initialize your database tables with `alembic`. + Check your README.txt for description 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 -- cgit v1.2.3 From 33768fb147c26d93b2894a3504bcb117319a3629 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 30 Aug 2018 03:49:21 -0700 Subject: Update quick_tutorial with starter cookiecutter source files --- docs/quick_tutorial/cookiecutters/.gitignore | 21 +++++++++++++++++++++ .../cookiecutters/cc_starter/__init__.py | 9 ++++----- .../cookiecutters/cc_starter/routes.py | 3 +++ .../cookiecutters/cc_starter/templates/404.jinja2 | 8 ++++++++ .../cookiecutters/cc_starter/tests.py | 2 +- .../cookiecutters/cc_starter/views.py | 6 ------ .../cookiecutters/cc_starter/views/__init__.py | 0 .../cookiecutters/cc_starter/views/default.py | 6 ++++++ .../cookiecutters/cc_starter/views/notfound.py | 7 +++++++ docs/quick_tutorial/cookiecutters/setup.py | 5 +++-- 10 files changed, 53 insertions(+), 14 deletions(-) create mode 100644 docs/quick_tutorial/cookiecutters/.gitignore create mode 100644 docs/quick_tutorial/cookiecutters/cc_starter/routes.py create mode 100644 docs/quick_tutorial/cookiecutters/cc_starter/templates/404.jinja2 delete mode 100644 docs/quick_tutorial/cookiecutters/cc_starter/views.py create mode 100644 docs/quick_tutorial/cookiecutters/cc_starter/views/__init__.py create mode 100644 docs/quick_tutorial/cookiecutters/cc_starter/views/default.py create mode 100644 docs/quick_tutorial/cookiecutters/cc_starter/views/notfound.py diff --git a/docs/quick_tutorial/cookiecutters/.gitignore b/docs/quick_tutorial/cookiecutters/.gitignore new file mode 100644 index 000000000..1853d983c --- /dev/null +++ b/docs/quick_tutorial/cookiecutters/.gitignore @@ -0,0 +1,21 @@ +*.egg +*.egg-info +*.pyc +*$py.class +*~ +.coverage +coverage.xml +build/ +dist/ +.tox/ +nosetests.xml +env*/ +tmp/ +Data.fs* +*.sublime-project +*.sublime-workspace +.*.sw? +.sw? +.DS_Store +coverage +test diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/__init__.py b/docs/quick_tutorial/cookiecutters/cc_starter/__init__.py index 49dde36d4..a3d5a6469 100644 --- a/docs/quick_tutorial/cookiecutters/cc_starter/__init__.py +++ b/docs/quick_tutorial/cookiecutters/cc_starter/__init__.py @@ -4,9 +4,8 @@ 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.add_static_view('static', 'static', cache_max_age=3600) - config.add_route('home', '/') - config.scan() + with Configurator(settings=settings) as config: + config.include('pyramid_jinja2') + config.include('.routes') + config.scan() return config.make_wsgi_app() diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/routes.py b/docs/quick_tutorial/cookiecutters/cc_starter/routes.py new file mode 100644 index 000000000..25504ad4d --- /dev/null +++ b/docs/quick_tutorial/cookiecutters/cc_starter/routes.py @@ -0,0 +1,3 @@ +def includeme(config): + config.add_static_view('static', 'static', cache_max_age=3600) + config.add_route('home', '/') diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/templates/404.jinja2 b/docs/quick_tutorial/cookiecutters/cc_starter/templates/404.jinja2 new file mode 100644 index 000000000..aaf12413f --- /dev/null +++ b/docs/quick_tutorial/cookiecutters/cc_starter/templates/404.jinja2 @@ -0,0 +1,8 @@ +{% extends "layout.jinja2" %} + +{% block content %} +
+

Pyramid Starter project

+

404 Page Not Found

+
+{% endblock content %} diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/tests.py b/docs/quick_tutorial/cookiecutters/cc_starter/tests.py index 2f553bbb4..f3886be84 100644 --- a/docs/quick_tutorial/cookiecutters/cc_starter/tests.py +++ b/docs/quick_tutorial/cookiecutters/cc_starter/tests.py @@ -11,7 +11,7 @@ class ViewTests(unittest.TestCase): testing.tearDown() def test_my_view(self): - from .views import my_view + from .views.default import my_view request = testing.DummyRequest() info = my_view(request) self.assertEqual(info['project'], 'cc_starter') diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/views.py b/docs/quick_tutorial/cookiecutters/cc_starter/views.py deleted file mode 100644 index deedd53b8..000000000 --- a/docs/quick_tutorial/cookiecutters/cc_starter/views.py +++ /dev/null @@ -1,6 +0,0 @@ -from pyramid.view import view_config - - -@view_config(route_name='home', renderer='templates/mytemplate.jinja2') -def my_view(request): - return {'project': 'cc_starter'} diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/views/__init__.py b/docs/quick_tutorial/cookiecutters/cc_starter/views/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/views/default.py b/docs/quick_tutorial/cookiecutters/cc_starter/views/default.py new file mode 100644 index 000000000..47af359b5 --- /dev/null +++ b/docs/quick_tutorial/cookiecutters/cc_starter/views/default.py @@ -0,0 +1,6 @@ +from pyramid.view import view_config + + +@view_config(route_name='home', renderer='../templates/mytemplate.jinja2') +def my_view(request): + return {'project': 'cc_starter'} diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/views/notfound.py b/docs/quick_tutorial/cookiecutters/cc_starter/views/notfound.py new file mode 100644 index 000000000..69d6e2804 --- /dev/null +++ b/docs/quick_tutorial/cookiecutters/cc_starter/views/notfound.py @@ -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 {} diff --git a/docs/quick_tutorial/cookiecutters/setup.py b/docs/quick_tutorial/cookiecutters/setup.py index 0d1b3f70e..9482e7c32 100644 --- a/docs/quick_tutorial/cookiecutters/setup.py +++ b/docs/quick_tutorial/cookiecutters/setup.py @@ -9,15 +9,16 @@ with open(os.path.join(here, 'CHANGES.txt')) as f: CHANGES = f.read() requires = [ + 'plaster_pastedeploy', 'pyramid', - 'pyramid_debugtoolbar', 'pyramid_jinja2', + 'pyramid_debugtoolbar', 'waitress', ] tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] -- cgit v1.2.3 From 7f5a799b0a5344d5460025c05dd33e360eb9a87e Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 30 Aug 2018 04:50:53 -0700 Subject: Update narr/project.rst and /myproject starter cookiecutter source files --- docs/narr/myproject/.gitignore | 21 ++++ docs/narr/myproject/myproject/__init__.py | 9 +- docs/narr/myproject/myproject/routes.py | 3 + docs/narr/myproject/myproject/templates/404.jinja2 | 8 ++ docs/narr/myproject/myproject/tests.py | 2 +- docs/narr/myproject/myproject/views.py | 6 - docs/narr/myproject/myproject/views/__init__.py | 0 docs/narr/myproject/myproject/views/default.py | 6 + docs/narr/myproject/myproject/views/notfound.py | 7 ++ docs/narr/myproject/setup.py | 2 +- docs/narr/project.rst | 124 +++++++++++++-------- 11 files changed, 129 insertions(+), 59 deletions(-) create mode 100644 docs/narr/myproject/.gitignore create mode 100644 docs/narr/myproject/myproject/routes.py create mode 100644 docs/narr/myproject/myproject/templates/404.jinja2 delete mode 100644 docs/narr/myproject/myproject/views.py create mode 100644 docs/narr/myproject/myproject/views/__init__.py create mode 100644 docs/narr/myproject/myproject/views/default.py create mode 100644 docs/narr/myproject/myproject/views/notfound.py diff --git a/docs/narr/myproject/.gitignore b/docs/narr/myproject/.gitignore new file mode 100644 index 000000000..1853d983c --- /dev/null +++ b/docs/narr/myproject/.gitignore @@ -0,0 +1,21 @@ +*.egg +*.egg-info +*.pyc +*$py.class +*~ +.coverage +coverage.xml +build/ +dist/ +.tox/ +nosetests.xml +env*/ +tmp/ +Data.fs* +*.sublime-project +*.sublime-workspace +.*.sw? +.sw? +.DS_Store +coverage +test diff --git a/docs/narr/myproject/myproject/__init__.py b/docs/narr/myproject/myproject/__init__.py index 49dde36d4..a3d5a6469 100644 --- a/docs/narr/myproject/myproject/__init__.py +++ b/docs/narr/myproject/myproject/__init__.py @@ -4,9 +4,8 @@ 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.add_static_view('static', 'static', cache_max_age=3600) - config.add_route('home', '/') - config.scan() + with Configurator(settings=settings) as config: + config.include('pyramid_jinja2') + config.include('.routes') + config.scan() return config.make_wsgi_app() diff --git a/docs/narr/myproject/myproject/routes.py b/docs/narr/myproject/myproject/routes.py new file mode 100644 index 000000000..25504ad4d --- /dev/null +++ b/docs/narr/myproject/myproject/routes.py @@ -0,0 +1,3 @@ +def includeme(config): + config.add_static_view('static', 'static', cache_max_age=3600) + config.add_route('home', '/') diff --git a/docs/narr/myproject/myproject/templates/404.jinja2 b/docs/narr/myproject/myproject/templates/404.jinja2 new file mode 100644 index 000000000..aaf12413f --- /dev/null +++ b/docs/narr/myproject/myproject/templates/404.jinja2 @@ -0,0 +1,8 @@ +{% extends "layout.jinja2" %} + +{% block content %} +
+

Pyramid Starter project

+

404 Page Not Found

+
+{% endblock content %} diff --git a/docs/narr/myproject/myproject/tests.py b/docs/narr/myproject/myproject/tests.py index fd414cced..05ccadcfb 100644 --- a/docs/narr/myproject/myproject/tests.py +++ b/docs/narr/myproject/myproject/tests.py @@ -11,7 +11,7 @@ class ViewTests(unittest.TestCase): testing.tearDown() def test_my_view(self): - from .views import my_view + from .views.default import my_view request = testing.DummyRequest() info = my_view(request) self.assertEqual(info['project'], 'MyProject') diff --git a/docs/narr/myproject/myproject/views.py b/docs/narr/myproject/myproject/views.py deleted file mode 100644 index 9e9ec4320..000000000 --- a/docs/narr/myproject/myproject/views.py +++ /dev/null @@ -1,6 +0,0 @@ -from pyramid.view import view_config - - -@view_config(route_name='home', renderer='templates/mytemplate.jinja2') -def my_view(request): - return {'project': 'MyProject'} diff --git a/docs/narr/myproject/myproject/views/__init__.py b/docs/narr/myproject/myproject/views/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/docs/narr/myproject/myproject/views/default.py b/docs/narr/myproject/myproject/views/default.py new file mode 100644 index 000000000..8324cfe32 --- /dev/null +++ b/docs/narr/myproject/myproject/views/default.py @@ -0,0 +1,6 @@ +from pyramid.view import view_config + + +@view_config(route_name='home', renderer='../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 new file mode 100644 index 000000000..69d6e2804 --- /dev/null +++ b/docs/narr/myproject/myproject/views/notfound.py @@ -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 {} diff --git a/docs/narr/myproject/setup.py b/docs/narr/myproject/setup.py index 153a659ba..cf626880f 100644 --- a/docs/narr/myproject/setup.py +++ b/docs/narr/myproject/setup.py @@ -18,7 +18,7 @@ requires = [ tests_require = [ 'WebTest >= 1.3.1', # py3 compat - 'pytest', + 'pytest>=3.7.4', 'pytest-cov', ] diff --git a/docs/narr/project.rst b/docs/narr/project.rst index f41e155e7..fb5a241db 100644 --- a/docs/narr/project.rst +++ b/docs/narr/project.rst @@ -525,21 +525,27 @@ The ``myproject`` project we've generated has the following directory structure: .. code-block:: text - myproject/ + myproject ├── .coveragerc + ├── .gitignore ├── CHANGES.txt ├── MANIFEST.in ├── myproject │   ├── __init__.py + │   ├── routes.py │   ├── static │   │   ├── pyramid-16x16.png │   │   ├── pyramid.png │   │   └── theme.css │   ├── templates + │   │   ├── 404.jinja2 │   │   ├── layout.jinja2 │   │   └── mytemplate.jinja2 │   ├── tests.py - │   └── views.py + │   └── views + │   ├── __init__.py + │   ├── default.py + │   └── notfound.py ├── README.txt ├── development.ini ├── production.ini @@ -557,6 +563,8 @@ describe, run, and test your application. #. ``.coveragerc`` configures coverage when running tests. +#. ``.gitignore`` tells git which files and directories to ignore from source code version control. + #. ``CHANGES.txt`` describes the changes you've made to the application. It is conventionally written in :term:`reStructuredText` format. @@ -810,7 +818,9 @@ The ``myproject`` :term:`package` lives inside the ``myproject`` #. A ``tests.py`` module, which contains unit test code for the application. -#. A ``views.py`` module, which contains view code for the application. +#. A ``views`` package, which contains view code for the application. + +#. A ``static`` directory, which contains static files, including images and CSS. These are purely conventions established by the cookiecutter. :app:`Pyramid` doesn't insist that you name things in any particular way. However, it's @@ -848,31 +858,53 @@ also informs Python that the directory which contains it is a *package*. Line 8 adds support for Jinja2 templating bindings, allowing us to specify renderers with the ``.jinja2`` extension. - Line 9 registers a static view, which will serve up the files from the - ``myproject:static`` :term:`asset specification` (the ``static`` directory - of the ``myproject`` package). + Line 9 includes the ``routes.py`` module. - Line 10 adds a :term:`route` to the configuration. This route is later used - by a view in the ``views`` module. - - Line 11 calls ``config.scan()``, which picks up view registrations declared + Line 10 calls ``config.scan()``, which picks up view registrations declared elsewhere in the package (in this case, in the ``views.py`` module). - Line 12 returns a :term:`WSGI` application to the caller of the function + Line 11 returns a :term:`WSGI` application to the caller of the function (Pyramid's pserve). + +.. index:: + single: routes.py + +.. _routes_py: + +``routes.py`` +~~~~~~~~~~~~~ + +The ``routes.py`` module gets included by the ``main`` function in our ``__init__.py``. +It registers a view and a route. + +.. literalinclude:: myproject/myproject/routes.py + :language: python + :linenos: + +Line 2 registers a static view, which will serve up the files from the ``myproject:static`` :term:`asset specification` (the ``static`` directory of the ``myproject`` package). + +Line 3 adds a :term:`route` to the configuration. This route is later used by a view in the ``views`` module. + + .. index:: single: views.py -``views.py`` -~~~~~~~~~~~~ +``views`` package +~~~~~~~~~~~~~~~~~ Much of the heavy lifting in a :app:`Pyramid` application is done by *view callables*. A :term:`view callable` is the main tool of a :app:`Pyramid` web application developer; it is a bit of code which accepts a :term:`request` and which returns a :term:`response`. -.. literalinclude:: myproject/myproject/views.py +Our project has a ``views`` package by virtue of it being a directory containing an ``__init__.py`` file. +This ``__init__.py`` file happens to have no content, although it could as a project develops. + +We have two view modules in the ``views`` package. +Let's look at ``default.py``. + +.. literalinclude:: myproject/myproject/views/default.py :language: python :linenos: @@ -880,17 +912,17 @@ Lines 4-6 define and register a :term:`view callable` named ``my_view``. The function named ``my_view`` is decorated with a ``view_config`` decorator (which is processed by the ``config.scan()`` line in our ``__init__.py``). The view_config decorator asserts that this view be found when a :term:`route` -named ``home`` is matched. In our case, because our ``__init__.py`` maps the +named ``home`` is matched. In our case, because our ``routes.py`` maps the 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.pt``, which is an :term:`asset specification` that -specifies the ``mytemplate.pt`` file within the ``templates`` directory of the +``../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.pt``; the leading package name and colon is +as ``myproject:templates/mytemplate.jinja2``; the leading package name and colon is optional. The template file pointed to is a :term:`Jinja2` template -file (``templates/my_template.jinja2``). +file (``templates/mytemplate.jinja2``). This view callable function is handed a single piece of information: the :term:`request`. The *request* is an instance of the :term:`WebOb` ``Request`` @@ -903,6 +935,15 @@ the HTML in a :term:`response`. .. note:: Dictionaries provide values to :term:`template`\s. +Now let's look at ``notfound.py``. + +.. literalinclude:: myproject/myproject/views/notfound.py + :language: python + :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``. + .. note:: When the application is run with the cookiecutter's :ref:`default development.ini ` configuration, :ref:`logging is set up ` to aid debugging. If an exception is raised, @@ -964,7 +1005,7 @@ This is the base layout content. It contains a single marker for content block. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is the content :term:`Jinja2` template that exists in the project. It is referenced by the call to ``@view_config`` as the ``renderer`` -of the ``my_view`` view callable in the ``views.py`` file. See +of the ``my_view`` view callable in the ``views/default.py`` file. See :ref:`views_which_use_a_renderer` for more information about renderers. It inherits ("extends") the HTML provided by ``layout.jinja2``, replacing the content block with its own content. .. literalinclude:: myproject/myproject/templates/mytemplate.jinja2 @@ -976,6 +1017,18 @@ functions themselves. See :ref:`templates_used_directly` and :ref:`templates_used_as_renderers`. +``templates/404.jinja2`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +This template is similar to ``mytemplate.jinja2``, but with a few differences. +It is referenced by the call to ``@notfound_view_config`` as the ``renderer`` of the ``notfound_view`` view callable in the ``views/notfound.py`` file. +It inherits the HTML provided by ``layout.jinja2``, replacing the content block with its own content. + +.. literalinclude:: myproject/myproject/templates/404.jinja2 + :language: jinja + :linenos: + + .. index:: single: tests.py @@ -1015,32 +1068,11 @@ cookiecutter, you can decide to lay your code out any way you see fit. For example, the configuration method named :meth:`~pyramid.config.Configurator.add_view` requires you to pass a :term:`dotted Python name` or a direct object reference as the class or -function to be used as a view. By default, the ``starter`` cookiecutter would have -you add view functions to the ``views.py`` module in your package. However, you -might be more comfortable creating a ``views`` *directory*, and adding a single -file for each view. - -If your project package name was ``myproject`` and you wanted to arrange all -your views in a Python subpackage within the ``myproject`` :term:`package` -named ``views`` instead of within a single ``views.py`` file, you might do the -following. - -- Create a ``views`` directory inside your ``myproject`` package directory (the - same directory which holds ``views.py``). - -- Create a file within the new ``views`` directory named ``__init__.py``. (It - can be empty. This just tells Python that the ``views`` directory is a - *package*.) - -- *Move* the content from the existing ``views.py`` file to a file inside the - new ``views`` directory named, say, ``blog.py``. Because the ``templates`` - directory remains in the ``myproject`` package, the template :term:`asset - specification` values in ``blog.py`` must now be fully qualified with the - project's package name (``myproject:templates/blog.pt``). - -You can then continue to add view callable functions to the ``blog.py`` module, -but you can also add other ``.py`` files which contain view callable functions -to the ``views`` directory. As long as you use the ``@view_config`` directive +function to be used as a view. +By default, the ``starter`` cookiecutter would have you create a ``views`` directory, and add a single file for each view or collection of related views. +However, you might be more comfortable creating a single ``views.py`` module in your package and add view functions to it. + +Whatever structure you prefer, as long as you use the ``@view_config`` directive to register views in conjunction with ``config.scan()``, they will be picked up automatically when the application is restarted. -- cgit v1.2.3 From e604ce4350ccb6a70f632d5a4fdc5984a4218fd1 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 30 Aug 2018 04:54:02 -0700 Subject: Update narr/testing.rst to updated files in narr/myproject/ --- docs/narr/testing.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst index 8f4d806e6..ad4ba2186 100644 --- a/docs/narr/testing.rst +++ b/docs/narr/testing.rst @@ -396,10 +396,10 @@ As always, whenever you change your dependencies, make sure to run the correct $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` +which contains a ``views`` package containing a ``default.py`` module, which in turn contains a :term:`view` function ``my_view`` that returns an HTML body when the root URL is invoked: - .. literalinclude:: myproject/myproject/views.py + .. literalinclude:: myproject/myproject/views/default.py :linenos: :language: python -- cgit v1.2.3 From 893cb6f6c00a6de5d85194f9164cb72f1a94dbac Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 1 Sep 2018 13:59:08 -0700 Subject: Remove extra "the" --- docs/tutorials/wiki2/basiclayout.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst index 671893b5f..315aca29e 100644 --- a/docs/tutorials/wiki2/basiclayout.rst +++ b/docs/tutorials/wiki2/basiclayout.rst @@ -65,7 +65,7 @@ with the ``.jinja2`` extension within our project. :lineno-match: :language: py -Next include the the package ``models`` using a dotted Python path. The exact +Next include the package ``models`` using a dotted Python path. The exact setup of the models will be covered later. .. literalinclude:: src/basiclayout/tutorial/__init__.py -- cgit v1.2.3 From 549412454ef49430daaba2fccac56619b2e0cb83 Mon Sep 17 00:00:00 2001 From: Stephen Martin Date: Tue, 4 Sep 2018 10:17:31 -0700 Subject: clarify session factory warnings --- CONTRIBUTORS.txt | 2 ++ docs/narr/sessions.rst | 33 +++++++++++++++++++++------------ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index a56821e74..593a078f2 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -326,3 +326,5 @@ Contributors - Jason Williams, 2018/06/11 - Benjamin Gmurczyk, 2018/06/14 + +- Stephen Martin, 2018/09/04 diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 6c88dcec5..6f826fe23 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -57,18 +57,27 @@ using the :meth:`pyramid.config.Configurator.set_session_factory` method. .. warning:: By default the :func:`~pyramid.session.SignedCookieSessionFactory` - implementation is *unencrypted*. You should not use it when you keep - sensitive information in the session object, as the information can be - easily read by both users of your application and third parties who have - access to your users' network traffic. And, if you use this sessioning - implementation, and you inadvertently create a cross-site scripting - vulnerability in your application, because the session data is stored - unencrypted in a cookie, it will also be easier for evildoers to obtain the - current user's cross-site scripting token. In short, use a different - session factory implementation (preferably one which keeps session data on - the server) for anything but the most basic of applications where "session - security doesn't matter", and you are sure your application has no - cross-site scripting vulnerabilities. + implementation contains the following security concerns: + + - Session data is *unencrypted*. You should not use it when you keep + sensitive information in the session object, as the information can be + easily read by both users of your application and third parties who have + access to your users' network traffic. + + - If you use this sessioning implementation, and you inadvertently create a + cross-site scripting vulnerability in your application, because the + session data is stored unencrypted in a cookie, it will also be easier for + evildoers to obtain the current user's cross-site scripting token. + + - The default serialization method, while replacable with something like + JSON, is implemented using pickle which can lead to remote code execution + if your secret key is compromised. + + In short, use a different session factory implementation (preferably one + which keeps session data on the server) for anything but the most basic of + applications where "session security doesn't matter", you are sure your + application has no cross-site scripting vulnerabilities, and you are confident + your secret key will not be exposed. .. index:: single: session object -- cgit v1.2.3 From 91f381754177896bf481e27ab53d33cac33e2a0d Mon Sep 17 00:00:00 2001 From: Stephen Martin Date: Tue, 4 Sep 2018 12:36:39 -0700 Subject: fix spelling error --- docs/narr/sessions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 6f826fe23..2d80b1a63 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -69,7 +69,7 @@ using the :meth:`pyramid.config.Configurator.set_session_factory` method. session data is stored unencrypted in a cookie, it will also be easier for evildoers to obtain the current user's cross-site scripting token. - - The default serialization method, while replacable with something like + - The default serialization method, while replaceable with something like JSON, is implemented using pickle which can lead to remote code execution if your secret key is compromised. -- cgit v1.2.3 From b8c17ee19fce1aa0e1c5331ebbcf69853d1e3c54 Mon Sep 17 00:00:00 2001 From: Kuzma Date: Fri, 7 Sep 2018 20:49:45 +0300 Subject: Update CONTRIBUTORS.txt --- CONTRIBUTORS.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 593a078f2..0c18d600f 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -328,3 +328,6 @@ Contributors - Benjamin Gmurczyk, 2018/06/14 - Stephen Martin, 2018/09/04 + +- Kuzma Leshakov, 2018/09/07 + -- cgit v1.2.3 From 8367b0b94c470c132ec0c4ba4669733b6ae4f5b7 Mon Sep 17 00:00:00 2001 From: Kuzma Date: Fri, 7 Sep 2018 20:51:56 +0300 Subject: Add missing waitress dependency Waitress is needed in the code used in this tutorial step: https://docs.pylonsproject.org/projects/pyramid/en/latest/quick_tutorial/package.html --- docs/quick_tutorial/package/setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/quick_tutorial/package/setup.py b/docs/quick_tutorial/package/setup.py index bcfcfa684..77fedee2d 100644 --- a/docs/quick_tutorial/package/setup.py +++ b/docs/quick_tutorial/package/setup.py @@ -2,8 +2,9 @@ from setuptools import setup requires = [ 'pyramid', + 'waitress', ] setup(name='tutorial', install_requires=requires, -) \ No newline at end of file +) -- cgit v1.2.3 From 0011d5e090bdc3571ddea18935903389b8364629 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 9 Sep 2018 06:02:55 -0700 Subject: grammar fixes --- pyramid/security.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyramid/security.py b/pyramid/security.py index d12314684..4e9672d6a 100644 --- a/pyramid/security.py +++ b/pyramid/security.py @@ -192,7 +192,7 @@ def forget(request): def principals_allowed_by_permission(context, permission): """ Provided a ``context`` (a resource object), and a ``permission`` - (a string or unicode object), if a :term:`authorization policy` is + (a string or unicode object), if an :term:`authorization policy` is in effect, return a sequence of :term:`principal` ids that possess the permission in the ``context``. If no authorization policy is in effect, this will return a sequence with the single value @@ -201,7 +201,7 @@ def principals_allowed_by_permission(context, permission): .. note:: - even if an :term:`authorization policy` is in effect, + Even if an :term:`authorization policy` is in effect, some (exotic) authorization policies may not implement the required machinery for this function; those will cause a :exc:`NotImplementedError` exception to be raised when this -- cgit v1.2.3 From b80e5cad76fde86d4ddbb6526383308cee00413a Mon Sep 17 00:00:00 2001 From: Colin Dunklau Date: Fri, 14 Sep 2018 15:58:32 +0200 Subject: Fix tiny typo in glossary doc ("l10" -> "l10n") --- docs/glossary.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/glossary.rst b/docs/glossary.rst index b05344ae9..587e7c63e 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -853,7 +853,7 @@ Glossary Localization The process of displaying the user interface of an internationalized application in a particular language or - cultural context. Often shortened to "l10" (because the word + cultural context. Often shortened to "l10n" (because the word "localization" is L, 10 letters, then N). .. seealso:: -- cgit v1.2.3 From bd618672acc84bbefefd22f7ab98ff585c4609d5 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 14 Sep 2018 13:29:46 -0700 Subject: Pin Sphinx to <=1.7.9 to avoid Travis build failure See https://github.com/sphinx-doc/sphinx/issues/5433 and #3350 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 10ed3fa23..56f9e30d1 100644 --- a/setup.py +++ b/setup.py @@ -41,7 +41,7 @@ tests_require = [ docs_extras = [ - 'Sphinx >= 1.7.4', + 'Sphinx >= 1.7.4,<=1.7.9', 'docutils', 'pylons-sphinx-themes', 'pylons_sphinx_latesturl', -- cgit v1.2.3 From c3188340e841633924e8ab7a055c1df0dffed9c1 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 16 Sep 2018 11:06:05 -0500 Subject: deprecate pickleable sessions, recommend json --- CHANGES.rst | 11 ++++++++ docs/api/session.rst | 2 ++ docs/narr/sessions.rst | 72 +++++++++++++++++++++++++++++++++++++------------- pyramid/interfaces.py | 8 ++++++ pyramid/session.py | 30 ++++++++++++++++++--- 5 files changed, 101 insertions(+), 22 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index d0dbbe5c0..92e1e4313 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -57,6 +57,11 @@ Features - Add support for Python 3.7. Add testing on Python 3.8 with allowed failures. See https://github.com/Pylons/pyramid/pull/3333 +- Added ``pyramid.session.JSONSerializer``. See "Upcoming Changes to ISession + in Pyramid 2.0" in the "Sessions" chapter of the documentation for more + information about this feature. + See https://github.com/Pylons/pyramid/pull/3353 + Bug Fixes --------- @@ -79,6 +84,12 @@ Bug Fixes Deprecations ------------ +- The ``pyramid.intefaces.ISession`` interface will move to require + json-serializable objects in Pyramid 2.0. See + "Upcoming Changes to ISession in Pyramid 2.0" in the "Sessions" chapter + of the documentation for more information about this change. + See https://github.com/Pylons/pyramid/pull/3353 + Backward Incompatibilities -------------------------- diff --git a/docs/api/session.rst b/docs/api/session.rst index 53bae7c52..e0d2db726 100644 --- a/docs/api/session.rst +++ b/docs/api/session.rst @@ -17,3 +17,5 @@ .. autoclass:: PickleSerializer + .. autoclass:: JSONSerializer + diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 2d80b1a63..17e8291a0 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -59,25 +59,59 @@ using the :meth:`pyramid.config.Configurator.set_session_factory` method. By default the :func:`~pyramid.session.SignedCookieSessionFactory` implementation contains the following security concerns: - - Session data is *unencrypted*. You should not use it when you keep - sensitive information in the session object, as the information can be - easily read by both users of your application and third parties who have - access to your users' network traffic. - - - If you use this sessioning implementation, and you inadvertently create a - cross-site scripting vulnerability in your application, because the - session data is stored unencrypted in a cookie, it will also be easier for - evildoers to obtain the current user's cross-site scripting token. - - - The default serialization method, while replaceable with something like - JSON, is implemented using pickle which can lead to remote code execution - if your secret key is compromised. - - In short, use a different session factory implementation (preferably one - which keeps session data on the server) for anything but the most basic of - applications where "session security doesn't matter", you are sure your - application has no cross-site scripting vulnerabilities, and you are confident - your secret key will not be exposed. + - Session data is *unencrypted* (but it is signed / authenticated). + + This means an attacker cannot change the session data, but they can view it. + You should not use it when you keep sensitive information in the session object, as the information can be easily read by both users of your application and third parties who have access to your users' network traffic. + + At the very least, use TLS and set ``secure=True`` to avoid arbitrary users on the network from viewing the session contents. + + - If you use this sessioning implementation, and you inadvertently create a cross-site scripting vulnerability in your application, because the session data is stored unencrypted in a cookie, it will also be easier for evildoers to obtain the current user's cross-site scripting token. + + Set ``httponly=True`` to mitigate this vulnerability by hiding the cookie from client-side JavaScript. + + - The default serialization method, while replaceable with something like JSON, is implemented using pickle which can lead to remote code execution if your secret key is compromised. + + To mitigate this, set ``serializer=pyramid.session.JSONSerializer()`` to use :class:`pyramid.session.JSONSerializer`. This option will be the default in :app:`Pyramid` 2.0. + See :ref:`pickle_session_deprecation` for more information about this change. + + In short, use a different session factory implementation (preferably one which keeps session data on the server) for anything but the most basic of applications where "session security doesn't matter", you are sure your application has no cross-site scripting vulnerabilities, and you are confident your secret key will not be exposed. + +.. _pickle_session_deprecation: + +Upcoming Changes to ISession in Pyramid 2.0 +------------------------------------------- + +In :app:`Pyramid` 2.0 the :class:`pyramid.interfaces.ISession` interface will be changing to require that session implementations only need to support json-serializable data types. +This is a stricter contract than the current requirement that all objects be pickleable and it is being done for security purposes. +This is a backward-incompatible change. +Currently, if a client-side session implementation is compromised, it leaves the application vulnerable to remote code execution attacks using specially-crafted sessions that execute code when deserialized. + +For users with compatibility concerns, it's possible to craft a serializer that can handle both formats until you are satisfied that clients have had time to reasonably upgrade. +Remember that sessions should be short-lived and thus the number of clients affected should be small (no longer than an auth token, at a maximum). An example serializer: + +.. code-block:: python + :linenos: + + from pyramid.session import JSONSerializer + from pyramid.session import PickleSerializer + + class JSONSerializerWithPickleFallback(object): + def __init__(self): + self.json = JSONSerializer() + self.pickle = PickleSerializer() + + def dumps(self, value): + # maybe catch serialization errors here and keep using pickle + # while finding spots in your app that are not storing + # json-serializable objects, falling back to pickle + return self.json.dumps(value) + + def loads(self, value): + try: + return self.json.loads(value) + except ValueError: + return self.pickle.loads(value) .. index:: single: session object diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py index bedfb60b3..551ab701e 100644 --- a/pyramid/interfaces.py +++ b/pyramid/interfaces.py @@ -960,6 +960,14 @@ class ISession(IDict): Keys and values of a session must be pickleable. + .. warning:: + + In :app:`Pyramid` 2.0 the session will only be required to support + types that can be serialized using JSON. It's recommended to switch any + session implementations to support only JSON and to only store primitive + types in sessions. See :ref:`pickle_session_deprecation` for more + information about why this change is being made. + .. versionchanged:: 1.9 Sessions are no longer required to implement ``get_csrf_token`` and diff --git a/pyramid/session.py b/pyramid/session.py index 97039a404..3caf4181a 100644 --- a/pyramid/session.py +++ b/pyramid/session.py @@ -4,11 +4,15 @@ import hashlib import hmac import os import time +import warnings from zope.deprecation import deprecated from zope.interface import implementer -from webob.cookies import SignedSerializer +from webob.cookies import ( + JSONSerializer, + SignedSerializer, +) from pyramid.compat import ( pickle, @@ -131,6 +135,10 @@ class PickleSerializer(object): """Accept a Python object and return bytes.""" return pickle.dumps(appstruct, self.protocol) + +JSONSerializer = JSONSerializer # api + + def BaseCookieSessionFactory( serializer, cookie_name='session', @@ -145,8 +153,6 @@ def BaseCookieSessionFactory( set_on_exception=True, ): """ - .. versionadded:: 1.5 - Configure a :term:`session factory` which will provide cookie-based sessions. The return value of this function is a :term:`session factory`, which may be provided as the ``session_factory`` argument of a @@ -508,6 +514,7 @@ deprecated( 'so existing user session data will be destroyed if you switch to it.' ) + def SignedCookieSessionFactory( secret, cookie_name='session', @@ -618,14 +625,31 @@ def SignedCookieSessionFactory( should be raised for malformed inputs. If a serializer is not passed, the :class:`pyramid.session.PickleSerializer` serializer will be used. + .. warning:: + + In :app:`Pyramid` 2.0 the default ``serializer`` option will change to + use :class:`pyramid.session.JSONSerializer`. See + :ref:`pickle_session_deprecation` for more information about why this + change is being made. + .. versionadded: 1.5a3 .. versionchanged: 1.10 Added the ``samesite`` option and made the default ``Lax``. + """ if serializer is None: serializer = PickleSerializer() + warnings.warn( + 'The default pickle serializer is deprecated as of Pyramid 1.9 ' + 'and it will be changed to use pyramid.session.JSONSerializer in ' + 'version 2.0. Explicitly set the serializer to avoid future ' + 'incompatibilities. See "Upcoming Changes to ISession in ' + 'Pyramid 2.0" for more information about this change.', + DeprecationWarning, + stacklevel=1, + ) signed_serializer = SignedSerializer( secret, -- cgit v1.2.3 From ba5ca651c2cba9e45c80e0fb0ed6c6408ea3e042 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 16 Sep 2018 11:35:49 -0500 Subject: deprecate signed_serialize and signed_deserialize --- CHANGES.rst | 9 +++++++++ docs/api/session.rst | 6 ------ pyramid/session.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 92e1e4313..97a38591c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -90,6 +90,15 @@ Deprecations of the documentation for more information about this change. See https://github.com/Pylons/pyramid/pull/3353 +- The ``pyramid.session.signed_serialize`` and + ``pyramid.session.signed_deserialize`` functions will be removed in Pyramid + 2.0, along with the removal of + ``pyramid.session.UnencryptedCookieSessionFactoryConfig`` which was + deprecated in Pyramid 1.5. Please switch to using the + ``SignedCookieSessionFactory``, copying the code, or another session + implementation if you're still using these features. + See https://github.com/Pylons/pyramid/pull/3353 + Backward Incompatibilities -------------------------- diff --git a/docs/api/session.rst b/docs/api/session.rst index e0d2db726..d0cb112ec 100644 --- a/docs/api/session.rst +++ b/docs/api/session.rst @@ -5,14 +5,8 @@ .. automodule:: pyramid.session - .. autofunction:: signed_serialize - - .. autofunction:: signed_deserialize - .. autofunction:: SignedCookieSessionFactory - .. autofunction:: UnencryptedCookieSessionFactoryConfig - .. autofunction:: BaseCookieSessionFactory .. autoclass:: PickleSerializer diff --git a/pyramid/session.py b/pyramid/session.py index 3caf4181a..b953fa184 100644 --- a/pyramid/session.py +++ b/pyramid/session.py @@ -64,6 +64,14 @@ def signed_serialize(data, secret): cookieval = signed_serialize({'a':1}, 'secret') response.set_cookie('signed_cookie', cookieval) + + .. deprecated:: 1.10 + + This function will be removed in :app:`Pyramid` 2.0. It is using + pickle-based serialization, which is considered vulnerable to remote + code execution attacks and will no longer be used by the default + session factories at that time. + """ pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL) try: @@ -74,6 +82,13 @@ def signed_serialize(data, secret): sig = hmac.new(secret, pickled, hashlib.sha1).hexdigest() return sig + native_(base64.b64encode(pickled)) +deprecated( + 'signed_serialize', + 'This function will be removed in Pyramid 2.0. It is using pickle-based ' + 'serialization, which is considered vulnerable to remote code execution ' + 'attacks.', +) + def signed_deserialize(serialized, secret, hmac=hmac): """ Deserialize the value returned from ``signed_serialize``. If the value cannot be deserialized for any reason, a @@ -86,6 +101,13 @@ def signed_deserialize(serialized, secret, hmac=hmac): cookieval = request.cookies['signed_cookie'] data = signed_deserialize(cookieval, 'secret') + + .. deprecated:: 1.10 + + This function will be removed in :app:`Pyramid` 2.0. It is using + pickle-based serialization, which is considered vulnerable to remote + code execution attacks and will no longer be used by the default + session factories at that time. """ # hmac parameterized only for unit tests try: @@ -109,6 +131,13 @@ def signed_deserialize(serialized, secret, hmac=hmac): return pickle.loads(pickled) +deprecated( + 'signed_deserialize', + 'This function will be removed in Pyramid 2.0. It is using pickle-based ' + 'serialization, which is considered vulnerable to remote code execution ' + 'attacks.', +) + class PickleSerializer(object): """ A serializer that uses the pickle protocol to dump Python -- cgit v1.2.3 From 38bbea331f9c485d40892a17674272a8876a55a1 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 16 Sep 2018 15:43:43 -0500 Subject: tweak some docs --- CHANGES.rst | 2 +- docs/narr/sessions.rst | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 97a38591c..54b8beba4 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -85,7 +85,7 @@ Deprecations ------------ - The ``pyramid.intefaces.ISession`` interface will move to require - json-serializable objects in Pyramid 2.0. See + JSON-serializable objects in Pyramid 2.0. See "Upcoming Changes to ISession in Pyramid 2.0" in the "Sessions" chapter of the documentation for more information about this change. See https://github.com/Pylons/pyramid/pull/3353 diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 17e8291a0..971b4502d 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -79,10 +79,13 @@ using the :meth:`pyramid.config.Configurator.set_session_factory` method. .. _pickle_session_deprecation: +.. index:: + triple: pickle deprecation; JSON-serializable; ISession interface + Upcoming Changes to ISession in Pyramid 2.0 ------------------------------------------- -In :app:`Pyramid` 2.0 the :class:`pyramid.interfaces.ISession` interface will be changing to require that session implementations only need to support json-serializable data types. +In :app:`Pyramid` 2.0 the :class:`pyramid.interfaces.ISession` interface will be changing to require that session implementations only need to support JSON-serializable data types. This is a stricter contract than the current requirement that all objects be pickleable and it is being done for security purposes. This is a backward-incompatible change. Currently, if a client-side session implementation is compromised, it leaves the application vulnerable to remote code execution attacks using specially-crafted sessions that execute code when deserialized. @@ -104,7 +107,7 @@ Remember that sessions should be short-lived and thus the number of clients affe def dumps(self, value): # maybe catch serialization errors here and keep using pickle # while finding spots in your app that are not storing - # json-serializable objects, falling back to pickle + # JSON-serializable objects, falling back to pickle return self.json.dumps(value) def loads(self, value): @@ -173,7 +176,7 @@ Some gotchas: that they are instances of basic types of objects, such as strings, lists, dictionaries, tuples, integers, etc. If you place an object in a session data key or value that is not pickleable, an error will be raised when the - session is serialized. + session is serialized. Please also see :ref:`pickle_session_deprecation`. - If you place a mutable value (for example, a list or a dictionary) in a session object, and you subsequently mutate that value, you must call the -- cgit v1.2.3 From 07207637818049d27abb90792d48d7ed8fdd2340 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 16 Sep 2018 22:45:05 -0500 Subject: ref after index apparently --- docs/narr/sessions.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 971b4502d..d4d3c1074 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -77,11 +77,11 @@ using the :meth:`pyramid.config.Configurator.set_session_factory` method. In short, use a different session factory implementation (preferably one which keeps session data on the server) for anything but the most basic of applications where "session security doesn't matter", you are sure your application has no cross-site scripting vulnerabilities, and you are confident your secret key will not be exposed. -.. _pickle_session_deprecation: - .. index:: triple: pickle deprecation; JSON-serializable; ISession interface +.. _pickle_session_deprecation: + Upcoming Changes to ISession in Pyramid 2.0 ------------------------------------------- -- cgit v1.2.3 From 0444edcf0254270157f1896eafaeae53a3956ea5 Mon Sep 17 00:00:00 2001 From: Colin Dunklau Date: Tue, 18 Sep 2018 23:44:26 +0200 Subject: Tweak tox links in HACKING.txt Move tox doc link to top, add PyPI link, remove dead codespeak.net link. --- HACKING.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/HACKING.txt b/HACKING.txt index 3a7774781..9416ac210 100644 --- a/HACKING.txt +++ b/HACKING.txt @@ -9,8 +9,9 @@ Using a Development Checkout You'll have to create a development environment to hack on Pyramid, using a Pyramid checkout. You can either do this by hand, or if you have ``tox`` -installed (it's on PyPI), you can use ``tox`` to set up a working development -environment. Each installation method is described below. +installed (`docs `_, +`PyPI `), you can use``tox`` to set up a +working development environment. Each installation method is described below. By Hand @@ -89,8 +90,7 @@ way to get going. Since Pyramid is a framework and not an application, it can be convenient to work against a sample application, preferably in its own virtual environment. A -quick way to achieve this is to use `tox -`_ with a custom configuration file +quick way to achieve this is to use `tox` with a custom configuration file that is part of the checkout: $ tox -c hacking-tox.ini @@ -178,8 +178,8 @@ Running Tests $ tox -e py2-cover,py3-cover,coverage -- To run the full set of Pyramid tests on all platforms, install `tox - `_ into a system Python. The ``tox`` console +- To run the full set of Pyramid tests on all platforms, install `tox` into a + system Python. The ``tox`` console script will be installed into the scripts location for that Python. While ``cd``'ed to the Pyramid checkout root directory (it contains ``tox.ini``), invoke the ``tox`` console script. This will read the ``tox.ini`` file and -- cgit v1.2.3 From 1281a5ccffdbf5a5f22da1a38c4c82075ff0505c Mon Sep 17 00:00:00 2001 From: Colin Dunklau Date: Wed, 19 Sep 2018 00:11:59 +0200 Subject: Add registry arg to pyramid.renderers.get_renderer --- CONTRIBUTORS.txt | 1 + pyramid/renderers.py | 10 ++++++++-- pyramid/tests/test_renderers.py | 6 ++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 0c18d600f..80b43c8ec 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -331,3 +331,4 @@ Contributors - Kuzma Leshakov, 2018/09/07 +- Colin Dunklau, 2018/09/19 diff --git a/pyramid/renderers.py b/pyramid/renderers.py index 6019f50fb..d1c85b371 100644 --- a/pyramid/renderers.py +++ b/pyramid/renderers.py @@ -147,7 +147,7 @@ def render_to_response(renderer_name, return result -def get_renderer(renderer_name, package=None): +def get_renderer(renderer_name, package=None, registry=None): """ Return the renderer object for the renderer ``renderer_name``. You may supply a relative asset spec as ``renderer_name``. If @@ -157,10 +157,16 @@ def get_renderer(renderer_name, package=None): asset specification ``renderer_name``. If ``package`` is ``None`` (the default), the package name of the *caller* of this function will be used as the package. + + You may directly supply an :term:`application registry` using the + ``registry`` argument, and it will be used to look up the renderer. + Otherwise, the current thread-local registry (obtained via + :func:`~pyramid.threadlocal.get_current_registry`) will be used. """ if package is None: package = caller_package() - helper = RendererHelper(name=renderer_name, package=package) + helper = RendererHelper(name=renderer_name, package=package, + registry=registry) return helper.renderer # concrete renderer factory implementations (also API) diff --git a/pyramid/tests/test_renderers.py b/pyramid/tests/test_renderers.py index 86d8b582a..ea5e317d3 100644 --- a/pyramid/tests/test_renderers.py +++ b/pyramid/tests/test_renderers.py @@ -624,6 +624,12 @@ class Test_get_renderer(unittest.TestCase): result = self._callFUT('abc/def.pt', package=pyramid.tests) self.assertEqual(result, renderer) + def test_it_with_registry(self): + renderer = self.config.testing_add_renderer( + 'pyramid.tests:abc/def.pt') + result = self._callFUT('abc/def.pt', registry=self.config.registry) + self.assertEqual(result, renderer) + class TestJSONP(unittest.TestCase): def _makeOne(self, param_name='callback'): from pyramid.renderers import JSONP -- cgit v1.2.3 From 80d7018acff59b34ddfd42031e8d766a803682dd Mon Sep 17 00:00:00 2001 From: Colin Dunklau Date: Wed, 19 Sep 2018 00:21:59 +0200 Subject: Update changelog for 3354 --- CHANGES.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index d0dbbe5c0..63c9979f0 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -57,6 +57,10 @@ Features - Add support for Python 3.7. Add testing on Python 3.8 with allowed failures. See https://github.com/Pylons/pyramid/pull/3333 +- Add a ``registry`` argument to ``pyramid.renderers.get_renderer`` + to allow users to avoid threadlocals during renderer lookup. + See https://github.com/Pylons/pyramid/pull/3358 + Bug Fixes --------- -- cgit v1.2.3 From b00acf61982a88ad675a81bc08d8ac9c3e8ab92b Mon Sep 17 00:00:00 2001 From: Colin Dunklau Date: Wed, 19 Sep 2018 10:17:33 +0200 Subject: Update copyright Fixes #3355 --- COPYRIGHT.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index 645160fa5..6e23cb876 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -1,4 +1,4 @@ -Copyright (c) 2008-2011 Agendaless Consulting and Contributors. +Copyright (c) 2008-2018 Agendaless Consulting and Contributors. (http://www.agendaless.com), All Rights Reserved Portions (c) Zope Foundation and contributors (http://www.zope.org/). -- cgit v1.2.3 From 081699993078baa817d0d1c220db6a0d87555a44 Mon Sep 17 00:00:00 2001 From: Colin Dunklau Date: Wed, 19 Sep 2018 11:47:42 +0200 Subject: Expunge reST markup, this is a plain text file - Rework tox URLs - Use single graves (not two) to quote literal text - Use parens for inline URLs --- HACKING.txt | 73 ++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/HACKING.txt b/HACKING.txt index 9416ac210..be770484a 100644 --- a/HACKING.txt +++ b/HACKING.txt @@ -8,10 +8,13 @@ Using a Development Checkout ---------------------------- You'll have to create a development environment to hack on Pyramid, using a -Pyramid checkout. You can either do this by hand, or if you have ``tox`` -installed (`docs `_, -`PyPI `), you can use``tox`` to set up a -working development environment. Each installation method is described below. +Pyramid checkout. You can either do this by hand, or if you have `tox` +installed, you can use it to set up a working development environment. + +tox docs: http://tox.readthedocs.org/en/latest/ +tox on PyPI: https://pypi.org/project/tox/ + +Each installation method is described below. By Hand @@ -47,20 +50,20 @@ repo, from which you can submit a pull request. $ cd ~/hack-on-pyramid $ python3 -m venv env - From here on in within these instructions, the ``~/hack-on-pyramid/env`` - virtual environment you created above will be referred to as ``$VENV``. + From here on in within these instructions, the `~/hack-on-pyramid/env` + virtual environment you created above will be referred to as `$VENV`. To use the instructions in the steps that follow literally, use the - ``export VENV=~/hack-on-pyramid/env`` command. + `export VENV=~/hack-on-pyramid/env` command. - Install Pyramid from the checkout into the virtual environment, where the - current working directory is the ``pyramid`` checkout directory. We will + current working directory is the `pyramid` checkout directory. We will install Pyramid in editable (development) mode as well as its testing requirements. $ cd ~/hack-on-pyramid $ $VENV/bin/pip install -e ".[testing,docs]" -- Optionally create a new Pyramid project using ``pcreate``: +- Optionally create a new Pyramid project using `pcreate`: $ cd $VENV $ bin/pcreate -s starter starter @@ -71,13 +74,13 @@ repo, from which you can submit a pull request. $ $VENV/bin/pip install -e . -Using ``Tox`` -+++++++++++++ +Using `Tox` ++++++++++++ -Alternatively, if you already have ``tox`` installed, there is an easier +Alternatively, if you already have `tox` installed, there is an easier way to get going. -- Create a new directory somewhere and ``cd`` to it: +- Create a new directory somewhere and `cd` to it: $ mkdir ~/hack-on-pyramid $ cd ~/hack-on-pyramid @@ -95,10 +98,10 @@ that is part of the checkout: $ tox -c hacking-tox.ini -This will create a python-2.7 based virtual environment named ``env27`` -(Pyramid's ``.gitconfig` ignores all top-level folders that start with ``env`` +This will create a python-2.7 based virtual environment named `env27` +(Pyramid's `.gitconfig` ignores all top-level folders that start with `env` specifically in our use case), and inside that a simple pyramid application -named ``hacking`` that you can then fire up like so: +named `hacking` that you can then fire up like so: $ cd env27/hacking $ ../bin/pip install -e ".[testing,docs]" @@ -111,7 +114,7 @@ Adding Features In order to add a feature to Pyramid: - The feature must be documented in both the API and narrative documentation - (in ``docs/``). + (in `docs/`). - The feature must work fully on the following CPython versions: 2.7, 3.4, 3.5, 3.6, and 3.7 on both UNIX and Windows. @@ -127,7 +130,7 @@ In order to add a feature to Pyramid: The above requirements are relaxed for scaffolding dependencies. If a scaffold has an install-time dependency on something that doesn't work on a particular platform, that caveat should be spelled out clearly in *its* documentation -(within its ``docs/`` directory). +(within its `docs/` directory). Coding Style @@ -147,11 +150,11 @@ Running Tests - To run all tests for Pyramid on a single Python version from your development virtual environment (See *Using a Development Checkout* above), run - ``nosetests``: + `nosetests`: $ $VENV/bin/nosetests -- To run individual tests (i.e., during development), you can use ``nosetests`` +- To run individual tests (i.e., during development), you can use `nosetests` syntax as follows: # run a single test @@ -160,14 +163,14 @@ Running Tests # run all tests in a class $ $VENV/bin/nosetests pyramid.tests.test_module:ClassName - Optionally you can install a nose plugin, `nose-selecttests - `_, and use a regular - expression with the ``-t`` parameter to run tests. + Optionally you can install a nose plugin, `nose-selecttests` + ( https://pypi.org/project/nose-selecttests/ ), and use a regular + expression with the `-t` parameter to run tests. # run a single test $ $VENV/bin/nosetests -t test_mytestname -- The ``tox.ini`` uses ``nose`` and ``coverage``. As such ``tox`` may be used +- The `tox.ini` uses `nose` and `coverage`. As such `tox` may be used to run groups of tests or only a specific version of Python. For example, the following command will run tests on Python 2.7 only without coverage: @@ -179,10 +182,10 @@ Running Tests $ tox -e py2-cover,py3-cover,coverage - To run the full set of Pyramid tests on all platforms, install `tox` into a - system Python. The ``tox`` console + system Python. The `tox` console script will be installed into the scripts location for that Python. While - ``cd``'ed to the Pyramid checkout root directory (it contains ``tox.ini``), - invoke the ``tox`` console script. This will read the ``tox.ini`` file and + `cd`'ed to the Pyramid checkout root directory (it contains `tox.ini`), + invoke the `tox` console script. This will read the `tox.ini` file and execute the tests on multiple Python versions and platforms. While it runs, it creates a virtual environment for each version/platform combination. For example: @@ -191,9 +194,9 @@ Running Tests $ cd ~/hack-on-pyramid/ $ /usr/bin/tox -- The tests can also be run using `pytest `_. This is +- The tests can also be run using `pytest` ( http://pytest.org/ ). This is intended as a convenience for people who are more used to or fond of - ``pytest``. Run the tests like so: + `pytest`. Run the tests like so: $ $VENV/bin/pip install pytest $ $VENV/bin/py.test --strict pyramid/ @@ -218,8 +221,8 @@ Test Coverage ------------- - The codebase *must* have 100% test statement coverage after each commit. You - can test coverage via ``./coverage.sh`` (which itself just executes ``tox - -epy2-cover,py3-cover,coverage``). + can test coverage via `./coverage.sh` (which itself just executes `tox + -epy2-cover,py3-cover,coverage`). Documentation Coverage and Building HTML Documentation @@ -230,19 +233,19 @@ documentation in this package which references that API or behavior must be changed to reflect the bug fix, ideally in the same commit that fixes the bug or adds the feature. To build and review docs, use the following steps. -1. In the main Pyramid checkout directory, run ``./builddocs.sh`` (which just - turns around and runs ``tox -e docs``): +1. In the main Pyramid checkout directory, run `./builddocs.sh` (which just + turns around and runs `tox -e docs`): $ ./builddocs.sh -2. Open the ``docs/_build/html/index.html`` file to see the resulting HTML +2. Open the `docs/_build/html/index.html` file to see the resulting HTML rendering. Change Log ---------- -- Feature additions and bugfixes must be added to the ``CHANGES.rst`` +- Feature additions and bugfixes must be added to the `CHANGES.rst` file in the prevailing style. Changelog entries should be long and descriptive, not cryptic. Other developers should be able to know what your changelog entry means. -- cgit v1.2.3 From 6447d59aa63852831ce60e99365dde52427893c9 Mon Sep 17 00:00:00 2001 From: Colin Dunklau Date: Wed, 19 Sep 2018 12:13:32 +0200 Subject: Rewrap paragraph --- HACKING.txt | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/HACKING.txt b/HACKING.txt index be770484a..fdfee58d6 100644 --- a/HACKING.txt +++ b/HACKING.txt @@ -182,13 +182,12 @@ Running Tests $ tox -e py2-cover,py3-cover,coverage - To run the full set of Pyramid tests on all platforms, install `tox` into a - system Python. The `tox` console - script will be installed into the scripts location for that Python. While - `cd`'ed to the Pyramid checkout root directory (it contains `tox.ini`), - invoke the `tox` console script. This will read the `tox.ini` file and - execute the tests on multiple Python versions and platforms. While it runs, - it creates a virtual environment for each version/platform combination. For - example: + system Python. The `tox` console script will be installed into the scripts + location for that Python. While `cd`'ed to the Pyramid checkout root + directory (it contains `tox.ini`), invoke the `tox` console script. This + will read the `tox.ini` file and execute the tests on multiple Python + versions and platforms. While it runs, it creates a virtual environment + for each version/platform combination. For example: $ sudo /usr/bin/pip install tox $ cd ~/hack-on-pyramid/ -- cgit v1.2.3 From 2cc524cc0e75e2242f17954c30415fb2b9ad32dd Mon Sep 17 00:00:00 2001 From: Colin Dunklau Date: Wed, 19 Sep 2018 17:08:09 +0200 Subject: Add a test with a different configurator instance --- pyramid/tests/test_renderers.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pyramid/tests/test_renderers.py b/pyramid/tests/test_renderers.py index ea5e317d3..a2f7bf8c2 100644 --- a/pyramid/tests/test_renderers.py +++ b/pyramid/tests/test_renderers.py @@ -630,6 +630,14 @@ class Test_get_renderer(unittest.TestCase): result = self._callFUT('abc/def.pt', registry=self.config.registry) self.assertEqual(result, renderer) + def test_it_with_isolated_registry(self): + from pyramid.config import Configurator + isolated_config = Configurator() + renderer = isolated_config.testing_add_renderer( + 'pyramid.tests:abc/def.pt') + result = self._callFUT('abc/def.pt', registry=isolated_config.registry) + self.assertEqual(result, renderer) + class TestJSONP(unittest.TestCase): def _makeOne(self, param_name='callback'): from pyramid.renderers import JSONP -- cgit v1.2.3 From d275ec131b63dd03f1922990752c5564841275cf Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 21 Sep 2018 18:07:22 -0700 Subject: Add support for RTD Ethical Ads --- docs/conf.py | 9 +++++++++ setup.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 8fe7108ff..6e3d41240 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -161,6 +161,15 @@ html_theme_options = dict( outdated='false', ) +# Control display of sidebars +html_sidebars = {'**': [ + 'localtoc.html', + 'ethicalads.html', + 'relations.html', + 'sourcelink.html', + 'searchbox.html', +]} + # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". html_title = 'The Pyramid Web Framework v%s' % release diff --git a/setup.py b/setup.py index 56f9e30d1..e38dcd656 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ tests_require = [ docs_extras = [ 'Sphinx >= 1.7.4,<=1.7.9', 'docutils', - 'pylons-sphinx-themes', + 'pylons-sphinx-themes >= 1.0.7', 'pylons_sphinx_latesturl', 'repoze.sphinx.autointerface', 'sphinxcontrib-autoprogram', -- cgit v1.2.3 From c8abfbba6414faeb85eb72b9d42825cbedc1ca48 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 21 Sep 2018 18:22:19 -0700 Subject: Add changelog entry --- CHANGES.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index d0dbbe5c0..3425a950f 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -110,6 +110,10 @@ Backward Incompatibilities Documentation Changes --------------------- +- Ad support for Read The Docs Ethical Ads. + https://github.com/Pylons/pyramid/pull/3360 + https://docs.readthedocs.io/en/latest/advertising/ethical-advertising.html + - Add support for alembic to the pyramid-cookiecutter-alchemy cookiecutter and update the wiki2 tutorial to explain how it works. See https://github.com/Pylons/pyramid/pull/3307 and -- cgit v1.2.3 From eed1d870ba39925c2154418e7ab88b713fb26447 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 21 Sep 2018 18:34:07 -0700 Subject: Use correct minimum version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e38dcd656..0310a2aa4 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ tests_require = [ docs_extras = [ 'Sphinx >= 1.7.4,<=1.7.9', 'docutils', - 'pylons-sphinx-themes >= 1.0.7', + 'pylons-sphinx-themes >= 1.0.8', 'pylons_sphinx_latesturl', 'repoze.sphinx.autointerface', 'sphinxcontrib-autoprogram', -- cgit v1.2.3 From 0296259599809671df9a4bb3b14623c117c09344 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 22 Sep 2018 01:33:35 -0700 Subject: Update links to trypyramid.com, Grok, gunicorn --- docs/glossary.rst | 4 ++-- docs/index.rst | 2 +- docs/narr/introduction.rst | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/glossary.rst b/docs/glossary.rst index 587e7c63e..ec4cffef2 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -343,7 +343,7 @@ Glossary full-featured Python web framework. Grok - `A web framework based on Zope 3 `_. + `A web framework based on Zope 3 `_. Django `A full-featured Python web framework `_. @@ -1083,7 +1083,7 @@ Glossary Green Unicorn Aka ``gunicorn``, a fast :term:`WSGI` server that runs on Unix under - Python 2.6+ or Python 3.1+. See http://gunicorn.org/ for detailed + Python 2.6+ or Python 3.1+. See https://gunicorn.org/ for detailed information. predicate factory diff --git a/docs/index.rst b/docs/index.rst index 76d23b4f4..19cff9414 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -66,7 +66,7 @@ Official tutorials provide a quick overview of :app:`Pyramid`'s features in more Support and Development ======================= -The `Pyramid website `_ is the main +The `Pyramid website `_ is the main entry point to :app:`Pyramid` web framework resources for support and development information. diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst index 3ee6b5367..9293386f2 100644 --- a/docs/narr/introduction.rst +++ b/docs/narr/introduction.rst @@ -52,7 +52,7 @@ Modern Tested ~~~~~~ -Untested code is broken by design. The :app:`Pyramid` community has a strong testing culture and our framework reflects that. Every release of :app:`Pyramid` has 100% statement coverage (as measured by `coverage `_) and 95% decision/condition coverage. (as measured by `instrumental `_) It is automatically tested using `Travis `_ and `Jenkins `_ on supported versions of Python after each commit to its GitHub repository. `Official Pyramid add-ons `_ are held to a similar testing standard. +Untested code is broken by design. The :app:`Pyramid` community has a strong testing culture and our framework reflects that. Every release of :app:`Pyramid` has 100% statement coverage (as measured by `coverage `_) and 95% decision/condition coverage. (as measured by `instrumental `_) It is automatically tested using `Travis `_ and `Jenkins `_ on supported versions of Python after each commit to its GitHub repository. `Official Pyramid add-ons `_ are held to a similar testing standard. We still find bugs in :app:`Pyramid`, but we've noticed we find a lot fewer of them while working on projects with a solid testing regime. @@ -173,7 +173,7 @@ Supported :app:`Pyramid` add-ons are held to the same demanding standards as the .. seealso:: - See also https://trypyramid.com/resources-extending-pyramid.html + See also https://trypyramid.com/extending-pyramid.html Write your views, *your* way ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- cgit v1.2.3 From 473663742fc4015d670a2218ba998fbf9aba92e5 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 22 Sep 2018 01:42:14 -0700 Subject: Bump Sphinx - See #3350 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 0310a2aa4..d3d453a0d 100644 --- a/setup.py +++ b/setup.py @@ -41,7 +41,7 @@ tests_require = [ docs_extras = [ - 'Sphinx >= 1.7.4,<=1.7.9', + 'Sphinx >= 1.8.1', 'docutils', 'pylons-sphinx-themes >= 1.0.8', 'pylons_sphinx_latesturl', -- cgit v1.2.3 From 97ee7f3aa8af74a01e51c0c14fda1c0a5a490663 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Tue, 25 Sep 2018 15:49:23 -0500 Subject: show how to use the serializer --- docs/narr/sessions.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index d4d3c1074..ded7e87e3 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -98,6 +98,7 @@ Remember that sessions should be short-lived and thus the number of clients affe from pyramid.session import JSONSerializer from pyramid.session import PickleSerializer + from pyramid.session import SignedCookieSessionFactory class JSONSerializerWithPickleFallback(object): def __init__(self): @@ -116,6 +117,11 @@ Remember that sessions should be short-lived and thus the number of clients affe except ValueError: return self.pickle.loads(value) + # somewhere in your configuration code + serializer = JSONSerializerWithPickleFallback() + session_factory = SignedCookieSessionFactory(..., serializer=serializer) + config.set_session_factory(session_factory) + .. index:: single: session object -- cgit v1.2.3 From 5f846f4b72e81bff1d1a2367fa129b924d772388 Mon Sep 17 00:00:00 2001 From: Alexander Lin Date: Thu, 27 Sep 2018 11:58:07 -0700 Subject: Fix typo --- docs/tutorials/wiki2/definingviews.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst index 700a105b1..fe539eca6 100644 --- a/docs/tutorials/wiki2/definingviews.rst +++ b/docs/tutorials/wiki2/definingviews.rst @@ -149,7 +149,7 @@ We'll describe each one briefly in the following sections. .. note:: - There is nothing special about the filename ``default.py`` exept that it is a + There is nothing special about the filename ``default.py`` except that it is a Python module. A project may have many view callables throughout its codebase in arbitrarily named modules. Modules implementing view callables often have ``view`` in their name (or may live in a Python subpackage of your -- cgit v1.2.3