From b1b92284f496800a4dfd2cea72cb9be07ba8661c Mon Sep 17 00:00:00 2001 From: Paul Everitt Date: Fri, 13 Sep 2013 16:52:14 -0400 Subject: First cut at import of quick tutorial. --- docs/quick_tutorial/authentication.rst | 134 ++++++++ docs/quick_tutorial/authentication/development.ini | 42 +++ docs/quick_tutorial/authentication/setup.py | 13 + .../authentication/tutorial/__init__.py | 24 ++ .../quick_tutorial/authentication/tutorial/home.pt | 18 + .../authentication/tutorial/login.pt | 25 ++ .../authentication/tutorial/security.py | 8 + .../authentication/tutorial/tests.py | 47 +++ .../authentication/tutorial/views.py | 64 ++++ docs/quick_tutorial/authorization.rst | 112 +++++++ docs/quick_tutorial/authorization/development.ini | 42 +++ docs/quick_tutorial/authorization/setup.py | 13 + .../authorization/tutorial/__init__.py | 25 ++ docs/quick_tutorial/authorization/tutorial/home.pt | 18 + .../quick_tutorial/authorization/tutorial/login.pt | 25 ++ .../authorization/tutorial/resources.py | 9 + .../authorization/tutorial/security.py | 8 + .../quick_tutorial/authorization/tutorial/tests.py | 47 +++ .../quick_tutorial/authorization/tutorial/views.py | 66 ++++ docs/quick_tutorial/conf.py | 281 ++++++++++++++++ docs/quick_tutorial/databases.rst | 184 ++++++++++ docs/quick_tutorial/databases/development.ini | 49 +++ docs/quick_tutorial/databases/setup.py | 20 ++ docs/quick_tutorial/databases/sqltutorial.sqlite | Bin 0 -> 12288 bytes docs/quick_tutorial/databases/tutorial/__init__.py | 20 ++ .../databases/tutorial/initialize_db.py | 37 ++ docs/quick_tutorial/databases/tutorial/models.py | 35 ++ docs/quick_tutorial/databases/tutorial/tests.py | 58 ++++ docs/quick_tutorial/databases/tutorial/views.py | 96 ++++++ .../quick_tutorial/databases/tutorial/wiki_view.pt | 19 ++ .../databases/tutorial/wikipage_addedit.pt | 22 ++ .../databases/tutorial/wikipage_view.pt | 17 + docs/quick_tutorial/debugtoolbar.rst | 87 +++++ docs/quick_tutorial/debugtoolbar/development.ini | 40 +++ docs/quick_tutorial/debugtoolbar/setup.py | 13 + .../debugtoolbar/tutorial/__init__.py | 13 + docs/quick_tutorial/forms.rst | 146 ++++++++ docs/quick_tutorial/forms/development.ini | 41 +++ docs/quick_tutorial/forms/setup.py | 14 + docs/quick_tutorial/forms/tutorial/__init__.py | 12 + docs/quick_tutorial/forms/tutorial/tests.py | 47 +++ docs/quick_tutorial/forms/tutorial/views.py | 96 ++++++ docs/quick_tutorial/forms/tutorial/wiki_view.pt | 19 ++ .../forms/tutorial/wikipage_addedit.pt | 22 ++ .../quick_tutorial/forms/tutorial/wikipage_view.pt | 17 + docs/quick_tutorial/functional_testing.rst | 68 ++++ .../functional_testing/development.ini | 40 +++ docs/quick_tutorial/functional_testing/setup.py | 13 + .../functional_testing/tutorial/__init__.py | 13 + .../functional_testing/tutorial/tests.py | 31 ++ docs/quick_tutorial/hello_world.rst | 111 ++++++ docs/quick_tutorial/hello_world/app.py | 17 + docs/quick_tutorial/index.rst | 51 +++ docs/quick_tutorial/ini.rst | 144 ++++++++ docs/quick_tutorial/ini/development.ini | 38 +++ docs/quick_tutorial/ini/setup.py | 13 + docs/quick_tutorial/ini/tutorial/__init__.py | 13 + docs/quick_tutorial/jinja2.rst | 96 ++++++ docs/quick_tutorial/jinja2/development.ini | 42 +++ docs/quick_tutorial/jinja2/setup.py | 13 + docs/quick_tutorial/jinja2/tutorial/__init__.py | 9 + docs/quick_tutorial/jinja2/tutorial/home.jinja2 | 9 + docs/quick_tutorial/jinja2/tutorial/home.pt | 9 + docs/quick_tutorial/jinja2/tutorial/tests.py | 50 +++ docs/quick_tutorial/jinja2/tutorial/views.py | 18 + docs/quick_tutorial/json.rst | 101 ++++++ docs/quick_tutorial/json/development.ini | 41 +++ docs/quick_tutorial/json/setup.py | 13 + docs/quick_tutorial/json/tutorial/__init__.py | 10 + docs/quick_tutorial/json/tutorial/home.pt | 9 + docs/quick_tutorial/json/tutorial/tests.py | 50 +++ docs/quick_tutorial/json/tutorial/views.py | 19 ++ docs/quick_tutorial/logging.rst | 77 +++++ docs/quick_tutorial/logging/development.ini | 41 +++ docs/quick_tutorial/logging/setup.py | 13 + docs/quick_tutorial/logging/tutorial/__init__.py | 9 + docs/quick_tutorial/logging/tutorial/home.pt | 9 + docs/quick_tutorial/logging/tutorial/tests.py | 44 +++ docs/quick_tutorial/logging/tutorial/views.py | 23 ++ docs/quick_tutorial/more_view_classes.rst | 180 ++++++++++ .../more_view_classes/development.ini | 41 +++ docs/quick_tutorial/more_view_classes/setup.py | 13 + .../more_view_classes/tutorial/__init__.py | 9 + .../more_view_classes/tutorial/delete.pt | 9 + .../more_view_classes/tutorial/edit.pt | 10 + .../more_view_classes/tutorial/hello.pt | 16 + .../more_view_classes/tutorial/home.pt | 12 + .../more_view_classes/tutorial/tests.py | 31 ++ .../more_view_classes/tutorial/views.py | 39 +++ docs/quick_tutorial/package.rst | 112 +++++++ docs/quick_tutorial/package/setup.py | 9 + docs/quick_tutorial/package/tutorial/__init__.py | 1 + docs/quick_tutorial/package/tutorial/app.py | 17 + docs/quick_tutorial/pyramid_setup.rst | 27 ++ docs/quick_tutorial/python_setup.rst | 88 +++++ docs/quick_tutorial/request_response.rst | 101 ++++++ .../request_response/development.ini | 41 +++ docs/quick_tutorial/request_response/setup.py | 13 + .../request_response/tutorial/__init__.py | 9 + .../request_response/tutorial/home.pt | 9 + .../request_response/tutorial/tests.py | 54 +++ .../request_response/tutorial/views.py | 22 ++ docs/quick_tutorial/rest_ajax.rst | 62 ++++ docs/quick_tutorial/rest_ajax_layout.rst | 50 +++ docs/quick_tutorial/rest_bootstrap.rst | 88 +++++ docs/quick_tutorial/routing.rst | 119 +++++++ docs/quick_tutorial/routing/development.ini | 41 +++ docs/quick_tutorial/routing/setup.py | 13 + docs/quick_tutorial/routing/tutorial/__init__.py | 8 + docs/quick_tutorial/routing/tutorial/home.pt | 10 + docs/quick_tutorial/routing/tutorial/tests.py | 36 ++ docs/quick_tutorial/routing/tutorial/views.py | 20 ++ docs/quick_tutorial/scaffolds.rst | 84 +++++ docs/quick_tutorial/scaffolds/CHANGES.txt | 4 + docs/quick_tutorial/scaffolds/MANIFEST.in | 2 + docs/quick_tutorial/scaffolds/README.txt | 1 + docs/quick_tutorial/scaffolds/development.ini | 60 ++++ docs/quick_tutorial/scaffolds/production.ini | 54 +++ .../quick_tutorial/scaffolds/scaffolds/__init__.py | 11 + .../scaffolds/scaffolds/static/favicon.ico | Bin 0 -> 1406 bytes .../scaffolds/scaffolds/static/footerbg.png | Bin 0 -> 333 bytes .../scaffolds/scaffolds/static/headerbg.png | Bin 0 -> 203 bytes .../scaffolds/scaffolds/static/ie6.css | 8 + .../scaffolds/scaffolds/static/middlebg.png | Bin 0 -> 2797 bytes .../scaffolds/scaffolds/static/pylons.css | 372 +++++++++++++++++++++ .../scaffolds/scaffolds/static/pyramid-small.png | Bin 0 -> 7044 bytes .../scaffolds/scaffolds/static/pyramid.png | Bin 0 -> 33055 bytes .../scaffolds/scaffolds/static/transparent.gif | Bin 0 -> 49 bytes .../scaffolds/scaffolds/templates/mytemplate.pt | 76 +++++ docs/quick_tutorial/scaffolds/scaffolds/tests.py | 17 + docs/quick_tutorial/scaffolds/scaffolds/views.py | 6 + docs/quick_tutorial/scaffolds/setup.cfg | 27 ++ docs/quick_tutorial/scaffolds/setup.py | 39 +++ docs/quick_tutorial/sessions.rst | 98 ++++++ docs/quick_tutorial/sessions/development.ini | 41 +++ docs/quick_tutorial/sessions/setup.py | 13 + docs/quick_tutorial/sessions/tutorial/__init__.py | 13 + docs/quick_tutorial/sessions/tutorial/home.pt | 10 + docs/quick_tutorial/sessions/tutorial/tests.py | 44 +++ docs/quick_tutorial/sessions/tutorial/views.py | 29 ++ docs/quick_tutorial/static_assets.rst | 89 +++++ docs/quick_tutorial/static_assets/development.ini | 41 +++ docs/quick_tutorial/static_assets/setup.py | 13 + .../static_assets/tutorial/__init__.py | 10 + docs/quick_tutorial/static_assets/tutorial/home.pt | 11 + .../static_assets/tutorial/static/app.css | 4 + .../quick_tutorial/static_assets/tutorial/tests.py | 44 +++ .../quick_tutorial/static_assets/tutorial/views.py | 18 + docs/quick_tutorial/templating.rst | 100 ++++++ docs/quick_tutorial/templating/development.ini | 41 +++ docs/quick_tutorial/templating/setup.py | 13 + .../quick_tutorial/templating/tutorial/__init__.py | 9 + docs/quick_tutorial/templating/tutorial/home.pt | 9 + docs/quick_tutorial/templating/tutorial/tests.py | 44 +++ docs/quick_tutorial/templating/tutorial/views.py | 13 + docs/quick_tutorial/traversal_addcontent.rst | 105 ++++++ docs/quick_tutorial/traversal_hierarchy.rst | 106 ++++++ docs/quick_tutorial/traversal_siteroot.rst | 153 +++++++++ docs/quick_tutorial/traversal_typeviews.rst | 112 +++++++ docs/quick_tutorial/traversal_zodb.rst | 121 +++++++ docs/quick_tutorial/tutorial_approach.rst | 45 +++ docs/quick_tutorial/unit_testing.rst | 117 +++++++ docs/quick_tutorial/unit_testing/development.ini | 40 +++ docs/quick_tutorial/unit_testing/setup.py | 13 + .../unit_testing/tutorial/__init__.py | 13 + docs/quick_tutorial/unit_testing/tutorial/tests.py | 18 + docs/quick_tutorial/view_classes.rst | 96 ++++++ docs/quick_tutorial/view_classes/development.ini | 41 +++ docs/quick_tutorial/view_classes/setup.py | 13 + .../view_classes/tutorial/__init__.py | 9 + docs/quick_tutorial/view_classes/tutorial/home.pt | 9 + docs/quick_tutorial/view_classes/tutorial/tests.py | 44 +++ docs/quick_tutorial/view_classes/tutorial/views.py | 17 + docs/quick_tutorial/views.rst | 120 +++++++ docs/quick_tutorial/views/development.ini | 40 +++ docs/quick_tutorial/views/setup.py | 13 + docs/quick_tutorial/views/tutorial/__init__.py | 9 + docs/quick_tutorial/views/tutorial/tests.py | 44 +++ docs/quick_tutorial/views/tutorial/views.py | 14 + 179 files changed, 7492 insertions(+) create mode 100644 docs/quick_tutorial/authentication.rst create mode 100644 docs/quick_tutorial/authentication/development.ini create mode 100644 docs/quick_tutorial/authentication/setup.py create mode 100644 docs/quick_tutorial/authentication/tutorial/__init__.py create mode 100644 docs/quick_tutorial/authentication/tutorial/home.pt create mode 100644 docs/quick_tutorial/authentication/tutorial/login.pt create mode 100644 docs/quick_tutorial/authentication/tutorial/security.py create mode 100644 docs/quick_tutorial/authentication/tutorial/tests.py create mode 100644 docs/quick_tutorial/authentication/tutorial/views.py create mode 100644 docs/quick_tutorial/authorization.rst create mode 100644 docs/quick_tutorial/authorization/development.ini create mode 100644 docs/quick_tutorial/authorization/setup.py create mode 100644 docs/quick_tutorial/authorization/tutorial/__init__.py create mode 100644 docs/quick_tutorial/authorization/tutorial/home.pt create mode 100644 docs/quick_tutorial/authorization/tutorial/login.pt create mode 100644 docs/quick_tutorial/authorization/tutorial/resources.py create mode 100644 docs/quick_tutorial/authorization/tutorial/security.py create mode 100644 docs/quick_tutorial/authorization/tutorial/tests.py create mode 100644 docs/quick_tutorial/authorization/tutorial/views.py create mode 100644 docs/quick_tutorial/conf.py create mode 100644 docs/quick_tutorial/databases.rst create mode 100644 docs/quick_tutorial/databases/development.ini create mode 100644 docs/quick_tutorial/databases/setup.py create mode 100644 docs/quick_tutorial/databases/sqltutorial.sqlite create mode 100644 docs/quick_tutorial/databases/tutorial/__init__.py create mode 100644 docs/quick_tutorial/databases/tutorial/initialize_db.py create mode 100644 docs/quick_tutorial/databases/tutorial/models.py create mode 100644 docs/quick_tutorial/databases/tutorial/tests.py create mode 100644 docs/quick_tutorial/databases/tutorial/views.py create mode 100644 docs/quick_tutorial/databases/tutorial/wiki_view.pt create mode 100644 docs/quick_tutorial/databases/tutorial/wikipage_addedit.pt create mode 100644 docs/quick_tutorial/databases/tutorial/wikipage_view.pt create mode 100644 docs/quick_tutorial/debugtoolbar.rst create mode 100644 docs/quick_tutorial/debugtoolbar/development.ini create mode 100644 docs/quick_tutorial/debugtoolbar/setup.py create mode 100644 docs/quick_tutorial/debugtoolbar/tutorial/__init__.py create mode 100644 docs/quick_tutorial/forms.rst create mode 100644 docs/quick_tutorial/forms/development.ini create mode 100644 docs/quick_tutorial/forms/setup.py create mode 100644 docs/quick_tutorial/forms/tutorial/__init__.py create mode 100644 docs/quick_tutorial/forms/tutorial/tests.py create mode 100644 docs/quick_tutorial/forms/tutorial/views.py create mode 100644 docs/quick_tutorial/forms/tutorial/wiki_view.pt create mode 100644 docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt create mode 100644 docs/quick_tutorial/forms/tutorial/wikipage_view.pt create mode 100644 docs/quick_tutorial/functional_testing.rst create mode 100644 docs/quick_tutorial/functional_testing/development.ini create mode 100644 docs/quick_tutorial/functional_testing/setup.py create mode 100644 docs/quick_tutorial/functional_testing/tutorial/__init__.py create mode 100644 docs/quick_tutorial/functional_testing/tutorial/tests.py create mode 100644 docs/quick_tutorial/hello_world.rst create mode 100644 docs/quick_tutorial/hello_world/app.py create mode 100644 docs/quick_tutorial/index.rst create mode 100644 docs/quick_tutorial/ini.rst create mode 100644 docs/quick_tutorial/ini/development.ini create mode 100644 docs/quick_tutorial/ini/setup.py create mode 100644 docs/quick_tutorial/ini/tutorial/__init__.py create mode 100644 docs/quick_tutorial/jinja2.rst create mode 100644 docs/quick_tutorial/jinja2/development.ini create mode 100644 docs/quick_tutorial/jinja2/setup.py create mode 100644 docs/quick_tutorial/jinja2/tutorial/__init__.py create mode 100644 docs/quick_tutorial/jinja2/tutorial/home.jinja2 create mode 100644 docs/quick_tutorial/jinja2/tutorial/home.pt create mode 100644 docs/quick_tutorial/jinja2/tutorial/tests.py create mode 100644 docs/quick_tutorial/jinja2/tutorial/views.py create mode 100644 docs/quick_tutorial/json.rst create mode 100644 docs/quick_tutorial/json/development.ini create mode 100644 docs/quick_tutorial/json/setup.py create mode 100644 docs/quick_tutorial/json/tutorial/__init__.py create mode 100644 docs/quick_tutorial/json/tutorial/home.pt create mode 100644 docs/quick_tutorial/json/tutorial/tests.py create mode 100644 docs/quick_tutorial/json/tutorial/views.py create mode 100644 docs/quick_tutorial/logging.rst create mode 100644 docs/quick_tutorial/logging/development.ini create mode 100644 docs/quick_tutorial/logging/setup.py create mode 100644 docs/quick_tutorial/logging/tutorial/__init__.py create mode 100644 docs/quick_tutorial/logging/tutorial/home.pt create mode 100644 docs/quick_tutorial/logging/tutorial/tests.py create mode 100644 docs/quick_tutorial/logging/tutorial/views.py create mode 100644 docs/quick_tutorial/more_view_classes.rst create mode 100644 docs/quick_tutorial/more_view_classes/development.ini create mode 100644 docs/quick_tutorial/more_view_classes/setup.py create mode 100644 docs/quick_tutorial/more_view_classes/tutorial/__init__.py create mode 100644 docs/quick_tutorial/more_view_classes/tutorial/delete.pt create mode 100644 docs/quick_tutorial/more_view_classes/tutorial/edit.pt create mode 100644 docs/quick_tutorial/more_view_classes/tutorial/hello.pt create mode 100644 docs/quick_tutorial/more_view_classes/tutorial/home.pt create mode 100644 docs/quick_tutorial/more_view_classes/tutorial/tests.py create mode 100644 docs/quick_tutorial/more_view_classes/tutorial/views.py create mode 100644 docs/quick_tutorial/package.rst create mode 100644 docs/quick_tutorial/package/setup.py create mode 100644 docs/quick_tutorial/package/tutorial/__init__.py create mode 100644 docs/quick_tutorial/package/tutorial/app.py create mode 100644 docs/quick_tutorial/pyramid_setup.rst create mode 100644 docs/quick_tutorial/python_setup.rst create mode 100644 docs/quick_tutorial/request_response.rst create mode 100644 docs/quick_tutorial/request_response/development.ini create mode 100644 docs/quick_tutorial/request_response/setup.py create mode 100644 docs/quick_tutorial/request_response/tutorial/__init__.py create mode 100644 docs/quick_tutorial/request_response/tutorial/home.pt create mode 100644 docs/quick_tutorial/request_response/tutorial/tests.py create mode 100644 docs/quick_tutorial/request_response/tutorial/views.py create mode 100644 docs/quick_tutorial/rest_ajax.rst create mode 100644 docs/quick_tutorial/rest_ajax_layout.rst create mode 100644 docs/quick_tutorial/rest_bootstrap.rst create mode 100644 docs/quick_tutorial/routing.rst create mode 100644 docs/quick_tutorial/routing/development.ini create mode 100644 docs/quick_tutorial/routing/setup.py create mode 100644 docs/quick_tutorial/routing/tutorial/__init__.py create mode 100644 docs/quick_tutorial/routing/tutorial/home.pt create mode 100644 docs/quick_tutorial/routing/tutorial/tests.py create mode 100644 docs/quick_tutorial/routing/tutorial/views.py create mode 100644 docs/quick_tutorial/scaffolds.rst create mode 100644 docs/quick_tutorial/scaffolds/CHANGES.txt create mode 100644 docs/quick_tutorial/scaffolds/MANIFEST.in create mode 100644 docs/quick_tutorial/scaffolds/README.txt create mode 100644 docs/quick_tutorial/scaffolds/development.ini create mode 100644 docs/quick_tutorial/scaffolds/production.ini create mode 100644 docs/quick_tutorial/scaffolds/scaffolds/__init__.py create mode 100644 docs/quick_tutorial/scaffolds/scaffolds/static/favicon.ico create mode 100644 docs/quick_tutorial/scaffolds/scaffolds/static/footerbg.png create mode 100644 docs/quick_tutorial/scaffolds/scaffolds/static/headerbg.png create mode 100644 docs/quick_tutorial/scaffolds/scaffolds/static/ie6.css create mode 100644 docs/quick_tutorial/scaffolds/scaffolds/static/middlebg.png create mode 100644 docs/quick_tutorial/scaffolds/scaffolds/static/pylons.css create mode 100644 docs/quick_tutorial/scaffolds/scaffolds/static/pyramid-small.png create mode 100644 docs/quick_tutorial/scaffolds/scaffolds/static/pyramid.png create mode 100644 docs/quick_tutorial/scaffolds/scaffolds/static/transparent.gif create mode 100644 docs/quick_tutorial/scaffolds/scaffolds/templates/mytemplate.pt create mode 100644 docs/quick_tutorial/scaffolds/scaffolds/tests.py create mode 100644 docs/quick_tutorial/scaffolds/scaffolds/views.py create mode 100644 docs/quick_tutorial/scaffolds/setup.cfg create mode 100644 docs/quick_tutorial/scaffolds/setup.py create mode 100644 docs/quick_tutorial/sessions.rst create mode 100644 docs/quick_tutorial/sessions/development.ini create mode 100644 docs/quick_tutorial/sessions/setup.py create mode 100644 docs/quick_tutorial/sessions/tutorial/__init__.py create mode 100644 docs/quick_tutorial/sessions/tutorial/home.pt create mode 100644 docs/quick_tutorial/sessions/tutorial/tests.py create mode 100644 docs/quick_tutorial/sessions/tutorial/views.py create mode 100644 docs/quick_tutorial/static_assets.rst create mode 100644 docs/quick_tutorial/static_assets/development.ini create mode 100644 docs/quick_tutorial/static_assets/setup.py create mode 100644 docs/quick_tutorial/static_assets/tutorial/__init__.py create mode 100644 docs/quick_tutorial/static_assets/tutorial/home.pt create mode 100644 docs/quick_tutorial/static_assets/tutorial/static/app.css create mode 100644 docs/quick_tutorial/static_assets/tutorial/tests.py create mode 100644 docs/quick_tutorial/static_assets/tutorial/views.py create mode 100644 docs/quick_tutorial/templating.rst create mode 100644 docs/quick_tutorial/templating/development.ini create mode 100644 docs/quick_tutorial/templating/setup.py create mode 100644 docs/quick_tutorial/templating/tutorial/__init__.py create mode 100644 docs/quick_tutorial/templating/tutorial/home.pt create mode 100644 docs/quick_tutorial/templating/tutorial/tests.py create mode 100644 docs/quick_tutorial/templating/tutorial/views.py create mode 100644 docs/quick_tutorial/traversal_addcontent.rst create mode 100644 docs/quick_tutorial/traversal_hierarchy.rst create mode 100644 docs/quick_tutorial/traversal_siteroot.rst create mode 100644 docs/quick_tutorial/traversal_typeviews.rst create mode 100644 docs/quick_tutorial/traversal_zodb.rst create mode 100644 docs/quick_tutorial/tutorial_approach.rst create mode 100644 docs/quick_tutorial/unit_testing.rst create mode 100644 docs/quick_tutorial/unit_testing/development.ini create mode 100644 docs/quick_tutorial/unit_testing/setup.py create mode 100644 docs/quick_tutorial/unit_testing/tutorial/__init__.py create mode 100644 docs/quick_tutorial/unit_testing/tutorial/tests.py create mode 100644 docs/quick_tutorial/view_classes.rst create mode 100644 docs/quick_tutorial/view_classes/development.ini create mode 100644 docs/quick_tutorial/view_classes/setup.py create mode 100644 docs/quick_tutorial/view_classes/tutorial/__init__.py create mode 100644 docs/quick_tutorial/view_classes/tutorial/home.pt create mode 100644 docs/quick_tutorial/view_classes/tutorial/tests.py create mode 100644 docs/quick_tutorial/view_classes/tutorial/views.py create mode 100644 docs/quick_tutorial/views.rst create mode 100644 docs/quick_tutorial/views/development.ini create mode 100644 docs/quick_tutorial/views/setup.py create mode 100644 docs/quick_tutorial/views/tutorial/__init__.py create mode 100644 docs/quick_tutorial/views/tutorial/tests.py create mode 100644 docs/quick_tutorial/views/tutorial/views.py (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/authentication.rst b/docs/quick_tutorial/authentication.rst new file mode 100644 index 000000000..6b9b5fafc --- /dev/null +++ b/docs/quick_tutorial/authentication.rst @@ -0,0 +1,134 @@ +============================== +20: Logins With Authentication +============================== + +Login views that authenticate a username/password against a list of +users. + +Background +========== + +Most web applications have URLs that allow people to add/edit/delete +content via a web browser. Time to add +:ref:`security ` +to the application. In this first step we introduce authentication. +That is, logging in and logging out using Pyramid's rich facilities for +pluggable user storages. + +In the next step we will introduce protection resources with +authorization security statements. + +Objectives +========== + +- Introduce the Pyramid concepts of authentication + +- Create login/logout views + +Steps +===== + +#. We are going to use the view classes step as our starting point: + + .. code-block:: bash + + (env27)$ cd ..; cp -r view_classes authentication; cd authentication + (env27)$ python setup.py develop + +#. Put the security hash in the ``authentication/development.ini`` + configuration file as ``tutorial.secret`` instead of putting it in + the code: + + .. literalinclude:: authentication/development.ini + :language: ini + :linenos: + +#. Get authentication (and for now, authorization policies) and login + route into the :term:`configurator` in + ``authentication/tutorial/__init__.py``: + + .. literalinclude:: authentication/tutorial/__init__.py + :linenos: + +#. Create a ``authentication/tutorial/security.py`` module that can find + our user information by providing an *authentication policy callback*: + + .. literalinclude:: authentication/tutorial/security.py + :linenos: + +#. Update the views in ``authentication/tutorial/views.py``: + + .. literalinclude:: authentication/tutorial/views.py + :linenos: + +#. Add a login template at ``authentication/tutorial/login.pt``: + + .. literalinclude:: authentication/tutorial/login.pt + :language: html + :linenos: + +#. Provide a login/logout box in ``authentication/tutorial/home.pt`` + + .. literalinclude:: authentication/tutorial/home.pt + :language: html + :linenos: + +#. Run your Pyramid application with: + + .. code-block:: bash + + (env27)$ pserve development.ini --reload + +#. Open ``http://localhost:6543/`` in a browser. + +#. Click the "Log In" link. + +#. Submit the login form with the username ``editor`` and the password + ``editor``. + +#. Note that the "Log In" link has changed to "Logout". + +#. Click the "Logout" link. + +Analysis +======== + +Unlike many web frameworks, Pyramid includes a built-in (but optional) +security model for authentication and authorization. This security +system is intended to be flexible and support many needs. In this +security model, authentication (who are you) and authorization (what +are you allowed to do) are not just pluggable, but de-coupled. To learn +one step at a time, we provide a system that identifies users and lets +them log out. + +In this example we chose to use the bundled +:ref:`AuthTktAuthenticationPolicy ` +policy. We enabled it in our configuration and provided a +ticket-signing secret in our INI file. + +Our view class grew a login view. When you reached it via a GET, +it returned a login form. When reached via POST, it processed the +username and password against the "groupfinder" callable that we +registered in the configuration. + +In our template, we fetched the ``logged_in`` value from the view +class. We use this to calculate the logged-in user, +if any. In the template we can then choose to show a login link to +anonymous visitors or a logout link to logged-in users. + +Extra Credit +============ + +#. What is the difference between a user and a principal? + +#. Can I use a database behind my ``groupfinder`` to look up principals? + +#. Do I have to put a ``renderer`` in my ``@forbidden_view_config`` + decorator? + +#. Once I am logged in, does any user-centric information get jammed + onto each request? Use ``import pdb; pdb.set_trace()`` to answer + this. + +.. seealso:: :ref:`pyramid:security_chapter`, + :ref:`AuthTktAuthenticationPolicy ` diff --git a/docs/quick_tutorial/authentication/development.ini b/docs/quick_tutorial/authentication/development.ini new file mode 100644 index 000000000..5d4580ff5 --- /dev/null +++ b/docs/quick_tutorial/authentication/development.ini @@ -0,0 +1,42 @@ +[app:main] +use = egg:tutorial +pyramid.reload_templates = true +pyramid.includes = + pyramid_debugtoolbar +tutorial.secret = 98zd + +[server:main] +use = egg:pyramid#wsgiref +host = 0.0.0.0 +port = 6543 + +# Begin logging configuration + +[loggers] +keys = root, tutorial + +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s + +# End logging configuration diff --git a/docs/quick_tutorial/authentication/setup.py b/docs/quick_tutorial/authentication/setup.py new file mode 100644 index 000000000..9997984d3 --- /dev/null +++ b/docs/quick_tutorial/authentication/setup.py @@ -0,0 +1,13 @@ +from setuptools import setup + +requires = [ + 'pyramid', +] + +setup(name='tutorial', + install_requires=requires, + entry_points="""\ + [paste.app_factory] + main = tutorial:main + """, +) \ No newline at end of file diff --git a/docs/quick_tutorial/authentication/tutorial/__init__.py b/docs/quick_tutorial/authentication/tutorial/__init__.py new file mode 100644 index 000000000..7aa049427 --- /dev/null +++ b/docs/quick_tutorial/authentication/tutorial/__init__.py @@ -0,0 +1,24 @@ +from pyramid.authentication import AuthTktAuthenticationPolicy +from pyramid.authorization import ACLAuthorizationPolicy +from pyramid.config import Configurator + +from .security import groupfinder + + +def main(global_config, **settings): + config = Configurator(settings=settings) + + # Security policies + authn_policy = AuthTktAuthenticationPolicy( + settings['tutorial.secret'], callback=groupfinder, + hashalg='sha512') + authz_policy = ACLAuthorizationPolicy() + config.set_authentication_policy(authn_policy) + config.set_authorization_policy(authz_policy) + + config.add_route('home', '/') + config.add_route('hello', '/howdy') + config.add_route('login', '/login') + config.add_route('logout', '/logout') + config.scan('.views') + return config.make_wsgi_app() \ No newline at end of file diff --git a/docs/quick_tutorial/authentication/tutorial/home.pt b/docs/quick_tutorial/authentication/tutorial/home.pt new file mode 100644 index 000000000..6ecd0081b --- /dev/null +++ b/docs/quick_tutorial/authentication/tutorial/home.pt @@ -0,0 +1,18 @@ + + + + Quick Tour: ${name} + + + +
+ Log In + Logout +
+ +

Hi ${name}

+

Visit hello

+ + \ No newline at end of file diff --git a/docs/quick_tutorial/authentication/tutorial/login.pt b/docs/quick_tutorial/authentication/tutorial/login.pt new file mode 100644 index 000000000..4451fc4f8 --- /dev/null +++ b/docs/quick_tutorial/authentication/tutorial/login.pt @@ -0,0 +1,25 @@ + + + + Quick Tour: ${name} + + +

Login

+ + +
+ + +
+ +
+ +
+ + \ No newline at end of file diff --git a/docs/quick_tutorial/authentication/tutorial/security.py b/docs/quick_tutorial/authentication/tutorial/security.py new file mode 100644 index 000000000..ab90bab2c --- /dev/null +++ b/docs/quick_tutorial/authentication/tutorial/security.py @@ -0,0 +1,8 @@ +USERS = {'editor': 'editor', + 'viewer': 'viewer'} +GROUPS = {'editor': ['group:editors']} + + +def groupfinder(userid, request): + if userid in USERS: + return GROUPS.get(userid, []) \ No newline at end of file diff --git a/docs/quick_tutorial/authentication/tutorial/tests.py b/docs/quick_tutorial/authentication/tutorial/tests.py new file mode 100644 index 000000000..6ff554a1e --- /dev/null +++ b/docs/quick_tutorial/authentication/tutorial/tests.py @@ -0,0 +1,47 @@ +import unittest + +from pyramid import testing + + +class TutorialViewTests(unittest.TestCase): + def setUp(self): + self.config = testing.setUp() + + def tearDown(self): + testing.tearDown() + + def test_home(self): + from .views import TutorialViews + + request = testing.DummyRequest() + inst = TutorialViews(request) + response = inst.home() + self.assertEqual('Home View', response['name']) + + def test_hello(self): + from .views import TutorialViews + + request = testing.DummyRequest() + inst = TutorialViews(request) + response = inst.hello() + self.assertEqual('Hello View', response['name']) + + +class TutorialFunctionalTests(unittest.TestCase): + def setUp(self): + from tutorial import main + app = main({}) + from webtest import TestApp + + self.testapp = TestApp(app) + + def tearDown(self): + testing.tearDown() + + def test_home(self): + res = self.testapp.get('/', status=200) + self.assertIn(b'

Hi Home View', res.body) + + def test_hello(self): + res = self.testapp.get('/howdy', status=200) + self.assertIn(b'

Hi Hello View', res.body) diff --git a/docs/quick_tutorial/authentication/tutorial/views.py b/docs/quick_tutorial/authentication/tutorial/views.py new file mode 100644 index 000000000..3038b6d9b --- /dev/null +++ b/docs/quick_tutorial/authentication/tutorial/views.py @@ -0,0 +1,64 @@ +from pyramid.httpexceptions import HTTPFound +from pyramid.security import ( + remember, + forget, + authenticated_userid + ) +from pyramid.view import ( + view_config, + view_defaults + ) + +from .security import USERS + + +@view_defaults(renderer='home.pt') +class TutorialViews: + def __init__(self, request): + self.request = request + self.logged_in = authenticated_userid(request) + + @view_config(route_name='home') + def home(self): + return {'name': 'Home View'} + + @view_config(route_name='hello') + def hello(self): + return {'name': 'Hello View'} + + @view_config(route_name='login', renderer='login.pt') + def login(self): + request = self.request + login_url = request.route_url('login') + referrer = request.url + if referrer == login_url: + referrer = '/' # never use login form itself as came_from + came_from = request.params.get('came_from', referrer) + message = '' + login = '' + password = '' + if 'form.submitted' in request.params: + login = request.params['login'] + password = request.params['password'] + if USERS.get(login) == password: + headers = remember(request, login) + return HTTPFound(location=came_from, + headers=headers) + message = 'Failed login' + + return dict( + name='Login', + message=message, + url=request.application_url + '/login', + came_from=came_from, + login=login, + password=password, + ) + + @view_config(route_name='logout') + def logout(self): + request = self.request + headers = forget(request) + url = request.route_url('home') + return HTTPFound(location=url, + headers=headers) diff --git a/docs/quick_tutorial/authorization.rst b/docs/quick_tutorial/authorization.rst new file mode 100644 index 000000000..37b1a0520 --- /dev/null +++ b/docs/quick_tutorial/authorization.rst @@ -0,0 +1,112 @@ +=========================================== +21: Protecting Resources With Authorization +=========================================== + +Assign security statements to resources describing the permissions +required to perform an operation. + +Background +========== + +Our application has URLs that allow people to add/edit/delete content +via a web browser. Time to add security to the application. Let's +protect our add/edit views to require a login (username of +``editor`` and password of ``editor``.) We will allow the other views +to continue working without a password. + +Objectives +========== + +- Introduce the Pyramid concepts of authentication, authorization, + permissions, and access control lists (ACLs) + +- Make a :term:`root factory` that returns an instance of our + class for the top of the application + +- Assign security statements to our root resource + +- Add a permissions predicate on a view + +- Provide a :term:`Forbidden view` to handle visiting a URL without + adequate permissions + +Steps +===== + +#. We are going to use the authentication step as our starting point: + + .. code-block:: bash + + (env27)$ cd ..; cp -r authentication authorization; cd authorization + (env27)$ python setup.py develop + +#. Start by changing ``authorization/tutorial/__init__.py`` to + specify a root factory to the :term:`pyramid:configurator`: + + .. literalinclude:: authorization/tutorial/__init__.py + :linenos: + +#. That means we need to implement + ``authorization/tutorial/resources.py`` + + .. literalinclude:: authorization/tutorial/resources.py + :linenos: + +#. Change ``authorization/tutorial/views.py`` to require the ``edit`` + permission on the ``hello`` view and implement the forbidden view: + + .. literalinclude:: authorization/tutorial/views.py + :linenos: + +#. Run your Pyramid application with: + + .. code-block:: bash + + (env27)$ pserve development.ini --reload + +#. Open ``http://localhost:6543/`` in a browser. + +#. If you are still logged in, click the "Log Out" link. + +#. Visit ``http://localhost:6543/howdy`` in a browser. You should be + asked to login. + +Analysis +======== + +This simple tutorial step can be boiled down to the following: + +- A view can require a *permission* (``edit``) + +- The context for our view (the ``Root``) has an access control list + (ACL) + +- This ACL says that the ``edit`` permission is available on ``Root`` + to the ``group:editors`` *principal* + +- The registered ``groupfinder`` answers whether a particular user + (``editor``) has a particular group (``group:editors``) + +In summary: ``hello`` wants ``edit`` permission, ``Root`` says +``group:editors`` has ``edit`` permission. + +Of course, this only applies on ``Root``. Some other part of the site +(a.k.a. *context*) might have a different ACL. + +If you are not logged in and visit ``/hello``, you need to get +shown the login screen. How does Pyramid know what is the login page to +use? We explicitly told Pyramid that the ``login`` view should be used +by decorating the view with ``@forbidden_view_config``. + +Extra Credit +============ + +#. Perhaps you would like experience of not having enough permissions + (forbidden) to be richer. How could you change this? + +#. Perhaps we want to store security statements in a database and + allow editing via a browser. How might this be done? + +#. What if we want different security statements on different kinds of + objects? Or on the same kinds of objects, but in different parts of a + URL hierarchy? diff --git a/docs/quick_tutorial/authorization/development.ini b/docs/quick_tutorial/authorization/development.ini new file mode 100644 index 000000000..5d4580ff5 --- /dev/null +++ b/docs/quick_tutorial/authorization/development.ini @@ -0,0 +1,42 @@ +[app:main] +use = egg:tutorial +pyramid.reload_templates = true +pyramid.includes = + pyramid_debugtoolbar +tutorial.secret = 98zd + +[server:main] +use = egg:pyramid#wsgiref +host = 0.0.0.0 +port = 6543 + +# Begin logging configuration + +[loggers] +keys = root, tutorial + +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s + +# End logging configuration diff --git a/docs/quick_tutorial/authorization/setup.py b/docs/quick_tutorial/authorization/setup.py new file mode 100644 index 000000000..9997984d3 --- /dev/null +++ b/docs/quick_tutorial/authorization/setup.py @@ -0,0 +1,13 @@ +from setuptools import setup + +requires = [ + 'pyramid', +] + +setup(name='tutorial', + install_requires=requires, + entry_points="""\ + [paste.app_factory] + main = tutorial:main + """, +) \ No newline at end of file diff --git a/docs/quick_tutorial/authorization/tutorial/__init__.py b/docs/quick_tutorial/authorization/tutorial/__init__.py new file mode 100644 index 000000000..715a14203 --- /dev/null +++ b/docs/quick_tutorial/authorization/tutorial/__init__.py @@ -0,0 +1,25 @@ +from pyramid.authentication import AuthTktAuthenticationPolicy +from pyramid.authorization import ACLAuthorizationPolicy +from pyramid.config import Configurator + +from .security import groupfinder + + +def main(global_config, **settings): + config = Configurator(settings=settings, + root_factory='.resources.Root') + + # Security policies + authn_policy = AuthTktAuthenticationPolicy( + settings['tutorial.secret'], callback=groupfinder, + hashalg='sha512') + authz_policy = ACLAuthorizationPolicy() + config.set_authentication_policy(authn_policy) + config.set_authorization_policy(authz_policy) + + config.add_route('home', '/') + config.add_route('hello', '/howdy') + config.add_route('login', '/login') + config.add_route('logout', '/logout') + config.scan('.views') + return config.make_wsgi_app() \ No newline at end of file diff --git a/docs/quick_tutorial/authorization/tutorial/home.pt b/docs/quick_tutorial/authorization/tutorial/home.pt new file mode 100644 index 000000000..6ecd0081b --- /dev/null +++ b/docs/quick_tutorial/authorization/tutorial/home.pt @@ -0,0 +1,18 @@ + + + + Quick Tour: ${name} + + + +
+ Log In + Logout +
+ +

Hi ${name}

+

Visit hello

+ + \ No newline at end of file diff --git a/docs/quick_tutorial/authorization/tutorial/login.pt b/docs/quick_tutorial/authorization/tutorial/login.pt new file mode 100644 index 000000000..4451fc4f8 --- /dev/null +++ b/docs/quick_tutorial/authorization/tutorial/login.pt @@ -0,0 +1,25 @@ + + + + Quick Tour: ${name} + + +

Login

+ + +
+ + +
+ +
+ +
+ + \ No newline at end of file diff --git a/docs/quick_tutorial/authorization/tutorial/resources.py b/docs/quick_tutorial/authorization/tutorial/resources.py new file mode 100644 index 000000000..0cb656f12 --- /dev/null +++ b/docs/quick_tutorial/authorization/tutorial/resources.py @@ -0,0 +1,9 @@ +from pyramid.security import Allow, Everyone + + +class Root(object): + __acl__ = [(Allow, Everyone, 'view'), + (Allow, 'group:editors', 'edit')] + + def __init__(self, request): + pass \ No newline at end of file diff --git a/docs/quick_tutorial/authorization/tutorial/security.py b/docs/quick_tutorial/authorization/tutorial/security.py new file mode 100644 index 000000000..ab90bab2c --- /dev/null +++ b/docs/quick_tutorial/authorization/tutorial/security.py @@ -0,0 +1,8 @@ +USERS = {'editor': 'editor', + 'viewer': 'viewer'} +GROUPS = {'editor': ['group:editors']} + + +def groupfinder(userid, request): + if userid in USERS: + return GROUPS.get(userid, []) \ No newline at end of file diff --git a/docs/quick_tutorial/authorization/tutorial/tests.py b/docs/quick_tutorial/authorization/tutorial/tests.py new file mode 100644 index 000000000..6ff554a1e --- /dev/null +++ b/docs/quick_tutorial/authorization/tutorial/tests.py @@ -0,0 +1,47 @@ +import unittest + +from pyramid import testing + + +class TutorialViewTests(unittest.TestCase): + def setUp(self): + self.config = testing.setUp() + + def tearDown(self): + testing.tearDown() + + def test_home(self): + from .views import TutorialViews + + request = testing.DummyRequest() + inst = TutorialViews(request) + response = inst.home() + self.assertEqual('Home View', response['name']) + + def test_hello(self): + from .views import TutorialViews + + request = testing.DummyRequest() + inst = TutorialViews(request) + response = inst.hello() + self.assertEqual('Hello View', response['name']) + + +class TutorialFunctionalTests(unittest.TestCase): + def setUp(self): + from tutorial import main + app = main({}) + from webtest import TestApp + + self.testapp = TestApp(app) + + def tearDown(self): + testing.tearDown() + + def test_home(self): + res = self.testapp.get('/', status=200) + self.assertIn(b'

Hi Home View', res.body) + + def test_hello(self): + res = self.testapp.get('/howdy', status=200) + self.assertIn(b'

Hi Hello View', res.body) diff --git a/docs/quick_tutorial/authorization/tutorial/views.py b/docs/quick_tutorial/authorization/tutorial/views.py new file mode 100644 index 000000000..92c1946ba --- /dev/null +++ b/docs/quick_tutorial/authorization/tutorial/views.py @@ -0,0 +1,66 @@ +from pyramid.httpexceptions import HTTPFound +from pyramid.security import ( + remember, + forget, + authenticated_userid + ) +from pyramid.view import ( + view_config, + view_defaults, + forbidden_view_config + ) + +from .security import USERS + + +@view_defaults(renderer='home.pt') +class TutorialViews: + def __init__(self, request): + self.request = request + self.logged_in = authenticated_userid(request) + + @view_config(route_name='home') + def home(self): + return {'name': 'Home View'} + + @view_config(route_name='hello', permission='edit') + def hello(self): + return {'name': 'Hello View'} + + @view_config(route_name='login', renderer='login.pt') + @forbidden_view_config(renderer='login.pt') + def login(self): + request = self.request + login_url = request.route_url('login') + referrer = request.url + if referrer == login_url: + referrer = '/' # never use login form itself as came_from + came_from = request.params.get('came_from', referrer) + message = '' + login = '' + password = '' + if 'form.submitted' in request.params: + login = request.params['login'] + password = request.params['password'] + if USERS.get(login) == password: + headers = remember(request, login) + return HTTPFound(location=came_from, + headers=headers) + message = 'Failed login' + + return dict( + name='Login', + message=message, + url=request.application_url + '/login', + came_from=came_from, + login=login, + password=password, + ) + + @view_config(route_name='logout') + def logout(self): + request = self.request + headers = forget(request) + url = request.route_url('home') + return HTTPFound(location=url, + headers=headers) diff --git a/docs/quick_tutorial/conf.py b/docs/quick_tutorial/conf.py new file mode 100644 index 000000000..47b8fae41 --- /dev/null +++ b/docs/quick_tutorial/conf.py @@ -0,0 +1,281 @@ +# -*- coding: utf-8 -*- +# +# Getting Started with Pyramid and REST documentation build configuration file, created by +# sphinx-quickstart on Mon Aug 26 14:44:57 2013. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.intersphinx'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Getting Started with Pyramid and REST' +copyright = u'2013, Agendaless Consulting' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +release = '1.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'GettingStartedwithPyramidandRESTdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + #'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + #'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + #'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'GettingStartedwithPyramidandREST.tex', + u'Getting Started with Pyramid and REST Documentation', + u'Agendaless Consulting', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'gettingstartedwithpyramidandrest', + u'Getting Started with Pyramid and REST Documentation', + [u'Agendaless Consulting'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'GettingStartedwithPyramidandREST', + u'Getting Started with Pyramid and REST Documentation', + u'Agendaless Consulting', 'GettingStartedwithPyramidandREST', + 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = { + 'python': ( + 'http://docs.python.org/2', + None), + 'sqla': ( + 'http://docs.sqlalchemy.org/en/latest', + None), + 'pyramid': ( + 'http://docs.pylonsproject.org/projects/pyramid/en/latest/', + None), + 'jinja2': ( + 'http://docs.pylonsproject.org/projects/pyramid_jinja2/en/latest/', + None), + 'toolbar': ( + 'http://docs.pylonsproject.org/projects/pyramid_debugtoolbar/en/latest', + None), + 'deform': ( + 'http://docs.pylonsproject.org/projects/deform/en/latest', + None), + 'colander': ( + 'http://docs.pylonsproject.org/projects/colander/en/latest', + None), + 'tutorials': ( + 'http://docs.pylonsproject.org/projects/pyramid_tutorials/en/latest/', + None), +} diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst new file mode 100644 index 000000000..d2d2ce699 --- /dev/null +++ b/docs/quick_tutorial/databases.rst @@ -0,0 +1,184 @@ +============================== +19: Databases Using SQLAlchemy +============================== + +Store/retrieve data using the SQLAlchemy ORM atop the SQLite database. + +Background +========== + +Our Pyramid-based wiki application now needs database-backed storage of +pages. This frequently means a SQL database. The Pyramid community +strongly supports the +:ref:`SQLAlchemy ` project and its +:ref:`object-relational mapper (ORM) ` +as a convenient, Pythonic way to interface to databases. + +In this step we hook up SQLAlchemy to a SQLite database table, +providing storage and retrieval for the wikipages in the previous step. + +.. note:: + + The ``alchemy`` scaffold is really helpful for getting a + SQLAlchemy project going, including generation of the console + script. Since we want to see all the decisions, we will forgo + convenience in this tutorial and wire it up ourselves. + +Objectives +========== + +- Store pages in SQLite by using SQLAlchemy models + +- Use SQLAlchemy queries to list/add/view/edit pages + +- Provide a database-initialize command by writing a Pyramid *console + script* which can be run from the command line + +Steps +===== + +#. We are going to use the forms step as our starting point: + + .. code-block:: bash + + (env27)$ cd ..; cp -r forms databases; cd databases + +#. We need to add some dependencies in ``databases/setup.py`` as well + as an "entry point" for the command-line script: + + .. literalinclude:: databases/setup.py + :linenos: + + .. note:: + + We aren't yet doing ``python3.3 setup.py develop`` as we + are changing it later. + +#. Our configuration file at ``databases/development.ini`` wires + together some new pieces: + + .. literalinclude:: databases/development.ini + :language: ini + +#. This engine configuration now needs to be read into the application + through changes in ``databases/tutorial/__init__.py``: + + .. literalinclude:: databases/tutorial/__init__.py + :linenos: + +#. Make a command-line script at ``databases/tutorial/initialize_db.py`` + to initialize the database: + + .. literalinclude:: databases/tutorial/initialize_db.py + +#. Since ``setup.py`` changed, we now run it: + + .. code-block:: bash + + (env27)$ python setup.py develop + +#. The script references some models in ``databases/tutorial/models.py``: + + .. literalinclude:: databases/tutorial/models.py + :linenos: + +#. Let's run this console script, thus producing our database and table: + + .. code-block:: bash + + (env27)$ initialize_tutorial_db development.ini + 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages") + 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2013-09-06 15:54:08,051 INFO [sqlalchemy.engine.base.Engine][MainThread] + CREATE TABLE wikipages ( + uid INTEGER NOT NULL, + title TEXT, + body TEXT, + PRIMARY KEY (uid), + UNIQUE (title) + ) + +#. With our data now driven by SQLAlchemy queries, we need to update + our ``databases/tutorial/views.py``: + + .. literalinclude:: databases/tutorial/views.py + +#. Our tests in ``databases/tutorial/tests.py`` changed to include + SQLAlchemy bootstrapping: + + .. literalinclude:: databases/tutorial/tests.py + :linenos: + +#. Run the tests in your package using ``nose``: + + .. code-block:: bash + + (env27)$ nosetests . + .. + ----------------------------------------------------------------- + Ran 2 tests in 1.141s + + OK + +#. Run your Pyramid application with: + + .. code-block:: bash + + (env27)$ pserve development.ini --reload + +#. Open ``http://localhost:6543/`` in a browser. + +Analysis +======== + +Let's start with the dependencies. We made the decision to use +``SQLAlchemy`` to talk to our database. We also, though, installed +``pyramid_tm`` and ``zope.sqlalchemy``. Why? + +Pyramid has a strong orientation towards support for ``transactions``. +Specifically, you can install a transaction manager into your app +application, either as middleware or a Pyramid "tween". Then, +just before you return the response, all transaction-aware parts of +your application are executed. + +This means Pyramid view code usually doesn't manage transactions. If +your view code or a template generates an error, the transaction manager +aborts the transaction. This is a very liberating way to write code. + +The ``pyramid_tm`` package provides a "tween" that is configured in the +``development.ini`` configuration file. That installs it. We then need +a package that makes SQLAlchemy and thus the RDBMS transaction manager +integrate with the Pyramid transaction manager. That's what +``zope.sqlalchemy`` does. + +Where do we point at the location on disk for the SQLite file? In the +configuration file. This lets consumers of our package change the +location in a safe (non-code) way. That is, in configuration. This +configuration-oriented approach isn't required in Pyramid; you can +still make such statements in your ``__init__.py`` or some companion +module. + +The ``initialize_tutorial_db`` is a nice example of framework support. +You point your setup at the location of some ``[console_scripts]`` and +these get generated into your virtualenv's ``bin`` directory. Our +console script follows the pattern of being fed a configuration file +with all the bootstrapping. It then opens SQLAlchemy and creates the +root of the wiki, which also makes the SQLite file. Note the +``with transaction.manager`` part that puts the work in the scope of a +transaction (as we aren't inside a web request where this is done +automatically.) + +The ``models.py`` does a little bit extra work to hook up SQLAlchemy +into the Pyramid transaction manager. It then declares the model for a +``Page``. + +Our views have changes primarily around replacing our dummy +dictionary-of-dictionaries data with proper database support: list the +rows, add a row, edit a row, and delete a row. + +Extra Credit +============ + +#. Why all this code? Why can't I just type 2 lines and have magic ensue? + +#. Give a try at a button that deletes a wiki page. diff --git a/docs/quick_tutorial/databases/development.ini b/docs/quick_tutorial/databases/development.ini new file mode 100644 index 000000000..270da960f --- /dev/null +++ b/docs/quick_tutorial/databases/development.ini @@ -0,0 +1,49 @@ +[app:main] +use = egg:tutorial +pyramid.reload_templates = true +pyramid.includes = + pyramid_debugtoolbar + pyramid_tm + +sqlalchemy.url = sqlite:///%(here)s/sqltutorial.sqlite + +[server:main] +use = egg:pyramid#wsgiref +host = 0.0.0.0 +port = 6543 + +# Begin logging configuration + +[loggers] +keys = root, tutorial, sqlalchemy + +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + +[logger_sqlalchemy] +level = INFO +handlers = +qualname = sqlalchemy.engine + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s + +# End logging configuration diff --git a/docs/quick_tutorial/databases/setup.py b/docs/quick_tutorial/databases/setup.py new file mode 100644 index 000000000..5cb197c39 --- /dev/null +++ b/docs/quick_tutorial/databases/setup.py @@ -0,0 +1,20 @@ +from setuptools import setup + +requires = [ + 'pyramid', + 'deform', + 'sqlalchemy', + 'pyramid_tm', + 'zope.sqlalchemy', + 'pysqlite' +] + +setup(name='tutorial', + install_requires=requires, + entry_points="""\ + [paste.app_factory] + main = tutorial:main + [console_scripts] + initialize_tutorial_db = tutorial.initialize_db:main + """, +) \ No newline at end of file diff --git a/docs/quick_tutorial/databases/sqltutorial.sqlite b/docs/quick_tutorial/databases/sqltutorial.sqlite new file mode 100644 index 000000000..b8bd856fd Binary files /dev/null and b/docs/quick_tutorial/databases/sqltutorial.sqlite differ diff --git a/docs/quick_tutorial/databases/tutorial/__init__.py b/docs/quick_tutorial/databases/tutorial/__init__.py new file mode 100644 index 000000000..47e8fefa6 --- /dev/null +++ b/docs/quick_tutorial/databases/tutorial/__init__.py @@ -0,0 +1,20 @@ +from pyramid.config import Configurator + +from sqlalchemy import engine_from_config + +from .models import DBSession, Base + +def main(global_config, **settings): + engine = engine_from_config(settings, 'sqlalchemy.') + DBSession.configure(bind=engine) + Base.metadata.bind = engine + + config = Configurator(settings=settings, + root_factory='tutorial.models.Root') + config.add_route('wiki_view', '/') + config.add_route('wikipage_add', '/add') + config.add_route('wikipage_view', '/{uid}') + config.add_route('wikipage_edit', '/{uid}/edit') + config.add_static_view('deform_static', 'deform:static/') + config.scan('.views') + return config.make_wsgi_app() \ No newline at end of file diff --git a/docs/quick_tutorial/databases/tutorial/initialize_db.py b/docs/quick_tutorial/databases/tutorial/initialize_db.py new file mode 100644 index 000000000..98be524a1 --- /dev/null +++ b/docs/quick_tutorial/databases/tutorial/initialize_db.py @@ -0,0 +1,37 @@ +import os +import sys +import transaction + +from sqlalchemy import engine_from_config + +from pyramid.paster import ( + get_appsettings, + setup_logging, + ) + +from .models import ( + DBSession, + Page, + Base, + ) + + +def usage(argv): + cmd = os.path.basename(argv[0]) + print('usage: %s \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] + setup_logging(config_uri) + settings = get_appsettings(config_uri) + engine = engine_from_config(settings, 'sqlalchemy.') + DBSession.configure(bind=engine) + Base.metadata.create_all(engine) + with transaction.manager: + model = Page(title='Root', body='

Root

') + DBSession.add(model) diff --git a/docs/quick_tutorial/databases/tutorial/models.py b/docs/quick_tutorial/databases/tutorial/models.py new file mode 100644 index 000000000..b27c38417 --- /dev/null +++ b/docs/quick_tutorial/databases/tutorial/models.py @@ -0,0 +1,35 @@ +from pyramid.security import Allow, Everyone + +from sqlalchemy import ( + Column, + Integer, + Text, + ) + +from sqlalchemy.ext.declarative import declarative_base + +from sqlalchemy.orm import ( + scoped_session, + sessionmaker, + ) + +from zope.sqlalchemy import ZopeTransactionExtension + +DBSession = scoped_session( + sessionmaker(extension=ZopeTransactionExtension())) +Base = declarative_base() + + +class Page(Base): + __tablename__ = 'wikipages' + uid = Column(Integer, primary_key=True) + title = Column(Text, unique=True) + body = Column(Text) + + +class Root(object): + __acl__ = [(Allow, Everyone, 'view'), + (Allow, 'group:editors', 'edit')] + + def __init__(self, request): + pass \ No newline at end of file diff --git a/docs/quick_tutorial/databases/tutorial/tests.py b/docs/quick_tutorial/databases/tutorial/tests.py new file mode 100644 index 000000000..e18e70c8c --- /dev/null +++ b/docs/quick_tutorial/databases/tutorial/tests.py @@ -0,0 +1,58 @@ +import unittest +import transaction + +from pyramid import testing + + +def _initTestingDB(): + from sqlalchemy import create_engine + from .models import ( + DBSession, + Page, + Base + ) + engine = create_engine('sqlite://') + Base.metadata.create_all(engine) + DBSession.configure(bind=engine) + with transaction.manager: + model = Page(title='FrontPage', body='This is the front page') + DBSession.add(model) + return DBSession + + +class WikiViewTests(unittest.TestCase): + def setUp(self): + self.session = _initTestingDB() + self.config = testing.setUp() + + def tearDown(self): + self.session.remove() + testing.tearDown() + + def test_wiki_view(self): + from tutorial.views import WikiViews + + request = testing.DummyRequest() + inst = WikiViews(request) + response = inst.wiki_view() + self.assertEqual(response['title'], 'Wiki View') + + +class WikiFunctionalTests(unittest.TestCase): + def setUp(self): + self.session = _initTestingDB() + self.config = testing.setUp() + from pyramid.paster import get_app + app = get_app('development.ini') + from webtest import TestApp + self.testapp = TestApp(app) + + def tearDown(self): + self.session.remove() + testing.tearDown() + + def test_it(self): + res = self.testapp.get('/', status=200) + self.assertIn(b'Wiki: View', res.body) + res = self.testapp.get('/add', status=200) + self.assertIn(b'Add/Edit', res.body) diff --git a/docs/quick_tutorial/databases/tutorial/views.py b/docs/quick_tutorial/databases/tutorial/views.py new file mode 100644 index 000000000..4608c6d43 --- /dev/null +++ b/docs/quick_tutorial/databases/tutorial/views.py @@ -0,0 +1,96 @@ +import colander +import deform.widget + +from pyramid.httpexceptions import HTTPFound +from pyramid.view import view_config + +from .models import DBSession, Page + + +class WikiPage(colander.MappingSchema): + title = colander.SchemaNode(colander.String()) + body = colander.SchemaNode( + colander.String(), + widget=deform.widget.RichTextWidget() + ) + + +class WikiViews(object): + def __init__(self, request): + self.request = request + + @property + def wiki_form(self): + schema = WikiPage() + return deform.Form(schema, buttons=('submit',)) + + @property + def reqts(self): + return self.wiki_form.get_widget_resources() + + @view_config(route_name='wiki_view', renderer='wiki_view.pt') + def wiki_view(self): + pages = DBSession.query(Page).order_by(Page.title) + return dict(title='Wiki View', pages=pages) + + @view_config(route_name='wikipage_add', + renderer='wikipage_addedit.pt') + def wikipage_add(self): + form = self.wiki_form.render() + + if 'submit' in self.request.params: + controls = self.request.POST.items() + try: + appstruct = self.wiki_form.validate(controls) + except deform.ValidationFailure as e: + # Form is NOT valid + return dict(form=e.render()) + + # Add a new page to the database + new_title = appstruct['title'] + new_body = appstruct['body'] + DBSession.add(Page(title=new_title, body=new_body)) + + # Get the new ID and redirect + page = DBSession.query(Page).filter_by(title=new_title).one() + new_uid = page.uid + + url = self.request.route_url('wikipage_view', uid=new_uid) + return HTTPFound(url) + + return dict(form=form) + + + @view_config(route_name='wikipage_view', renderer='wikipage_view.pt') + def wikipage_view(self): + uid = int(self.request.matchdict['uid']) + page = DBSession.query(Page).filter_by(uid=uid).one() + return dict(page=page) + + + @view_config(route_name='wikipage_edit', + renderer='wikipage_addedit.pt') + def wikipage_edit(self): + uid = int(self.request.matchdict['uid']) + page = DBSession.query(Page).filter_by(uid=uid).one() + + wiki_form = self.wiki_form + + if 'submit' in self.request.params: + controls = self.request.POST.items() + try: + appstruct = wiki_form.validate(controls) + except deform.ValidationFailure as e: + return dict(page=page, form=e.render()) + + # Change the content and redirect to the view + page.title = appstruct['title'] + page.body = appstruct['body'] + url = self.request.route_url('wikipage_view', uid=uid) + return HTTPFound(url) + + form = self.wiki_form.render(dict( + uid=page.uid, title=page.title, body=page.body) + ) + + return dict(page=page, form=form) diff --git a/docs/quick_tutorial/databases/tutorial/wiki_view.pt b/docs/quick_tutorial/databases/tutorial/wiki_view.pt new file mode 100644 index 000000000..9e3afe495 --- /dev/null +++ b/docs/quick_tutorial/databases/tutorial/wiki_view.pt @@ -0,0 +1,19 @@ + + + + Wiki: View + + +

Wiki

+ +Add + WikiPage + + + \ No newline at end of file diff --git a/docs/quick_tutorial/databases/tutorial/wikipage_addedit.pt b/docs/quick_tutorial/databases/tutorial/wikipage_addedit.pt new file mode 100644 index 000000000..d1fea0d7f --- /dev/null +++ b/docs/quick_tutorial/databases/tutorial/wikipage_addedit.pt @@ -0,0 +1,22 @@ + + + + WikiPage: Add/Edit + + + + + + + + +

Wiki

+ +

${structure: form}

+ + + diff --git a/docs/quick_tutorial/databases/tutorial/wikipage_view.pt b/docs/quick_tutorial/databases/tutorial/wikipage_view.pt new file mode 100644 index 000000000..cb9ff526e --- /dev/null +++ b/docs/quick_tutorial/databases/tutorial/wikipage_view.pt @@ -0,0 +1,17 @@ + + + + WikiPage: View + + + + Up + | + + Edit + + +

${page.title}

+

${structure: page.body}

+ + \ No newline at end of file diff --git a/docs/quick_tutorial/debugtoolbar.rst b/docs/quick_tutorial/debugtoolbar.rst new file mode 100644 index 000000000..42e665d4f --- /dev/null +++ b/docs/quick_tutorial/debugtoolbar.rst @@ -0,0 +1,87 @@ +============================================ +04: Easier Development with ``debugtoolbar`` +============================================ + +Error-handling and introspection using the ``pyramid_debugtoolbar`` +add-on. + +Background +========== + +As we introduce the basics we also want to show how to be productive in +development and debugging. For example, we just discussed template +reloading and earlier we showed ``--reload`` for application reloading. + +``pyramid_debugtoolbar`` is a popular Pyramid add-on which makes +several tools available in your browser. Adding it to your project +illustrates several points about configuration. + +Objectives +========== + +- Install and enable the toolbar to help during development + +- Explain Pyramid add-ons + +- Show how an add-on gets configured into your application + +Steps +===== + +#. First we copy the results of the previous step, as well as install + the ``pyramid_debugtoolbar`` package: + + .. code-block:: bash + + (env27)$ cd ..; cp -r ini debugtoolbar; cd debugtoolbar + (env27)$ python setup.py develop + (env27)$ easy_install pyramid_debugtoolbar + + +#. Our ``debugtoolbar/development.ini`` gets a configuration entry for + ``pyramid.includes``: + + .. literalinclude:: debugtoolbar/development.ini + :language: ini + :linenos: + +#. Run the WSGI application with: + + .. code-block:: bash + + (env27)$ pserve development.ini --reload + +#. Open ``http://localhost:6543/`` in your browser. See the handy + toolbar on the right. + +Analysis +======== + +``pyramid_debugtoolbar`` is a full-fledged Python package, +available on PyPI just like thousands of other Python packages. Thus we +start by installing the ``pyramid_debugtoolbar`` package into our +virtual environment using normal Python package installation commands. + +The ``pyramid_debugtoolbar`` Python package is also a Pyramid add-on, +which means we need to include its add-on configuration into our web +application. We could do this with imperative configuration in +``tutorial/__init__.py`` by using ``config.include``. Pyramid also +supports wiring in add-on configuration via our ``development.ini`` +using ``pyramid.includes``. We use this to load the configuration for +the debugtoolbar. + +You'll now see an attractive (and collapsible) menu in the right of +your browser, providing introspective access to debugging information. +Even better, if your web application generates an error, +you will see a nice traceback on the screen. When you want to disable +this toolbar, no need to change code: you can remove it from +``pyramid.includes`` in the relevant ``.ini`` configuration file (thus +showing why configuration files are handy.) + +Note that the toolbar mutates the HTML generated by our app and uses jQuery to +overlay itself. If you are using the toolbar while you're developing and you +start to experience otherwise inexplicable client-side weirdness, you can shut +it off by commenting out the ``pyramid_debugtoolbar`` line in +``pyramid.includes`` temporarily. + +.. seealso:: See Also: :ref:`pyramid_debugtoolbar ` diff --git a/docs/quick_tutorial/debugtoolbar/development.ini b/docs/quick_tutorial/debugtoolbar/development.ini new file mode 100644 index 000000000..470d92c57 --- /dev/null +++ b/docs/quick_tutorial/debugtoolbar/development.ini @@ -0,0 +1,40 @@ +[app:main] +use = egg:tutorial +pyramid.includes = + pyramid_debugtoolbar + +[server:main] +use = egg:pyramid#wsgiref +host = 0.0.0.0 +port = 6543 + +# Begin logging configuration + +[loggers] +keys = root, tutorial + +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s + +# End logging configuration diff --git a/docs/quick_tutorial/debugtoolbar/setup.py b/docs/quick_tutorial/debugtoolbar/setup.py new file mode 100644 index 000000000..9997984d3 --- /dev/null +++ b/docs/quick_tutorial/debugtoolbar/setup.py @@ -0,0 +1,13 @@ +from setuptools import setup + +requires = [ + 'pyramid', +] + +setup(name='tutorial', + install_requires=requires, + entry_points="""\ + [paste.app_factory] + main = tutorial:main + """, +) \ No newline at end of file diff --git a/docs/quick_tutorial/debugtoolbar/tutorial/__init__.py b/docs/quick_tutorial/debugtoolbar/tutorial/__init__.py new file mode 100644 index 000000000..2b4e84f30 --- /dev/null +++ b/docs/quick_tutorial/debugtoolbar/tutorial/__init__.py @@ -0,0 +1,13 @@ +from pyramid.config import Configurator +from pyramid.response import Response + + +def hello_world(request): + return Response('

Hello World!

') + + +def main(global_config, **settings): + config = Configurator(settings=settings) + config.add_route('hello', '/') + config.add_view(hello_world, route_name='hello') + return config.make_wsgi_app() \ No newline at end of file diff --git a/docs/quick_tutorial/forms.rst b/docs/quick_tutorial/forms.rst new file mode 100644 index 000000000..bb7cab3f7 --- /dev/null +++ b/docs/quick_tutorial/forms.rst @@ -0,0 +1,146 @@ +==================================== +18: Forms and Validation With Deform +==================================== + +Schema-driven, autogenerated forms with validation. + +Background +========== + +Modern web applications deal extensively with forms. Developers, +though, have a wide range of philosophies about how frameworks should +help them with their forms. As such, Pyramid doesn't directly bundle +one particular form library. Instead, there are a variety of form +libraries that are easy to use in Pyramid. + +:ref:`Deform ` +is one such library. In this step, we introduce Deform for our +forms and validation. This also gives us the +:ref:`Colander ` for schemas and validation. + +Deform is getting a facelift, with styling from Twitter Bootstrap and +advanced widgets from popular JavaScript projects. The work began in +``deform_bootstrap`` and is being merged into an update to Deform. + +Objectives +========== + +- Make a schema using Colander, the companion to Deform + +- Create a form with Deform and change our views to handle validation + +Steps +===== + +#. First we copy the results of the ``view_classes`` step: + + .. code-block:: bash + + (env27)$ cd ..; cp -r view_classes forms; cd forms + +#. Let's edit ``forms/setup.py`` to declare a dependency on Deform + (which then pulls in Colander as a dependency: + + .. literalinclude:: forms/setup.py + :linenos: + +#. We can now install our project in development mode: + + .. code-block:: bash + + (env27)$ python setup.py develop + +#. Register a static view in ``forms/tutorial/__init__.py`` for + Deform's CSS/JS etc. as well as our demo wikipage scenario's + views: + + .. literalinclude:: forms/tutorial/__init__.py + :linenos: + +#. Implement the new views, as well as the form schemas and some + dummy data, in ``forms/tutorial/views.py``: + + .. literalinclude:: forms/tutorial/views.py + :linenos: + +#. A template for the top of the "wiki" in + ``forms/tutorial/wiki_view.pt``: + + .. literalinclude:: forms/tutorial/wiki_view.pt + :language: html + :linenos: + +#. Another template for adding/editing in + ``forms/tutorial/wikipage_addedit.pt``: + + .. literalinclude:: forms/tutorial/wikipage_addedit.pt + :language: html + :linenos: + +#. Finally, a template at ``forms/tutorial/wikipage_view.pt`` + for viewing a wiki page: + + .. literalinclude:: forms/tutorial/wikipage_view.pt + :language: html + :linenos: + +#. Run your Pyramid application with: + + .. code-block:: bash + + (env27)$ pserve development.ini --reload + +#. Open ``http://localhost:6543/`` in a browser. + + +Analysis +======== + +This step helps illustrate the utility of asset specifications for +static assets. We have an outside package called Deform with static +assets which need to be published. We don't have to know where on disk +it is located. We point at the package, then the path inside the package. + +We just need to include a call to ``add_static_view`` to make that +directory available at a URL. For Pyramid-specific pages, +Pyramid provides a facility (``config.include()``) which even makes +that unnecessary for consumers of a package. (Deform is not specific to +Pyramid.) + +Our forms have rich widgets which need the static CSS and JS just +mentioned. Deform has a :term:`resource registry` which allows widgets +to specify which JS and CSS are needed. Our ``wikipage_addedit.pt`` +template shows how we iterated over that data to generate markup that +includes the needed resources. + +Our add and edit views use a pattern called *self-posting forms*. +Meaning, the same URL is used to ``GET`` the form as is used to +``POST`` the form. The route, the view, and the template are the same +whether you are walking up to it the first time or you clicked a button. + +Inside the view we do ``if 'submit' in self.request.params:`` to see if +this form was a ``POST`` where the user clicked on a particular button +````. + +The form controller then follows a typical pattern: + +- If you are doing a GET, skip over and just return the form + +- If you are doing a POST, validate the form contents + +- If the form is invalid, bail out by re-rendering the form with the + supplied ``POST`` data + +- If the validation succeeded, perform some action and issue a + redirect via ``HTTPFound``. + +We are, in essence, writing our own form controller. Other +Pyramid-based systems, including ``pyramid_deform``, provide a +form-centric view class which automates much of this branching and +routing. + +Extra Credit +============ + +#. Give a try at a button that goes to a delete view for a + particular wiki page. diff --git a/docs/quick_tutorial/forms/development.ini b/docs/quick_tutorial/forms/development.ini new file mode 100644 index 000000000..62e0c5123 --- /dev/null +++ b/docs/quick_tutorial/forms/development.ini @@ -0,0 +1,41 @@ +[app:main] +use = egg:tutorial +pyramid.reload_templates = true +pyramid.includes = + pyramid_debugtoolbar + +[server:main] +use = egg:pyramid#wsgiref +host = 0.0.0.0 +port = 6543 + +# Begin logging configuration + +[loggers] +keys = root, tutorial + +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s + +# End logging configuration diff --git a/docs/quick_tutorial/forms/setup.py b/docs/quick_tutorial/forms/setup.py new file mode 100644 index 000000000..5db620eb9 --- /dev/null +++ b/docs/quick_tutorial/forms/setup.py @@ -0,0 +1,14 @@ +from setuptools import setup + +requires = [ + 'pyramid', + 'deform' +] + +setup(name='tutorial', + install_requires=requires, + entry_points="""\ + [paste.app_factory] + main = tutorial:main + """, +) \ No newline at end of file diff --git a/docs/quick_tutorial/forms/tutorial/__init__.py b/docs/quick_tutorial/forms/tutorial/__init__.py new file mode 100644 index 000000000..b12a4154a --- /dev/null +++ b/docs/quick_tutorial/forms/tutorial/__init__.py @@ -0,0 +1,12 @@ +from pyramid.config import Configurator + + +def main(global_config, **settings): + config = Configurator(settings=settings) + config.add_route('wiki_view', '/') + config.add_route('wikipage_add', '/add') + config.add_route('wikipage_view', '/{uid}') + config.add_route('wikipage_edit', '/{uid}/edit') + config.add_static_view('deform_static', 'deform:static/') + config.scan('.views') + return config.make_wsgi_app() diff --git a/docs/quick_tutorial/forms/tutorial/tests.py b/docs/quick_tutorial/forms/tutorial/tests.py new file mode 100644 index 000000000..6ff554a1e --- /dev/null +++ b/docs/quick_tutorial/forms/tutorial/tests.py @@ -0,0 +1,47 @@ +import unittest + +from pyramid import testing + + +class TutorialViewTests(unittest.TestCase): + def setUp(self): + self.config = testing.setUp() + + def tearDown(self): + testing.tearDown() + + def test_home(self): + from .views import TutorialViews + + request = testing.DummyRequest() + inst = TutorialViews(request) + response = inst.home() + self.assertEqual('Home View', response['name']) + + def test_hello(self): + from .views import TutorialViews + + request = testing.DummyRequest() + inst = TutorialViews(request) + response = inst.hello() + self.assertEqual('Hello View', response['name']) + + +class TutorialFunctionalTests(unittest.TestCase): + def setUp(self): + from tutorial import main + app = main({}) + from webtest import TestApp + + self.testapp = TestApp(app) + + def tearDown(self): + testing.tearDown() + + def test_home(self): + res = self.testapp.get('/', status=200) + self.assertIn(b'

Hi Home View', res.body) + + def test_hello(self): + res = self.testapp.get('/howdy', status=200) + self.assertIn(b'

Hi Hello View', res.body) diff --git a/docs/quick_tutorial/forms/tutorial/views.py b/docs/quick_tutorial/forms/tutorial/views.py new file mode 100644 index 000000000..004d2aba9 --- /dev/null +++ b/docs/quick_tutorial/forms/tutorial/views.py @@ -0,0 +1,96 @@ +import colander +import deform.widget + +from pyramid.httpexceptions import HTTPFound +from pyramid.view import view_config + +pages = { + '100': dict(uid='100', title='Page 100', body='100'), + '101': dict(uid='101', title='Page 101', body='101'), + '102': dict(uid='102', title='Page 102', body='102') +} + +class WikiPage(colander.MappingSchema): + title = colander.SchemaNode(colander.String()) + body = colander.SchemaNode( + colander.String(), + widget=deform.widget.RichTextWidget() + ) + + +class WikiViews(object): + def __init__(self, request): + self.request = request + + @property + def wiki_form(self): + schema = WikiPage() + return deform.Form(schema, buttons=('submit',)) + + @property + def reqts(self): + return self.wiki_form.get_widget_resources() + + @view_config(route_name='wiki_view', renderer='wiki_view.pt') + def wiki_view(self): + return dict(pages=pages.values()) + + @view_config(route_name='wikipage_add', + renderer='wikipage_addedit.pt') + def wikipage_add(self): + form = self.wiki_form.render() + + if 'submit' in self.request.params: + controls = self.request.POST.items() + try: + appstruct = self.wiki_form.validate(controls) + except deform.ValidationFailure as e: + # Form is NOT valid + return dict(form=e.render()) + + # Form is valid, make a new identifier and add to list + last_uid = int(sorted(pages.keys())[-1]) + new_uid = str(last_uid + 1) + pages[new_uid] = dict( + uid=new_uid, title=appstruct['title'], + body=appstruct['body'] + ) + + # Now visit new page + url = self.request.route_url('wikipage_view', uid=new_uid) + return HTTPFound(url) + + return dict(form=form) + + @view_config(route_name='wikipage_view', renderer='wikipage_view.pt') + def wikipage_view(self): + uid = self.request.matchdict['uid'] + page = pages[uid] + return dict(page=page) + + @view_config(route_name='wikipage_edit', + renderer='wikipage_addedit.pt') + def wikipage_edit(self): + uid = self.request.matchdict['uid'] + page = pages[uid] + + wiki_form = self.wiki_form + + if 'submit' in self.request.params: + controls = self.request.POST.items() + try: + appstruct = wiki_form.validate(controls) + except deform.ValidationFailure as e: + return dict(page=page, form=e.render()) + + # Change the content and redirect to the view + page['title'] = appstruct['title'] + page['body'] = appstruct['body'] + + url = self.request.route_url('wikipage_view', + uid=page['uid']) + return HTTPFound(url) + + form = wiki_form.render(page) + + return dict(page=page, form=form) \ No newline at end of file diff --git a/docs/quick_tutorial/forms/tutorial/wiki_view.pt b/docs/quick_tutorial/forms/tutorial/wiki_view.pt new file mode 100644 index 000000000..9e3afe495 --- /dev/null +++ b/docs/quick_tutorial/forms/tutorial/wiki_view.pt @@ -0,0 +1,19 @@ + + + + Wiki: View + + +

Wiki

+ +Add + WikiPage + + + \ No newline at end of file diff --git a/docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt b/docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt new file mode 100644 index 000000000..d1fea0d7f --- /dev/null +++ b/docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt @@ -0,0 +1,22 @@ + + + + WikiPage: Add/Edit + + + + + + + + +

Wiki

+ +

${structure: form}

+ + + diff --git a/docs/quick_tutorial/forms/tutorial/wikipage_view.pt b/docs/quick_tutorial/forms/tutorial/wikipage_view.pt new file mode 100644 index 000000000..cb9ff526e --- /dev/null +++ b/docs/quick_tutorial/forms/tutorial/wikipage_view.pt @@ -0,0 +1,17 @@ + + + + WikiPage: View + + + + Up + | + + Edit + + +

${page.title}

+

${structure: page.body}

+ + \ No newline at end of file diff --git a/docs/quick_tutorial/functional_testing.rst b/docs/quick_tutorial/functional_testing.rst new file mode 100644 index 000000000..777cb01e2 --- /dev/null +++ b/docs/quick_tutorial/functional_testing.rst @@ -0,0 +1,68 @@ +=================================== +06: Functional Testing with WebTest +=================================== + +Write end-to-end full-stack testing using ``webtest``. + +Background +========== + +Unit tests are a common and popular approach to test-driven development +(TDD.) In web applications, though, the templating and entire apparatus +of a web site are important parts of the delivered quality. We'd like a +way to test these. + +WebTest is a Python package that does functional testing. With WebTest +you can write tests which simulate a full HTTP request against a WSGI +application, then test the information in the response. For speed +purposes, WebTest skips the setup/teardown of an actual HTTP server, +providing tests that run fast enough to be part of TDD. + +Objectives +========== + +- Write a test which checks the contents of the returned HTML + +Steps +===== + +#. First we copy the results of the previous step, as well as install + the ``webtest`` package: + + .. code-block:: bash + + (env27)$ cd ..; cp -r unit_testing functional_testing; cd functional_testing + (env27)$ python setup.py develop + (env27)$ easy_install webtest + +#. Let's extend ``unit_testing/tutorial/tests.py`` to include a + functional test: + + .. literalinclude:: functional_testing/tutorial/tests.py + :linenos: + +#. Now run the tests: + + .. code-block:: bash + + + (env27)$ nosetests tutorial + . + ---------------------------------------------------------------------- + Ran 2 tests in 0.141s + + OK + +Analysis +======== + +We now have the end-to-end testing we were looking for. WebTest lets us +simply extend our existing ``nose``-based test approach with functional +tests that are reported in the same output. These new tests not only +cover our templating, but they didn't dramatically increase the +execution time of our tests. + +Extra Credit +============ + +#. Why do our functional tests use ``b''``? \ No newline at end of file diff --git a/docs/quick_tutorial/functional_testing/development.ini b/docs/quick_tutorial/functional_testing/development.ini new file mode 100644 index 000000000..470d92c57 --- /dev/null +++ b/docs/quick_tutorial/functional_testing/development.ini @@ -0,0 +1,40 @@ +[app:main] +use = egg:tutorial +pyramid.includes = + pyramid_debugtoolbar + +[server:main] +use = egg:pyramid#wsgiref +host = 0.0.0.0 +port = 6543 + +# Begin logging configuration + +[loggers] +keys = root, tutorial + +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s + +# End logging configuration diff --git a/docs/quick_tutorial/functional_testing/setup.py b/docs/quick_tutorial/functional_testing/setup.py new file mode 100644 index 000000000..9997984d3 --- /dev/null +++ b/docs/quick_tutorial/functional_testing/setup.py @@ -0,0 +1,13 @@ +from setuptools import setup + +requires = [ + 'pyramid', +] + +setup(name='tutorial', + install_requires=requires, + entry_points="""\ + [paste.app_factory] + main = tutorial:main + """, +) \ No newline at end of file diff --git a/docs/quick_tutorial/functional_testing/tutorial/__init__.py b/docs/quick_tutorial/functional_testing/tutorial/__init__.py new file mode 100644 index 000000000..2b4e84f30 --- /dev/null +++ b/docs/quick_tutorial/functional_testing/tutorial/__init__.py @@ -0,0 +1,13 @@ +from pyramid.config import Configurator +from pyramid.response import Response + + +def hello_world(request): + return Response('

Hello World!

') + + +def main(global_config, **settings): + config = Configurator(settings=settings) + config.add_route('hello', '/') + config.add_view(hello_world, route_name='hello') + return config.make_wsgi_app() \ No newline at end of file diff --git a/docs/quick_tutorial/functional_testing/tutorial/tests.py b/docs/quick_tutorial/functional_testing/tutorial/tests.py new file mode 100644 index 000000000..4248acbe7 --- /dev/null +++ b/docs/quick_tutorial/functional_testing/tutorial/tests.py @@ -0,0 +1,31 @@ +import unittest + +from pyramid import testing + + +class TutorialViewTests(unittest.TestCase): + def setUp(self): + self.config = testing.setUp() + + def tearDown(self): + testing.tearDown() + + def test_hello_world(self): + from tutorial import hello_world + + request = testing.DummyRequest() + response = hello_world(request) + self.assertEqual(response.status_code, 200) + + +class TutorialFunctionalTests(unittest.TestCase): + def setUp(self): + from tutorial import main + app = main({}) + from webtest import TestApp + + self.testapp = TestApp(app) + + def test_hello_world(self): + res = self.testapp.get('/', status=200) + self.assertIn(b'

Hello World!

', res.body) diff --git a/docs/quick_tutorial/hello_world.rst b/docs/quick_tutorial/hello_world.rst new file mode 100644 index 000000000..e44ef616d --- /dev/null +++ b/docs/quick_tutorial/hello_world.rst @@ -0,0 +1,111 @@ +================================ +01: Single-File Web Applications +================================ + +What's the simplest way to get started in Pyramid? A single-file module. +No Python packages, no ``setup.py``, no other machinery. + +Background +========== + +Microframeworks are all the rage these days. "Microframework" is a +marketing term, not a technical one. They have a low mental overhead: +they do so little, the only things you have to worry about are *your +things*. + +Pyramid is special because it can act as a single-file module +microframework. You can have a single Python file that can be executed +directly by Python. But Pyramid also provides facilities to scale to +the largest of applications. + +Python has a standard called :term:`WSGI` that defines how +Python web applications plug into standard servers, getting passed +incoming requests and returning responses. Most modern Python web +frameworks obey an "MVC" (model-view-controller) application pattern, +where the data in the model has a view that mediates interaction with +outside systems. + +In this step we'll see a brief glimpse of WSGI servers, WSGI +applications, requests, responses, and views. + +Objectives +========== + +- Get a running Pyramid web application, as simply as possible + +- Use that as a well-understood base for adding each unit of complexity + +- Initial exposure to WSGI apps, requests, views, and responses + +Steps +===== + +#. Make sure you have followed the steps in :doc:`python_setup`. + +#. Create a directory for this step: + + .. code-block:: bash + + (env27)$ mkdir hello_world; cd hello_world + +#. Copy the following into ``hello_world/app.py``: + + .. literalinclude:: hello_world/app.py + :linenos: + +#. Run the application: + + .. code-block:: bash + + (env27)$ python app.py + +#. Open ``http://localhost:6543/`` in your browser. + +Analysis +======== + +New to Python web programming? If so, some lines in module merit +explanation: + +#. *Line 11*. The ``if __name__ == '__main__':`` is Python's way of + saying "Start here when running from the command line". + +#. *Lines 12-14*. Use Pyramid's :term:`pyramid:configurator` to connect + :term:`pyramid:view` code to a particular URL + :term:`pyramid:route`. + +#. *Lines 6-7*. Implement the view code that generates the + :term:`pyramid:response`. + +#. *Lines 15-17*. Publish a :term:`pyramid:WSGI` app using an HTTP + server. + +As shown in this example, the :term:`pyramid:configurator` plays a +central role in Pyramid development. Building an application from +loosely-coupled parts via :ref:`pyramid:configuration_narr` is a +central idea in Pyramid, one that we will revisit regularly in this +*Quick Tour*. + +Extra Credit +============ + +#. Why do we do this: + + .. code-block:: python + + print ('Starting up server on http://localhost:6547') + + ...instead of: + + .. code-block:: python + + print 'Starting up server on http://localhost:6547' + +#. What happens if you return a string of HTML? A sequence of integers? + +#. Put something invalid, such as ``print xyz``, in the view function. + Kill your ``python app.py`` with ``cntrl-c`` and restart, + then reload your browser. See the exception in the console? + +#. The ``GI`` in ``WSGI`` stands for "Gateway Interface". What web + standard is this modelled after? \ No newline at end of file diff --git a/docs/quick_tutorial/hello_world/app.py b/docs/quick_tutorial/hello_world/app.py new file mode 100644 index 000000000..210075023 --- /dev/null +++ b/docs/quick_tutorial/hello_world/app.py @@ -0,0 +1,17 @@ +from wsgiref.simple_server import make_server +from pyramid.config import Configurator +from pyramid.response import Response + + +def hello_world(request): + print ('Incoming request') + return Response('

Hello World!

') + + +if __name__ == '__main__': + config = Configurator() + config.add_route('hello', '/') + config.add_view(hello_world, route_name='hello') + app = config.make_wsgi_app() + server = make_server('0.0.0.0', 6543, app) + server.serve_forever() \ No newline at end of file diff --git a/docs/quick_tutorial/index.rst b/docs/quick_tutorial/index.rst new file mode 100644 index 000000000..9d32f9a81 --- /dev/null +++ b/docs/quick_tutorial/index.rst @@ -0,0 +1,51 @@ +.. _quick_tutorial: + +========================== +Quick Tutorial for Pyramid +========================== + +Pyramid is a web framework for Python 2 and 3. This tutorial gives a +Python 2/3-compatible, high-level tour of the major features. + +This hands-on tutorial covers "a little about a lot": practical +introductions to the most common facilities. Fun, fast-paced, and most +certainly not aimed at experts of the Pyramid web framework. + +Contents +======== + +.. toctree:: + :maxdepth: 1 + + python_setup + pyramid_setup + tutorial_approach + scaffolds + hello_world + package + ini + debugtoolbar + unit_testing + functional_testing + views + templating + view_classes + request_response + routing + jinja2 + static_assets + json + more_view_classes + logging + sessions + forms + databases + authentication + authorization + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/quick_tutorial/ini.rst b/docs/quick_tutorial/ini.rst new file mode 100644 index 000000000..85b07812e --- /dev/null +++ b/docs/quick_tutorial/ini.rst @@ -0,0 +1,144 @@ +================================================= +03: Application Configuration with ``.ini`` Files +================================================= + +Use Pyramid's ``pserve`` command with a ``.ini`` configuration file for +simpler, better application running. + +Background +========== + +Pyramid has a first-class concept of +:ref:`configuration ` distinct from code. +This approach is optional, but its presence makes it distinct from +other Python web frameworks. It taps into Python's ``setuptools`` +library, which establishes conventions for how Python projects can be +installed and provide "entry points". Pyramid uses an entry point to +let a Pyramid application it where to find the WSGI app. + +Objectives +========== + +- Modify our ``setup.py`` to have an entry point telling Pyramid the + location of the WSGI app + +- Create an application driven by a ``.ini`` file + +- Startup the application with Pyramid's ``pserve`` command + +- Move code into the package's ``__init__.py`` + +Steps +===== + +#. First we copy the results of the previous step: + + .. code-block:: bash + + (env27)$ cd ..; cp -r package ini; cd ini + +#. Our ``ini/setup.py`` needs a setuptools "entry point" in the + ``setup()`` function: + + .. literalinclude:: ini/setup.py + :linenos: + +#. We can now install our project, thus generating (or re-generating) an + "egg" at ``ini/tutorial.egg-info``: + + .. code-block:: bash + + (env27)$ python setup.py develop + +#. Let's make a file ``ini/development.ini`` for our configuration: + + .. literalinclude:: ini/development.ini + :language: ini + :linenos: + +#. We can refactor our startup code from the previous step's ``app.py`` + into ``ini/tutorial/__init__.py``: + + .. literalinclude:: ini/tutorial/__init__.py + :linenos: + +#. Now that ``ini/tutorial/app.py`` isn't used, let's remove it: + + .. code-block:: bash + + (env27)$ rm tutorial/app.py + +#. Run your Pyramid application with: + + .. code-block:: bash + + (env27)$ pserve development.ini --reload + +#. Open ``http://localhost:6543/``. + +Analysis +======== + +Our ``development.ini`` file is read by ``pserve`` and serves to +bootstrap our application. Processing then proceeds as described in +the Pyramid chapter on +:ref:`application startup `: + +- ``pserve`` looks for ``[app:main]`` and finds ``use = egg:tutorial`` + +- The projects's ``setup.py`` has defined an "entry point" (lines 9-10) + for the project "main" entry point of ``tutorial:main`` + +- The ``tutorial`` package's ``__init__`` has a ``main`` function + +- This function is invoked, with the values from certain ``.ini`` + sections passed in + +The ``.ini`` file is also used for two other functions: + +- *Choice of WSGI server*. ``[server:main]`` wires up the choice of WSGI + *server* for your WSGI *application*. In this case, we are using + ``wsgiref`` bundled in the Python library. + +- *Python logging*. Pyramid uses Python standard logging, which needs a + number of configuration values. The ``.ini`` serves this function. + This provides the console log output that you see on startup and each + request. + +- *Port number*. ``port = 6543`` tells ``wsgiref`` to listen on port + 6543. + +We moved our startup code from ``app.py`` to the package's +``tutorial/__init__.py``. This isn't necessary, +but it is a common style in Pyramid to take the WSGI app bootstrapping +out of your module's code and put it in the package's ``__init__.py``. + +The ``pserve`` application runner has a number of command-line arguments +and options. We are using ``--reload`` which tells ``pserve`` to watch +the filesystem for changes to relevant code (Python files, the INI file, +etc.) and, when something changes, restart the application. Very handy +during development. + +Extra Credit +============ + +#. If you don't like configuration and/or ``.ini`` files, + could you do this yourself in Python code? + +#. Can we have multiple ``.ini`` configuration files for a project? Why + might you want to do that? + +#. The entry point in ``setup.py`` didn't mention ``__init__.py`` when + it the ``main`` function. Why not? + +.. seealso:: + :ref:`pyramid:project_narr`, + :ref:`pyramid:scaffolding_chapter`, + :ref:`pyramid:what_is_this_pserve_thing`, + :ref:`pyramid:environment_chapter`, + :ref:`pyramid:paste_chapter` + +Extra Credit +============ + +#. What is the purpose of ``**settings``? What does the ``**`` signify? diff --git a/docs/quick_tutorial/ini/development.ini b/docs/quick_tutorial/ini/development.ini new file mode 100644 index 000000000..ca7d9bf81 --- /dev/null +++ b/docs/quick_tutorial/ini/development.ini @@ -0,0 +1,38 @@ +[app:main] +use = egg:tutorial + +[server:main] +use = egg:pyramid#wsgiref +host = 0.0.0.0 +port = 6543 + +# Begin logging configuration + +[loggers] +keys = root, tutorial + +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s + +# End logging configuration diff --git a/docs/quick_tutorial/ini/setup.py b/docs/quick_tutorial/ini/setup.py new file mode 100644 index 000000000..9997984d3 --- /dev/null +++ b/docs/quick_tutorial/ini/setup.py @@ -0,0 +1,13 @@ +from setuptools import setup + +requires = [ + 'pyramid', +] + +setup(name='tutorial', + install_requires=requires, + entry_points="""\ + [paste.app_factory] + main = tutorial:main + """, +) \ No newline at end of file diff --git a/docs/quick_tutorial/ini/tutorial/__init__.py b/docs/quick_tutorial/ini/tutorial/__init__.py new file mode 100644 index 000000000..2b4e84f30 --- /dev/null +++ b/docs/quick_tutorial/ini/tutorial/__init__.py @@ -0,0 +1,13 @@ +from pyramid.config import Configurator +from pyramid.response import Response + + +def hello_world(request): + return Response('

Hello World!

') + + +def main(global_config, **settings): + config = Configurator(settings=settings) + config.add_route('hello', '/') + config.add_view(hello_world, route_name='hello') + return config.make_wsgi_app() \ No newline at end of file diff --git a/docs/quick_tutorial/jinja2.rst b/docs/quick_tutorial/jinja2.rst new file mode 100644 index 000000000..ad5b8a9ca --- /dev/null +++ b/docs/quick_tutorial/jinja2.rst @@ -0,0 +1,96 @@ +============================== +12: Templating With ``jinja2`` +============================== + +We just said Pyramid doesn't prefer one templating language over +another. Time to prove it. Jinja2 is a popular templating system, +used in Flask and modelled after Django's templates. Let's add +``pyramid_jinja2``, a Pyramid :term:`add-on` which enables Jinja2 as a +:term:`renderer` in our Pyramid applications. + +Objectives +========== + +- Show Pyramid's support for different templating systems + +- Learn about installing Pyramid add-ons + +Steps +===== + +#. In this step let's start by installing the ``pyramid_jinja2`` + add-on, the copying the ``view_class`` step's directory: + + .. code-block:: bash + + (env27)$ cd ..; cp -r view_classes jinja2; cd jinja2 + (env27)$ python setup.py develop + (env27)$ easy_install pyramid_jinja2 + +#. We need to add an item to ``pyramid.includes`` in + ``jinja2/development.ini``: + + .. literalinclude:: jinja2/development.ini + :language: ini + :linenos: + +#. Our ``jinja2/tutorial/views.py`` simply changes its ``renderer``: + + .. literalinclude:: jinja2/tutorial/views.py + :linenos: + +#. Add ``jinja2/tutorial/home.jinja2`` as a template: + + .. literalinclude:: jinja2/tutorial/home.jinja2 + :language: html + +#. Get the ``pyramid.includes`` into the functional test setup in + ``jinja2/tutorial/tests.py``: + + .. literalinclude:: jinja2/tutorial/tests.py + :linenos: + +#. Now run the tests: + + .. code-block:: bash + + (env27)$ nosetests tutorial + +#. Run your Pyramid application with: + + .. code-block:: bash + + (env27)$ pserve development.ini --reload + +#. Open ``http://localhost:6543/`` in your browser. + +Analysis +======== + +Getting a Pyramid add-on into Pyramid is simple. First you use normal +Python package installation tools to install the add-on package into +your Python. You then tell Pyramid's configurator to run the setup code +in the add-on. In this case the setup code told Pyramid to make a new +"renderer" available that looked for ``.jinja2`` file extensions. + +Our view code stayed largely the same. We simply changed the file +extension on the renderer. For the template, the syntax for Chameleon +and Jinja2's basic variable insertion is very similar. + +Our functional tests don't have ``development.ini`` so they needed the +``pyramid.includes`` to be setup in the test setup. + +Extra Credit +============ + +#. Our project now depends on ``pyramid_jinja2``. We installed that + dependency manually. What is another way we could have made the + association? + +#. We used ``development.ini`` to get the :term:`configurator` to + load ``pyramid_jinja2``'s configuration. What is another way could + include it into the config? + +.. seealso:: `Jinja2 homepage `_, + and + :ref:`pyramid_jinja2 Overview ` diff --git a/docs/quick_tutorial/jinja2/development.ini b/docs/quick_tutorial/jinja2/development.ini new file mode 100644 index 000000000..c096fa936 --- /dev/null +++ b/docs/quick_tutorial/jinja2/development.ini @@ -0,0 +1,42 @@ +[app:main] +use = egg:tutorial +pyramid.reload_templates = true +pyramid.includes = + pyramid_debugtoolbar + pyramid_jinja2 + +[server:main] +use = egg:pyramid#wsgiref +host = 0.0.0.0 +port = 6543 + +# Begin logging configuration + +[loggers] +keys = root, tutorial + +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s + +# End logging configuration diff --git a/docs/quick_tutorial/jinja2/setup.py b/docs/quick_tutorial/jinja2/setup.py new file mode 100644 index 000000000..9997984d3 --- /dev/null +++ b/docs/quick_tutorial/jinja2/setup.py @@ -0,0 +1,13 @@ +from setuptools import setup + +requires = [ + 'pyramid', +] + +setup(name='tutorial', + install_requires=requires, + entry_points="""\ + [paste.app_factory] + main = tutorial:main + """, +) \ No newline at end of file diff --git a/docs/quick_tutorial/jinja2/tutorial/__init__.py b/docs/quick_tutorial/jinja2/tutorial/__init__.py new file mode 100644 index 000000000..013d4538f --- /dev/null +++ b/docs/quick_tutorial/jinja2/tutorial/__init__.py @@ -0,0 +1,9 @@ +from pyramid.config import Configurator + + +def main(global_config, **settings): + config = Configurator(settings=settings) + config.add_route('home', '/') + config.add_route('hello', '/howdy') + config.scan('.views') + return config.make_wsgi_app() \ No newline at end of file diff --git a/docs/quick_tutorial/jinja2/tutorial/home.jinja2 b/docs/quick_tutorial/jinja2/tutorial/home.jinja2 new file mode 100644 index 000000000..975323169 --- /dev/null +++ b/docs/quick_tutorial/jinja2/tutorial/home.jinja2 @@ -0,0 +1,9 @@ + + + + Quick Tour: {{ name }} + + +

Hi {{ name }}

+ + \ No newline at end of file diff --git a/docs/quick_tutorial/jinja2/tutorial/home.pt b/docs/quick_tutorial/jinja2/tutorial/home.pt new file mode 100644 index 000000000..a0cc08e7a --- /dev/null +++ b/docs/quick_tutorial/jinja2/tutorial/home.pt @@ -0,0 +1,9 @@ + + + + Quick Tour: ${name} + + +

Hi ${name}

+ + \ No newline at end of file diff --git a/docs/quick_tutorial/jinja2/tutorial/tests.py b/docs/quick_tutorial/jinja2/tutorial/tests.py new file mode 100644 index 000000000..0b22946f3 --- /dev/null +++ b/docs/quick_tutorial/jinja2/tutorial/tests.py @@ -0,0 +1,50 @@ +import unittest + +from pyramid import testing + + +class TutorialViewTests(unittest.TestCase): + def setUp(self): + self.config = testing.setUp() + + def tearDown(self): + testing.tearDown() + + def test_home(self): + from .views import TutorialViews + + request = testing.DummyRequest() + inst = TutorialViews(request) + response = inst.home() + self.assertEqual('Home View', response['name']) + + def test_hello(self): + from .views import TutorialViews + + request = testing.DummyRequest() + inst = TutorialViews(request) + response = inst.hello() + self.assertEqual('Hello View', response['name']) + + +class TutorialFunctionalTests(unittest.TestCase): + def setUp(self): + from tutorial import main + + settings = { + 'pyramid.includes': [ + 'pyramid_jinja2' + ] + } + app = main({}, **settings) + from webtest import TestApp + + self.testapp = TestApp(app) + + def test_home(self): + res = self.testapp.get('/', status=200) + self.assertIn(b'

Hi Home View', res.body) + + def test_hello(self): + res = self.testapp.get('/howdy', status=200) + self.assertIn(b'

Hi Hello View', res.body) diff --git a/docs/quick_tutorial/jinja2/tutorial/views.py b/docs/quick_tutorial/jinja2/tutorial/views.py new file mode 100644 index 000000000..fa9ec5121 --- /dev/null +++ b/docs/quick_tutorial/jinja2/tutorial/views.py @@ -0,0 +1,18 @@ +from pyramid.view import ( + view_config, + view_defaults + ) + + +@view_defaults(renderer='home.jinja2') +class TutorialViews: + def __init__(self, request): + self.request = request + + @view_config(route_name='home') + def home(self): + return {'name': 'Home View'} + + @view_config(route_name='hello') + def hello(self): + return {'name': 'Hello View'} diff --git a/docs/quick_tutorial/json.rst b/docs/quick_tutorial/json.rst new file mode 100644 index 000000000..213de8364 --- /dev/null +++ b/docs/quick_tutorial/json.rst @@ -0,0 +1,101 @@ +======================================== +14: Ajax Development With JSON Renderers +======================================== + +Modern web apps are more than rendered HTML. Dynamic pages now use +JavaScript to update the UI in the browser by requesting server data as +JSON. Pyramid supports this with a *JSON renderer*. + +Background +========== + +As we saw in :doc:`templating`, view declarations can specify a +renderer. Output from the view is then run through the renderer, +which generates and returns the ``Response``. We first used a Chameleon +renderer, then a Jinja2 renderer. + +Renderers aren't limited, however, to templates that generate HTML. +Pyramid supplies a JSON renderer which takes Python data, +serializes it to JSON, and performs some other functions such as +setting the content type. In fact, you can write your own renderer (or +extend a built-in renderer) containing custom logic for your unique +application. + +Steps +===== + +#. First we copy the results of the ``view_classes`` step: + + .. code-block:: bash + + (env27)$ cd ..; cp -r view_classes json; cd json + (env27)$ python setup.py develop + +#. We add a new route for ``hello_json`` in + ``json/tutorial/__init__.py``: + + .. literalinclude:: json/tutorial/__init__.py + :linenos: + +#. Rather than implement a new view, we will "stack" another decorator + on the ``hello`` view: + + .. literalinclude:: json/tutorial/views.py + :linenos: + +#. We need a new functional test at the end of + ``json/tutorial/tests.py``: + + .. literalinclude:: json/tutorial/tests.py + :linenos: + +#. Run the tests: + + .. code-block:: bash + + (env27)$ nosetests tutorial + +#. Run your Pyramid application with: + + .. code-block:: bash + + (env27)$ pserve development.ini --reload + +#. Open ``http://localhost:6543/howdy.json`` in your browser and you + will see the resulting JSON response. + +Analysis +======== + +Earlier we changed our view functions and methods to return Python +data. This change to a data-oriented view layer made test writing +easier, decoupling the templating from the view logic. + +Since Pyramid has a JSON renderer as well as the templating renderers, +it is an easy step to return JSON. In this case we kept the exact same +view and arranged to return a JSON encoding of the view data. We did +this by: + +- Adding a route to map ``/howdy.json`` to a route name + +- Providing a ``@view_config`` that associated that route name with an + existing view + +- *overriding* the view defaults in the view config that mentions the + ``hello_json`` route, so that when the route is matched, we use the JSON + renderer rather than the ``home.pt`` template renderer that would otherwise + be used. + +In fact, for pure Ajax-style web applications, we could re-use the existing +route by using Pyramid's view predicates to match on the +``Accepts:`` header sent by modern Ajax implementation. + +Pyramid's JSON renderer uses the base Python JSON encoder, +thus inheriting its strengths and weaknesses. For example, +Python can't natively JSON encode DateTime objects. There are a number +of solutions for this in Pyramid, including extending the JSON renderer +with a custom renderer. + +.. seealso:: :ref:`pyramid:views_which_use_a_renderer`, + :ref:`pyramid:json_renderer`, and + :ref:`pyramid:adding_and_overriding_renderers` diff --git a/docs/quick_tutorial/json/development.ini b/docs/quick_tutorial/json/development.ini new file mode 100644 index 000000000..62e0c5123 --- /dev/null +++ b/docs/quick_tutorial/json/development.ini @@ -0,0 +1,41 @@ +[app:main] +use = egg:tutorial +pyramid.reload_templates = true +pyramid.includes = + pyramid_debugtoolbar + +[server:main] +use = egg:pyramid#wsgiref +host = 0.0.0.0 +port = 6543 + +# Begin logging configuration + +[loggers] +keys = root, tutorial + +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s + +# End logging configuration diff --git a/docs/quick_tutorial/json/setup.py b/docs/quick_tutorial/json/setup.py new file mode 100644 index 000000000..9997984d3 --- /dev/null +++ b/docs/quick_tutorial/json/setup.py @@ -0,0 +1,13 @@ +from setuptools import setup + +requires = [ + 'pyramid', +] + +setup(name='tutorial', + install_requires=requires, + entry_points="""\ + [paste.app_factory] + main = tutorial:main + """, +) \ No newline at end of file diff --git a/docs/quick_tutorial/json/tutorial/__init__.py b/docs/quick_tutorial/json/tutorial/__init__.py new file mode 100644 index 000000000..61ddb5129 --- /dev/null +++ b/docs/quick_tutorial/json/tutorial/__init__.py @@ -0,0 +1,10 @@ +from pyramid.config import Configurator + + +def main(global_config, **settings): + config = Configurator(settings=settings) + config.add_route('home', '/') + config.add_route('hello', '/howdy') + config.add_route('hello_json', 'howdy.json') + config.scan('.views') + return config.make_wsgi_app() \ No newline at end of file diff --git a/docs/quick_tutorial/json/tutorial/home.pt b/docs/quick_tutorial/json/tutorial/home.pt new file mode 100644 index 000000000..a0cc08e7a --- /dev/null +++ b/docs/quick_tutorial/json/tutorial/home.pt @@ -0,0 +1,9 @@ + + + + Quick Tour: ${name} + + +

Hi ${name}

+ + \ No newline at end of file diff --git a/docs/quick_tutorial/json/tutorial/tests.py b/docs/quick_tutorial/json/tutorial/tests.py new file mode 100644 index 000000000..c3cdacbdb --- /dev/null +++ b/docs/quick_tutorial/json/tutorial/tests.py @@ -0,0 +1,50 @@ +import unittest + +from pyramid import testing + + +class TutorialViewTests(unittest.TestCase): + def setUp(self): + self.config = testing.setUp() + + def tearDown(self): + testing.tearDown() + + def test_home(self): + from .views import TutorialViews + + request = testing.DummyRequest() + inst = TutorialViews(request) + response = inst.home() + self.assertEqual('Home View', response['name']) + + def test_hello(self): + from .views import TutorialViews + + request = testing.DummyRequest() + inst = TutorialViews(request) + response = inst.hello() + self.assertEqual('Hello View', response['name']) + + +class TutorialFunctionalTests(unittest.TestCase): + def setUp(self): + from tutorial import main + app = main({}) + from webtest import TestApp + + self.testapp = TestApp(app) + + def test_home(self): + res = self.testapp.get('/', status=200) + self.assertIn(b'

Hi Home View', res.body) + + def test_hello(self): + res = self.testapp.get('/howdy', status=200) + self.assertIn(b'

Hi Hello View', res.body) + + def test_hello_json(self): + res = self.testapp.get('/howdy.json', status=200) + self.assertIn(b'{"name": "Hello View"}', res.body) + self.assertEqual(res.content_type, 'application/json') + diff --git a/docs/quick_tutorial/json/tutorial/views.py b/docs/quick_tutorial/json/tutorial/views.py new file mode 100644 index 000000000..f15e55d1b --- /dev/null +++ b/docs/quick_tutorial/json/tutorial/views.py @@ -0,0 +1,19 @@ +from pyramid.view import ( + view_config, + view_defaults + ) + + +@view_defaults(renderer='home.pt') +class TutorialViews: + def __init__(self, request): + self.request = request + + @view_config(route_name='home') + def home(self): + return {'name': 'Home View'} + + @view_config(route_name='hello') + @view_config(route_name='hello_json', renderer='json') + def hello(self): + return {'name': 'Hello View'} diff --git a/docs/quick_tutorial/logging.rst b/docs/quick_tutorial/logging.rst new file mode 100644 index 000000000..a81b961b0 --- /dev/null +++ b/docs/quick_tutorial/logging.rst @@ -0,0 +1,77 @@ +============================================ +16: Collecting Application Info With Logging +============================================ + +Capture debugging and error output from your web applications using +standard Python logging. + +Background +========== + +It's important to know what is going on inside our web application. +In development we might need to collect some output. In production, +we might need to detect problems when other people use the site. We +need *logging*. + +Fortunately Pyramid uses the normal Python approach to logging. The +scaffold generated, in your ``development.ini``, a number of lines that +configure the logging for you to some reasonable defaults. You then see +messages sent by Pyramid (for example, when a new request comes in.) + +Objectives +========== + +- Inspect the configuration setup used for logging + +- Add logging statements to your view code + +Steps +===== + +#. First we copy the results of the ``view_classes`` step: + + .. code-block:: bash + + (env27)$ cd ..; cp -r view_classes logging; cd logging + (env27)$ python setup.py develop + +#. Extend ``logging/tutorial/views.py`` to log a message: + + .. literalinclude:: logging/tutorial/views.py + :linenos: + +#. Make sure the tests still pass: + + .. code-block:: bash + + (env27)$ nosetests tutorial + +#. Run your Pyramid application with: + + .. code-block:: bash + + (env27)$ pserve development.ini --reload + +#. Open ``http://localhost:6543/`` and ``http://localhost:6543/howdy`` + in your browser. Note, both in the console and in the debug + toolbar, the message that you logged. + +Analysis +======== + +Our ``development.ini`` configuration file wires up Python standard +logging for our Pyramid application: + +.. literalinclude:: logging/development.ini + :language: ini + +In this, our ``tutorial`` Python package is setup as a logger +and configured to log messages at a ``DEBUG`` or higher level. When you +visit ``http://localhost:6543`` your console will now show:: + + 2013-08-09 10:42:42,968 DEBUG [tutorial.views][MainThread] In home view + +Also, if you have configured your Pyramid application to use the +``pyramid_debugtoolbar``, logging statements appear in one of its menus. + +.. seealso:: See Also: :ref:`pyramid:logging_chapter` diff --git a/docs/quick_tutorial/logging/development.ini b/docs/quick_tutorial/logging/development.ini new file mode 100644 index 000000000..62e0c5123 --- /dev/null +++ b/docs/quick_tutorial/logging/development.ini @@ -0,0 +1,41 @@ +[app:main] +use = egg:tutorial +pyramid.reload_templates = true +pyramid.includes = + pyramid_debugtoolbar + +[server:main] +use = egg:pyramid#wsgiref +host = 0.0.0.0 +port = 6543 + +# Begin logging configuration + +[loggers] +keys = root, tutorial + +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s + +# End logging configuration diff --git a/docs/quick_tutorial/logging/setup.py b/docs/quick_tutorial/logging/setup.py new file mode 100644 index 000000000..9997984d3 --- /dev/null +++ b/docs/quick_tutorial/logging/setup.py @@ -0,0 +1,13 @@ +from setuptools import setup + +requires = [ + 'pyramid', +] + +setup(name='tutorial', + install_requires=requires, + entry_points="""\ + [paste.app_factory] + main = tutorial:main + """, +) \ No newline at end of file diff --git a/docs/quick_tutorial/logging/tutorial/__init__.py b/docs/quick_tutorial/logging/tutorial/__init__.py new file mode 100644 index 000000000..013d4538f --- /dev/null +++ b/docs/quick_tutorial/logging/tutorial/__init__.py @@ -0,0 +1,9 @@ +from pyramid.config import Configurator + + +def main(global_config, **settings): + config = Configurator(settings=settings) + config.add_route('home', '/') + config.add_route('hello', '/howdy') + config.scan('.views') + return config.make_wsgi_app() \ No newline at end of file diff --git a/docs/quick_tutorial/logging/tutorial/home.pt b/docs/quick_tutorial/logging/tutorial/home.pt new file mode 100644 index 000000000..a0cc08e7a --- /dev/null +++ b/docs/quick_tutorial/logging/tutorial/home.pt @@ -0,0 +1,9 @@ + + + + Quick Tour: ${name} + + +

Hi ${name}

+ + \ No newline at end of file diff --git a/docs/quick_tutorial/logging/tutorial/tests.py b/docs/quick_tutorial/logging/tutorial/tests.py new file mode 100644 index 000000000..4381235ec --- /dev/null +++ b/docs/quick_tutorial/logging/tutorial/tests.py @@ -0,0 +1,44 @@ +import unittest + +from pyramid import testing + + +class TutorialViewTests(unittest.TestCase): + def setUp(self): + self.config = testing.setUp() + + def tearDown(self): + testing.tearDown() + + def test_home(self): + from .views import TutorialViews + + request = testing.DummyRequest() + inst = TutorialViews(request) + response = inst.home() + self.assertEqual('Home View', response['name']) + + def test_hello(self): + from .views import TutorialViews + + request = testing.DummyRequest() + inst = TutorialViews(request) + response = inst.hello() + self.assertEqual('Hello View', response['name']) + + +class TutorialFunctionalTests(unittest.TestCase): + def setUp(self): + from tutorial import main + app = main({}) + from webtest import TestApp + + self.testapp = TestApp(app) + + def test_home(self): + res = self.testapp.get('/', status=200) + self.assertIn(b'

Hi Home View', res.body) + + def test_hello(self): + res = self.testapp.get('/howdy', status=200) + self.assertIn(b'

Hi Hello View', res.body) diff --git a/docs/quick_tutorial/logging/tutorial/views.py b/docs/quick_tutorial/logging/tutorial/views.py new file mode 100644 index 000000000..63d95f405 --- /dev/null +++ b/docs/quick_tutorial/logging/tutorial/views.py @@ -0,0 +1,23 @@ +import logging +log = logging.getLogger(__name__) + +from pyramid.view import ( + view_config, + view_defaults + ) + + +@view_defaults(renderer='home.pt') +class TutorialViews: + def __init__(self, request): + self.request = request + + @view_config(route_name='home') + def home(self): + log.debug('In home view') + return {'name': 'Home View'} + + @view_config(route_name='hello') + def hello(self): + log.debug('In hello view') + return {'name': 'Hello View'} diff --git a/docs/quick_tutorial/more_view_classes.rst b/docs/quick_tutorial/more_view_classes.rst new file mode 100644 index 000000000..b01e17a67 --- /dev/null +++ b/docs/quick_tutorial/more_view_classes.rst @@ -0,0 +1,180 @@ +========================== +15: More With View Classes +========================== + +Group views into a class, sharing configuration, state, and logic. + +Background +========== + +As part of its mission to help build more ambitious web applications, +Pyramid provides many more features for views and view classes. + +The Pyramid documentation discusses views as a Python "callable". This +callable can be a function, an object with an ``__call__``, +or a Python class. In this last case, methods on the class can be +decorated with ``@view_config`` to register the class methods with the +:term:`configurator` as a view. + +So far our views have been simple, free-standing functions. Many times +your views are related: different ways to look at or work on the same +data or a REST API that handles multiple operations. Grouping these +together as a +:ref:`view class ` makes sense: + +- Group views + +- Centralize some repetitive defaults + +- Share some state and helpers + +Pyramid views have +:ref:`view predicates ` that +help determine which view is matched to a request. These predicates +provide many axes of flexibility. + +The following shows a simple example with four operations operations: +view a home page which leads to a form, save a change, +and press the delete button. + +Objectives +========== + +- Group related views into a view class + +- Centralize configuration with class-level ``@view_defaults`` + +- Dispatch one route/URL to multiple views based on request data + +- Share stated and logic between views and templates via the view class + +Steps +===== + +#. First we copy the results of the previous step: + + .. code-block:: bash + + (env27)$ cd ..; cp -r templating more_view_classes; cd more_view_classes + (env27)$ python setup.py develop + +#. Our route in ``more_view_classes/tutorial/__init__.py`` needs some + replacement patterns: + + .. literalinclude:: more_view_classes/tutorial/__init__.py + :linenos: + +#. Our ``more_view_classes/tutorial/views.py`` now has a view class with + several views: + + .. literalinclude:: more_view_classes/tutorial/views.py + :linenos: + +#. Our primary view needs a template at + ``more_view_classes/tutorial/home.pt``: + + .. literalinclude:: more_view_classes/tutorial/home.pt + :language: html + +#. Ditto for our other view from the previous section at + ``more_view_classes/tutorial/hello.pt``: + + .. literalinclude:: more_view_classes/tutorial/hello.pt + :language: html + +#. We have an edit view that also needs a template at + ``more_view_classes/tutorial/edit.pt``: + + .. literalinclude:: more_view_classes/tutorial/edit.pt + :language: html + +#. And finally the delete view's template at + ``more_view_classes/tutorial/delete.pt``: + + .. literalinclude:: more_view_classes/tutorial/delete.pt + :language: html + +#. Run your Pyramid application with: + + .. code-block:: bash + + (env27)$ pserve development.ini --reload + +#. Open ``http://localhost:6543/howdy/jane/doe`` in your browser. Click + the ``Save`` and ``Delete`` buttons and watch the output in the + console window. + +Analysis +======== + +As you can see, the four views are logically grouped together. +Specifically: + +- We have a ``home`` view available at ``http://localhost:6543/`` with + a clickable link to the ``hello`` view. + +- The second view is returned when you go to ``/howdy/jane/doe``. This + URL is + mapped to the ``hello`` route that we centrally set using the optional + ``@view_defaults``. + +- The third view is returned when the form is submitted with a ``POST`` + method. This rule is specified in the ``@view_config`` for that view. + +- The fourth view is returned when clicking on a button such + as ````. + +In this step we show using the following information as criteria to +decide which view to use: + +- Method of the HTTP request (``GET``, ``POST``, etc.) + +- Parameter information in the request (submitted form field names) + +We also centralize part of the view configuration to the class level +with ``@view_defaults``, then in one view, override that default just +for that one view. Finally, we put this commonality between views to +work in the view class by sharing: + +- State assigned in ``TutorialViews.__init__`` + +- A computed value + +These are then available both in the view methods but also in the +templates (e.g. ``${view.view_name}`` and ``${view.full_name}``. + +As a note, we made a switch in our templates on how we generate URLs. +We previously hardcode the URLs, such as:: + + Howdy + +In ``home.pt`` we switched to:: + + form + +Pyramid has rich facilities to help generate URLs in a flexible, +non-error-prone fashion. + +Extra Credit +============ + +#. Why could our template do ``${view.full_name}`` and not have to do + ``${view.full_name()}``? + +#. The ``edit`` and ``delete`` views are both submitted to with + ``POST``. Why does the ``edit`` view configuration not catch the + the ``POST`` used by ``delete``? + +#. We used Python ``@property`` on ``full_name``. If we reference this + many times in a template or view code, it would re-compute this + every time. Does Pyramid provide something that will cache the initial + computation on a property? + +#. Can you associate more than one route with the same view? + +#. There is also a ``request.route_path`` API. How does this differ from + ``request.route_url``? + +.. seealso:: :ref:`pyramid:class_as_view`, `Weird Stuff You Can Do With + URL Dispatch `_ diff --git a/docs/quick_tutorial/more_view_classes/development.ini b/docs/quick_tutorial/more_view_classes/development.ini new file mode 100644 index 000000000..62e0c5123 --- /dev/null +++ b/docs/quick_tutorial/more_view_classes/development.ini @@ -0,0 +1,41 @@ +[app:main] +use = egg:tutorial +pyramid.reload_templates = true +pyramid.includes = + pyramid_debugtoolbar + +[server:main] +use = egg:pyramid#wsgiref +host = 0.0.0.0 +port = 6543 + +# Begin logging configuration + +[loggers] +keys = root, tutorial + +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s + +# End logging configuration diff --git a/docs/quick_tutorial/more_view_classes/setup.py b/docs/quick_tutorial/more_view_classes/setup.py new file mode 100644 index 000000000..9997984d3 --- /dev/null +++ b/docs/quick_tutorial/more_view_classes/setup.py @@ -0,0 +1,13 @@ +from setuptools import setup + +requires = [ + 'pyramid', +] + +setup(name='tutorial', + install_requires=requires, + entry_points="""\ + [paste.app_factory] + main = tutorial:main + """, +) \ No newline at end of file diff --git a/docs/quick_tutorial/more_view_classes/tutorial/__init__.py b/docs/quick_tutorial/more_view_classes/tutorial/__init__.py new file mode 100644 index 000000000..4ab83b413 --- /dev/null +++ b/docs/quick_tutorial/more_view_classes/tutorial/__init__.py @@ -0,0 +1,9 @@ +from pyramid.config import Configurator + + +def main(global_config, **settings): + config = Configurator(settings=settings) + config.add_route('home', '/') + config.add_route('hello', '/howdy/{first}/{last}') + config.scan('.views') + return config.make_wsgi_app() \ No newline at end of file diff --git a/docs/quick_tutorial/more_view_classes/tutorial/delete.pt b/docs/quick_tutorial/more_view_classes/tutorial/delete.pt new file mode 100644 index 000000000..67cc8bf09 --- /dev/null +++ b/docs/quick_tutorial/more_view_classes/tutorial/delete.pt @@ -0,0 +1,9 @@ + + + + Quick Tour: ${page_title} + + +

${view.view_name} - ${page_title}

+ + \ No newline at end of file diff --git a/docs/quick_tutorial/more_view_classes/tutorial/edit.pt b/docs/quick_tutorial/more_view_classes/tutorial/edit.pt new file mode 100644 index 000000000..1bd204065 --- /dev/null +++ b/docs/quick_tutorial/more_view_classes/tutorial/edit.pt @@ -0,0 +1,10 @@ + + + + Quick Tour: ${view.view_name} - ${page_title} + + +

${view.view_name} - ${page_title}

+

You submitted ${new_name}

+ + \ No newline at end of file diff --git a/docs/quick_tutorial/more_view_classes/tutorial/hello.pt b/docs/quick_tutorial/more_view_classes/tutorial/hello.pt new file mode 100644 index 000000000..8a39aed09 --- /dev/null +++ b/docs/quick_tutorial/more_view_classes/tutorial/hello.pt @@ -0,0 +1,16 @@ + + + + Quick Tour: ${view.view_name} - ${page_title} + + +

${view.view_name} - ${page_title}

+

Welcome, ${view.full_name}

+
+ + + +
+ + \ No newline at end of file diff --git a/docs/quick_tutorial/more_view_classes/tutorial/home.pt b/docs/quick_tutorial/more_view_classes/tutorial/home.pt new file mode 100644 index 000000000..fa9016705 --- /dev/null +++ b/docs/quick_tutorial/more_view_classes/tutorial/home.pt @@ -0,0 +1,12 @@ + + + + Quick Tour: ${view.view_name} - ${page_title} + + +

${view.view_name} - ${page_title}

+ +

Go to the form.

+ + \ No newline at end of file diff --git a/docs/quick_tutorial/more_view_classes/tutorial/tests.py b/docs/quick_tutorial/more_view_classes/tutorial/tests.py new file mode 100644 index 000000000..dca8d7f7b --- /dev/null +++ b/docs/quick_tutorial/more_view_classes/tutorial/tests.py @@ -0,0 +1,31 @@ +import unittest + +from pyramid import testing + + +class TutorialViewTests(unittest.TestCase): + def setUp(self): + self.config = testing.setUp() + + def tearDown(self): + testing.tearDown() + + def test_home(self): + from .views import TutorialViews + + request = testing.DummyRequest() + inst = TutorialViews(request) + response = inst.home() + self.assertEqual('Home View', response['page_title']) + +class TutorialFunctionalTests(unittest.TestCase): + def setUp(self): + from tutorial import main + app = main({}) + from webtest import TestApp + + self.testapp = TestApp(app) + + def test_home(self): + res = self.testapp.get('/', status=200) + self.assertIn(b'TutorialViews - Home View', res.body) diff --git a/docs/quick_tutorial/more_view_classes/tutorial/views.py b/docs/quick_tutorial/more_view_classes/tutorial/views.py new file mode 100644 index 000000000..fdba04ba8 --- /dev/null +++ b/docs/quick_tutorial/more_view_classes/tutorial/views.py @@ -0,0 +1,39 @@ +from pyramid.view import ( + view_config, + view_defaults + ) + + +@view_defaults(route_name='hello') +class TutorialViews: + def __init__(self, request): + self.request = request + self.view_name = 'TutorialViews' + + @property + def full_name(self): + first = self.request.matchdict['first'] + last = self.request.matchdict['last'] + return first + ' ' + last + + @view_config(route_name='home', renderer='home.pt') + def home(self): + return {'page_title': 'Home View'} + + + # Retrieving /howdy/first/last the first time + @view_config(renderer='hello.pt') + def hello(self): + return {'page_title': 'Hello View'} + + # Posting to /home via the "Edit" submit button + @view_config(request_method='POST', renderer='edit.pt') + def edit(self): + new_name = self.request.params['new_name'] + return {'page_title': 'Edit View', 'new_name': new_name} + + # Posting to /home via the "Delete" submit button + @view_config(request_param='form.delete', renderer='delete.pt') + def delete(self): + print ('Deleted') + return {'page_title': 'Delete View'} diff --git a/docs/quick_tutorial/package.rst b/docs/quick_tutorial/package.rst new file mode 100644 index 000000000..da6624cb1 --- /dev/null +++ b/docs/quick_tutorial/package.rst @@ -0,0 +1,112 @@ +============================================ +02: Python Packages for Pyramid Applications +============================================ + +Most modern Python development is done using Python packages, an approach +Pyramid puts to good use. In this step we re-do "Hello World" as a +minimum Python package inside a minimum Python project. + +Background +========== + +Python developers can organize a collection of modules and files into a +namespaced unit called a :ref:`package `. If a +directory is on ``sys.path`` and has a special file named +``__init__.py``, it is treated as a Python package. + +Packages can be bundled up, made available for installation, +and installed through a (muddled, but improving) toolchain oriented +around a ``setup.py`` file for a +`setuptools project `_. +Explaining it all in this +tutorial will induce madness. For this tutorial, this is all you need to +know: + +- We will have a directory for each tutorial step as a + setuptools *project* + +- This project will contain a ``setup.py`` which injects the features + of the setuptool's project machinery into the directory + +- In this project we will make a ``tutorial`` subdirectory into a Python + *package* using an ``__init__.py`` Python module file + +- We will run ``python setup.py develop`` to install our project in + development mode + +In summary: + +- You'll do your development in a Python *package* + +- That package will be part of a setuptools *project* + +Objectives +========== + +- Make a Python "package" directory with an ``__init__.py`` + +- Get a minimum Python "project" in place by making a ``setup.py`` + +- Install our ``tutorial`` project in development mode + +Steps +===== + +#. Make an area for this tutorial step: + + .. code-block:: bash + + (env27)$ cd ..; mkdir package; cd package + +#. In ``package/setup.py``, enter the following: + + .. literalinclude:: package/setup.py + +#. Make the new project installed for development then make a directory + for the actual code: + + .. code-block:: bash + + (env27)$ python setup.py develop + (env27)$ mkdir tutorial + +#. Enter the following into ``package/tutorial/__init__.py``: + + .. literalinclude:: package/tutorial/__init__.py + +#. Enter the following into ``package/tutorial/app.py``: + + .. literalinclude:: package/tutorial/app.py + +#. Run the WSGI application with: + + .. code-block:: bash + + (env27)$ python tutorial/app.py + +#. Open ``http://localhost:6543/`` in your browser. + +Analysis +======== + +Python packages give us an organized unit of project development. +Python projects, via ``setup.py``, gives us special features when +our package is installed (in this case, in local development mode.) + +In this step we have a Python package called ``tutorial``. We use the +same name in each step of the tutorial, to avoid unnecessary re-typing. + +Above this ``tutorial`` directory we have the files that handle the +packaging of this, well, package. At the moment, all we need is a +bare-bones ``ini/setup.py``. + +Everything else is the same about our application. We simply made a +Python package with a ``setup.py`` and installed it in development mode. + +Note that the way we're running the app (``python tutorial/app.py``) is a bit +of an odd duck. We would never do this unless we were writing a tutorial that +tries to capture how this stuff works a step at a time. It's generally a bad +idea to run a Python module inside a package directly as a script. + +.. seealso:: :ref:`Python Packages `, + `setuptools Entry Points `_ diff --git a/docs/quick_tutorial/package/setup.py b/docs/quick_tutorial/package/setup.py new file mode 100644 index 000000000..bcfcfa684 --- /dev/null +++ b/docs/quick_tutorial/package/setup.py @@ -0,0 +1,9 @@ +from setuptools import setup + +requires = [ + 'pyramid', +] + +setup(name='tutorial', + install_requires=requires, +) \ No newline at end of file diff --git a/docs/quick_tutorial/package/tutorial/__init__.py b/docs/quick_tutorial/package/tutorial/__init__.py new file mode 100644 index 000000000..d310fdde9 --- /dev/null +++ b/docs/quick_tutorial/package/tutorial/__init__.py @@ -0,0 +1 @@ +# package \ No newline at end of file diff --git a/docs/quick_tutorial/package/tutorial/app.py b/docs/quick_tutorial/package/tutorial/app.py new file mode 100644 index 000000000..210075023 --- /dev/null +++ b/docs/quick_tutorial/package/tutorial/app.py @@ -0,0 +1,17 @@ +from wsgiref.simple_server import make_server +from pyramid.config import Configurator +from pyramid.response import Response + + +def hello_world(request): + print ('Incoming request') + return Response('

Hello World!

') + + +if __name__ == '__main__': + config = Configurator() + config.add_route('hello', '/') + config.add_view(hello_world, route_name='hello') + app = config.make_wsgi_app() + server = make_server('0.0.0.0', 6543, app) + server.serve_forever() \ No newline at end of file diff --git a/docs/quick_tutorial/pyramid_setup.rst b/docs/quick_tutorial/pyramid_setup.rst new file mode 100644 index 000000000..5efcc7dc7 --- /dev/null +++ b/docs/quick_tutorial/pyramid_setup.rst @@ -0,0 +1,27 @@ +============= +Pyramid Setup +============= + +Installing Pyramid is easy and normal from a Python packaging +perspective. Again, *make sure* you have your virtual environment first +in your path using ``source bin/activate``. + +.. code-block:: bash + + (env27)$ easy_install pyramid + ....chuggalugga... + (env27ß)$ which pserve + +You now have Pyramid installed. The second command confirms this by +looking for the Pyramid ``pserve`` command that should be on your +``$PATH`` in the ``bin`` of your virtual environment. + +Installing Everything +===================== + +Later parts of the tutorial install more packages. Most likely, +you'd like to go ahead and get much of it now: + +.. code-block:: bash + + (env27)$ easy_install pyramid nose webtest deform sqlalchemy \ No newline at end of file diff --git a/docs/quick_tutorial/python_setup.rst b/docs/quick_tutorial/python_setup.rst new file mode 100644 index 000000000..2d56a0327 --- /dev/null +++ b/docs/quick_tutorial/python_setup.rst @@ -0,0 +1,88 @@ +============ +Python Setup +============ + +First things first: we need our Python environment in ship-shape. +Pyramid encourages standard Python development practices (virtual +environments, packaging tools, logging, etc.) so let's get our working +area in place. + +.. note:: + + This tutorial is aimed at Python 2.7. It also works with + Python 3.3. + +*This step has most likely been performed already on the CCDC computers.* + +Prequisites +=========== + +Modern Python development means two tools to add to the standard +Python installation: packaging and virtual environments. + +Python's tools for installing packages is undergoing rapid change. For +this tutorial, we will install the latest version of +`setuptools `_. This gives us +the ``easy_install`` command-line tool for installing Python packages. +Presuming you have Python on your ``PATH``: + +.. code-block:: bash + + $ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | python + +We now have an ``easy_install`` command that we can use to install +``virtualenv``: + +.. code-block:: bash + + $ easy_install virtualenv + +Making a Virtual Environment +============================ + +Developing in isolation helps us ensure what we are learning doesn't +conflict with any packages installed from other work on the machine. +*Virtual environments* let us do just this. + +Presuming you have made a tutorial area at some location (referenced as +``your/tutorial/directory`` below): + +.. code-block:: bash + + $ cd your/tutorial/directory + $ virtualenv env27 + $ source env27/bin/activate + (env27)$ which python2.7 + +Once you do this, your path will be setup to point at the ``bin`` of +your virtual environment. Your prompt will also change, as noted above. + +.. note:: + + This tutorial presumes you are working in a command-line shell + which has performed the ``source env27/bin/activate``. If you + close that shell, or open a new one, you will need to re-perform + that command. + +Discussion +========== + +The modern world of Python packaging eschews ``easy_install`` in favor +of ``pip``, a more-recent and maintained packaging tool. Why doesn't +this tutorial use it? + +- ``pip`` is only gradually getting the ability to install Windows + binaries. ``easy_install`` has been able to do this for years. + +- Until recently, ``pip`` has not been able to use "namespace + packages." As the ``pip`` support for this stabilizes, + we can switch to using ``pip``. + +- You have to use ``easy_install`` to get ``pip`` installed, so why not + just stick with ``easy_install``. + +Python 3.3 has a `built-in story for virtual +environments `_. This +eliminates the requirement for installing ``virtualenv``. Instead, +Python 3.3 provides the ``pyvenv`` command for creating virtual +environments. \ No newline at end of file diff --git a/docs/quick_tutorial/request_response.rst b/docs/quick_tutorial/request_response.rst new file mode 100644 index 000000000..74409711f --- /dev/null +++ b/docs/quick_tutorial/request_response.rst @@ -0,0 +1,101 @@ +======================================= +10: Handling Web Requests and Responses +======================================= + +Web applications handle incoming requests and return outgoing responses. +Pyramid makes working with requests and responses convenient and +reliable. + +Objectives +========== + +- Learn the background on Pyramid's choices for requests and responses + +- Grab data out of the request + +- Change information in the response headers + +Background +========== + +Developing for the web means processing web requests. As this is a +critical part of a web application, web developers need a robust, +mature set of software for web requests and returning web +responses. + +Pyramid has always fit nicely into the existing world of Python web +development (virtual environments, packaging, scaffolding, +first to embrace Python 3, etc.) For request handling, Pyramid turned +to the well-regarded :term:`WebOb` Python library for request and +response handling. In our example +above, Pyramid hands ``hello_world`` a ``request`` that is +:ref:`based on WebOb `. + +Steps +===== + +#. First we copy the results of the ``view_classes`` step: + + .. code-block:: bash + + (env27)$ cd ..; cp -r view_classes request_response; cd request_response + (env27)$ python setup.py develop + +#. Simplify the routes in ``request_response/tutorial/__init__.py``: + + .. literalinclude:: request_response/tutorial/__init__.py + +#. We only need one view in ``request_response/tutorial/views.py``: + + .. literalinclude:: request_response/tutorial/views.py + +#. Update the tests in ``request_response/tutorial/tests.py``: + + .. literalinclude:: request_response/tutorial/tests.py + +#. Now run the tests: + + .. code-block:: bash + + (env27)$ nosetests tutorial + +#. Run your Pyramid application with: + + .. code-block:: bash + + (env27)$ pserve development.ini --reload + +#. Open ``http://localhost:6543/`` in your browser. You will be + redirected to ``http://localhost:6543/plain`` + +#. Open ``http://localhost:6543/plain?name=alice`` in your browser. + +Analysis +======== + +In this view class we have two routes and two views, with the first +leading to the second by an HTTP redirect. Pyramid can +:ref:`generate redirects ` by returning a +special object from a view or raising a special exception. + +In this Pyramid view, we get the URL being visited from ``request.url``. +Also, if you visited ``http://localhost:6543/plain?name=alice``, +the name is included in the body of the response:: + + URL http://localhost:6543/plain?name=alice with name: alice + +Finally, we set the response's content type and body, then return the +Response. + +We updated the unit and functional tests to prove that our code +does the redirection, but also handles sending and not sending +``/plain?name``. + +Extra Credit +============ + +#. Could we also ``raise HTTPFound(location='/plain')`` instead of + returning it? If so, what's the difference? + +.. seealso:: :ref:`pyramid:webob_chapter`, + :ref:`generate redirects ` diff --git a/docs/quick_tutorial/request_response/development.ini b/docs/quick_tutorial/request_response/development.ini new file mode 100644 index 000000000..62e0c5123 --- /dev/null +++ b/docs/quick_tutorial/request_response/development.ini @@ -0,0 +1,41 @@ +[app:main] +use = egg:tutorial +pyramid.reload_templates = true +pyramid.includes = + pyramid_debugtoolbar + +[server:main] +use = egg:pyramid#wsgiref +host = 0.0.0.0 +port = 6543 + +# Begin logging configuration + +[loggers] +keys = root, tutorial + +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s + +# End logging configuration diff --git a/docs/quick_tutorial/request_response/setup.py b/docs/quick_tutorial/request_response/setup.py new file mode 100644 index 000000000..9997984d3 --- /dev/null +++ b/docs/quick_tutorial/request_response/setup.py @@ -0,0 +1,13 @@ +from setuptools import setup + +requires = [ + 'pyramid', +] + +setup(name='tutorial', + install_requires=requires, + entry_points="""\ + [paste.app_factory] + main = tutorial:main + """, +) \ No newline at end of file diff --git a/docs/quick_tutorial/request_response/tutorial/__init__.py b/docs/quick_tutorial/request_response/tutorial/__init__.py new file mode 100644 index 000000000..77a172888 --- /dev/null +++ b/docs/quick_tutorial/request_response/tutorial/__init__.py @@ -0,0 +1,9 @@ +from pyramid.config import Configurator + + +def main(global_config, **settings): + config = Configurator(settings=settings) + config.add_route('home', '/') + config.add_route('plain', '/plain') + config.scan('.views') + return config.make_wsgi_app() \ No newline at end of file diff --git a/docs/quick_tutorial/request_response/tutorial/home.pt b/docs/quick_tutorial/request_response/tutorial/home.pt new file mode 100644 index 000000000..a0cc08e7a --- /dev/null +++ b/docs/quick_tutorial/request_response/tutorial/home.pt @@ -0,0 +1,9 @@ + + + + Quick Tour: ${name} + + +

Hi ${name}

+ + \ No newline at end of file diff --git a/docs/quick_tutorial/request_response/tutorial/tests.py b/docs/quick_tutorial/request_response/tutorial/tests.py new file mode 100644 index 000000000..87c853375 --- /dev/null +++ b/docs/quick_tutorial/request_response/tutorial/tests.py @@ -0,0 +1,54 @@ +import unittest + +from pyramid import testing + + +class TutorialViewTests(unittest.TestCase): + def setUp(self): + self.config = testing.setUp() + + def tearDown(self): + testing.tearDown() + + def test_home(self): + from .views import TutorialViews + + request = testing.DummyRequest() + inst = TutorialViews(request) + response = inst.home() + self.assertEqual(response.status, '302 Found') + + def test_plain_without_name(self): + from .views import TutorialViews + + request = testing.DummyRequest() + inst = TutorialViews(request) + response = inst.plain() + self.assertIn('No Name Provided', response.body) + + def test_plain_with_name(self): + from .views import TutorialViews + + request = testing.DummyRequest() + request.GET['name'] = 'Jane Doe' + inst = TutorialViews(request) + response = inst.plain() + self.assertIn('Jane Doe', response.body) + + +class TutorialFunctionalTests(unittest.TestCase): + def setUp(self): + from tutorial import main + + app = main({}) + from webtest import TestApp + + self.testapp = TestApp(app) + + def test_plain_without_name(self): + res = self.testapp.get('/plain', status=200) + self.assertIn(b'No Name Provided', res.body) + + def test_plain_with_name(self): + res = self.testapp.get('/plain?name=Jane%20Doe', status=200) + self.assertIn(b'Jane Doe', res.body) diff --git a/docs/quick_tutorial/request_response/tutorial/views.py b/docs/quick_tutorial/request_response/tutorial/views.py new file mode 100644 index 000000000..8c7ff5f37 --- /dev/null +++ b/docs/quick_tutorial/request_response/tutorial/views.py @@ -0,0 +1,22 @@ +from pyramid.httpexceptions import HTTPFound +from pyramid.response import Response +from pyramid.view import view_config + + +class TutorialViews: + def __init__(self, request): + self.request = request + + @view_config(route_name='home') + def home(self): + return HTTPFound(location='/plain') + + @view_config(route_name='plain') + def plain(self): + name = self.request.params.get('name', 'No Name Provided') + + body = 'URL %s with name: %s' % (self.request.url, name) + return Response( + content_type='text/plain', + body=body + ) diff --git a/docs/quick_tutorial/rest_ajax.rst b/docs/quick_tutorial/rest_ajax.rst new file mode 100644 index 000000000..69a940818 --- /dev/null +++ b/docs/quick_tutorial/rest_ajax.rst @@ -0,0 +1,62 @@ +================== +29: REST with Ajax +================== + +Use Ajax operations to talk to a REST interface. + +Objectives +========== + +- Populate a list with JSON data + +- Update contents with client-side forms that post to REST operations + +Steps +===== + +#. We are going to use the previous step as our starting point: + + .. code-block:: bash + + (env27)$ cd ..; cp -r rest_ajax_layout rest_ajax; cd rest_ajax + (env27)$ python setup.py develop + +#. Let's first add a Javascript file that implements our browser-side + logic and talks to the REST service: + +#. Introduce ``pyramid_jinja2`` dependency in + ``rest_ajax/tutorial/static/site.js``: + + .. literalinclude:: rest_ajax/tutorial/static/site.js + :language: js + :linenos: + +#. Add a `` + + + +

Wiki

+ +
+
+ ${structure:field.title} + * +
+
+ ${structure:field.serialize()} +
+
    +
  • + ${structure:error} +
  • +
+
+ + + + diff --git a/docs/quick_tutorial/retail_forms/tutorial/wikipage_view.pt b/docs/quick_tutorial/retail_forms/tutorial/wikipage_view.pt new file mode 100644 index 000000000..cb9ff526e --- /dev/null +++ b/docs/quick_tutorial/retail_forms/tutorial/wikipage_view.pt @@ -0,0 +1,17 @@ + + + + WikiPage: View + + + + Up + | + + Edit + + +

${page.title}

+

${structure: page.body}

+ + \ No newline at end of file diff --git a/docs/quick_tutorial/unit_testing.rst b/docs/quick_tutorial/unit_testing.rst index 73b33c588..ed33f62d7 100644 --- a/docs/quick_tutorial/unit_testing.rst +++ b/docs/quick_tutorial/unit_testing.rst @@ -77,7 +77,7 @@ some ``pyramid.testing`` helpers which we use in the test setup and teardown. Our one test imports the view, makes a dummy request, and sees if the view returns what we expected. -The ``tests.HelloWorldViewTests.test_hello_world`` test is a small +The ``tests.TutorialViewTests.test_hello_world`` test is a small example of a unit test. First, we import the view inside each test. Why not import at the top, like in normal Python code? Because imports can cause effects that break a test. We'd like our tests to be in *units*, diff --git a/docs/quick_tutorial/views.rst b/docs/quick_tutorial/views.rst index 15785e902..529bba0a4 100644 --- a/docs/quick_tutorial/views.rst +++ b/docs/quick_tutorial/views.rst @@ -42,7 +42,7 @@ Steps .. code-block:: bash - $ cd ..; cp -r function_testing views; cd views + $ cd ..; cp -r functional_testing views; cd views $ $VENV/bin/python setup.py develop #. Our ``views/tutorial/__init__.py`` gets a lot shorter: -- cgit v1.2.3 From bd3d23330abfe39182b7c47f79f61f26e20d1221 Mon Sep 17 00:00:00 2001 From: Paul Everitt Date: Wed, 9 Oct 2013 13:53:10 -0400 Subject: Hedge a little while the compendium of session add-ons is written. --- docs/quick_tutorial/sessions.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/sessions.rst b/docs/quick_tutorial/sessions.rst index ba26d0133..0f284e9a7 100644 --- a/docs/quick_tutorial/sessions.rst +++ b/docs/quick_tutorial/sessions.rst @@ -13,8 +13,8 @@ When people use your web application, they frequently perform a task that requires semi-permanent data to be saved. For example, a shopping cart. This is called a :term:`session`. -Pyramid has basic built-in support for sessions, with add-ons such as -*dogpile.cache* (or your own custom sessioning engine) that provide +Pyramid has basic built-in support for sessions, with add-ons +or your own custom sessioning engine) that can provide richer session support. Let's take a look at the :ref:`built-in sessioning support `. -- cgit v1.2.3 From 8df7a71d99bbeb7819e8a2752012d51202669aa6 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sat, 19 Oct 2013 01:30:58 -0500 Subject: update the docs --- docs/quick_tutorial/sessions/tutorial/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/sessions/tutorial/__init__.py b/docs/quick_tutorial/sessions/tutorial/__init__.py index ecf57bb32..9ddc2e1b1 100644 --- a/docs/quick_tutorial/sessions/tutorial/__init__.py +++ b/docs/quick_tutorial/sessions/tutorial/__init__.py @@ -1,9 +1,9 @@ from pyramid.config import Configurator -from pyramid.session import UnencryptedCookieSessionFactoryConfig +from pyramid.session import SignedCookieSessionFactory def main(global_config, **settings): - my_session_factory = UnencryptedCookieSessionFactoryConfig( + my_session_factory = SignedCookieSessionFactory( 'itsaseekreet') config = Configurator(settings=settings, session_factory=my_session_factory) @@ -11,4 +11,4 @@ def main(global_config, **settings): config.add_route('home', '/') config.add_route('hello', '/howdy') config.scan('.views') - return config.make_wsgi_app() \ No newline at end of file + return config.make_wsgi_app() -- cgit v1.2.3 From 675e0d4cf01840740490c03a2e3704b0b7d98de3 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 30 Oct 2013 20:24:34 -0400 Subject: convert remember/forget to request-method-based --- docs/quick_tutorial/authentication/tutorial/views.py | 17 +++++------------ docs/quick_tutorial/authorization/tutorial/views.py | 17 +++++------------ 2 files changed, 10 insertions(+), 24 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/authentication/tutorial/views.py b/docs/quick_tutorial/authentication/tutorial/views.py index 3038b6d9b..240a23d3e 100644 --- a/docs/quick_tutorial/authentication/tutorial/views.py +++ b/docs/quick_tutorial/authentication/tutorial/views.py @@ -1,9 +1,4 @@ from pyramid.httpexceptions import HTTPFound -from pyramid.security import ( - remember, - forget, - authenticated_userid - ) from pyramid.view import ( view_config, view_defaults @@ -16,7 +11,7 @@ from .security import USERS class TutorialViews: def __init__(self, request): self.request = request - self.logged_in = authenticated_userid(request) + self.logged_in = request.authenticated_userid @view_config(route_name='home') def home(self): @@ -41,9 +36,8 @@ class TutorialViews: login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - headers = remember(request, login) - return HTTPFound(location=came_from, - headers=headers) + request.remember_userid(login) + return HTTPFound(location=came_from) message = 'Failed login' return dict( @@ -58,7 +52,6 @@ class TutorialViews: @view_config(route_name='logout') def logout(self): request = self.request - headers = forget(request) + request.forget_userid() url = request.route_url('home') - return HTTPFound(location=url, - headers=headers) + return HTTPFound(location=url) diff --git a/docs/quick_tutorial/authorization/tutorial/views.py b/docs/quick_tutorial/authorization/tutorial/views.py index 92c1946ba..2ce2c37b4 100644 --- a/docs/quick_tutorial/authorization/tutorial/views.py +++ b/docs/quick_tutorial/authorization/tutorial/views.py @@ -1,9 +1,4 @@ from pyramid.httpexceptions import HTTPFound -from pyramid.security import ( - remember, - forget, - authenticated_userid - ) from pyramid.view import ( view_config, view_defaults, @@ -17,7 +12,7 @@ from .security import USERS class TutorialViews: def __init__(self, request): self.request = request - self.logged_in = authenticated_userid(request) + self.logged_in = request.authenticated_userid @view_config(route_name='home') def home(self): @@ -43,9 +38,8 @@ class TutorialViews: login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - headers = remember(request, login) - return HTTPFound(location=came_from, - headers=headers) + request.remember_userid(login) + return HTTPFound(location=came_from) message = 'Failed login' return dict( @@ -60,7 +54,6 @@ class TutorialViews: @view_config(route_name='logout') def logout(self): request = self.request - headers = forget(request) + request.forget_userid() url = request.route_url('home') - return HTTPFound(location=url, - headers=headers) + return HTTPFound(location=url) -- cgit v1.2.3 From 0dcd56c2c30863c6683c0cf442aa73dfdcd11b13 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 9 Nov 2013 17:11:16 -0500 Subject: undeprecate remember/forget functions and remove remember_userid/forget_userid methods from request --- docs/quick_tutorial/authentication/tutorial/views.py | 15 +++++++++++---- docs/quick_tutorial/authorization/tutorial/views.py | 15 +++++++++++---- 2 files changed, 22 insertions(+), 8 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/authentication/tutorial/views.py b/docs/quick_tutorial/authentication/tutorial/views.py index 240a23d3e..ab46eb2dd 100644 --- a/docs/quick_tutorial/authentication/tutorial/views.py +++ b/docs/quick_tutorial/authentication/tutorial/views.py @@ -1,4 +1,9 @@ from pyramid.httpexceptions import HTTPFound +from pyramid.security import ( + remember, + forget, + ) + from pyramid.view import ( view_config, view_defaults @@ -36,8 +41,9 @@ class TutorialViews: login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - request.remember_userid(login) - return HTTPFound(location=came_from) + headers = remember(request, login) + return HTTPFound(location=came_from, + headers=headers) message = 'Failed login' return dict( @@ -52,6 +58,7 @@ class TutorialViews: @view_config(route_name='logout') def logout(self): request = self.request - request.forget_userid() + headers = forget(request) url = request.route_url('home') - return HTTPFound(location=url) + return HTTPFound(location=url, + headers=headers) diff --git a/docs/quick_tutorial/authorization/tutorial/views.py b/docs/quick_tutorial/authorization/tutorial/views.py index 2ce2c37b4..43d14455a 100644 --- a/docs/quick_tutorial/authorization/tutorial/views.py +++ b/docs/quick_tutorial/authorization/tutorial/views.py @@ -1,4 +1,9 @@ from pyramid.httpexceptions import HTTPFound +from pyramid.security import ( + remember, + forget, + ) + from pyramid.view import ( view_config, view_defaults, @@ -38,8 +43,9 @@ class TutorialViews: login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: - request.remember_userid(login) - return HTTPFound(location=came_from) + headers = remember(request, login) + return HTTPFound(location=came_from, + headers=headers) message = 'Failed login' return dict( @@ -54,6 +60,7 @@ class TutorialViews: @view_config(route_name='logout') def logout(self): request = self.request - request.forget_userid() + headers = forget(request) url = request.route_url('home') - return HTTPFound(location=url) + return HTTPFound(location=url, + headers=headers) -- cgit v1.2.3 From 2033eeb3602f330930585678aac926749b9c22f7 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Mon, 10 Feb 2014 03:22:33 -0600 Subject: - Garden PR #1121 --- docs/quick_tutorial/authentication.rst | 4 ++-- docs/quick_tutorial/debugtoolbar.rst | 2 +- docs/quick_tutorial/logging.rst | 2 +- docs/quick_tutorial/requirements.rst | 2 +- docs/quick_tutorial/tutorial_approach.rst | 6 +++--- docs/quick_tutorial/unit_testing.rst | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/authentication.rst b/docs/quick_tutorial/authentication.rst index 8380a75ed..4b4eb1ba3 100644 --- a/docs/quick_tutorial/authentication.rst +++ b/docs/quick_tutorial/authentication.rst @@ -130,5 +130,5 @@ Extra Credit onto each request? Use ``import pdb; pdb.set_trace()`` to answer this. -.. seealso:: :ref:`security_chapter`, - :ref:`AuthTktAuthenticationPolicy ` +.. seealso:: See also :ref:`security_chapter`, + :ref:`AuthTktAuthenticationPolicy `. diff --git a/docs/quick_tutorial/debugtoolbar.rst b/docs/quick_tutorial/debugtoolbar.rst index d25588c49..9a37c5f0e 100644 --- a/docs/quick_tutorial/debugtoolbar.rst +++ b/docs/quick_tutorial/debugtoolbar.rst @@ -86,4 +86,4 @@ start to experience otherwise inexplicable client-side weirdness, you can shut it off by commenting out the ``pyramid_debugtoolbar`` line in ``pyramid.includes`` temporarily. -.. seealso:: See Also: :ref:`pyramid_debugtoolbar ` +.. seealso:: See also :ref:`pyramid_debugtoolbar `. diff --git a/docs/quick_tutorial/logging.rst b/docs/quick_tutorial/logging.rst index 0167e5249..855ded59f 100644 --- a/docs/quick_tutorial/logging.rst +++ b/docs/quick_tutorial/logging.rst @@ -76,4 +76,4 @@ visit http://localhost:6543 your console will now show:: Also, if you have configured your Pyramid application to use the ``pyramid_debugtoolbar``, logging statements appear in one of its menus. -.. seealso:: See Also: :ref:`logging_chapter` +.. seealso:: See also :ref:`logging_chapter`. diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index 234e4aa0d..df920ea39 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -240,7 +240,7 @@ during this tutorial: some optional C extensions for performance. With ``easy_install``, Windows users can get these extensions without needing a C compiler. -.. seealso:: See Also: :ref:`installing_unix`. For instructions to set up your +.. seealso:: See also :ref:`installing_unix`. For instructions to set up your Python environment for development using Windows or Python 2, see Pyramid's :ref:`Before You Install `. diff --git a/docs/quick_tutorial/tutorial_approach.rst b/docs/quick_tutorial/tutorial_approach.rst index 52d768306..204d388b0 100644 --- a/docs/quick_tutorial/tutorial_approach.rst +++ b/docs/quick_tutorial/tutorial_approach.rst @@ -4,9 +4,9 @@ Tutorial Approach This tutorial uses conventions to keep the introduction focused and concise. Details, references, and deeper discussions are mentioned in -"See Also" notes. +"See also" notes. -.. seealso:: This is an example "See Also" note. +.. seealso:: This is an example "See also" note. This "Getting Started" tutorial is broken into independent steps, starting with the smallest possible "single file WSGI app" example. @@ -42,4 +42,4 @@ Each of the first-level directories (e.g. ``request_response``) is a *Python project* (except, as noted, the ``hello_world`` step.) The ``tutorial`` directory is a *Python package*. At the end of each step, we copy a previous directory into a new directory to use as a starting -point. \ No newline at end of file +point. diff --git a/docs/quick_tutorial/unit_testing.rst b/docs/quick_tutorial/unit_testing.rst index ed33f62d7..f8a33b39d 100644 --- a/docs/quick_tutorial/unit_testing.rst +++ b/docs/quick_tutorial/unit_testing.rst @@ -116,4 +116,4 @@ Extra Credit #. Why do we import the ``hello_world`` view function *inside* the ``test_hello_world`` method instead of at the top of the module? -.. seealso:: See Also: :ref:`testing_chapter` +.. seealso:: See also :ref:`testing_chapter` -- cgit v1.2.3 From 2292ae27dc0061f524a59a5e25b4578b0885d4b9 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Sun, 16 Feb 2014 20:53:27 -0500 Subject: Clarify reasons for preferring easy_install over pip. --- docs/quick_tutorial/requirements.rst | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index df920ea39..fa5263856 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -226,25 +226,27 @@ during this tutorial: # Mac and Linux $ $VENV/bin/easy_install nose webtest deform sqlalchemy \ pyramid_chameleon pyramid_debugtoolbar waitress \ - pyramid_jinja2 pyramid_tm zope.sqlalchemy + pyramid_tm zope.sqlalchemy # Windows c:\> %VENV%\Scripts\easy_install nose webtest deform sqlalchemy pyramid_chameleon - - .. note:: Why ``easy_install`` and not ``pip``? Pyramid encourages use of namespace - packages which, until recently, ``pip`` didn't permit. Also, Pyramid has - some optional C extensions for performance. With ``easy_install``, Windows - users can get these extensions without needing a C compiler. + packages, for which ``pip``'s support is less-than-optimal. Also, Pyramid's + dependencies use some optional C extensions for performance: with + ``easy_install``, Windows users can get these extensions without needing + a C compiler (``pip`` does not support installing binary Windows + distributions, except for ``wheels``, which are not yet available for + all dependencies). .. seealso:: See also :ref:`installing_unix`. For instructions to set up your Python environment for development using Windows or Python 2, see Pyramid's :ref:`Before You Install `. - See also Python 3's :mod:`venv module `, the `setuptools` `installation instructions + See also Python 3's :mod:`venv module `, the `setuptools + installation instructions `_, and `easy_install help `_. -- cgit v1.2.3 From 0c25b7b36f6c8c43513bd557ac63bdde64168a46 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Sun, 16 Feb 2014 21:05:35 -0500 Subject: Clarify vs. import time. --- docs/quick_tutorial/hello_world.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/hello_world.rst b/docs/quick_tutorial/hello_world.rst index c7a8eaf5e..86e1319f0 100644 --- a/docs/quick_tutorial/hello_world.rst +++ b/docs/quick_tutorial/hello_world.rst @@ -71,11 +71,11 @@ New to Python web programming? If so, some lines in module merit explanation: #. *Line 11*. The ``if __name__ == '__main__':`` is Python's way of - saying "Start here when running from the command line". + saying "Start here when running from the command line", rather than + when this module is imported. #. *Lines 12-14*. Use Pyramid's :term:`configurator` to connect - :term:`view` code to a particular URL - :term:`route`. + :term:`view` code to a particular URL :term:`route`. #. *Lines 6-7*. Implement the view code that generates the :term:`response`. @@ -111,4 +111,4 @@ Extra Credit then reload your browser. See the exception in the console? #. The ``GI`` in ``WSGI`` stands for "Gateway Interface". What web - standard is this modelled after? \ No newline at end of file + standard is this modelled after? -- cgit v1.2.3 From c0587cc2fce880950e5da4b34cc23c9df94893a2 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Sun, 16 Feb 2014 21:11:56 -0500 Subject: Avoid re-ambiguating 'project' vs. 'package. --- docs/quick_tutorial/package.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/package.rst b/docs/quick_tutorial/package.rst index 90d022b29..8fb052d5b 100644 --- a/docs/quick_tutorial/package.rst +++ b/docs/quick_tutorial/package.rst @@ -22,8 +22,7 @@ Explaining it all in this tutorial will induce madness. For this tutorial, this is all you need to know: -- We will have a directory for each tutorial step as a - setuptools *project* +- We will have a directory for each tutorial step as a setuptools *project* - This project will contain a ``setup.py`` which injects the features of the setuptool's project machinery into the directory @@ -97,8 +96,8 @@ In this step we have a Python package called ``tutorial``. We use the same name in each step of the tutorial, to avoid unnecessary re-typing. Above this ``tutorial`` directory we have the files that handle the -packaging of this, well, package. At the moment, all we need is a -bare-bones ``ini/setup.py``. +packaging of this project. At the moment, all we need is a +bare-bones ``setup.py``. Everything else is the same about our application. We simply made a Python package with a ``setup.py`` and installed it in development mode. -- cgit v1.2.3 From 3c6ea2ef47488ef800ed9bc9981726b1dc6f5839 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Sun, 16 Feb 2014 21:20:59 -0500 Subject: Clarifications. --- docs/quick_tutorial/ini.rst | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/ini.rst b/docs/quick_tutorial/ini.rst index 618b8e5e8..3402c50e8 100644 --- a/docs/quick_tutorial/ini.rst +++ b/docs/quick_tutorial/ini.rst @@ -98,18 +98,16 @@ the Pyramid chapter on The ``.ini`` file is also used for two other functions: -- *Choice of WSGI server*. ``[server:main]`` wires up the choice of WSGI - *server* for your WSGI *application*. In this case, we are using - ``wsgiref`` bundled in the Python library. +- *Configuring the WSGI server*. ``[server:main]`` wires up the choice of + which WSGI *server* for your WSGI *application*. In this case, we are using + ``wsgiref`` bundled in the Python library. It also wires up the *port + number*: ``port = 6543`` tells ``wsgiref`` to listen on port 6543. -- *Python logging*. Pyramid uses Python standard logging, which needs a - number of configuration values. The ``.ini`` serves this function. +- *Configuring Python logging*. Pyramid uses Python standard logging, which + needs a number of configuration values. The ``.ini`` serves this function. This provides the console log output that you see on startup and each request. -- *Port number*. ``port = 6543`` tells ``wsgiref`` to listen on port - 6543. - We moved our startup code from ``app.py`` to the package's ``tutorial/__init__.py``. This isn't necessary, but it is a common style in Pyramid to take the WSGI app bootstrapping @@ -131,7 +129,7 @@ Extra Credit might you want to do that? #. The entry point in ``setup.py`` didn't mention ``__init__.py`` when - it the ``main`` function. Why not? + it declared ``tutorial:main`` function. Why not? .. seealso:: :ref:`project_narr`, -- cgit v1.2.3 From ddcc03dc12ee6a82099cee95589cba700b3d7ef4 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Sun, 16 Feb 2014 21:37:20 -0500 Subject: EC: why not add 'pyramid_debugtoolbar' to our 'install_requires'? --- docs/quick_tutorial/debugtoolbar.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/debugtoolbar.rst b/docs/quick_tutorial/debugtoolbar.rst index 9a37c5f0e..95cf229b2 100644 --- a/docs/quick_tutorial/debugtoolbar.rst +++ b/docs/quick_tutorial/debugtoolbar.rst @@ -39,7 +39,6 @@ Steps $ $VENV/bin/python setup.py develop $ $VENV/bin/easy_install pyramid_debugtoolbar - #. Our ``debugtoolbar/development.ini`` gets a configuration entry for ``pyramid.includes``: @@ -87,3 +86,9 @@ it off by commenting out the ``pyramid_debugtoolbar`` line in ``pyramid.includes`` temporarily. .. seealso:: See also :ref:`pyramid_debugtoolbar `. + +Extra Credit +============ + +# Why don't we add ``pyramid_debugtoolbar`` to the list of + ``install_requires`` dependencies in ``debugtoolbar/setup.py``? -- cgit v1.2.3 From fa20e0a093de3961c0f50aff906afd5b6790e673 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Sun, 16 Feb 2014 21:53:54 -0500 Subject: Match optional reqs on Windows to those on POSIX. --- docs/quick_tutorial/requirements.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index fa5263856..72bb4a4f8 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -229,7 +229,8 @@ during this tutorial: pyramid_tm zope.sqlalchemy # Windows - c:\> %VENV%\Scripts\easy_install nose webtest deform sqlalchemy pyramid_chameleon + c:\> %VENV%\Scripts\easy_install nose webtest deform sqlalchemy pyramid_chameleon pyramid_debugtoolbar waitress pyramid_tm zope.sqlalchemy + .. note:: -- cgit v1.2.3 From f77c69c68665e81ffc89f4aa13f6e9af13df6cb0 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Sun, 16 Feb 2014 22:28:03 -0500 Subject: Don't leave the page broken. --- docs/quick_tutorial/debugtoolbar/tutorial/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/debugtoolbar/tutorial/__init__.py b/docs/quick_tutorial/debugtoolbar/tutorial/__init__.py index 0993b25be..d784292ee 100644 --- a/docs/quick_tutorial/debugtoolbar/tutorial/__init__.py +++ b/docs/quick_tutorial/debugtoolbar/tutorial/__init__.py @@ -3,7 +3,7 @@ from pyramid.response import Response def hello_world(request): - return xResponse('

Hello World!

') + return Response('

Hello World!

') def main(global_config, **settings): -- cgit v1.2.3 From 76ff93079eac35d529a2a316248b8cca750ef5e4 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Sun, 16 Feb 2014 22:28:33 -0500 Subject: EC: break the page and see the DBT traceback display. --- docs/quick_tutorial/debugtoolbar.rst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/debugtoolbar.rst b/docs/quick_tutorial/debugtoolbar.rst index 95cf229b2..1c540d8a2 100644 --- a/docs/quick_tutorial/debugtoolbar.rst +++ b/docs/quick_tutorial/debugtoolbar.rst @@ -92,3 +92,22 @@ Extra Credit # Why don't we add ``pyramid_debugtoolbar`` to the list of ``install_requires`` dependencies in ``debugtoolbar/setup.py``? + +# Introduce a bug into your application: Change: + + .. code-block:: python + + def hello_world(request): + return Response('

Hello World!

') + + to: + + .. code-block:: python + + def hello_world(request): + return xResponse('

Hello World!

') + + Save, and visit http://localhost:6543/ again. Notice the nice + traceback display. On the lowest line, click the "screen" icon to the + right, and try typing the variable names ``request`` and ``Response``. + What else can you discover? -- cgit v1.2.3 From 111aef8a7d0e000d6ff65cc15138c2d376b1efc4 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Sun, 16 Feb 2014 22:38:00 -0500 Subject: Trailing commas are good. --- docs/quick_tutorial/templating/setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/templating/setup.py b/docs/quick_tutorial/templating/setup.py index 2221b72e9..0b71b73e6 100644 --- a/docs/quick_tutorial/templating/setup.py +++ b/docs/quick_tutorial/templating/setup.py @@ -2,7 +2,7 @@ from setuptools import setup requires = [ 'pyramid', - 'pyramid_chameleon' + 'pyramid_chameleon', ] setup(name='tutorial', @@ -11,4 +11,4 @@ setup(name='tutorial', [paste.app_factory] main = tutorial:main """, -) \ No newline at end of file +) -- cgit v1.2.3 From 3c87ad81b0e846e7d61f86f8a5a6aff6ec3a2b9e Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Sun, 16 Feb 2014 23:00:38 -0500 Subject: Clarify. --- docs/quick_tutorial/more_view_classes.rst | 11 +++++------ docs/quick_tutorial/more_view_classes/tutorial/views.py | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/more_view_classes.rst b/docs/quick_tutorial/more_view_classes.rst index 21b353b7c..1e5603554 100644 --- a/docs/quick_tutorial/more_view_classes.rst +++ b/docs/quick_tutorial/more_view_classes.rst @@ -18,11 +18,10 @@ or a Python class. In this last case, methods on the class can be decorated with ``@view_config`` to register the class methods with the :term:`configurator` as a view. -So far our views have been simple, free-standing functions. Many times +At first, our views were simple, free-standing functions. Many times your views are related: different ways to look at or work on the same data or a REST API that handles multiple operations. Grouping these -together as a -:ref:`view class ` makes sense: +together as a :ref:`view class ` makes sense: - Group views @@ -30,9 +29,9 @@ together as a - Share some state and helpers -Pyramid views have -:ref:`view predicates ` that -help determine which view is matched to a request. These predicates +Pyramid views have :ref:`view predicates ` +that determine which view is matched to a request, based on factors +such as the request method, the form parameters, etc. These predicates provide many axes of flexibility. The following shows a simple example with four operations operations: diff --git a/docs/quick_tutorial/more_view_classes/tutorial/views.py b/docs/quick_tutorial/more_view_classes/tutorial/views.py index fdba04ba8..635de0520 100644 --- a/docs/quick_tutorial/more_view_classes/tutorial/views.py +++ b/docs/quick_tutorial/more_view_classes/tutorial/views.py @@ -20,7 +20,6 @@ class TutorialViews: def home(self): return {'page_title': 'Home View'} - # Retrieving /howdy/first/last the first time @view_config(renderer='hello.pt') def hello(self): @@ -33,7 +32,8 @@ class TutorialViews: return {'page_title': 'Edit View', 'new_name': new_name} # Posting to /home via the "Delete" submit button - @view_config(request_param='form.delete', renderer='delete.pt') + @view_config(request_method='POST', request_param='form.delete', + renderer='delete.pt') def delete(self): print ('Deleted') return {'page_title': 'Delete View'} -- cgit v1.2.3 From 5c5edadd089f3c3f13751bde3f691ad19339b551 Mon Sep 17 00:00:00 2001 From: sbivol Date: Mon, 10 Mar 2014 16:28:56 +0200 Subject: Remove extra concatenation from request.static_url() fixes issue #1266 --- docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt b/docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt index d1fea0d7f..3292dfd90 100644 --- a/docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt +++ b/docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt @@ -4,10 +4,10 @@ WikiPage: Add/Edit + href="${request.static_url(reqt)}"/> - -- cgit v1.2.3 From ba85e591d563ed654f492f7cab5ca492a32a86d7 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 13 Mar 2014 18:17:43 -0400 Subject: Strip redundant logging config from tutorial INI files. Leave it for the 'logging' and 'scaffolds' sections, where it is germane. --- docs/quick_tutorial/authentication/development.ini | 31 ------------------- docs/quick_tutorial/authorization/development.ini | 31 ------------------- docs/quick_tutorial/databases/development.ini | 36 ---------------------- docs/quick_tutorial/debugtoolbar/development.ini | 31 ------------------- docs/quick_tutorial/forms/development.ini | 31 ------------------- .../functional_testing/development.ini | 31 ------------------- docs/quick_tutorial/ini/development.ini | 31 ------------------- docs/quick_tutorial/jinja2/development.ini | 31 ------------------- docs/quick_tutorial/json/development.ini | 31 ------------------- .../more_view_classes/development.ini | 31 ------------------- .../request_response/development.ini | 31 ------------------- docs/quick_tutorial/retail_forms/development.ini | 31 ------------------- docs/quick_tutorial/routing/development.ini | 31 ------------------- docs/quick_tutorial/sessions/development.ini | 31 ------------------- docs/quick_tutorial/static_assets/development.ini | 31 ------------------- docs/quick_tutorial/templating/development.ini | 31 ------------------- docs/quick_tutorial/unit_testing/development.ini | 31 ------------------- docs/quick_tutorial/view_classes/development.ini | 31 ------------------- docs/quick_tutorial/views/development.ini | 31 ------------------- 19 files changed, 594 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/authentication/development.ini b/docs/quick_tutorial/authentication/development.ini index 5d4580ff5..8a39b2fe7 100644 --- a/docs/quick_tutorial/authentication/development.ini +++ b/docs/quick_tutorial/authentication/development.ini @@ -9,34 +9,3 @@ tutorial.secret = 98zd use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/authorization/development.ini b/docs/quick_tutorial/authorization/development.ini index 5d4580ff5..8a39b2fe7 100644 --- a/docs/quick_tutorial/authorization/development.ini +++ b/docs/quick_tutorial/authorization/development.ini @@ -9,34 +9,3 @@ tutorial.secret = 98zd use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/databases/development.ini b/docs/quick_tutorial/databases/development.ini index 270da960f..04c249a62 100644 --- a/docs/quick_tutorial/databases/development.ini +++ b/docs/quick_tutorial/databases/development.ini @@ -11,39 +11,3 @@ sqlalchemy.url = sqlite:///%(here)s/sqltutorial.sqlite use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial, sqlalchemy - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[logger_sqlalchemy] -level = INFO -handlers = -qualname = sqlalchemy.engine - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/debugtoolbar/development.ini b/docs/quick_tutorial/debugtoolbar/development.ini index 470d92c57..52b2a3a41 100644 --- a/docs/quick_tutorial/debugtoolbar/development.ini +++ b/docs/quick_tutorial/debugtoolbar/development.ini @@ -7,34 +7,3 @@ pyramid.includes = use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/forms/development.ini b/docs/quick_tutorial/forms/development.ini index 62e0c5123..4d47e54a5 100644 --- a/docs/quick_tutorial/forms/development.ini +++ b/docs/quick_tutorial/forms/development.ini @@ -8,34 +8,3 @@ pyramid.includes = use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/functional_testing/development.ini b/docs/quick_tutorial/functional_testing/development.ini index 470d92c57..52b2a3a41 100644 --- a/docs/quick_tutorial/functional_testing/development.ini +++ b/docs/quick_tutorial/functional_testing/development.ini @@ -7,34 +7,3 @@ pyramid.includes = use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/ini/development.ini b/docs/quick_tutorial/ini/development.ini index ca7d9bf81..8853e2c2b 100644 --- a/docs/quick_tutorial/ini/development.ini +++ b/docs/quick_tutorial/ini/development.ini @@ -5,34 +5,3 @@ use = egg:tutorial use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/jinja2/development.ini b/docs/quick_tutorial/jinja2/development.ini index 62e0c5123..4d47e54a5 100644 --- a/docs/quick_tutorial/jinja2/development.ini +++ b/docs/quick_tutorial/jinja2/development.ini @@ -8,34 +8,3 @@ pyramid.includes = use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/json/development.ini b/docs/quick_tutorial/json/development.ini index 62e0c5123..4d47e54a5 100644 --- a/docs/quick_tutorial/json/development.ini +++ b/docs/quick_tutorial/json/development.ini @@ -8,34 +8,3 @@ pyramid.includes = use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/more_view_classes/development.ini b/docs/quick_tutorial/more_view_classes/development.ini index 62e0c5123..4d47e54a5 100644 --- a/docs/quick_tutorial/more_view_classes/development.ini +++ b/docs/quick_tutorial/more_view_classes/development.ini @@ -8,34 +8,3 @@ pyramid.includes = use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/request_response/development.ini b/docs/quick_tutorial/request_response/development.ini index 62e0c5123..4d47e54a5 100644 --- a/docs/quick_tutorial/request_response/development.ini +++ b/docs/quick_tutorial/request_response/development.ini @@ -8,34 +8,3 @@ pyramid.includes = use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/retail_forms/development.ini b/docs/quick_tutorial/retail_forms/development.ini index 62e0c5123..4d47e54a5 100644 --- a/docs/quick_tutorial/retail_forms/development.ini +++ b/docs/quick_tutorial/retail_forms/development.ini @@ -8,34 +8,3 @@ pyramid.includes = use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/routing/development.ini b/docs/quick_tutorial/routing/development.ini index 62e0c5123..4d47e54a5 100644 --- a/docs/quick_tutorial/routing/development.ini +++ b/docs/quick_tutorial/routing/development.ini @@ -8,34 +8,3 @@ pyramid.includes = use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/sessions/development.ini b/docs/quick_tutorial/sessions/development.ini index 62e0c5123..4d47e54a5 100644 --- a/docs/quick_tutorial/sessions/development.ini +++ b/docs/quick_tutorial/sessions/development.ini @@ -8,34 +8,3 @@ pyramid.includes = use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/static_assets/development.ini b/docs/quick_tutorial/static_assets/development.ini index 62e0c5123..4d47e54a5 100644 --- a/docs/quick_tutorial/static_assets/development.ini +++ b/docs/quick_tutorial/static_assets/development.ini @@ -8,34 +8,3 @@ pyramid.includes = use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/templating/development.ini b/docs/quick_tutorial/templating/development.ini index 62e0c5123..4d47e54a5 100644 --- a/docs/quick_tutorial/templating/development.ini +++ b/docs/quick_tutorial/templating/development.ini @@ -8,34 +8,3 @@ pyramid.includes = use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/unit_testing/development.ini b/docs/quick_tutorial/unit_testing/development.ini index 470d92c57..52b2a3a41 100644 --- a/docs/quick_tutorial/unit_testing/development.ini +++ b/docs/quick_tutorial/unit_testing/development.ini @@ -7,34 +7,3 @@ pyramid.includes = use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/view_classes/development.ini b/docs/quick_tutorial/view_classes/development.ini index 62e0c5123..4d47e54a5 100644 --- a/docs/quick_tutorial/view_classes/development.ini +++ b/docs/quick_tutorial/view_classes/development.ini @@ -8,34 +8,3 @@ pyramid.includes = use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/quick_tutorial/views/development.ini b/docs/quick_tutorial/views/development.ini index 470d92c57..52b2a3a41 100644 --- a/docs/quick_tutorial/views/development.ini +++ b/docs/quick_tutorial/views/development.ini @@ -7,34 +7,3 @@ pyramid.includes = use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 - -# Begin logging configuration - -[loggers] -keys = root, tutorial - -[logger_tutorial] -level = DEBUG -handlers = -qualname = tutorial - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration -- cgit v1.2.3 From 49923dbf430fc6becc92133ba7672e93f1bc955e Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 21 Mar 2014 06:47:55 -0700 Subject: - fix indentation of code block --- docs/quick_tutorial/scaffolds.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/scaffolds.rst b/docs/quick_tutorial/scaffolds.rst index 8ca2d27df..4f2694100 100644 --- a/docs/quick_tutorial/scaffolds.rst +++ b/docs/quick_tutorial/scaffolds.rst @@ -63,11 +63,11 @@ Steps On startup, ``pserve`` logs some output: - .. code-block:: bash + .. code-block:: bash - Starting subprocess with file monitor - Starting server in PID 72213. - Starting HTTP server on http://0.0.0.0:6543 + Starting subprocess with file monitor + Starting server in PID 72213. + Starting HTTP server on http://0.0.0.0:6543 #. Open http://localhost:6543/ in your browser. -- cgit v1.2.3 From 71c979fb9a89cffdc57a9533a61101483c23b93b Mon Sep 17 00:00:00 2001 From: Daniel Haaker Date: Wed, 26 Mar 2014 09:56:15 +0100 Subject: Remove whitespace before the open parenthesis --- docs/quick_tutorial/hello_world/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/hello_world/app.py b/docs/quick_tutorial/hello_world/app.py index 210075023..0a95f9ad3 100644 --- a/docs/quick_tutorial/hello_world/app.py +++ b/docs/quick_tutorial/hello_world/app.py @@ -4,7 +4,7 @@ from pyramid.response import Response def hello_world(request): - print ('Incoming request') + print('Incoming request') return Response('

Hello World!

') @@ -14,4 +14,4 @@ if __name__ == '__main__': config.add_view(hello_world, route_name='hello') app = config.make_wsgi_app() server = make_server('0.0.0.0', 6543, app) - server.serve_forever() \ No newline at end of file + server.serve_forever() -- cgit v1.2.3 From 92b27dc06a4a73ea4ff0649855a5a84cd30b458c Mon Sep 17 00:00:00 2001 From: Daniel Haaker Date: Wed, 26 Mar 2014 10:10:54 +0100 Subject: Update hello_world.rst Modify 'Extra Credit' to reflect code example --- docs/quick_tutorial/hello_world.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/hello_world.rst b/docs/quick_tutorial/hello_world.rst index 86e1319f0..1a9ba4c9d 100644 --- a/docs/quick_tutorial/hello_world.rst +++ b/docs/quick_tutorial/hello_world.rst @@ -96,13 +96,13 @@ Extra Credit .. code-block:: python - print ('Starting up server on http://localhost:6547') + print('Incoming request') ...instead of: .. code-block:: python - print 'Starting up server on http://localhost:6547' + print 'Incoming request' #. What happens if you return a string of HTML? A sequence of integers? -- cgit v1.2.3 From 832c2e8967fa1904fb1a0d3e5d707a11c32aa543 Mon Sep 17 00:00:00 2001 From: Wichert Akkerman Date: Tue, 8 Apr 2014 21:49:44 +0200 Subject: Remove Babel from all setup.cfg files --- docs/quick_tutorial/scaffolds/setup.cfg | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/scaffolds/setup.cfg b/docs/quick_tutorial/scaffolds/setup.cfg index c980261e3..16e18719c 100644 --- a/docs/quick_tutorial/scaffolds/setup.cfg +++ b/docs/quick_tutorial/scaffolds/setup.cfg @@ -4,24 +4,3 @@ nocapture = 1 cover-package = scaffolds with-coverage = 1 cover-erase = 1 - -[compile_catalog] -directory = scaffolds/locale -domain = scaffolds -statistics = true - -[extract_messages] -add_comments = TRANSLATORS: -output_file = scaffolds/locale/scaffolds.pot -width = 80 - -[init_catalog] -domain = scaffolds -input_file = scaffolds/locale/scaffolds.pot -output_dir = scaffolds/locale - -[update_catalog] -domain = scaffolds -input_file = scaffolds/locale/scaffolds.pot -output_dir = scaffolds/locale -previous = true -- cgit v1.2.3 From eab0eb5068754da33123d5a7bc3faf025a3fc14e Mon Sep 17 00:00:00 2001 From: Wichert Akkerman Date: Tue, 8 Apr 2014 22:04:47 +0200 Subject: Drop setup.cfg from scaffolds Since setup.cfg is no longer needed for Babel, and no scaffold or documentation references nose there is no need to keep them. --- docs/quick_tutorial/scaffolds/setup.cfg | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 docs/quick_tutorial/scaffolds/setup.cfg (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/scaffolds/setup.cfg b/docs/quick_tutorial/scaffolds/setup.cfg deleted file mode 100644 index 16e18719c..000000000 --- a/docs/quick_tutorial/scaffolds/setup.cfg +++ /dev/null @@ -1,6 +0,0 @@ -[nosetests] -match = ^test -nocapture = 1 -cover-package = scaffolds -with-coverage = 1 -cover-erase = 1 -- cgit v1.2.3 From 25c886ebad924786bef43cd27ce7a57d95ce3482 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 9 Apr 2014 14:46:30 -0400 Subject: - clarify Windows setuptools instructions - correct typo on location --- docs/quick_tutorial/requirements.rst | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index 72bb4a4f8..b79be4b3a 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -187,9 +187,15 @@ pipe it to your environment's version of Python. $ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | $VENV/bin/python # Windows - # Use your browser to download: - # https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.p - # ...into c:\projects\quick_tutorial\ez_setup.py + # + # Use your web browser to download this file: + # https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setupy + # + # ...and save it to: + # c:\projects\quick_tutorial\ez_setup.py + # + # Then run the following command: + c:\> %VENV%\Scripts\python ez_setup.py If ``wget`` complains with a certificate error, then run this command instead: -- cgit v1.2.3 From ca1273b6897a42d72adca8276e78458962c1b9bb Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 9 Apr 2014 16:29:55 -0400 Subject: - add name of views.py --- docs/quick_tutorial/json.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/json.rst b/docs/quick_tutorial/json.rst index ece8a61c0..aa789d833 100644 --- a/docs/quick_tutorial/json.rst +++ b/docs/quick_tutorial/json.rst @@ -40,7 +40,7 @@ Steps :linenos: #. Rather than implement a new view, we will "stack" another decorator - on the ``hello`` view: + on the ``hello`` view in ``views.py``: .. literalinclude:: json/tutorial/views.py :linenos: -- cgit v1.2.3 From c462c0770b801be06f26acdbdcc00b9b92260286 Mon Sep 17 00:00:00 2001 From: thapar Date: Wed, 9 Apr 2014 16:38:47 -0400 Subject: Typo correction "setupy"-->"setup.py" --- docs/quick_tutorial/requirements.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index b79be4b3a..b5778ea42 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -189,7 +189,7 @@ pipe it to your environment's version of Python. # Windows # # Use your web browser to download this file: - # https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setupy + # https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py # # ...and save it to: # c:\projects\quick_tutorial\ez_setup.py -- cgit v1.2.3 From 1aa8eb60c7d54324d8d0d31a667b3e9c4c4e3b25 Mon Sep 17 00:00:00 2001 From: tylereaves Date: Wed, 16 Apr 2014 16:13:03 -0400 Subject: Update debugtoolbar.rst Fix wording to reflect how debugtoolbar actually works --- docs/quick_tutorial/debugtoolbar.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/debugtoolbar.rst b/docs/quick_tutorial/debugtoolbar.rst index 1c540d8a2..88b55869e 100644 --- a/docs/quick_tutorial/debugtoolbar.rst +++ b/docs/quick_tutorial/debugtoolbar.rst @@ -71,9 +71,9 @@ supports wiring in add-on configuration via our ``development.ini`` using ``pyramid.includes``. We use this to load the configuration for the debugtoolbar. -You'll now see an attractive (and collapsible) menu in the right of -your browser, providing introspective access to debugging information. -Even better, if your web application generates an error, +You'll now see an attractive button in the right of +your browser, which you may click to provide introspective access to debugging +information in a new browser tab. Even better, if your web application generates an error, you will see a nice traceback on the screen. When you want to disable this toolbar, no need to change code: you can remove it from ``pyramid.includes`` in the relevant ``.ini`` configuration file (thus -- cgit v1.2.3 From b6ff39af94797c3b81adc367e86a546a099df519 Mon Sep 17 00:00:00 2001 From: tylereaves Date: Wed, 16 Apr 2014 16:13:33 -0400 Subject: Update debugtoolbar.rst grammar fix --- docs/quick_tutorial/debugtoolbar.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/debugtoolbar.rst b/docs/quick_tutorial/debugtoolbar.rst index 88b55869e..45279b541 100644 --- a/docs/quick_tutorial/debugtoolbar.rst +++ b/docs/quick_tutorial/debugtoolbar.rst @@ -71,7 +71,7 @@ supports wiring in add-on configuration via our ``development.ini`` using ``pyramid.includes``. We use this to load the configuration for the debugtoolbar. -You'll now see an attractive button in the right of +You'll now see an attractive button on the right side of your browser, which you may click to provide introspective access to debugging information in a new browser tab. Even better, if your web application generates an error, you will see a nice traceback on the screen. When you want to disable -- cgit v1.2.3 From b666df0d5f299eca20e9370ac43cddee71b6dd06 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 16 Apr 2014 15:15:50 -0500 Subject: minor tweaks based on toolbar changes in 2.x --- docs/quick_tutorial/debugtoolbar.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/debugtoolbar.rst b/docs/quick_tutorial/debugtoolbar.rst index 45279b541..90750c633 100644 --- a/docs/quick_tutorial/debugtoolbar.rst +++ b/docs/quick_tutorial/debugtoolbar.rst @@ -73,14 +73,15 @@ the debugtoolbar. You'll now see an attractive button on the right side of your browser, which you may click to provide introspective access to debugging -information in a new browser tab. Even better, if your web application generates an error, +information in a new browser tab. Even better, if your web application +generates an error, you will see a nice traceback on the screen. When you want to disable this toolbar, no need to change code: you can remove it from ``pyramid.includes`` in the relevant ``.ini`` configuration file (thus showing why configuration files are handy.) -Note that the toolbar mutates the HTML generated by our app and uses jQuery to -overlay itself. If you are using the toolbar while you're developing and you +Note injects a small amount of html/css into your app just before the closing +```` tag in order to display itself. If you start to experience otherwise inexplicable client-side weirdness, you can shut it off by commenting out the ``pyramid_debugtoolbar`` line in ``pyramid.includes`` temporarily. -- cgit v1.2.3 From ef7a4e90de2f78a57e4a3326072f8b40b449182c Mon Sep 17 00:00:00 2001 From: Omid Raha Date: Sun, 20 Apr 2014 17:14:45 +0430 Subject: Remove repeated word. Remove repeated `operations` word. --- docs/quick_tutorial/more_view_classes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/more_view_classes.rst b/docs/quick_tutorial/more_view_classes.rst index 1e5603554..9cc4cc520 100644 --- a/docs/quick_tutorial/more_view_classes.rst +++ b/docs/quick_tutorial/more_view_classes.rst @@ -34,7 +34,7 @@ that determine which view is matched to a request, based on factors such as the request method, the form parameters, etc. These predicates provide many axes of flexibility. -The following shows a simple example with four operations operations: +The following shows a simple example with four operations: view a home page which leads to a form, save a change, and press the delete button. -- cgit v1.2.3 From 872796d2c1743430ab04364d05657b46133fa230 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 20 Apr 2014 06:50:44 -0700 Subject: Merge pull request #1309 from omidraha/patch-1 Correct question to adapt to the the text. --- docs/quick_tutorial/jinja2.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/jinja2.rst b/docs/quick_tutorial/jinja2.rst index 44d9f635b..2f1e295dd 100644 --- a/docs/quick_tutorial/jinja2.rst +++ b/docs/quick_tutorial/jinja2.rst @@ -88,9 +88,9 @@ Extra Credit dependency manually. What is another way we could have made the association? -#. We used ``development.ini`` to get the :term:`configurator` to - load ``pyramid_jinja2``'s configuration. What is another way could - include it into the config? +#. We used ``config.include`` which is an imperative configuration to get the + :term:`Configurator` to load ``pyramid_jinja2``'s configuration. + What is another way could include it into the config? .. seealso:: `Jinja2 homepage `_, and -- cgit v1.2.3 From e5346a5dae13357917b7a91472e129a8841e79c9 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Mon, 21 Apr 2014 14:37:30 -0700 Subject: Update background section same as quick_tour.rst Update text of ``background`` section same as ``sessions`` section of ``quick_tour.rst`` --- docs/quick_tutorial/sessions.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/sessions.rst b/docs/quick_tutorial/sessions.rst index 0f284e9a7..b4887beb8 100644 --- a/docs/quick_tutorial/sessions.rst +++ b/docs/quick_tutorial/sessions.rst @@ -13,10 +13,10 @@ When people use your web application, they frequently perform a task that requires semi-permanent data to be saved. For example, a shopping cart. This is called a :term:`session`. -Pyramid has basic built-in support for sessions, with add-ons -or your own custom sessioning engine) that can provide -richer session support. Let's take a look at the -:ref:`built-in sessioning support `. +Pyramid has basic built-in support for sessions. Third party packages such as +``pyramid_redis_sessions`` provide richer session support. Or you can create +your own custom sessioning engine. Let's take a look at the +:doc:`built-in sessioning support <../narr/sessions>`. Objectives ========== -- cgit v1.2.3 From c79c2d9f36f27abfa5e2a72e021298728734138d Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 25 May 2014 16:36:09 -0700 Subject: Bring in #1352 --- docs/quick_tutorial/databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index 20b3cd46d..7c019dbfc 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -115,7 +115,7 @@ Steps .. code-block:: bash - $ $VENV/bin/nosetests . + $ $VENV/bin/nosetests tutorial .. ----------------------------------------------------------------- Ran 2 tests in 1.141s -- cgit v1.2.3 From c688c70fb2bf6731bbdbf68682eebb203b540a04 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 2 Jul 2014 14:36:27 -0400 Subject: dont need to use any settings, we include pyramid_jinja2 in main --- docs/quick_tutorial/jinja2.rst | 6 ------ docs/quick_tutorial/jinja2/tutorial/tests.py | 8 +------- 2 files changed, 1 insertion(+), 13 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/jinja2.rst b/docs/quick_tutorial/jinja2.rst index 2f1e295dd..ad6da7a9e 100644 --- a/docs/quick_tutorial/jinja2.rst +++ b/docs/quick_tutorial/jinja2.rst @@ -45,12 +45,6 @@ Steps .. literalinclude:: jinja2/tutorial/home.jinja2 :language: html -#. Get the ``pyramid.includes`` into the functional test setup in - ``jinja2/tutorial/tests.py``: - - .. literalinclude:: jinja2/tutorial/tests.py - :linenos: - #. Now run the tests: .. code-block:: bash diff --git a/docs/quick_tutorial/jinja2/tutorial/tests.py b/docs/quick_tutorial/jinja2/tutorial/tests.py index 0b22946f3..4381235ec 100644 --- a/docs/quick_tutorial/jinja2/tutorial/tests.py +++ b/docs/quick_tutorial/jinja2/tutorial/tests.py @@ -30,13 +30,7 @@ class TutorialViewTests(unittest.TestCase): class TutorialFunctionalTests(unittest.TestCase): def setUp(self): from tutorial import main - - settings = { - 'pyramid.includes': [ - 'pyramid_jinja2' - ] - } - app = main({}, **settings) + app = main({}) from webtest import TestApp self.testapp = TestApp(app) -- cgit v1.2.3 From 9101510d3c08814e5a77683bf56f66a5b852e44e Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 17 Sep 2014 03:23:42 -0700 Subject: fix typo Re: https://github.com/Pylons/pyramid/pull/1411/files --- docs/quick_tutorial/ini.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/ini.rst b/docs/quick_tutorial/ini.rst index 3402c50e8..132bc30be 100644 --- a/docs/quick_tutorial/ini.rst +++ b/docs/quick_tutorial/ini.rst @@ -16,7 +16,7 @@ This approach is optional, but its presence makes it distinct from other Python web frameworks. It taps into Python's ``setuptools`` library, which establishes conventions for how Python projects can be installed and provide "entry points". Pyramid uses an entry point to -let a Pyramid application it where to find the WSGI app. +let a Pyramid application know where to find the WSGI app. Objectives ========== -- cgit v1.2.3 From fea1750c7a70a666c7bcff40525206397c1080df Mon Sep 17 00:00:00 2001 From: Jay Martin Date: Sat, 20 Sep 2014 11:54:13 -0400 Subject: Update hello_world.rst --- docs/quick_tutorial/hello_world.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/hello_world.rst b/docs/quick_tutorial/hello_world.rst index 1a9ba4c9d..4ae80ca87 100644 --- a/docs/quick_tutorial/hello_world.rst +++ b/docs/quick_tutorial/hello_world.rst @@ -77,7 +77,7 @@ explanation: #. *Lines 12-14*. Use Pyramid's :term:`configurator` to connect :term:`view` code to a particular URL :term:`route`. -#. *Lines 6-7*. Implement the view code that generates the +#. *Lines 6-8*. Implement the view code that generates the :term:`response`. #. *Lines 15-17*. Publish a :term:`WSGI` app using an HTTP -- cgit v1.2.3 From 5f0c50dc5f2d739a816f35992a024f616117b44c Mon Sep 17 00:00:00 2001 From: Jay Martin Date: Fri, 26 Sep 2014 06:38:55 -0400 Subject: Update ini.rst grammar tweak (former discussion:https://github.com/Pylons/pyramid/pull/1413#issuecomment-56891441) --- docs/quick_tutorial/ini.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/ini.rst b/docs/quick_tutorial/ini.rst index 132bc30be..b8720711b 100644 --- a/docs/quick_tutorial/ini.rst +++ b/docs/quick_tutorial/ini.rst @@ -14,8 +14,8 @@ Pyramid has a first-class concept of :ref:`configuration ` distinct from code. This approach is optional, but its presence makes it distinct from other Python web frameworks. It taps into Python's ``setuptools`` -library, which establishes conventions for how Python projects can be -installed and provide "entry points". Pyramid uses an entry point to +library, which establishes conventions for installing and providing +"entry points" for Python projects. Pyramid uses an entry point to let a Pyramid application know where to find the WSGI app. Objectives -- cgit v1.2.3 From c92f49b63f005a63a0d9ac33973e7cec84b07c55 Mon Sep 17 00:00:00 2001 From: deisner Date: Mon, 6 Oct 2014 17:01:40 -0400 Subject: Update functional_testing.rst Make it clear that the tests.py file in the functional_testing directory is the one to edit. Also, warn about a potential "gotcha": if the tests.py file is executable, it will be silently ignored. (I ran into this problem while going through the tutorial. This can happen if the file is being edited on a network file share from a different OS, for example.). --- docs/quick_tutorial/functional_testing.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/functional_testing.rst b/docs/quick_tutorial/functional_testing.rst index 205ddf5cb..ddcf6b77d 100644 --- a/docs/quick_tutorial/functional_testing.rst +++ b/docs/quick_tutorial/functional_testing.rst @@ -37,12 +37,14 @@ Steps $ $VENV/bin/python setup.py develop $ $VENV/bin/easy_install webtest -#. Let's extend ``unit_testing/tutorial/tests.py`` to include a +#. Let's extend ``functional_testing/tutorial/tests.py`` to include a functional test: .. literalinclude:: functional_testing/tutorial/tests.py :linenos: + Be sure this file is not executable, or ``nosetests`` may not include your tests. + #. Now run the tests: .. code-block:: bash @@ -67,4 +69,4 @@ execution time of our tests. Extra Credit ============ -#. Why do our functional tests use ``b''``? \ No newline at end of file +#. Why do our functional tests use ``b''``? -- cgit v1.2.3 From 34e9381a628d4e5d061d8fe902579a9b9b9cb33c Mon Sep 17 00:00:00 2001 From: David Eisner Date: Mon, 6 Oct 2014 19:27:36 -0400 Subject: Update functional_testing.rst Wrap long line. --- docs/quick_tutorial/functional_testing.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/functional_testing.rst b/docs/quick_tutorial/functional_testing.rst index ddcf6b77d..09b05b0bc 100644 --- a/docs/quick_tutorial/functional_testing.rst +++ b/docs/quick_tutorial/functional_testing.rst @@ -43,7 +43,8 @@ Steps .. literalinclude:: functional_testing/tutorial/tests.py :linenos: - Be sure this file is not executable, or ``nosetests`` may not include your tests. + Be sure this file is not executable, or ``nosetests`` may not + include your tests. #. Now run the tests: -- cgit v1.2.3 From 9095de6ac110a7d31ea76a5dbb5b65408897c75e Mon Sep 17 00:00:00 2001 From: David Eisner Date: Wed, 8 Oct 2014 11:46:21 -0400 Subject: Minor edits to Templating With jinja2 * Fix grammar, order of operations in step 1. * Remove Analysis section reference to pyramid.includes in functional tests, which is no longer accurate. --- docs/quick_tutorial/jinja2.rst | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/jinja2.rst b/docs/quick_tutorial/jinja2.rst index ad6da7a9e..613542349 100644 --- a/docs/quick_tutorial/jinja2.rst +++ b/docs/quick_tutorial/jinja2.rst @@ -20,8 +20,8 @@ Objectives Steps ===== -#. In this step let's start by installing the ``pyramid_jinja2`` - add-on, the copying the ``view_class`` step's directory: +#. In this step let's start by copying the ``view_class`` step's + directory, and then installing the ``pyramid_jinja2`` add-on. .. code-block:: bash @@ -72,9 +72,6 @@ Our view code stayed largely the same. We simply changed the file extension on the renderer. For the template, the syntax for Chameleon and Jinja2's basic variable insertion is very similar. -Our functional tests don't have ``development.ini`` so they needed the -``pyramid.includes`` to be setup in the test setup. - Extra Credit ============ -- cgit v1.2.3 From 6aa96d5d40f8c420f020ae187d6842e01e6c668c Mon Sep 17 00:00:00 2001 From: Jay Martin Date: Tue, 14 Oct 2014 09:19:47 -0400 Subject: fix route name in comments --- docs/quick_tutorial/more_view_classes/tutorial/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/more_view_classes/tutorial/views.py b/docs/quick_tutorial/more_view_classes/tutorial/views.py index 635de0520..fc0ccc37f 100644 --- a/docs/quick_tutorial/more_view_classes/tutorial/views.py +++ b/docs/quick_tutorial/more_view_classes/tutorial/views.py @@ -25,13 +25,13 @@ class TutorialViews: def hello(self): return {'page_title': 'Hello View'} - # Posting to /home via the "Edit" submit button + # Posting to /hello via the "Edit" submit button @view_config(request_method='POST', renderer='edit.pt') def edit(self): new_name = self.request.params['new_name'] return {'page_title': 'Edit View', 'new_name': new_name} - # Posting to /home via the "Delete" submit button + # Posting to /hello via the "Delete" submit button @view_config(request_method='POST', request_param='form.delete', renderer='delete.pt') def delete(self): -- cgit v1.2.3 From ac1bc3cb042fce04696bd799e095722be0d63fb9 Mon Sep 17 00:00:00 2001 From: Jay Martin Date: Tue, 14 Oct 2014 09:09:36 -0400 Subject: typo fix --- docs/quick_tutorial/forms.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/forms.rst b/docs/quick_tutorial/forms.rst index e8bc0c8b4..b08167edc 100644 --- a/docs/quick_tutorial/forms.rst +++ b/docs/quick_tutorial/forms.rst @@ -104,7 +104,7 @@ assets which need to be published. We don't have to know where on disk it is located. We point at the package, then the path inside the package. We just need to include a call to ``add_static_view`` to make that -directory available at a URL. For Pyramid-specific pages, +directory available at a URL. For Pyramid-specific packages, Pyramid provides a facility (``config.include()``) which even makes that unnecessary for consumers of a package. (Deform is not specific to Pyramid.) -- cgit v1.2.3 From 2c3ed01554f0fdceeff425b44f7f80c55b9a3545 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Tue, 14 Oct 2014 10:03:28 -0500 Subject: fix comment on hello view --- docs/quick_tutorial/more_view_classes/tutorial/views.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/more_view_classes/tutorial/views.py b/docs/quick_tutorial/more_view_classes/tutorial/views.py index fc0ccc37f..156e468a9 100644 --- a/docs/quick_tutorial/more_view_classes/tutorial/views.py +++ b/docs/quick_tutorial/more_view_classes/tutorial/views.py @@ -5,7 +5,7 @@ from pyramid.view import ( @view_defaults(route_name='hello') -class TutorialViews: +class TutorialViews(object): def __init__(self, request): self.request = request self.view_name = 'TutorialViews' @@ -25,13 +25,13 @@ class TutorialViews: def hello(self): return {'page_title': 'Hello View'} - # Posting to /hello via the "Edit" submit button + # Posting to /howdy/first/last via the "Edit" submit button @view_config(request_method='POST', renderer='edit.pt') def edit(self): new_name = self.request.params['new_name'] return {'page_title': 'Edit View', 'new_name': new_name} - # Posting to /hello via the "Delete" submit button + # Posting to /howdy/first/last via the "Delete" submit button @view_config(request_method='POST', request_param='form.delete', renderer='delete.pt') def delete(self): -- cgit v1.2.3 From 903f48c1e2a9a309b7386f3d69ae20433d0e7dfa Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 9 Nov 2014 20:44:10 -0800 Subject: - rewrap - add missing clause in last paragraph --- docs/quick_tutorial/debugtoolbar.rst | 52 +++++++++++++++++------------------- 1 file changed, 25 insertions(+), 27 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/debugtoolbar.rst b/docs/quick_tutorial/debugtoolbar.rst index 90750c633..d138eb760 100644 --- a/docs/quick_tutorial/debugtoolbar.rst +++ b/docs/quick_tutorial/debugtoolbar.rst @@ -58,33 +58,31 @@ Steps Analysis ======== -``pyramid_debugtoolbar`` is a full-fledged Python package, -available on PyPI just like thousands of other Python packages. Thus we -start by installing the ``pyramid_debugtoolbar`` package into our -virtual environment using normal Python package installation commands. - -The ``pyramid_debugtoolbar`` Python package is also a Pyramid add-on, -which means we need to include its add-on configuration into our web -application. We could do this with imperative configuration in -``tutorial/__init__.py`` by using ``config.include``. Pyramid also -supports wiring in add-on configuration via our ``development.ini`` -using ``pyramid.includes``. We use this to load the configuration for -the debugtoolbar. - -You'll now see an attractive button on the right side of -your browser, which you may click to provide introspective access to debugging -information in a new browser tab. Even better, if your web application -generates an error, -you will see a nice traceback on the screen. When you want to disable -this toolbar, no need to change code: you can remove it from -``pyramid.includes`` in the relevant ``.ini`` configuration file (thus -showing why configuration files are handy.) - -Note injects a small amount of html/css into your app just before the closing -```` tag in order to display itself. If you -start to experience otherwise inexplicable client-side weirdness, you can shut -it off by commenting out the ``pyramid_debugtoolbar`` line in -``pyramid.includes`` temporarily. +``pyramid_debugtoolbar`` is a full-fledged Python package, available on PyPI +just like thousands of other Python packages. Thus we start by installing the +``pyramid_debugtoolbar`` package into our virtual environment using normal +Python package installation commands. + +The ``pyramid_debugtoolbar`` Python package is also a Pyramid add-on, which +means we need to include its add-on configuration into our web application. We +could do this with imperative configuration in ``tutorial/__init__.py`` by +using ``config.include``. Pyramid also supports wiring in add-on configuration +via our ``development.ini`` using ``pyramid.includes``. We use this to load +the configuration for the debugtoolbar. + +You'll now see an attractive button on the right side of your browser, which +you may click to provide introspective access to debugging information in a +new browser tab. Even better, if your web application generates an error, you +will see a nice traceback on the screen. When you want to disable this +toolbar, no need to change code: you can remove it from ``pyramid.includes`` +in the relevant ``.ini`` configuration file (thus showing why configuration +files are handy.) + +Note that the toolbar injects a small amount of html/css into your app just +before the closing ```` tag in order to display itself. If you start to +experience otherwise inexplicable client-side weirdness, you can shut it off +by commenting out the ``pyramid_debugtoolbar`` line in ``pyramid.includes`` +temporarily. .. seealso:: See also :ref:`pyramid_debugtoolbar `. -- cgit v1.2.3 From 95bf541f94513b5ec2585c5ecf9f9aa684853676 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 9 Nov 2014 20:45:37 -0800 Subject: - add missing "has" --- docs/quick_tutorial/logging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/logging.rst b/docs/quick_tutorial/logging.rst index 855ded59f..e07d23d6d 100644 --- a/docs/quick_tutorial/logging.rst +++ b/docs/quick_tutorial/logging.rst @@ -16,7 +16,7 @@ we might need to detect problems when other people use the site. We need *logging*. Fortunately Pyramid uses the normal Python approach to logging. The -scaffold generated, in your ``development.ini``, a number of lines that +scaffold generated, in your ``development.ini``, has a number of lines that configure the logging for you to some reasonable defaults. You then see messages sent by Pyramid (for example, when a new request comes in.) -- cgit v1.2.3 From f9dd376581bdd4b45a28cfffafc2f08343f7c5d0 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 30 Apr 2015 03:34:13 -0700 Subject: correct view name --- docs/quick_tutorial/views.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/views.rst b/docs/quick_tutorial/views.rst index 529bba0a4..6728925fd 100644 --- a/docs/quick_tutorial/views.rst +++ b/docs/quick_tutorial/views.rst @@ -92,7 +92,7 @@ module ``views.py`` which is scanned via ``config.scan('.views')``. We have 2 views, each leading to the other. If you start at http://localhost:6543/, you get a response with a link to the next -view. The ``hello_view`` (available at the URL ``/howdy``) has a link +view. The ``hello`` view (available at the URL ``/howdy``) has a link back to the first view. This step also shows that the name appearing in the URL, -- cgit v1.2.3 From a4239799f7520729e395210ba4f69d57060d723b Mon Sep 17 00:00:00 2001 From: Areski Belaid Date: Fri, 1 May 2015 00:38:58 +0200 Subject: Update logging.rst The point 5 from this tutorial http://docs.pylonsproject.org/projects/pyramid/en/latest/quick_tutorial/logging.html mention that we should see a debug message. This appears before any needed changes in `development.ini`, thus this patch intend to change the order and add an extra point to put forward changes in the ini file. --- docs/quick_tutorial/logging.rst | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/logging.rst b/docs/quick_tutorial/logging.rst index e07d23d6d..82cfbe3c3 100644 --- a/docs/quick_tutorial/logging.rst +++ b/docs/quick_tutorial/logging.rst @@ -42,6 +42,12 @@ Steps .. literalinclude:: logging/tutorial/views.py :linenos: +#. Finally let's edit ``development.ini`` configuration file + to enable logging for our Pyramid application: + + .. literalinclude:: logging/development.ini + :language: ini + #. Make sure the tests still pass: .. code-block:: bash @@ -61,15 +67,10 @@ Steps Analysis ======== -Our ``development.ini`` configuration file wires up Python standard -logging for our Pyramid application: - -.. literalinclude:: logging/development.ini - :language: ini - -In this, our ``tutorial`` Python package is setup as a logger -and configured to log messages at a ``DEBUG`` or higher level. When you -visit http://localhost:6543 your console will now show:: +In our configuration file ``development.ini``, our ``tutorial`` Python +package is setup as a logger and configured to log messages at a +``DEBUG`` or higher level. When you visit http://localhost:6543 your +console will now show:: 2013-08-09 10:42:42,968 DEBUG [tutorial.views][MainThread] In home view -- cgit v1.2.3 From 6799b83daa8406168f0361b7550a8f7ea98bf373 Mon Sep 17 00:00:00 2001 From: Florian Klemme Date: Fri, 8 May 2015 13:56:41 +0200 Subject: Fixed minor highlighting mistake. There was just an apostrophe missing. --- docs/quick_tutorial/static_assets.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/static_assets.rst b/docs/quick_tutorial/static_assets.rst index 19d33f00f..3a7496ec7 100644 --- a/docs/quick_tutorial/static_assets.rst +++ b/docs/quick_tutorial/static_assets.rst @@ -25,7 +25,7 @@ Steps $ cd ..; cp -r view_classes static_assets; cd static_assets $ $VENV/bin/python setup.py develop -#. We add a call ``config.add_static_view in +#. We add a call ``config.add_static_view`` in ``static_assets/tutorial/__init__.py``: .. literalinclude:: static_assets/tutorial/__init__.py -- cgit v1.2.3 From de117d259b08c4a46dc67b5362cdd4db2e10dc97 Mon Sep 17 00:00:00 2001 From: Areski Belaid Date: Mon, 11 May 2015 16:52:17 +0200 Subject: Update authorization.rst fix the url for hello route '/howdy' --- docs/quick_tutorial/authorization.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/authorization.rst b/docs/quick_tutorial/authorization.rst index 6b10d3409..dc159234c 100644 --- a/docs/quick_tutorial/authorization.rst +++ b/docs/quick_tutorial/authorization.rst @@ -93,7 +93,7 @@ In summary: ``hello`` wants ``edit`` permission, ``Root`` says Of course, this only applies on ``Root``. Some other part of the site (a.k.a. *context*) might have a different ACL. -If you are not logged in and visit ``/hello``, you need to get +If you are not logged in and visit ``/howdy``, you need to get shown the login screen. How does Pyramid know what is the login page to use? We explicitly told Pyramid that the ``login`` view should be used by decorating the view with ``@forbidden_view_config``. -- cgit v1.2.3 From 109792709bf90eddf85eaaed1743b5cbb1faa34e Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 May 2015 16:12:35 -0700 Subject: cherrypick from 1.5 --- docs/quick_tutorial/requirements.rst | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index b5778ea42..6628c4f17 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -58,11 +58,8 @@ Steps Install Python 3.3 or greater ----------------------------- -Download the latest standard Python 3.3+ release (not development -release) from -`python.org `_. On that page, you -must click the latest version, then scroll down to the "Downloads" section -for your operating system. +Download the latest standard Python 3.3+ release (not development release) +from `python.org `_. Windows and Mac OS X users can download and run an installer. @@ -73,8 +70,7 @@ directions. Make sure you get the proper 32- or 64-bit build and Python version. Linux users can either use their package manager to install Python 3.3 -or may -`build Python 3.3 from source +or may `build Python 3.3 from source `_. -- cgit v1.2.3 From 0d4d7cb81ae162cafe21546b1ae1df8f33b4b8af Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 May 2015 16:54:56 -0700 Subject: - replace image with ASCII tree diagram - make venv name generic without a version to reduce future maintenance --- docs/quick_tutorial/requirements.rst | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index 6628c4f17..a737ede0e 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -82,13 +82,21 @@ Create a project directory structure We will arrive at a directory structure of ``workspace->project->package``, with our workspace named -``quick_tutorial``. The following diagram shows how this is structured -and where our virtual environment will reside: - -.. figure:: ../_static/directory_structure_pyramid.png - :alt: Final directory structure - - Final directory structure. +``quick_tutorial``. The following tree diagram shows how this will be +structured and where our virtual environment will reside as we proceed through +the tutorial: + +.. code-block:: text + + └── ~ + └── projects + └── quick_tutorial + ├── env + └── step_one + ├── intro + │ ├── __init__.py + │ └── app.py + └── setup.py For Linux, the commands to do so are as follows: @@ -132,11 +140,11 @@ environment. We set an environment variable to save typing later. .. code-block:: bash # Mac and Linux - $ export VENV=~/projects/quick_tutorial/env33/ + $ export VENV=~/projects/quick_tutorial/env # Windows # TODO: This command does not work - c:\> set VENV=c:\projects\quick_tutorial\env33 + c:\> set VENV=c:\projects\quick_tutorial\env .. _create-a-virtual-environment: -- cgit v1.2.3 From 6c4df679cb7ad75c7ffa3ca8bf320be76d0c8d98 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 20 May 2015 01:17:45 -0700 Subject: re-moving unnecessary hyphenation (see what I did there?) --- docs/quick_tutorial/package.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/package.rst b/docs/quick_tutorial/package.rst index 8fb052d5b..54a6a0bd9 100644 --- a/docs/quick_tutorial/package.rst +++ b/docs/quick_tutorial/package.rst @@ -3,7 +3,7 @@ ============================================ Most modern Python development is done using Python packages, an approach -Pyramid puts to good use. In this step we re-do "Hello World" as a +Pyramid puts to good use. In this step we redo "Hello World" as a minimum Python package inside a minimum Python project. Background @@ -93,7 +93,7 @@ Python projects, via ``setup.py``, gives us special features when our package is installed (in this case, in local development mode.) In this step we have a Python package called ``tutorial``. We use the -same name in each step of the tutorial, to avoid unnecessary re-typing. +same name in each step of the tutorial, to avoid unnecessary retyping. Above this ``tutorial`` directory we have the files that handle the packaging of this project. At the moment, all we need is a -- cgit v1.2.3 From 722a0e2b2ced00d1375ef70f4c86652522a03081 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 20 May 2015 01:35:22 -0700 Subject: correct reference to line numbers --- docs/quick_tutorial/ini.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/ini.rst b/docs/quick_tutorial/ini.rst index b8720711b..4e062e575 100644 --- a/docs/quick_tutorial/ini.rst +++ b/docs/quick_tutorial/ini.rst @@ -88,7 +88,7 @@ the Pyramid chapter on - ``pserve`` looks for ``[app:main]`` and finds ``use = egg:tutorial`` -- The projects's ``setup.py`` has defined an "entry point" (lines 9-10) +- The projects's ``setup.py`` has defined an "entry point" (lines 9-12) for the project "main" entry point of ``tutorial:main`` - The ``tutorial`` package's ``__init__`` has a ``main`` function -- cgit v1.2.3 From ab06fa193d61dc2c5280fa4fbeed364795ec04ae Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 20 May 2015 02:14:40 -0700 Subject: - grammar/wrapping - capitalization --- docs/quick_tutorial/debugtoolbar.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/debugtoolbar.rst b/docs/quick_tutorial/debugtoolbar.rst index d138eb760..a5623ae2a 100644 --- a/docs/quick_tutorial/debugtoolbar.rst +++ b/docs/quick_tutorial/debugtoolbar.rst @@ -74,11 +74,11 @@ You'll now see an attractive button on the right side of your browser, which you may click to provide introspective access to debugging information in a new browser tab. Even better, if your web application generates an error, you will see a nice traceback on the screen. When you want to disable this -toolbar, no need to change code: you can remove it from ``pyramid.includes`` -in the relevant ``.ini`` configuration file (thus showing why configuration -files are handy.) +toolbar, there's no need to change code: you can remove it from +``pyramid.includes`` in the relevant ``.ini`` configuration file (thus showing +why configuration files are handy.) -Note that the toolbar injects a small amount of html/css into your app just +Note that the toolbar injects a small amount of HTML/CSS into your app just before the closing ```` tag in order to display itself. If you start to experience otherwise inexplicable client-side weirdness, you can shut it off by commenting out the ``pyramid_debugtoolbar`` line in ``pyramid.includes`` -- cgit v1.2.3 From f818fabb72f0aa53beb2b559b079dcc038530442 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 20 May 2015 03:23:12 -0700 Subject: punctuation fix --- docs/quick_tutorial/unit_testing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/unit_testing.rst b/docs/quick_tutorial/unit_testing.rst index f8a33b39d..4cb7ef714 100644 --- a/docs/quick_tutorial/unit_testing.rst +++ b/docs/quick_tutorial/unit_testing.rst @@ -24,7 +24,7 @@ and functionality. The Pyramid developers use ``nose``, which we'll thus use in this tutorial. Don't worry, this tutorial won't be pedantic about "test-driven -development" (TDD.) We'll do just enough to ensure that, in each step, +development" (TDD). We'll do just enough to ensure that, in each step, we haven't majorly broken the code. As you're writing your code you might find this more convenient than changing to your browser constantly and clicking reload. -- cgit v1.2.3 From bbb8f374eb7a1dcbc92f732cc4ccc0a2c92526d5 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 20 May 2015 23:47:23 -0700 Subject: punctuation fix --- docs/quick_tutorial/functional_testing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/functional_testing.rst b/docs/quick_tutorial/functional_testing.rst index 09b05b0bc..6f1544e79 100644 --- a/docs/quick_tutorial/functional_testing.rst +++ b/docs/quick_tutorial/functional_testing.rst @@ -10,7 +10,7 @@ Background ========== Unit tests are a common and popular approach to test-driven development -(TDD.) In web applications, though, the templating and entire apparatus +(TDD). In web applications, though, the templating and entire apparatus of a web site are important parts of the delivered quality. We'd like a way to test these. -- cgit v1.2.3 From 0c78388845bd4a020b924c7689f88168531427a7 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 21 May 2015 00:24:47 -0700 Subject: - correct title tag - grammar --- docs/quick_tutorial/templating.rst | 2 +- docs/quick_tutorial/templating/tutorial/home.pt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/templating.rst b/docs/quick_tutorial/templating.rst index d73067f48..cf56d2a96 100644 --- a/docs/quick_tutorial/templating.rst +++ b/docs/quick_tutorial/templating.rst @@ -112,7 +112,7 @@ Analysis Ahh, that looks better. We have a view that is focused on Python code. Our ``@view_config`` decorator specifies a :term:`renderer` that points -our template file. Our view then simply returns data which is then +to our template file. Our view then simply returns data which is then supplied to our template. Note that we used the same template for both views. diff --git a/docs/quick_tutorial/templating/tutorial/home.pt b/docs/quick_tutorial/templating/tutorial/home.pt index a0cc08e7a..fd4ef8764 100644 --- a/docs/quick_tutorial/templating/tutorial/home.pt +++ b/docs/quick_tutorial/templating/tutorial/home.pt @@ -1,9 +1,9 @@ - Quick Tour: ${name} + Quick Tutorial: ${name}

Hi ${name}

- \ No newline at end of file + -- cgit v1.2.3 From 511dc7b09996d91b8158b70607107d109b1015b6 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 21 May 2015 01:02:12 -0700 Subject: grammar fixes --- docs/quick_tutorial/view_classes.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/view_classes.rst b/docs/quick_tutorial/view_classes.rst index 58ab43e40..50a7ee0af 100644 --- a/docs/quick_tutorial/view_classes.rst +++ b/docs/quick_tutorial/view_classes.rst @@ -51,7 +51,7 @@ Steps :linenos: #. Our unit tests in ``view_classes/tutorial/tests.py`` don't run, - so let's modify the to import the view class and make an instance + so let's modify them to import the view class and make an instance before getting a response: .. literalinclude:: view_classes/tutorial/tests.py @@ -88,7 +88,7 @@ view class, then updated the tests. In our ``TutorialViews`` view class you can see that our two view classes are logically grouped together as methods on a common class. Since the two views shared the same template, we could move that to a -``@view_defaults`` decorator on at the class level. +``@view_defaults`` decorator at the class level. The tests needed to change. Obviously we needed to import the view class. But you can also see the pattern in the tests of instantiating -- cgit v1.2.3 From ef8791f0af1124ce5b862b9ea245840b58f5408d Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 22 May 2015 01:45:26 -0700 Subject: add linenos to python code --- docs/quick_tutorial/request_response.rst | 3 +++ 1 file changed, 3 insertions(+) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/request_response.rst b/docs/quick_tutorial/request_response.rst index 504803804..4f8de0221 100644 --- a/docs/quick_tutorial/request_response.rst +++ b/docs/quick_tutorial/request_response.rst @@ -46,14 +46,17 @@ Steps #. Simplify the routes in ``request_response/tutorial/__init__.py``: .. literalinclude:: request_response/tutorial/__init__.py + :linenos: #. We only need one view in ``request_response/tutorial/views.py``: .. literalinclude:: request_response/tutorial/views.py + :linenos: #. Update the tests in ``request_response/tutorial/tests.py``: .. literalinclude:: request_response/tutorial/tests.py + :linenos: #. Now run the tests: -- cgit v1.2.3 From 4caf31c082d4d4577ff09d67d420d5f50ecfe042 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 22 May 2015 02:14:00 -0700 Subject: add missing word; correct title tag --- docs/quick_tutorial/routing.rst | 2 +- docs/quick_tutorial/routing/tutorial/home.pt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/routing.rst b/docs/quick_tutorial/routing.rst index 54dff5c39..1b79a5889 100644 --- a/docs/quick_tutorial/routing.rst +++ b/docs/quick_tutorial/routing.rst @@ -14,7 +14,7 @@ Writing web applications usually means sophisticated URL design. We just saw some Pyramid machinery for requests and views. Let's look at features that help in routing. -Previously we saw the basics of routing URLs to views in +Previously we saw the basics of routing URLs to views in Pyramid. - Your project's "setup" code registers a route name to be used when matching part of the URL diff --git a/docs/quick_tutorial/routing/tutorial/home.pt b/docs/quick_tutorial/routing/tutorial/home.pt index f2b991059..b68e96338 100644 --- a/docs/quick_tutorial/routing/tutorial/home.pt +++ b/docs/quick_tutorial/routing/tutorial/home.pt @@ -1,10 +1,10 @@ - Quick Tour: ${name} + Quick Tutorial: ${name}

${name}

First: ${first}, Last: ${last}

- \ No newline at end of file + -- cgit v1.2.3 From 5cef2824260103212eb96d7d372c72cdc45c4deb Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 22 May 2015 02:31:36 -0700 Subject: spelling; correct title tag --- docs/quick_tutorial/jinja2.rst | 2 +- docs/quick_tutorial/jinja2/tutorial/home.jinja2 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/jinja2.rst b/docs/quick_tutorial/jinja2.rst index 613542349..2121803f9 100644 --- a/docs/quick_tutorial/jinja2.rst +++ b/docs/quick_tutorial/jinja2.rst @@ -6,7 +6,7 @@ We just said Pyramid doesn't prefer one templating language over another. Time to prove it. Jinja2 is a popular templating system, -used in Flask and modelled after Django's templates. Let's add +used in Flask and modeled after Django's templates. Let's add ``pyramid_jinja2``, a Pyramid :term:`add-on` which enables Jinja2 as a :term:`renderer` in our Pyramid applications. diff --git a/docs/quick_tutorial/jinja2/tutorial/home.jinja2 b/docs/quick_tutorial/jinja2/tutorial/home.jinja2 index 975323169..20d33b733 100644 --- a/docs/quick_tutorial/jinja2/tutorial/home.jinja2 +++ b/docs/quick_tutorial/jinja2/tutorial/home.jinja2 @@ -1,9 +1,9 @@ - Quick Tour: {{ name }} + Quick Tutorial: {{ name }}

Hi {{ name }}

- \ No newline at end of file + -- cgit v1.2.3 From e3489b18d9aa6c6e03b5a3808c07ef07b1836bef Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 22 May 2015 02:47:00 -0700 Subject: correct title tag --- docs/quick_tutorial/static_assets/tutorial/home.pt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/static_assets/tutorial/home.pt b/docs/quick_tutorial/static_assets/tutorial/home.pt index 5d347f057..57867a1ff 100644 --- a/docs/quick_tutorial/static_assets/tutorial/home.pt +++ b/docs/quick_tutorial/static_assets/tutorial/home.pt @@ -1,11 +1,11 @@ - Quick Tour: ${name} + Quick Tutorial: ${name}

Hi ${name}

- \ No newline at end of file + -- cgit v1.2.3 From 6e5b726e6a14d789bf0b1cf190c635e626f805ce Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 22 May 2015 02:58:21 -0700 Subject: correct title tag --- docs/quick_tutorial/json/tutorial/home.pt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/json/tutorial/home.pt b/docs/quick_tutorial/json/tutorial/home.pt index a0cc08e7a..fd4ef8764 100644 --- a/docs/quick_tutorial/json/tutorial/home.pt +++ b/docs/quick_tutorial/json/tutorial/home.pt @@ -1,9 +1,9 @@ - Quick Tour: ${name} + Quick Tutorial: ${name}

Hi ${name}

- \ No newline at end of file + -- cgit v1.2.3 From fee4d401797e71f4c7c43744054ad6f6877cd77b Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 22 May 2015 03:49:59 -0700 Subject: include tests; grammar; correct title tag --- docs/quick_tutorial/more_view_classes.rst | 19 ++++++++++++++++++- .../more_view_classes/tutorial/delete.pt | 4 ++-- .../quick_tutorial/more_view_classes/tutorial/edit.pt | 4 ++-- .../more_view_classes/tutorial/hello.pt | 4 ++-- .../quick_tutorial/more_view_classes/tutorial/home.pt | 4 ++-- 5 files changed, 26 insertions(+), 9 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/more_view_classes.rst b/docs/quick_tutorial/more_view_classes.rst index 9cc4cc520..c06fb0f15 100644 --- a/docs/quick_tutorial/more_view_classes.rst +++ b/docs/quick_tutorial/more_view_classes.rst @@ -95,6 +95,23 @@ Steps .. literalinclude:: more_view_classes/tutorial/delete.pt :language: html +#. Our tests in ``more_view_classes/tutorial/tests.py`` fail, so let's modify + them: + + .. literalinclude:: more_view_classes/tutorial/tests.py + :linenos: + +#. Now run the tests: + + .. code-block:: bash + + $ $VENV/bin/nosetests tutorial + . + ---------------------------------------------------------------------- + Ran 2 tests in 0.248s + + OK + #. Run your Pyramid application with: .. code-block:: bash @@ -125,7 +142,7 @@ Specifically: - The fourth view is returned when clicking on a button such as ````. -In this step we show using the following information as criteria to +In this step we show, using the following information as criteria, how to decide which view to use: - Method of the HTTP request (``GET``, ``POST``, etc.) diff --git a/docs/quick_tutorial/more_view_classes/tutorial/delete.pt b/docs/quick_tutorial/more_view_classes/tutorial/delete.pt index 67cc8bf09..7bd4d3b0d 100644 --- a/docs/quick_tutorial/more_view_classes/tutorial/delete.pt +++ b/docs/quick_tutorial/more_view_classes/tutorial/delete.pt @@ -1,9 +1,9 @@ - Quick Tour: ${page_title} + Quick Tutorial: ${page_title}

${view.view_name} - ${page_title}

- \ No newline at end of file + diff --git a/docs/quick_tutorial/more_view_classes/tutorial/edit.pt b/docs/quick_tutorial/more_view_classes/tutorial/edit.pt index 1bd204065..523a4ce5d 100644 --- a/docs/quick_tutorial/more_view_classes/tutorial/edit.pt +++ b/docs/quick_tutorial/more_view_classes/tutorial/edit.pt @@ -1,10 +1,10 @@ - Quick Tour: ${view.view_name} - ${page_title} + Quick Tutorial: ${view.view_name} - ${page_title}

${view.view_name} - ${page_title}

You submitted ${new_name}

- \ No newline at end of file + diff --git a/docs/quick_tutorial/more_view_classes/tutorial/hello.pt b/docs/quick_tutorial/more_view_classes/tutorial/hello.pt index 8a39aed09..40b00bfe4 100644 --- a/docs/quick_tutorial/more_view_classes/tutorial/hello.pt +++ b/docs/quick_tutorial/more_view_classes/tutorial/hello.pt @@ -1,7 +1,7 @@ - Quick Tour: ${view.view_name} - ${page_title} + Quick Tutorial: ${view.view_name} - ${page_title}

${view.view_name} - ${page_title}

@@ -13,4 +13,4 @@ - \ No newline at end of file + diff --git a/docs/quick_tutorial/more_view_classes/tutorial/home.pt b/docs/quick_tutorial/more_view_classes/tutorial/home.pt index fa9016705..fa0436f7e 100644 --- a/docs/quick_tutorial/more_view_classes/tutorial/home.pt +++ b/docs/quick_tutorial/more_view_classes/tutorial/home.pt @@ -1,7 +1,7 @@ - Quick Tour: ${view.view_name} - ${page_title} + Quick Tutorial: ${view.view_name} - ${page_title}

${view.view_name} - ${page_title}

@@ -9,4 +9,4 @@

Go to the form.

- \ No newline at end of file + -- cgit v1.2.3 From 955f6fa9646cf99c850c80a00c79f411578e8387 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 22 May 2015 13:06:55 -0700 Subject: punctuation; correct title tag --- docs/quick_tutorial/logging.rst | 4 ++-- docs/quick_tutorial/logging/tutorial/home.pt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/logging.rst b/docs/quick_tutorial/logging.rst index 82cfbe3c3..5d29cd196 100644 --- a/docs/quick_tutorial/logging.rst +++ b/docs/quick_tutorial/logging.rst @@ -16,9 +16,9 @@ we might need to detect problems when other people use the site. We need *logging*. Fortunately Pyramid uses the normal Python approach to logging. The -scaffold generated, in your ``development.ini``, has a number of lines that +scaffold generated in your ``development.ini`` has a number of lines that configure the logging for you to some reasonable defaults. You then see -messages sent by Pyramid (for example, when a new request comes in.) +messages sent by Pyramid, for example, when a new request comes in. Objectives ========== diff --git a/docs/quick_tutorial/logging/tutorial/home.pt b/docs/quick_tutorial/logging/tutorial/home.pt index a0cc08e7a..fd4ef8764 100644 --- a/docs/quick_tutorial/logging/tutorial/home.pt +++ b/docs/quick_tutorial/logging/tutorial/home.pt @@ -1,9 +1,9 @@ - Quick Tour: ${name} + Quick Tutorial: ${name}

Hi ${name}

- \ No newline at end of file + -- cgit v1.2.3 From 3ce38a3acef836aa264a9b6d7694833257c2c6d5 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 22 May 2015 13:19:15 -0700 Subject: grammar; correct title tag --- docs/quick_tutorial/sessions.rst | 2 +- docs/quick_tutorial/sessions/tutorial/home.pt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/sessions.rst b/docs/quick_tutorial/sessions.rst index b4887beb8..f97405500 100644 --- a/docs/quick_tutorial/sessions.rst +++ b/docs/quick_tutorial/sessions.rst @@ -89,7 +89,7 @@ when you add an item using a form ``POST``, the site usually issues a second HTTP Redirect web request to view the new item. You might want a message to appear after that second web request saying "Your item was added." You can't just return it in the web response for the POST, -as it will be tossed out during the second web requests. +as it will be tossed out during the second web request. Flash messages are a technique where messages can be stored between requests, using sessions, then removed when they finally get displayed. diff --git a/docs/quick_tutorial/sessions/tutorial/home.pt b/docs/quick_tutorial/sessions/tutorial/home.pt index 0b27ba1d8..50342e52f 100644 --- a/docs/quick_tutorial/sessions/tutorial/home.pt +++ b/docs/quick_tutorial/sessions/tutorial/home.pt @@ -1,10 +1,10 @@ - Quick Tour: ${name} + Quick Tutorial: ${name}

Hi ${name}

Count: ${view.counter}

- \ No newline at end of file + -- cgit v1.2.3 From 003b9aaef924ba3934a8e23854be5b7a6e6ae7e0 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 22 May 2015 17:37:58 -0700 Subject: - add jQuery to the template - punctuation, grammar --- docs/quick_tutorial/forms.rst | 6 +++--- docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/forms.rst b/docs/quick_tutorial/forms.rst index b08167edc..f81b88fc2 100644 --- a/docs/quick_tutorial/forms.rst +++ b/docs/quick_tutorial/forms.rst @@ -12,13 +12,13 @@ Background Modern web applications deal extensively with forms. Developers, though, have a wide range of philosophies about how frameworks should help them with their forms. As such, Pyramid doesn't directly bundle -one particular form library. Instead, there are a variety of form +one particular form library. Instead there are a variety of form libraries that are easy to use in Pyramid. :ref:`Deform ` is one such library. In this step, we introduce Deform for our -forms and validation. This also gives us the -:ref:`Colander ` for schemas and validation. +forms and validation. This also gives us :ref:`Colander ` +for schemas and validation. Deform is getting a facelift, with styling from Twitter Bootstrap and advanced widgets from popular JavaScript projects. The work began in diff --git a/docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt b/docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt index 3292dfd90..547465018 100644 --- a/docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt +++ b/docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt @@ -6,6 +6,8 @@ + -- cgit v1.2.3 From c8e23eca583e1e3dd770951e820004a1477c4e11 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 23 May 2015 12:05:56 -0700 Subject: fix template static asset URLs; grammar; line numbers --- docs/quick_tutorial/databases.rst | 16 +++++++++------- .../databases/tutorial/wikipage_addedit.pt | 6 ++++-- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index 7c019dbfc..580774163 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -53,8 +53,8 @@ Steps .. note:: - We aren't yet doing ``python3.3 setup.py develop`` as we - are changing it later. + We aren't yet doing ``$VENV/bin/python setup.py develop`` as we + will change it later. #. Our configuration file at ``databases/development.ini`` wires together some new pieces: @@ -72,6 +72,7 @@ Steps to initialize the database: .. literalinclude:: databases/tutorial/initialize_db.py + :linenos: #. Since ``setup.py`` changed, we now run it: @@ -104,6 +105,7 @@ Steps our ``databases/tutorial/views.py``: .. literalinclude:: databases/tutorial/views.py + :linenos: #. Our tests in ``databases/tutorial/tests.py`` changed to include SQLAlchemy bootstrapping: @@ -138,8 +140,8 @@ Let's start with the dependencies. We made the decision to use ``pyramid_tm`` and ``zope.sqlalchemy``. Why? Pyramid has a strong orientation towards support for ``transactions``. -Specifically, you can install a transaction manager into your app -application, either as middleware or a Pyramid "tween". Then, +Specifically, you can install a transaction manager into your +application either as middleware or a Pyramid "tween". Then, just before you return the response, all transaction-aware parts of your application are executed. @@ -149,7 +151,7 @@ aborts the transaction. This is a very liberating way to write code. The ``pyramid_tm`` package provides a "tween" that is configured in the ``development.ini`` configuration file. That installs it. We then need -a package that makes SQLAlchemy and thus the RDBMS transaction manager +a package that makes SQLAlchemy, and thus the RDBMS transaction manager, integrate with the Pyramid transaction manager. That's what ``zope.sqlalchemy`` does. @@ -167,8 +169,8 @@ console script follows the pattern of being fed a configuration file with all the bootstrapping. It then opens SQLAlchemy and creates the root of the wiki, which also makes the SQLite file. Note the ``with transaction.manager`` part that puts the work in the scope of a -transaction (as we aren't inside a web request where this is done -automatically.) +transaction, as we aren't inside a web request where this is done +automatically. The ``models.py`` does a little bit extra work to hook up SQLAlchemy into the Pyramid transaction manager. It then declares the model for a diff --git a/docs/quick_tutorial/databases/tutorial/wikipage_addedit.pt b/docs/quick_tutorial/databases/tutorial/wikipage_addedit.pt index d1fea0d7f..01955ef72 100644 --- a/docs/quick_tutorial/databases/tutorial/wikipage_addedit.pt +++ b/docs/quick_tutorial/databases/tutorial/wikipage_addedit.pt @@ -4,10 +4,12 @@ WikiPage: Add/Edit + href="${request.static_url(reqt)}"> + - -- cgit v1.2.3 From ce2ba51a51a773af0e9b0d63236fb6522aa6cf50 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 23 May 2015 15:13:58 -0700 Subject: correct title tag; punctuation --- docs/quick_tutorial/authentication.rst | 2 +- docs/quick_tutorial/authentication/tutorial/home.pt | 4 ++-- docs/quick_tutorial/authentication/tutorial/login.pt | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/authentication.rst b/docs/quick_tutorial/authentication.rst index 4b4eb1ba3..a4ab83c45 100644 --- a/docs/quick_tutorial/authentication.rst +++ b/docs/quick_tutorial/authentication.rst @@ -93,7 +93,7 @@ Steps Analysis ======== -Unlike many web frameworks, Pyramid includes a built-in (but optional) +Unlike many web frameworks, Pyramid includes a built-in but optional security model for authentication and authorization. This security system is intended to be flexible and support many needs. In this security model, authentication (who are you) and authorization (what diff --git a/docs/quick_tutorial/authentication/tutorial/home.pt b/docs/quick_tutorial/authentication/tutorial/home.pt index 6ecd0081b..ed911b673 100644 --- a/docs/quick_tutorial/authentication/tutorial/home.pt +++ b/docs/quick_tutorial/authentication/tutorial/home.pt @@ -1,7 +1,7 @@ - Quick Tour: ${name} + Quick Tutorial: ${name} @@ -15,4 +15,4 @@

Hi ${name}

Visit hello

- \ No newline at end of file + diff --git a/docs/quick_tutorial/authentication/tutorial/login.pt b/docs/quick_tutorial/authentication/tutorial/login.pt index 4451fc4f8..9e5bfe2ad 100644 --- a/docs/quick_tutorial/authentication/tutorial/login.pt +++ b/docs/quick_tutorial/authentication/tutorial/login.pt @@ -1,7 +1,7 @@ - Quick Tour: ${name} + Quick Tutorial: ${name}

Login

@@ -22,4 +22,4 @@ value="Log In"/> - \ No newline at end of file + -- cgit v1.2.3 From 5fc95b6926b2049b2bbec53c6fc5a83a81018629 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 23 May 2015 15:29:06 -0700 Subject: correct title tag; grammar, punctuation --- docs/quick_tutorial/authorization.rst | 4 ++-- docs/quick_tutorial/authorization/tutorial/home.pt | 4 ++-- docs/quick_tutorial/authorization/tutorial/login.pt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/authorization.rst b/docs/quick_tutorial/authorization.rst index dc159234c..08df15a28 100644 --- a/docs/quick_tutorial/authorization.rst +++ b/docs/quick_tutorial/authorization.rst @@ -11,7 +11,7 @@ Background Our application has URLs that allow people to add/edit/delete content via a web browser. Time to add security to the application. Let's protect our add/edit views to require a login (username of -``editor`` and password of ``editor``.) We will allow the other views +``editor`` and password of ``editor``). We will allow the other views to continue working without a password. Objectives @@ -101,7 +101,7 @@ by decorating the view with ``@forbidden_view_config``. Extra Credit ============ -#. Perhaps you would like experience of not having enough permissions +#. Perhaps you would like the experience of not having enough permissions (forbidden) to be richer. How could you change this? #. Perhaps we want to store security statements in a database and diff --git a/docs/quick_tutorial/authorization/tutorial/home.pt b/docs/quick_tutorial/authorization/tutorial/home.pt index 6ecd0081b..ed911b673 100644 --- a/docs/quick_tutorial/authorization/tutorial/home.pt +++ b/docs/quick_tutorial/authorization/tutorial/home.pt @@ -1,7 +1,7 @@ - Quick Tour: ${name} + Quick Tutorial: ${name} @@ -15,4 +15,4 @@

Hi ${name}

Visit hello

- \ No newline at end of file + diff --git a/docs/quick_tutorial/authorization/tutorial/login.pt b/docs/quick_tutorial/authorization/tutorial/login.pt index 4451fc4f8..9e5bfe2ad 100644 --- a/docs/quick_tutorial/authorization/tutorial/login.pt +++ b/docs/quick_tutorial/authorization/tutorial/login.pt @@ -1,7 +1,7 @@ - Quick Tour: ${name} + Quick Tutorial: ${name}

Login

@@ -22,4 +22,4 @@ value="Log In"/> - \ No newline at end of file + -- cgit v1.2.3 From 608f955e20723723f33750211bb12debf613819b Mon Sep 17 00:00:00 2001 From: Karen Dalton Date: Mon, 1 Jun 2015 12:54:43 -0700 Subject: Add additional logging configs necessary for db script output and update tests.py to fix the 'At least one scoped session' warning --- docs/quick_tutorial/databases.rst | 28 +++++++++++++------ docs/quick_tutorial/databases/development.ini | 36 +++++++++++++++++++++++++ docs/quick_tutorial/databases/tutorial/tests.py | 4 +-- 3 files changed, 58 insertions(+), 10 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index 580774163..19dfd066d 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -90,17 +90,29 @@ Steps .. code-block:: bash $ $VENV/bin/initialize_tutorial_db development.ini - 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages") - 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] () - 2013-09-06 15:54:08,051 INFO [sqlalchemy.engine.base.Engine][MainThread] + 2015-06-01 11:22:52,650 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1 + 2015-06-01 11:22:52,650 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2015-06-01 11:22:52,651 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1 + 2015-06-01 11:22:52,651 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2015-06-01 11:22:52,652 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages") + 2015-06-01 11:22:52,652 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2015-06-01 11:22:52,653 INFO [sqlalchemy.engine.base.Engine][MainThread] CREATE TABLE wikipages ( - uid INTEGER NOT NULL, - title TEXT, - body TEXT, - PRIMARY KEY (uid), - UNIQUE (title) + uid INTEGER NOT NULL, + title TEXT, + body TEXT, + PRIMARY KEY (uid), + UNIQUE (title) ) + + 2015-06-01 11:22:52,653 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2015-06-01 11:22:52,655 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT + 2015-06-01 11:22:52,658 INFO [sqlalchemy.engine.base.Engine][MainThread] BEGIN (implicit) + 2015-06-01 11:22:52,659 INFO [sqlalchemy.engine.base.Engine][MainThread] INSERT INTO wikipages (title, body) VALUES (?, ?) + 2015-06-01 11:22:52,659 INFO [sqlalchemy.engine.base.Engine][MainThread] ('Root', '

Root

') + 2015-06-01 11:22:52,659 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT + #. With our data now driven by SQLAlchemy queries, we need to update our ``databases/tutorial/views.py``: diff --git a/docs/quick_tutorial/databases/development.ini b/docs/quick_tutorial/databases/development.ini index 04c249a62..5da87d602 100644 --- a/docs/quick_tutorial/databases/development.ini +++ b/docs/quick_tutorial/databases/development.ini @@ -11,3 +11,39 @@ sqlalchemy.url = sqlite:///%(here)s/sqltutorial.sqlite use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 + +# Begin logging configuration + +[loggers] +keys = root, tutorial, sqlalchemy.engine.base.Engine + +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[logger_sqlalchemy.engine.base.Engine] +level = INFO +handlers = +qualname = sqlalchemy.engine.base.Engine + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s + +# End logging configuration diff --git a/docs/quick_tutorial/databases/tutorial/tests.py b/docs/quick_tutorial/databases/tutorial/tests.py index e18e70c8c..1e08ef760 100644 --- a/docs/quick_tutorial/databases/tutorial/tests.py +++ b/docs/quick_tutorial/databases/tutorial/tests.py @@ -40,7 +40,6 @@ class WikiViewTests(unittest.TestCase): class WikiFunctionalTests(unittest.TestCase): def setUp(self): - self.session = _initTestingDB() self.config = testing.setUp() from pyramid.paster import get_app app = get_app('development.ini') @@ -48,7 +47,8 @@ class WikiFunctionalTests(unittest.TestCase): self.testapp = TestApp(app) def tearDown(self): - self.session.remove() + from .models import DBSession + DBSession.remove() testing.tearDown() def test_it(self): -- cgit v1.2.3 From cd979b7d0e8a9e17d07fd76dd09ad9ea60cd2c9b Mon Sep 17 00:00:00 2001 From: Karen Dalton Date: Mon, 1 Jun 2015 14:05:51 -0700 Subject: remove some calls to the testing module and self.config as they are not used --- docs/quick_tutorial/databases/tutorial/tests.py | 4 ---- 1 file changed, 4 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/databases/tutorial/tests.py b/docs/quick_tutorial/databases/tutorial/tests.py index 1e08ef760..4aeb718e6 100644 --- a/docs/quick_tutorial/databases/tutorial/tests.py +++ b/docs/quick_tutorial/databases/tutorial/tests.py @@ -23,11 +23,9 @@ def _initTestingDB(): class WikiViewTests(unittest.TestCase): def setUp(self): self.session = _initTestingDB() - self.config = testing.setUp() def tearDown(self): self.session.remove() - testing.tearDown() def test_wiki_view(self): from tutorial.views import WikiViews @@ -40,7 +38,6 @@ class WikiViewTests(unittest.TestCase): class WikiFunctionalTests(unittest.TestCase): def setUp(self): - self.config = testing.setUp() from pyramid.paster import get_app app = get_app('development.ini') from webtest import TestApp @@ -49,7 +46,6 @@ class WikiFunctionalTests(unittest.TestCase): def tearDown(self): from .models import DBSession DBSession.remove() - testing.tearDown() def test_it(self): res = self.testapp.get('/', status=200) -- cgit v1.2.3 From 3da8dd06f1f5ac41b548755f68906d4a0934e3b2 Mon Sep 17 00:00:00 2001 From: Karen Dalton Date: Mon, 1 Jun 2015 14:22:01 -0700 Subject: add self.config = testing.setUp and testing.tearDown back to WikiViewTests as it is a standard pattern for view tests --- docs/quick_tutorial/databases/tutorial/tests.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/databases/tutorial/tests.py b/docs/quick_tutorial/databases/tutorial/tests.py index 4aeb718e6..11e747d15 100644 --- a/docs/quick_tutorial/databases/tutorial/tests.py +++ b/docs/quick_tutorial/databases/tutorial/tests.py @@ -23,9 +23,11 @@ def _initTestingDB(): class WikiViewTests(unittest.TestCase): def setUp(self): self.session = _initTestingDB() + self.config = testing.setUp() def tearDown(self): self.session.remove() + testing.tearDown() def test_wiki_view(self): from tutorial.views import WikiViews -- cgit v1.2.3 From 24c406cbab40285a9fa13285714f450830d5a674 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 18 Jun 2015 01:02:07 -0700 Subject: combine extra credit sections --- docs/quick_tutorial/ini.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/ini.rst b/docs/quick_tutorial/ini.rst index 4e062e575..36942c767 100644 --- a/docs/quick_tutorial/ini.rst +++ b/docs/quick_tutorial/ini.rst @@ -131,6 +131,8 @@ Extra Credit #. The entry point in ``setup.py`` didn't mention ``__init__.py`` when it declared ``tutorial:main`` function. Why not? +#. What is the purpose of ``**settings``? What does the ``**`` signify? + .. seealso:: :ref:`project_narr`, :ref:`scaffolding_chapter`, @@ -138,7 +140,3 @@ Extra Credit :ref:`environment_chapter`, :ref:`paste_chapter` -Extra Credit -============ - -#. What is the purpose of ``**settings``? What does the ``**`` signify? -- cgit v1.2.3 From ced8b4d6fc138e11d97f85ccb88ed619f50fdc0d Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 18 Jun 2015 04:30:28 -0700 Subject: rst numbering syntax --- docs/quick_tutorial/debugtoolbar.rst | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/debugtoolbar.rst b/docs/quick_tutorial/debugtoolbar.rst index a5623ae2a..f11abc493 100644 --- a/docs/quick_tutorial/debugtoolbar.rst +++ b/docs/quick_tutorial/debugtoolbar.rst @@ -89,24 +89,24 @@ temporarily. Extra Credit ============ -# Why don't we add ``pyramid_debugtoolbar`` to the list of - ``install_requires`` dependencies in ``debugtoolbar/setup.py``? +#. Why don't we add ``pyramid_debugtoolbar`` to the list of + ``install_requires`` dependencies in ``debugtoolbar/setup.py``? -# Introduce a bug into your application: Change: +#. Introduce a bug into your application: Change: - .. code-block:: python + .. code-block:: python - def hello_world(request): - return Response('

Hello World!

') + def hello_world(request): + return Response('

Hello World!

') - to: + to: - .. code-block:: python + .. code-block:: python def hello_world(request): return xResponse('

Hello World!

') - Save, and visit http://localhost:6543/ again. Notice the nice - traceback display. On the lowest line, click the "screen" icon to the - right, and try typing the variable names ``request`` and ``Response``. - What else can you discover? + Save, and visit http://localhost:6543/ again. Notice the nice + traceback display. On the lowest line, click the "screen" icon to the + right, and try typing the variable names ``request`` and ``Response``. + What else can you discover? -- cgit v1.2.3 From 8111d1e300cc90dabc38d7f5e7dfc0b9d25d9171 Mon Sep 17 00:00:00 2001 From: Ismail Date: Mon, 10 Aug 2015 14:49:17 +0100 Subject: Fix minor typo --- docs/quick_tutorial/more_view_classes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/more_view_classes.rst b/docs/quick_tutorial/more_view_classes.rst index c06fb0f15..afbb7cc3a 100644 --- a/docs/quick_tutorial/more_view_classes.rst +++ b/docs/quick_tutorial/more_view_classes.rst @@ -47,7 +47,7 @@ Objectives - Dispatch one route/URL to multiple views based on request data -- Share stated and logic between views and templates via the view class +- Share states and logic between views and templates via the view class Steps ===== -- cgit v1.2.3 From a512769644eb6e9773d9805a5fe4dfc85e31ded9 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Mon, 31 Aug 2015 01:54:35 -0700 Subject: move extra credit question about @forbidden_view_config from authentication to authorization --- docs/quick_tutorial/authentication.rst | 3 --- docs/quick_tutorial/authorization.rst | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/authentication.rst b/docs/quick_tutorial/authentication.rst index a4ab83c45..7fd8173d4 100644 --- a/docs/quick_tutorial/authentication.rst +++ b/docs/quick_tutorial/authentication.rst @@ -123,9 +123,6 @@ Extra Credit #. Can I use a database behind my ``groupfinder`` to look up principals? -#. Do I have to put a ``renderer`` in my ``@forbidden_view_config`` - decorator? - #. Once I am logged in, does any user-centric information get jammed onto each request? Use ``import pdb; pdb.set_trace()`` to answer this. diff --git a/docs/quick_tutorial/authorization.rst b/docs/quick_tutorial/authorization.rst index 08df15a28..855043f7f 100644 --- a/docs/quick_tutorial/authorization.rst +++ b/docs/quick_tutorial/authorization.rst @@ -101,6 +101,9 @@ by decorating the view with ``@forbidden_view_config``. Extra Credit ============ +#. Do I have to put a ``renderer`` in my ``@forbidden_view_config`` + decorator? + #. Perhaps you would like the experience of not having enough permissions (forbidden) to be richer. How could you change this? -- cgit v1.2.3 From 4064028cadc63ed1aceb14e6c88827b88b12f839 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 20 Jan 2016 00:38:09 -0800 Subject: Update docs to reflect dropping Python 3.2 support --- docs/quick_tutorial/requirements.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index a737ede0e..6d5a965cd 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -19,7 +19,7 @@ make an isolated environment, and setup packaging tools.) This *Quick Tutorial* is based on: -* **Python 3.3**. Pyramid fully supports Python 3.2+ and Python 2.6+. +* **Python 3.3**. Pyramid fully supports Python 3.3+ and Python 2.6+. This tutorial uses **Python 3.3** but runs fine under Python 2.7. * **pyvenv**. We believe in virtual environments. For this tutorial, -- cgit v1.2.3 From 22f221099e785cb763e9659da029933ca9fc11e6 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 24 Jan 2016 01:10:13 -0800 Subject: Use proper syntax names in code samples to allow highlighting and avoid errors. See https://github.com/sphinx-doc/sphinx/issues/2264 --- docs/quick_tutorial/requirements.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index 6d5a965cd..f855dcb55 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -109,7 +109,7 @@ For Linux, the commands to do so are as follows: For Windows: -.. code-block:: posh +.. code-block:: ps1con # Windows c:\> cd \ -- cgit v1.2.3 From eee002a2b0b010834a2ebede550329dbea3b3732 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Sun, 14 Feb 2016 06:56:17 -0500 Subject: Use lexer name compatible w/ Pygments 1.5. Attempt to fix Jenkins build failures such as: http://jenkins.pylonsproject.org/job/pyramid/1992/console. --- docs/quick_tutorial/requirements.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index f855dcb55..b00cb141e 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -109,7 +109,7 @@ For Linux, the commands to do so are as follows: For Windows: -.. code-block:: ps1con +.. code-block:: powershell # Windows c:\> cd \ -- cgit v1.2.3 From 3ef43f3560ed1b28def03bb8973c0f287134ba6b Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Sun, 14 Feb 2016 07:07:18 -0500 Subject: Revert "Use lexer name compatible w/ Pygments 1.5." This reverts commit eee002a2b0b010834a2ebede550329dbea3b3732. --- docs/quick_tutorial/requirements.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index b00cb141e..f855dcb55 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -109,7 +109,7 @@ For Linux, the commands to do so are as follows: For Windows: -.. code-block:: powershell +.. code-block:: ps1con # Windows c:\> cd \ -- cgit v1.2.3 From 51f056043f9286734e93cb61f44bb0163c5b1fa3 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 2 Mar 2016 03:47:56 -0800 Subject: give sentence a colostomy, break into two --- docs/quick_tutorial/view_classes.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/view_classes.rst b/docs/quick_tutorial/view_classes.rst index 50a7ee0af..6198eed63 100644 --- a/docs/quick_tutorial/view_classes.rst +++ b/docs/quick_tutorial/view_classes.rst @@ -10,11 +10,10 @@ then move some declarations to the class level. Background ========== -So far our views have been simple, free-standing functions. Many times -your views are related: different ways to look at or work on the same -data or a REST API that handles multiple operations. Grouping these -together as a -:ref:`view class ` makes sense: +So far our views have been simple, free-standing functions. Many times your +views are related to one another. They may be different ways to look at or work +on the same data, or be a REST API that handles multiple operations. Grouping +these views together as a :ref:`view class ` makes sense: - Group views -- cgit v1.2.3 From 6c36d783bf6d3a289afe559d6595d96de3d99d89 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 2 Mar 2016 22:57:48 -0800 Subject: update link to videos --- docs/quick_tutorial/routing.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/routing.rst b/docs/quick_tutorial/routing.rst index 1b79a5889..416a346fa 100644 --- a/docs/quick_tutorial/routing.rst +++ b/docs/quick_tutorial/routing.rst @@ -23,14 +23,14 @@ Previously we saw the basics of routing URLs to views in Pyramid. .. note:: - Why do this twice? Other Python web frameworks let you create a - route and associate it with a view in one step. As - illustrated in :ref:`routes_need_ordering`, multiple routes might match the - same URL pattern. Rather than provide ways to help guess, Pyramid lets you - be explicit in ordering. Pyramid also gives facilities to avoid the - problem. It's relatively easy to build a system that uses implicit route - ordering with Pyramid too. See `The Groundhog series of screencasts - `_ if you're interested in + Why do this twice? Other Python web frameworks let you create a route and + associate it with a view in one step. As illustrated in + :ref:`routes_need_ordering`, multiple routes might match the same URL + pattern. Rather than provide ways to help guess, Pyramid lets you be + explicit in ordering. Pyramid also gives facilities to avoid the problem. + It's relatively easy to build a system that uses implicit route ordering + with Pyramid too. See `The Groundhog series of screencasts + `_ if you're interested in doing so. Objectives -- cgit v1.2.3 From 44bbbc32b607b043e708a625c4b1756db8919bdd Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 3 Apr 2016 02:17:59 -0700 Subject: - replace easy_install with pip - bump Python version to 3.5 or generalize to Python 3 - rewrite seealso's - use ps1con lexer for windows powershell console - add hyperlink targets --- docs/quick_tutorial/requirements.rst | 118 +++++++++++------------------------ 1 file changed, 36 insertions(+), 82 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index f855dcb55..3373ba2bc 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -4,9 +4,9 @@ Requirements ============ -Let's get our tutorial environment setup. Most of the setup work is in -standard Python development practices (install Python, -make an isolated environment, and setup packaging tools.) +Let's get our tutorial environment set up. Most of the set up work is in +standard Python development practices (install Python and make an isolated +environment.) .. note:: @@ -19,16 +19,14 @@ make an isolated environment, and setup packaging tools.) This *Quick Tutorial* is based on: -* **Python 3.3**. Pyramid fully supports Python 3.3+ and Python 2.6+. - This tutorial uses **Python 3.3** but runs fine under Python 2.7. +* **Python 3.5**. Pyramid fully supports Python 3.3+ and Python 2.6+. This + tutorial uses **Python 3.5** but runs fine under Python 2.7. -* **pyvenv**. We believe in virtual environments. For this tutorial, - we use Python 3.3's built-in solution, the ``pyvenv`` command. - For Python 2.7, you can install ``virtualenv``. +* **pyvenv**. We believe in virtual environments. For this tutorial, we use + Python 3.5's built-in solution, the ``pyvenv`` command. For Python 2.7, you + can install ``virtualenv``. -* **setuptools and easy_install**. We use - `setuptools `_ - and its ``easy_install`` for package management. +* **pip**. We use ``pip`` for package management. * **Workspaces, projects, and packages.** Our home directory will contain a *tutorial workspace* with our Python virtual @@ -46,34 +44,39 @@ This *Quick Tutorial* is based on: Steps ===== -#. :ref:`install-python-3.3-or-greater` +#. :ref:`install-python-3` #. :ref:`create-a-project-directory-structure` #. :ref:`set-an-environment-variable` #. :ref:`create-a-virtual-environment` -#. :ref:`install-setuptools-(python-packaging-tools)` #. :ref:`install-pyramid` -.. _install-python-3.3-or-greater: -Install Python 3.3 or greater ------------------------------ +.. _install-python-3: -Download the latest standard Python 3.3+ release (not development release) -from `python.org `_. +Install Python 3 +---------------- Windows and Mac OS X users can download and run an installer. +Download the latest standard Python 3 release (not development release) from +`python.org `_. + Windows users should also install the `Python for Windows extensions `_. Carefully read the ``README.txt`` file at the end of the list of builds, and follow its directions. Make sure you get the proper 32- or 64-bit build and Python version. -Linux users can either use their package manager to install Python 3.3 -or may `build Python 3.3 from source +Linux users can either use their package manager to install Python 3 +or may `build Python 3 from source `_. +.. seealso:: See also :ref:`For Mac OS X Users `, + :ref:`If You Don't Yet Have a Python Interpreter (UNIX) + `, and :ref:`Installing + Pyramid on a Windows System `. + .. _create-a-project-directory-structure: @@ -142,6 +145,8 @@ environment. We set an environment variable to save typing later. # Mac and Linux $ export VENV=~/projects/quick_tutorial/env +.. code-block:: ps1con + # Windows # TODO: This command does not work c:\> set VENV=c:\projects\quick_tutorial\env @@ -158,7 +163,7 @@ Create a Virtual Environment and `PEP 453 `_ for a proposed resolution. -``pyvenv`` is a tool to create isolated Python 3.3 environments, each +``pyvenv`` is a tool to create isolated Python 3 environments, each with its own Python binary and independent set of installed Python packages in its site directories. Let's create one, using the location we just specified in the environment variable. @@ -168,46 +173,13 @@ we just specified in the environment variable. # Mac and Linux $ pyvenv $VENV - # Windows - c:\> c:\Python33\python -m venv %VENV% - -.. seealso:: See also Python 3's :mod:`venv module `, - Python 2's `virtualenv `_ - package, - :ref:`Installing Pyramid on a Windows System ` - - -.. _install-setuptools-(python-packaging-tools): - -Install ``setuptools`` (Python packaging tools) ------------------------------------------------ - -The following command will download a script to install ``setuptools``, then -pipe it to your environment's version of Python. - -.. code-block:: bash - - # Mac and Linux - $ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | $VENV/bin/python +.. code-block:: ps1con # Windows - # - # Use your web browser to download this file: - # https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py - # - # ...and save it to: - # c:\projects\quick_tutorial\ez_setup.py - # - # Then run the following command: - - c:\> %VENV%\Scripts\python ez_setup.py - -If ``wget`` complains with a certificate error, then run this command instead: + c:\> c:\Python35\python -m venv %VENV% -.. code-block:: bash - - # Mac and Linux - $ wget --no-check-certificate https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | $VENV/bin/python +.. seealso:: See also Python 3's :mod:`venv module ` and Python + 2's `virtualenv `_ package. .. _install-pyramid: @@ -221,10 +193,10 @@ part is pretty easy: .. parsed-literal:: # Mac and Linux - $ $VENV/bin/easy_install "pyramid==\ |release|\ " + $ $VENV/bin/pip install "pyramid==\ |release|\ " # Windows - c:\\> %VENV%\\Scripts\\easy_install "pyramid==\ |release|\ " + c:\\> %VENV%\\Scripts\\pip install "pyramid==\ |release|\ " Our Python virtual environment now has the Pyramid software available. @@ -234,30 +206,12 @@ during this tutorial: .. code-block:: bash # Mac and Linux - $ $VENV/bin/easy_install nose webtest deform sqlalchemy \ + $ $VENV/bin/pip install nose webtest deform sqlalchemy \ pyramid_chameleon pyramid_debugtoolbar waitress \ pyramid_tm zope.sqlalchemy - # Windows - c:\> %VENV%\Scripts\easy_install nose webtest deform sqlalchemy pyramid_chameleon pyramid_debugtoolbar waitress pyramid_tm zope.sqlalchemy - - -.. note:: +.. code-block:: ps1con - Why ``easy_install`` and not ``pip``? Pyramid encourages use of namespace - packages, for which ``pip``'s support is less-than-optimal. Also, Pyramid's - dependencies use some optional C extensions for performance: with - ``easy_install``, Windows users can get these extensions without needing - a C compiler (``pip`` does not support installing binary Windows - distributions, except for ``wheels``, which are not yet available for - all dependencies). - -.. seealso:: See also :ref:`installing_unix`. For instructions to set up your - Python environment for development using Windows or Python 2, see Pyramid's - :ref:`Before You Install `. - - See also Python 3's :mod:`venv module `, the `setuptools - installation instructions - `_, - and `easy_install help `_. + # Windows + c:\> %VENV%\Scripts\pip install nose webtest deform sqlalchemy pyramid_chameleon pyramid_debugtoolbar waitress pyramid_tm zope.sqlalchemy -- cgit v1.2.3 From 74c56e0e8d767ac0942cb17cde535113e97d8db1 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Mon, 4 Apr 2016 00:43:27 -0700 Subject: - replace setup.py with pip --- docs/quick_tutorial/hello_world.rst | 2 +- docs/quick_tutorial/scaffolds.rst | 11 ++++++----- docs/quick_tutorial/tutorial_approach.rst | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/hello_world.rst b/docs/quick_tutorial/hello_world.rst index 4ae80ca87..fb661e9c5 100644 --- a/docs/quick_tutorial/hello_world.rst +++ b/docs/quick_tutorial/hello_world.rst @@ -5,7 +5,7 @@ ================================ What's the simplest way to get started in Pyramid? A single-file module. -No Python packages, no ``setup.py``, no other machinery. +No Python packages, no ``pip install -e .``, no other machinery. Background ========== diff --git a/docs/quick_tutorial/scaffolds.rst b/docs/quick_tutorial/scaffolds.rst index 4f2694100..319eb9d90 100644 --- a/docs/quick_tutorial/scaffolds.rst +++ b/docs/quick_tutorial/scaffolds.rst @@ -12,7 +12,7 @@ Background ========== We're going to cover a lot in this tutorial, focusing on one topic at a -time and writing everything from scratch. As a warmup, though, +time and writing everything from scratch. As a warm up, though, it sure would be nice to see some pixels on a screen. Like other web development frameworks, Pyramid provides a number of @@ -47,21 +47,22 @@ Steps $ $VENV/bin/pcreate --scaffold starter scaffolds -#. Use normal Python development to setup our project for development: +#. Install our project in editable mode for development in the current + directory: .. code-block:: bash $ cd scaffolds - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . -#. Startup the application by pointing Pyramid's ``pserve`` command at +#. Start up the application by pointing Pyramid's ``pserve`` command at the project's (generated) configuration file: .. code-block:: bash $ $VENV/bin/pserve development.ini --reload - On startup, ``pserve`` logs some output: + On start up, ``pserve`` logs some output: .. code-block:: bash diff --git a/docs/quick_tutorial/tutorial_approach.rst b/docs/quick_tutorial/tutorial_approach.rst index 204d388b0..8298a4710 100644 --- a/docs/quick_tutorial/tutorial_approach.rst +++ b/docs/quick_tutorial/tutorial_approach.rst @@ -17,7 +17,7 @@ repo, where each step/topic/directory is a Python package. To successfully run each step:: $ cd request_response - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . ...and repeat for each step you would like to work on. In most cases we will start with the results of an earlier step. -- cgit v1.2.3 From 7c29ea97c6617d1f6b2f621bf88aa6a0ab0209fa Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Tue, 5 Apr 2016 03:34:34 -0700 Subject: - replace easy_install with pip - add python3 for intersphinx. See #2429 - minor grammar --- docs/quick_tutorial/conf.py | 3 +++ docs/quick_tutorial/package.rst | 40 ++++++++++++++++++---------------------- 2 files changed, 21 insertions(+), 22 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/conf.py b/docs/quick_tutorial/conf.py index 47b8fae41..feebdf02a 100644 --- a/docs/quick_tutorial/conf.py +++ b/docs/quick_tutorial/conf.py @@ -257,6 +257,9 @@ intersphinx_mapping = { 'python': ( 'http://docs.python.org/2', None), + 'python3': ( + 'https://docs.python.org/3/', + None), 'sqla': ( 'http://docs.sqlalchemy.org/en/latest', None), diff --git a/docs/quick_tutorial/package.rst b/docs/quick_tutorial/package.rst index 54a6a0bd9..9e175bdaa 100644 --- a/docs/quick_tutorial/package.rst +++ b/docs/quick_tutorial/package.rst @@ -10,43 +10,38 @@ Background ========== Python developers can organize a collection of modules and files into a -namespaced unit called a :ref:`package `. If a +namespaced unit called a :ref:`package `. If a directory is on ``sys.path`` and has a special file named ``__init__.py``, it is treated as a Python package. -Packages can be bundled up, made available for installation, -and installed through a (muddled, but improving) toolchain oriented -around a ``setup.py`` file for a -`setuptools project `_. -Explaining it all in this -tutorial will induce madness. For this tutorial, this is all you need to -know: +Packages can be bundled up, made available for installation, and installed +through a toolchain oriented around a ``setup.py`` file. For this tutorial, +this is all you need to know: -- We will have a directory for each tutorial step as a setuptools *project* +- We will have a directory for each tutorial step as a *project*. -- This project will contain a ``setup.py`` which injects the features - of the setuptool's project machinery into the directory +- This project will contain a ``setup.py`` which injects the features of the + project machinery into the directory. - In this project we will make a ``tutorial`` subdirectory into a Python - *package* using an ``__init__.py`` Python module file + *package* using an ``__init__.py`` Python module file. -- We will run ``python setup.py develop`` to install our project in - development mode +- We will run ``pip install -e .`` to install our project in development mode. In summary: -- You'll do your development in a Python *package* +- You'll do your development in a Python *package*. -- That package will be part of a setuptools *project* +- That package will be part of a *project*. Objectives ========== -- Make a Python "package" directory with an ``__init__.py`` +- Make a Python "package" directory with an ``__init__.py``. -- Get a minimum Python "project" in place by making a ``setup.py`` +- Get a minimum Python "project" in place by making a ``setup.py``. -- Install our ``tutorial`` project in development mode +- Install our ``tutorial`` project in development mode. Steps ===== @@ -66,7 +61,7 @@ Steps .. code-block:: bash - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . $ mkdir tutorial #. Enter the following into ``package/tutorial/__init__.py``: @@ -107,5 +102,6 @@ of an odd duck. We would never do this unless we were writing a tutorial that tries to capture how this stuff works a step at a time. It's generally a bad idea to run a Python module inside a package directly as a script. -.. seealso:: :ref:`Python Packages `, - `setuptools Entry Points `_ +.. seealso:: :ref:`Python Packages ` and `Working in + "Development Mode" + `_. -- cgit v1.2.3 From 186b72e56600c79888795fa4eed286a5ebf71974 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 6 Apr 2016 04:24:28 -0700 Subject: - remove conf.py straggler - update intersphinx link to python3 docs - Closes #2429 --- docs/quick_tutorial/conf.py | 284 ----------------------------------- docs/quick_tutorial/package.rst | 4 +- docs/quick_tutorial/requirements.rst | 2 +- 3 files changed, 3 insertions(+), 287 deletions(-) delete mode 100644 docs/quick_tutorial/conf.py (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/conf.py b/docs/quick_tutorial/conf.py deleted file mode 100644 index feebdf02a..000000000 --- a/docs/quick_tutorial/conf.py +++ /dev/null @@ -1,284 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Getting Started with Pyramid and REST documentation build configuration file, created by -# sphinx-quickstart on Mon Aug 26 14:44:57 2013. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.intersphinx'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'Getting Started with Pyramid and REST' -copyright = u'2013, Agendaless Consulting' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '1.0' -# The full version, including alpha/beta/rc tags. -release = '1.0' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['_build'] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'default' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'GettingStartedwithPyramidandRESTdoc' - - -# -- Options for LaTeX output -------------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - #'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - #'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - #'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'GettingStartedwithPyramidandREST.tex', - u'Getting Started with Pyramid and REST Documentation', - u'Agendaless Consulting', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'gettingstartedwithpyramidandrest', - u'Getting Started with Pyramid and REST Documentation', - [u'Agendaless Consulting'], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------------ - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'GettingStartedwithPyramidandREST', - u'Getting Started with Pyramid and REST Documentation', - u'Agendaless Consulting', 'GettingStartedwithPyramidandREST', - 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False - - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { - 'python': ( - 'http://docs.python.org/2', - None), - 'python3': ( - 'https://docs.python.org/3/', - None), - 'sqla': ( - 'http://docs.sqlalchemy.org/en/latest', - None), - 'pyramid': ( - 'http://docs.pylonsproject.org/projects/pyramid/en/latest/', - None), - 'jinja2': ( - 'http://docs.pylonsproject.org/projects/pyramid_jinja2/en/latest/', - None), - 'toolbar': ( - 'http://docs.pylonsproject.org/projects/pyramid_debugtoolbar/en/latest', - None), - 'deform': ( - 'http://docs.pylonsproject.org/projects/deform/en/latest', - None), - 'colander': ( - 'http://docs.pylonsproject.org/projects/colander/en/latest', - None), - 'tutorials': ( - 'http://docs.pylonsproject.org/projects/pyramid_tutorials/en/latest/', - None), -} diff --git a/docs/quick_tutorial/package.rst b/docs/quick_tutorial/package.rst index 9e175bdaa..6a379032e 100644 --- a/docs/quick_tutorial/package.rst +++ b/docs/quick_tutorial/package.rst @@ -10,7 +10,7 @@ Background ========== Python developers can organize a collection of modules and files into a -namespaced unit called a :ref:`package `. If a +namespaced unit called a :ref:`package `. If a directory is on ``sys.path`` and has a special file named ``__init__.py``, it is treated as a Python package. @@ -102,6 +102,6 @@ of an odd duck. We would never do this unless we were writing a tutorial that tries to capture how this stuff works a step at a time. It's generally a bad idea to run a Python module inside a package directly as a script. -.. seealso:: :ref:`Python Packages ` and `Working in +.. seealso:: :ref:`Python Packages ` and `Working in "Development Mode" `_. diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index 3373ba2bc..299ad2ac0 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -178,7 +178,7 @@ we just specified in the environment variable. # Windows c:\> c:\Python35\python -m venv %VENV% -.. seealso:: See also Python 3's :mod:`venv module ` and Python +.. seealso:: See also Python 3's :mod:`venv module ` and Python 2's `virtualenv `_ package. -- cgit v1.2.3 From 21fd514e069f9d172ac0f96febd721ed93917ae3 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:12:27 -0700 Subject: - update ini.rst --- docs/quick_tutorial/ini.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/ini.rst b/docs/quick_tutorial/ini.rst index 36942c767..0aed304df 100644 --- a/docs/quick_tutorial/ini.rst +++ b/docs/quick_tutorial/ini.rst @@ -50,7 +50,7 @@ Steps .. code-block:: bash - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. Let's make a file ``ini/development.ini`` for our configuration: -- cgit v1.2.3 From ba78808ec3749aeb6bf5512c06a7999abeacd08f Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:14:04 -0700 Subject: - update debugtoolbar --- docs/quick_tutorial/debugtoolbar.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/debugtoolbar.rst b/docs/quick_tutorial/debugtoolbar.rst index f11abc493..1f89cd319 100644 --- a/docs/quick_tutorial/debugtoolbar.rst +++ b/docs/quick_tutorial/debugtoolbar.rst @@ -4,8 +4,7 @@ 04: Easier Development with ``debugtoolbar`` ============================================ -Error-handling and introspection using the ``pyramid_debugtoolbar`` -add-on. +Error handling and introspection using the ``pyramid_debugtoolbar`` add-on. Background ========== @@ -36,8 +35,8 @@ Steps .. code-block:: bash $ cd ..; cp -r ini debugtoolbar; cd debugtoolbar - $ $VENV/bin/python setup.py develop - $ $VENV/bin/easy_install pyramid_debugtoolbar + $ $VENV/bin/pip install -e . + $ $VENV/bin/pip install pyramid_debugtoolbar #. Our ``debugtoolbar/development.ini`` gets a configuration entry for ``pyramid.includes``: -- cgit v1.2.3 From d68cbc6f69446317bc8b01062609c4779624cfc5 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:15:45 -0700 Subject: - update unit_testing.rst --- docs/quick_tutorial/unit_testing.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/unit_testing.rst b/docs/quick_tutorial/unit_testing.rst index 4cb7ef714..58512d1cc 100644 --- a/docs/quick_tutorial/unit_testing.rst +++ b/docs/quick_tutorial/unit_testing.rst @@ -48,8 +48,8 @@ Steps .. code-block:: bash $ cd ..; cp -r debugtoolbar unit_testing; cd unit_testing - $ $VENV/bin/python setup.py develop - $ $VENV/bin/easy_install nose + $ $VENV/bin/pip install -e . + $ $VENV/bin/pip install nose #. Now we write a simple unit test in ``unit_testing/tutorial/tests.py``: -- cgit v1.2.3 From 9459d8c11a1bd8d62c84c7ff1f761c6aead61510 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:17:03 -0700 Subject: - update functional_testing.rst --- docs/quick_tutorial/functional_testing.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/functional_testing.rst b/docs/quick_tutorial/functional_testing.rst index 6f1544e79..b8aa7e87d 100644 --- a/docs/quick_tutorial/functional_testing.rst +++ b/docs/quick_tutorial/functional_testing.rst @@ -34,8 +34,8 @@ Steps .. code-block:: bash $ cd ..; cp -r unit_testing functional_testing; cd functional_testing - $ $VENV/bin/python setup.py develop - $ $VENV/bin/easy_install webtest + $ $VENV/bin/pip install -e . + $ $VENV/bin/pip install webtest #. Let's extend ``functional_testing/tutorial/tests.py`` to include a functional test: -- cgit v1.2.3 From 010b7cf0e08f1d9815e66fc915bf7412df699f1f Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:18:24 -0700 Subject: - update views.rst --- docs/quick_tutorial/views.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/views.rst b/docs/quick_tutorial/views.rst index 6728925fd..5b6e2960b 100644 --- a/docs/quick_tutorial/views.rst +++ b/docs/quick_tutorial/views.rst @@ -43,7 +43,7 @@ Steps .. code-block:: bash $ cd ..; cp -r functional_testing views; cd views - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. Our ``views/tutorial/__init__.py`` gets a lot shorter: -- cgit v1.2.3 From 96ca13ad07593fe15c8981e8a0372d749f6bd411 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:19:59 -0700 Subject: - update templating.rst --- docs/quick_tutorial/jinja2.rst | 2 +- docs/quick_tutorial/templating.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/jinja2.rst b/docs/quick_tutorial/jinja2.rst index 2121803f9..8622e968a 100644 --- a/docs/quick_tutorial/jinja2.rst +++ b/docs/quick_tutorial/jinja2.rst @@ -27,7 +27,7 @@ Steps $ cd ..; cp -r view_classes jinja2; cd jinja2 $ $VENV/bin/python setup.py develop - $ $VENV/bin/easy_install pyramid_jinja2 + $ $VENV/bin/pip install pyramid_jinja2 #. We need to include ``pyramid_jinja2`` in ``jinja2/tutorial/__init__.py``: diff --git a/docs/quick_tutorial/templating.rst b/docs/quick_tutorial/templating.rst index cf56d2a96..a975d9ec2 100644 --- a/docs/quick_tutorial/templating.rst +++ b/docs/quick_tutorial/templating.rst @@ -56,7 +56,7 @@ Steps .. code-block:: bash - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. We need to connect ``pyramid_chameleon`` as a renderer by making a call in the setup of ``templating/tutorial/__init__.py``: -- cgit v1.2.3 From fd965fe8bfb62a467521e3883237b0506296b7b4 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:21:14 -0700 Subject: - update view_classes.rst --- docs/quick_tutorial/view_classes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/view_classes.rst b/docs/quick_tutorial/view_classes.rst index 6198eed63..cc5337493 100644 --- a/docs/quick_tutorial/view_classes.rst +++ b/docs/quick_tutorial/view_classes.rst @@ -41,7 +41,7 @@ Steps .. code-block:: bash $ cd ..; cp -r templating view_classes; cd view_classes - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. Our ``view_classes/tutorial/views.py`` now has a view class with our two views: -- cgit v1.2.3 From 5e088cc17818cf3921c3634ca4e35011525e4076 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:22:20 -0700 Subject: - update request_response.rst --- docs/quick_tutorial/request_response.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/request_response.rst b/docs/quick_tutorial/request_response.rst index 4f8de0221..f42423de8 100644 --- a/docs/quick_tutorial/request_response.rst +++ b/docs/quick_tutorial/request_response.rst @@ -41,7 +41,7 @@ Steps .. code-block:: bash $ cd ..; cp -r view_classes request_response; cd request_response - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. Simplify the routes in ``request_response/tutorial/__init__.py``: -- cgit v1.2.3 From e612f1ef16a25febbb61ed1b12634c814b251d83 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:23:47 -0700 Subject: - update routing.rst --- docs/quick_tutorial/routing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/routing.rst b/docs/quick_tutorial/routing.rst index 416a346fa..7b6d0904d 100644 --- a/docs/quick_tutorial/routing.rst +++ b/docs/quick_tutorial/routing.rst @@ -48,7 +48,7 @@ Steps .. code-block:: bash $ cd ..; cp -r view_classes routing; cd routing - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. Our ``routing/tutorial/__init__.py`` needs a route with a replacement pattern: -- cgit v1.2.3 From 45fabb70bf376b4ee1ae6594be71577f4e3ebb08 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:24:59 -0700 Subject: - update jinja2.rst --- docs/quick_tutorial/jinja2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/jinja2.rst b/docs/quick_tutorial/jinja2.rst index 8622e968a..6b9d5feba 100644 --- a/docs/quick_tutorial/jinja2.rst +++ b/docs/quick_tutorial/jinja2.rst @@ -26,7 +26,7 @@ Steps .. code-block:: bash $ cd ..; cp -r view_classes jinja2; cd jinja2 - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . $ $VENV/bin/pip install pyramid_jinja2 #. We need to include ``pyramid_jinja2`` in -- cgit v1.2.3 From 2d2ced28cd261b0080bcec9f101432b4fe40c13b Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:26:06 -0700 Subject: - update static_assets.rst --- docs/quick_tutorial/static_assets.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/static_assets.rst b/docs/quick_tutorial/static_assets.rst index 3a7496ec7..61c5fbd50 100644 --- a/docs/quick_tutorial/static_assets.rst +++ b/docs/quick_tutorial/static_assets.rst @@ -23,7 +23,7 @@ Steps .. code-block:: bash $ cd ..; cp -r view_classes static_assets; cd static_assets - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. We add a call ``config.add_static_view`` in ``static_assets/tutorial/__init__.py``: -- cgit v1.2.3 From b37b6f4b5393191047edf44173d3d8c2581861a7 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:26:52 -0700 Subject: - update json.rst --- docs/quick_tutorial/json.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/json.rst b/docs/quick_tutorial/json.rst index aa789d833..49421829b 100644 --- a/docs/quick_tutorial/json.rst +++ b/docs/quick_tutorial/json.rst @@ -31,7 +31,7 @@ Steps .. code-block:: bash $ cd ..; cp -r view_classes json; cd json - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. We add a new route for ``hello_json`` in ``json/tutorial/__init__.py``: -- cgit v1.2.3 From 9f66915a3878ad9764b8fd5039465db54f7a47c1 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:27:57 -0700 Subject: - update more_view_classes.rst --- docs/quick_tutorial/more_view_classes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/more_view_classes.rst b/docs/quick_tutorial/more_view_classes.rst index afbb7cc3a..fb97cceb2 100644 --- a/docs/quick_tutorial/more_view_classes.rst +++ b/docs/quick_tutorial/more_view_classes.rst @@ -57,7 +57,7 @@ Steps .. code-block:: bash $ cd ..; cp -r templating more_view_classes; cd more_view_classes - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. Our route in ``more_view_classes/tutorial/__init__.py`` needs some replacement patterns: -- cgit v1.2.3 From 14fd6dc1d9b74b2ea0034d9c485e50ad9bcbbecf Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:28:38 -0700 Subject: - update logging.rst --- docs/quick_tutorial/logging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/logging.rst b/docs/quick_tutorial/logging.rst index 5d29cd196..556a09bf0 100644 --- a/docs/quick_tutorial/logging.rst +++ b/docs/quick_tutorial/logging.rst @@ -35,7 +35,7 @@ Steps .. code-block:: bash $ cd ..; cp -r view_classes logging; cd logging - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. Extend ``logging/tutorial/views.py`` to log a message: -- cgit v1.2.3 From 6e45624d143631aafc808d97cff66263e6152ed5 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:29:16 -0700 Subject: - update sessions.rst --- docs/quick_tutorial/sessions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/sessions.rst b/docs/quick_tutorial/sessions.rst index f97405500..06176f2b6 100644 --- a/docs/quick_tutorial/sessions.rst +++ b/docs/quick_tutorial/sessions.rst @@ -34,7 +34,7 @@ Steps .. code-block:: bash $ cd ..; cp -r view_classes sessions; cd sessions - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. Our ``sessions/tutorial/__init__.py`` needs a choice of session factory to get registered with the :term:`configurator`: -- cgit v1.2.3 From 9845f718ccd609b6ecf514b165a4fd2f9dfb8d8c Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:30:26 -0700 Subject: - update forms.rst --- docs/quick_tutorial/forms.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/forms.rst b/docs/quick_tutorial/forms.rst index f81b88fc2..023e7127f 100644 --- a/docs/quick_tutorial/forms.rst +++ b/docs/quick_tutorial/forms.rst @@ -50,7 +50,7 @@ Steps .. code-block:: bash - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. Register a static view in ``forms/tutorial/__init__.py`` for Deform's CSS/JS etc. as well as our demo wikipage scenario's -- cgit v1.2.3 From a42b09be68e52d8204bc0f3c18697bb2020f8fc4 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:31:34 -0700 Subject: - update databases.rst --- docs/quick_tutorial/databases.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index 19dfd066d..311ff6ec5 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -53,7 +53,7 @@ Steps .. note:: - We aren't yet doing ``$VENV/bin/python setup.py develop`` as we + We aren't yet doing ``$VENV/bin/pip install -e .`` as we will change it later. #. Our configuration file at ``databases/development.ini`` wires @@ -78,7 +78,7 @@ Steps .. code-block:: bash - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. The script references some models in ``databases/tutorial/models.py``: -- cgit v1.2.3 From 2c8511fffc2914480646ab5afb47d12c44ffc6a3 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:32:19 -0700 Subject: - update authentication.rst --- docs/quick_tutorial/authentication.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/authentication.rst b/docs/quick_tutorial/authentication.rst index 7fd8173d4..5b4a6224d 100644 --- a/docs/quick_tutorial/authentication.rst +++ b/docs/quick_tutorial/authentication.rst @@ -33,7 +33,7 @@ Steps .. code-block:: bash $ cd ..; cp -r view_classes authentication; cd authentication - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. Put the security hash in the ``authentication/development.ini`` configuration file as ``tutorial.secret`` instead of putting it in -- cgit v1.2.3 From d9c4cbb73b974db2973985369493efe0aec63737 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:34:05 -0700 Subject: - update authorization.rst - add intersphinx target links --- docs/quick_tutorial/authentication.rst | 2 ++ docs/quick_tutorial/authorization.rst | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/authentication.rst b/docs/quick_tutorial/authentication.rst index 5b4a6224d..cb3839b08 100644 --- a/docs/quick_tutorial/authentication.rst +++ b/docs/quick_tutorial/authentication.rst @@ -1,3 +1,5 @@ +.. _qtut_authentication: + ============================== 20: Logins With Authentication ============================== diff --git a/docs/quick_tutorial/authorization.rst b/docs/quick_tutorial/authorization.rst index 855043f7f..a4a12774b 100644 --- a/docs/quick_tutorial/authorization.rst +++ b/docs/quick_tutorial/authorization.rst @@ -1,3 +1,5 @@ +.. _qtut_authorization: + =========================================== 21: Protecting Resources With Authorization =========================================== @@ -38,7 +40,7 @@ Steps .. code-block:: bash $ cd ..; cp -r authentication authorization; cd authorization - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. Start by changing ``authorization/tutorial/__init__.py`` to specify a root factory to the :term:`configurator`: -- cgit v1.2.3 From ec1bbffae07cd8b573ba007b367b9eec2902a364 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 10 Apr 2016 16:08:38 -0700 Subject: - update installation.rst to use pip, pyvenv, Python 3.4 - simplify installation.rst by removing not-Pyramid things (installing Python and requirements for installing packages) while providing official external references - update cross-reference in quick_tutorial requirements.rst - add glossary entry for pyvenv --- docs/quick_tutorial/requirements.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index 299ad2ac0..c4e6beecb 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -72,10 +72,11 @@ or may `build Python 3 from source `_. -.. seealso:: See also :ref:`For Mac OS X Users `, - :ref:`If You Don't Yet Have a Python Interpreter (UNIX) - `, and :ref:`Installing - Pyramid on a Windows System `. +.. seealso:: See also :ref:`For Mac OS X Users `, :ref:`If + You Don't Yet Have a Python Interpreter (UNIX) + `, and :ref:`If You Don't + Yet Have a Python Interpreter (Windows) + `. .. _create-a-project-directory-structure: -- cgit v1.2.3 From d603697517d56a1e2f2a5707ebba922db24f5c71 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Tue, 12 Apr 2016 02:47:57 -0700 Subject: - replace `pyvenv` with `python3 -m venv` --- docs/quick_tutorial/requirements.rst | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index c4e6beecb..17ce845e2 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -22,9 +22,9 @@ This *Quick Tutorial* is based on: * **Python 3.5**. Pyramid fully supports Python 3.3+ and Python 2.6+. This tutorial uses **Python 3.5** but runs fine under Python 2.7. -* **pyvenv**. We believe in virtual environments. For this tutorial, we use - Python 3.5's built-in solution, the ``pyvenv`` command. For Python 2.7, you - can install ``virtualenv``. +* **venv**. We believe in virtual environments. For this tutorial, we use + Python 3.5's built-in solution ``venv``. For Python 2.7, you can install + ``virtualenv``. * **pip**. We use ``pip`` for package management. @@ -158,26 +158,20 @@ environment. We set an environment variable to save typing later. Create a Virtual Environment ---------------------------- -.. warning:: The current state of isolated Python environments using - ``pyvenv`` on Windows is suboptimal in comparison to Mac and Linux. See - http://stackoverflow.com/q/15981111/95735 for a discussion of the issue - and `PEP 453 `_ for a proposed - resolution. - -``pyvenv`` is a tool to create isolated Python 3 environments, each -with its own Python binary and independent set of installed Python -packages in its site directories. Let's create one, using the location -we just specified in the environment variable. +``venv`` is a tool to create isolated Python 3 environments, each with its own +Python binary and independent set of installed Python packages in its site +directories. Let's create one, using the location we just specified in the +environment variable. .. code-block:: bash # Mac and Linux - $ pyvenv $VENV + $ python3 -m venv $VENV .. code-block:: ps1con # Windows - c:\> c:\Python35\python -m venv %VENV% + c:\> c:\Python35\python3 -m venv %VENV% .. seealso:: See also Python 3's :mod:`venv module ` and Python 2's `virtualenv `_ package. -- cgit v1.2.3 From d67566acebf890a603fad0e9069d5e131dfb5b31 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Tue, 12 Apr 2016 06:43:38 -0700 Subject: one does not simply "create a virtualenv". one should "create a virtual environment". - Fixes #2483 --- docs/quick_tutorial/databases.rst | 2 +- docs/quick_tutorial/requirements.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index 311ff6ec5..f9f548585 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -176,7 +176,7 @@ module. The ``initialize_tutorial_db`` is a nice example of framework support. You point your setup at the location of some ``[console_scripts]`` and -these get generated into your virtualenv's ``bin`` directory. Our +these get generated into your virtual environment's ``bin`` directory. Our console script follows the pattern of being fed a configuration file with all the bootstrapping. It then opens SQLAlchemy and creates the root of the wiki, which also makes the SQLite file. Note the diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index 17ce845e2..9e10e3ebe 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -129,7 +129,7 @@ order to avoid spaces in any of the path names. Next within ``projects`` is your workspace directory, here named ``quick_tutorial``. A workspace is a common term used by integrated development environments (IDE) like PyCharm and PyDev that stores -isolated Python environments (virtualenvs) and specific project files +isolated Python environments (virtual environments) and specific project files and repositories. @@ -174,7 +174,7 @@ environment variable. c:\> c:\Python35\python3 -m venv %VENV% .. seealso:: See also Python 3's :mod:`venv module ` and Python - 2's `virtualenv `_ package. + 2's `virtualenv `_ package. .. _install-pyramid: -- cgit v1.2.3 From ecb8cd2805514839fbf4e801edfe6b8632709c01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arian=20Maykon=20de=20Arau=CC=81jo=20Dio=CC=81genes?= Date: Wed, 13 Apr 2016 15:40:30 -0300 Subject: Issue #2493: Fixing Quick Tutorial Step 18 - CSS/JS Paths --- docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt b/docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt index 547465018..d1fea0d7f 100644 --- a/docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt +++ b/docs/quick_tutorial/forms/tutorial/wikipage_addedit.pt @@ -4,12 +4,10 @@ WikiPage: Add/Edit + href="${request.static_url('deform:static/' + reqt)}"/> - - -- cgit v1.2.3 From 122a5164c7f0f279580a6c291de5c0a8adee1ac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arian=20Maykon=20de=20Arau=CC=81jo=20Dio=CC=81genes?= Date: Thu, 14 Apr 2016 10:50:40 -0300 Subject: Issue #2493: Fixing Quick Tutorial Step 18 - CSS/JS Paths, also on Step 19 - Database --- docs/quick_tutorial/databases/tutorial/wikipage_addedit.pt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/databases/tutorial/wikipage_addedit.pt b/docs/quick_tutorial/databases/tutorial/wikipage_addedit.pt index 01955ef72..d1fea0d7f 100644 --- a/docs/quick_tutorial/databases/tutorial/wikipage_addedit.pt +++ b/docs/quick_tutorial/databases/tutorial/wikipage_addedit.pt @@ -4,12 +4,10 @@ WikiPage: Add/Edit + href="${request.static_url('deform:static/' + reqt)}"/> - - -- cgit v1.2.3 From 1220ce51e492caad3d361c9fd32dc79065b16f92 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 15 Apr 2016 02:27:01 -0700 Subject: rewrap 79-col --- docs/quick_tutorial/index.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/index.rst b/docs/quick_tutorial/index.rst index 9373fe38a..29b4d8fb7 100644 --- a/docs/quick_tutorial/index.rst +++ b/docs/quick_tutorial/index.rst @@ -4,12 +4,12 @@ Quick Tutorial for Pyramid ========================== -Pyramid is a web framework for Python 2 and 3. This tutorial gives a -Python 3/2-compatible, high-level tour of the major features. +Pyramid is a web framework for Python 2 and 3. This tutorial gives a Python +3/2-compatible, high-level tour of the major features. -This hands-on tutorial covers "a little about a lot": practical -introductions to the most common facilities. Fun, fast-paced, and most -certainly not aimed at experts of the Pyramid web framework. +This hands-on tutorial covers "a little about a lot": practical introductions +to the most common facilities. Fun, fast-paced, and most certainly not aimed at +experts of the Pyramid web framework. Contents ======== -- cgit v1.2.3 From b61a8ba298a7e474d4d209967791a0b13bc5d77d Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 02:39:17 -0700 Subject: quick_tutorial cleanup - replace nose and coverage with pytest and pytest-cov - update glossary and terms - use doscon lexer for Windows commands - refer to Pyramid Installation and put an end to copy-pasta - fix directory tree --- docs/quick_tutorial/requirements.rst | 115 +++++++++++++----------------- docs/quick_tutorial/tutorial_approach.rst | 66 ++++++++--------- 2 files changed, 83 insertions(+), 98 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index 9e10e3ebe..76af2c8ab 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -6,41 +6,44 @@ Requirements Let's get our tutorial environment set up. Most of the set up work is in standard Python development practices (install Python and make an isolated -environment.) +virtual environment.) .. note:: - Pyramid encourages standard Python development practices with - packaging tools, virtual environments, logging, and so on. There - are many variations, implementations, and opinions across the Python - community. For consistency, ease of documentation maintenance, - and to minimize confusion, the Pyramid *documentation* has adopted - specific conventions. + Pyramid encourages standard Python development practices with packaging + tools, virtual environments, logging, and so on. There are many variations, + implementations, and opinions across the Python community. For consistency, + ease of documentation maintenance, and to minimize confusion, the Pyramid + *documentation* has adopted specific conventions that are consistent with the + :term:`Python Packaging Authority`. This *Quick Tutorial* is based on: -* **Python 3.5**. Pyramid fully supports Python 3.3+ and Python 2.6+. This +* **Python 3.5**. Pyramid fully supports Python 3.3+ and Python 2.7+. This tutorial uses **Python 3.5** but runs fine under Python 2.7. * **venv**. We believe in virtual environments. For this tutorial, we use - Python 3.5's built-in solution ``venv``. For Python 2.7, you can install - ``virtualenv``. + Python 3.5's built-in solution :term:`venv`. For Python 2.7, you can install + :term:`virtualenv`. -* **pip**. We use ``pip`` for package management. +* **pip**. We use :term:`pip` for package management. -* **Workspaces, projects, and packages.** Our home directory - will contain a *tutorial workspace* with our Python virtual - environment(s) and *Python projects* (a directory with packaging - information and *Python packages* of working code.) +* **Workspaces, projects, and packages.** Our home directory will contain a + *tutorial workspace* with our Python virtual environment and *Python + projects* (a directory with packaging information and *Python packages* of + working code.) -* **Unix commands**. Commands in this tutorial use UNIX syntax and - paths. Windows users should adjust commands accordingly. +* **Unix commands**. Commands in this tutorial use UNIX syntax and paths. + Windows users should adjust commands accordingly. .. note:: - Pyramid was one of the first web frameworks to fully support Python 3 in October 2011. +.. note:: + Windows commands use the plain old MSDOS shell. For PowerShell command + syntax, see its documentation. + Steps ===== @@ -56,27 +59,12 @@ Steps Install Python 3 ---------------- -Windows and Mac OS X users can download and run an installer. - -Download the latest standard Python 3 release (not development release) from -`python.org `_. +See the detailed recommendation for your operating system described under +:ref:`installing_chapter`. -Windows users should also install the `Python for Windows extensions -`_. Carefully read the -``README.txt`` file at the end of the list of builds, and follow its -directions. Make sure you get the proper 32- or 64-bit build and Python -version. - -Linux users can either use their package manager to install Python 3 -or may `build Python 3 from source -`_. - -.. seealso:: See also :ref:`For Mac OS X Users `, :ref:`If - You Don't Yet Have a Python Interpreter (UNIX) - `, and :ref:`If You Don't - Yet Have a Python Interpreter (Windows) - `. +- :ref:`for-mac-os-x-users` +- :ref:`if-you-don-t-yet-have-a-python-interpreter-unix` +- :ref:`if-you-don-t-yet-have-a-python-interpreter-windows` .. _create-a-project-directory-structure: @@ -84,11 +72,10 @@ method>`_. Create a project directory structure ------------------------------------ -We will arrive at a directory structure of -``workspace->project->package``, with our workspace named -``quick_tutorial``. The following tree diagram shows how this will be -structured and where our virtual environment will reside as we proceed through -the tutorial: +We will arrive at a directory structure of ``workspace -> project -> package``, +where our workspace is named ``quick_tutorial``. The following tree diagram +shows how this will be structured, and where our :term:`virtual environment` +will reside as we proceed through the tutorial: .. code-block:: text @@ -113,43 +100,41 @@ For Linux, the commands to do so are as follows: For Windows: -.. code-block:: ps1con +.. code-block:: doscon # Windows c:\> cd \ c:\> mkdir projects\quick_tutorial c:\> cd projects\quick_tutorial -In the above figure, your user home directory is represented by ``~``. In -your home directory, all of your projects are in the ``projects`` directory. -This is a general convention not specific to Pyramid that many developers use. -Windows users will do well to use ``c:\`` as the location for ``projects`` in -order to avoid spaces in any of the path names. +In the above figure, your user home directory is represented by ``~``. In your +home directory, all of your projects are in the ``projects`` directory. This is +a general convention not specific to Pyramid that many developers use. Windows +users will do well to use ``c:\`` as the location for ``projects`` in order to +avoid spaces in any of the path names. Next within ``projects`` is your workspace directory, here named ``quick_tutorial``. A workspace is a common term used by integrated -development environments (IDE) like PyCharm and PyDev that stores -isolated Python environments (virtual environments) and specific project files -and repositories. +development environments (IDE), like PyCharm and PyDev, where virtual +environments, specific project files, and repositories are stored. .. _set-an-environment-variable: -Set an Environment Variable +Set an environment variable --------------------------- -This tutorial will refer frequently to the location of the virtual -environment. We set an environment variable to save typing later. +This tutorial will refer frequently to the location of the :term:`virtual +environment`. We set an environment variable to save typing later. .. code-block:: bash # Mac and Linux $ export VENV=~/projects/quick_tutorial/env -.. code-block:: ps1con +.. code-block:: doscon # Windows - # TODO: This command does not work c:\> set VENV=c:\projects\quick_tutorial\env @@ -168,7 +153,7 @@ environment variable. # Mac and Linux $ python3 -m venv $VENV -.. code-block:: ps1con +.. code-block:: doscon # Windows c:\> c:\Python35\python3 -m venv %VENV% @@ -195,18 +180,16 @@ part is pretty easy: Our Python virtual environment now has the Pyramid software available. -You can optionally install some of the extra Python packages used -during this tutorial: +You can optionally install some of the extra Python packages used in this +tutorial: .. code-block:: bash # Mac and Linux - $ $VENV/bin/pip install nose webtest deform sqlalchemy \ - pyramid_chameleon pyramid_debugtoolbar waitress \ - pyramid_tm zope.sqlalchemy + $ $VENV/bin/pip install webtest deform sqlalchemy pyramid_chameleon \ + pyramid_debugtoolbar waitress pyramid_tm zope.sqlalchemy -.. code-block:: ps1con +.. code-block:: doscon # Windows - c:\> %VENV%\Scripts\pip install nose webtest deform sqlalchemy pyramid_chameleon pyramid_debugtoolbar waitress pyramid_tm zope.sqlalchemy - + c:\> %VENV%\Scripts\pip install webtest deform sqlalchemy pyramid_chameleon pyramid_debugtoolbar waitress pyramid_tm zope.sqlalchemy diff --git a/docs/quick_tutorial/tutorial_approach.rst b/docs/quick_tutorial/tutorial_approach.rst index 8298a4710..09e0217c6 100644 --- a/docs/quick_tutorial/tutorial_approach.rst +++ b/docs/quick_tutorial/tutorial_approach.rst @@ -2,44 +2,46 @@ Tutorial Approach ================= -This tutorial uses conventions to keep the introduction focused and -concise. Details, references, and deeper discussions are mentioned in -"See also" notes. +This tutorial uses conventions to keep the introduction focused and concise. +Details, references, and deeper discussions are mentioned in "See also" notes. .. seealso:: This is an example "See also" note. -This "Getting Started" tutorial is broken into independent steps, -starting with the smallest possible "single file WSGI app" example. -Each of these steps introduce a topic and a very small set of concepts -via working code. The steps each correspond to a directory in this -repo, where each step/topic/directory is a Python package. +This "Getting Started" tutorial is broken into independent steps, starting with +the smallest possible "single file WSGI app" example. Each of these steps +introduce a topic and a very small set of concepts via working code. The steps +each correspond to a directory in this repo, where each step/topic/directory is +a Python package. -To successfully run each step:: +To successfully run each step: - $ cd request_response - $ $VENV/bin/pip install -e . +.. code-block:: bash -...and repeat for each step you would like to work on. In most cases we -will start with the results of an earlier step. + $ cd request_response + $ $VENV/bin/pip install -e . -Directory Tree +...and repeat for each step you would like to work on. In most cases we will +start with the results of an earlier step. + +Directory tree ============== -As we develop our tutorial our directory tree will resemble the -structure below:: - - quicktutorial/ - request_response/ - development.ini - setup.py - tutorial/ - __init__.py - home.pt - tests.py - views.py - -Each of the first-level directories (e.g. ``request_response``) is a -*Python project* (except, as noted, the ``hello_world`` step.) The -``tutorial`` directory is a *Python package*. At the end of each step, -we copy a previous directory into a new directory to use as a starting -point. +As we develop our tutorial, our directory tree will resemble the structure +below: + +.. code-block:: text + + quick_tutorial + ├── env + └── request_response + ├── tutorial + │ ├── __init__.py + │ ├── tests.py + │ └── views.py + ├── development.ini + └── setup.py + +Each of the first-level directories (e.g., ``request_response``) is a *Python +project* (except as noted for the ``hello_world`` step). The``tutorial`` +directory is a *Python package*. At the end of each step, we copy a previous +directory into a new directory to use as a starting point. -- cgit v1.2.3 From 789a9059a1190b3f1e748dda4b3755d1b26d43fa Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 03:03:10 -0700 Subject: quick_tutorial cleanup - update pip and setuptools - moar cleanup --- docs/quick_tutorial/requirements.rst | 24 +++++++++++++++++++++--- docs/quick_tutorial/tutorial_approach.rst | 2 +- 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index 76af2c8ab..9174ea657 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -140,7 +140,7 @@ environment`. We set an environment variable to save typing later. .. _create-a-virtual-environment: -Create a Virtual Environment +Create a virtual environment ---------------------------- ``venv`` is a tool to create isolated Python 3 environments, each with its own @@ -162,13 +162,31 @@ environment variable. 2's `virtualenv `_ package. +Update packaging tools in the virtual environment +------------------------------------------------- + +It's always a good idea to update to the very latest version of packaging tools +because the installed Python bundles only the version that was available at the +time of its release. + +.. code-block:: bash + + # Mac and Linux + $VENV/bin/pip install --upgrade pip setuptools + +.. code-block:: doscon + + # Windows + c:\> %VENV%\Scripts\pip install --upgrade pip setuptools + + .. _install-pyramid: Install Pyramid --------------- We have our Python standard prerequisites out of the way. The Pyramid -part is pretty easy: +part is pretty easy. .. parsed-literal:: @@ -181,7 +199,7 @@ part is pretty easy: Our Python virtual environment now has the Pyramid software available. You can optionally install some of the extra Python packages used in this -tutorial: +tutorial. .. code-block:: bash diff --git a/docs/quick_tutorial/tutorial_approach.rst b/docs/quick_tutorial/tutorial_approach.rst index 09e0217c6..6d534fe13 100644 --- a/docs/quick_tutorial/tutorial_approach.rst +++ b/docs/quick_tutorial/tutorial_approach.rst @@ -42,6 +42,6 @@ below: └── setup.py Each of the first-level directories (e.g., ``request_response``) is a *Python -project* (except as noted for the ``hello_world`` step). The``tutorial`` +project* (except as noted for the ``hello_world`` step). The ``tutorial`` directory is a *Python package*. At the end of each step, we copy a previous directory into a new directory to use as a starting point. -- cgit v1.2.3 From 878d1aa1ea7a9208d70cf3092d0a3dcd11775a74 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 03:39:51 -0700 Subject: quick_tutorial cleanup - cleanup hello_world.rst --- docs/quick_tutorial/hello_world.rst | 81 ++++++++++++++++++------------------ docs/quick_tutorial/requirements.rst | 5 ++- docs/quick_tutorial/scaffolds.rst | 48 ++++++++++----------- 3 files changed, 67 insertions(+), 67 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/hello_world.rst b/docs/quick_tutorial/hello_world.rst index fb661e9c5..4e35da7bb 100644 --- a/docs/quick_tutorial/hello_world.rst +++ b/docs/quick_tutorial/hello_world.rst @@ -4,40 +4,40 @@ 01: Single-File Web Applications ================================ -What's the simplest way to get started in Pyramid? A single-file module. -No Python packages, no ``pip install -e .``, no other machinery. +What's the simplest way to get started in Pyramid? A single-file module. No +Python packages, no ``pip install -e .``, no other machinery. + Background ========== -Microframeworks are all the rage these days. "Microframework" is a -marketing term, not a technical one. They have a low mental overhead: -they do so little, the only things you have to worry about are *your -things*. +Microframeworks are all the rage these days. "Microframework" is a marketing +term, not a technical one. They have a low mental overhead: they do so little, +the only things you have to worry about are *your things*. + +Pyramid is special because it can act as a single-file module microframework. +You can have a single Python file that can be executed directly by Python. But +Pyramid also provides facilities to scale to the largest of applications. -Pyramid is special because it can act as a single-file module -microframework. You can have a single Python file that can be executed -directly by Python. But Pyramid also provides facilities to scale to -the largest of applications. +Python has a standard called :term:`WSGI` that defines how Python web +applications plug into standard servers, getting passed incoming requests, and +returning responses. Most modern Python web frameworks obey an "MVC" +(model-view-controller) application pattern, where the data in the model has a +view that mediates interaction with outside systems. -Python has a standard called :term:`WSGI` that defines how -Python web applications plug into standard servers, getting passed -incoming requests and returning responses. Most modern Python web -frameworks obey an "MVC" (model-view-controller) application pattern, -where the data in the model has a view that mediates interaction with -outside systems. +In this step we'll see a brief glimpse of WSGI servers, WSGI applications, +requests, responses, and views. -In this step we'll see a brief glimpse of WSGI servers, WSGI -applications, requests, responses, and views. Objectives ========== -- Get a running Pyramid web application, as simply as possible +- Get a running Pyramid web application, as simply as possible. + +- Use that as a well-understood base for adding each unit of complexity. -- Use that as a well-understood base for adding each unit of complexity +- Initial exposure to WSGI apps, requests, views, and responses. -- Initial exposure to WSGI apps, requests, views, and responses Steps ===== @@ -64,30 +64,29 @@ Steps #. Open http://localhost:6543/ in your browser. + Analysis ======== -New to Python web programming? If so, some lines in module merit +New to Python web programming? If so, some lines in the module merit explanation: -#. *Line 11*. The ``if __name__ == '__main__':`` is Python's way of - saying "Start here when running from the command line", rather than - when this module is imported. +#. *Line 11*. The ``if __name__ == '__main__':`` is Python's way of saying, + "Start here when running from the command line", rather than when this + module is imported. + +#. *Lines 12-14*. Use Pyramid's :term:`configurator` to connect :term:`view` + code to a particular URL :term:`route`. -#. *Lines 12-14*. Use Pyramid's :term:`configurator` to connect - :term:`view` code to a particular URL :term:`route`. +#. *Lines 6-8*. Implement the view code that generates the :term:`response`. -#. *Lines 6-8*. Implement the view code that generates the - :term:`response`. +#. *Lines 15-17*. Publish a :term:`WSGI` app using an HTTP server. -#. *Lines 15-17*. Publish a :term:`WSGI` app using an HTTP - server. +As shown in this example, the :term:`configurator` plays a central role in +Pyramid development. Building an application from loosely-coupled parts via +:ref:`configuration_narr` is a central idea in Pyramid, one that we will +revisit regularly in this *Quick Tutorial*. -As shown in this example, the :term:`configurator` plays a -central role in Pyramid development. Building an application from -loosely-coupled parts via :ref:`configuration_narr` is a -central idea in Pyramid, one that we will revisit regularly in this -*Quick Tour*. Extra Credit ============ @@ -106,9 +105,9 @@ Extra Credit #. What happens if you return a string of HTML? A sequence of integers? -#. Put something invalid, such as ``print xyz``, in the view function. - Kill your ``python app.py`` with ``cntrl-c`` and restart, - then reload your browser. See the exception in the console? +#. Put something invalid, such as ``print xyz``, in the view function. Kill + your ``python app.py`` with ``ctrl-C`` and restart, then reload your + browser. See the exception in the console? -#. The ``GI`` in ``WSGI`` stands for "Gateway Interface". What web - standard is this modelled after? +#. The ``GI`` in ``WSGI`` stands for "Gateway Interface". What web standard is + this modelled after? diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index 9174ea657..f4c1e70ac 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -204,8 +204,9 @@ tutorial. .. code-block:: bash # Mac and Linux - $ $VENV/bin/pip install webtest deform sqlalchemy pyramid_chameleon \ - pyramid_debugtoolbar waitress pyramid_tm zope.sqlalchemy + $ $VENV/bin/pip install webtest pytest pytest-cov deform sqlalchemy \ + pyramid_chameleon pyramid_debugtoolbar waitress pyramid_tm \ + zope.sqlalchemy .. code-block:: doscon diff --git a/docs/quick_tutorial/scaffolds.rst b/docs/quick_tutorial/scaffolds.rst index 319eb9d90..7845f2b71 100644 --- a/docs/quick_tutorial/scaffolds.rst +++ b/docs/quick_tutorial/scaffolds.rst @@ -4,29 +4,30 @@ Prelude: Quick Project Startup with Scaffolds ============================================= -To ease the process of getting started, Pyramid provides *scaffolds* -that generate sample projects from templates in Pyramid and Pyramid -add-ons. +To ease the process of getting started, Pyramid provides *scaffolds* that +generate sample projects from templates in Pyramid and Pyramid add-ons. + Background ========== -We're going to cover a lot in this tutorial, focusing on one topic at a -time and writing everything from scratch. As a warm up, though, -it sure would be nice to see some pixels on a screen. +We're going to cover a lot in this tutorial, focusing on one topic at a time +and writing everything from scratch. As a warm up, though, it sure would be +nice to see some pixels on a screen. + +Like other web development frameworks, Pyramid provides a number of "scaffolds" +that generate working Python, template, and CSS code for sample applications. +In this step we'll use a built-in scaffold to let us preview a Pyramid +application, before starting from scratch on Step 1. -Like other web development frameworks, Pyramid provides a number of -"scaffolds" that generate working Python, template, and CSS code for -sample applications. In this step we'll use a built-in scaffold to let -us preview a Pyramid application, before starting from scratch on Step 1. Objectives ========== -- Use Pyramid's ``pcreate`` command to list scaffolds and make a new - project +- Use Pyramid's ``pcreate`` command to list scaffolds and make a new project. + +- Start up a Pyramid application and visit it in a web browser. -- Start up a Pyramid application and visit it in a web browser Steps ===== @@ -55,8 +56,8 @@ Steps $ cd scaffolds $ $VENV/bin/pip install -e . -#. Start up the application by pointing Pyramid's ``pserve`` command at - the project's (generated) configuration file: +#. Start up the application by pointing Pyramid's ``pserve`` command at the + project's (generated) configuration file: .. code-block:: bash @@ -75,13 +76,12 @@ Steps Analysis ======== -Rather than starting from scratch, ``pcreate`` can make getting a -Python project containing a Pyramid application a quick matter. -Pyramid ships with a few scaffolds. But installing a Pyramid add-on can -give you new scaffolds from that add-on. +Rather than starting from scratch, ``pcreate`` can make getting a Python +project containing a Pyramid application a quick matter. Pyramid ships with a +few scaffolds. But installing a Pyramid add-on can give you new scaffolds from +that add-on. -``pserve`` is Pyramid's application runner, separating operational -details from your code. When you install Pyramid, a small command -program called ``pserve`` is written to your ``bin`` directory. This -program is an executable Python module. It is passed a configuration -file (in this case, ``development.ini``.) +``pserve`` is Pyramid's application runner, separating operational details from +your code. When you install Pyramid, a small command program called ``pserve`` +is written to your ``bin`` directory. This program is an executable Python +module. It is passed a configuration file (in this case, ``development.ini``). -- cgit v1.2.3 From 4e34c51b1e7c1ffa836cef81ee7b31cfdbdf69df Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 03:57:50 -0700 Subject: quick_tutorial cleanup - cleanup package.rst --- docs/quick_tutorial/package.rst | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/package.rst b/docs/quick_tutorial/package.rst index 6a379032e..94cb39fc9 100644 --- a/docs/quick_tutorial/package.rst +++ b/docs/quick_tutorial/package.rst @@ -3,16 +3,17 @@ ============================================ Most modern Python development is done using Python packages, an approach -Pyramid puts to good use. In this step we redo "Hello World" as a -minimum Python package inside a minimum Python project. +Pyramid puts to good use. In this step we redo "Hello World" as a minimal +Python package inside a minimal Python project. + Background ========== Python developers can organize a collection of modules and files into a -namespaced unit called a :ref:`package `. If a -directory is on ``sys.path`` and has a special file named -``__init__.py``, it is treated as a Python package. +namespaced unit called a :ref:`package `. If a directory +is on ``sys.path`` and has a special file named ``__init__.py``, it is treated +as a Python package. Packages can be bundled up, made available for installation, and installed through a toolchain oriented around a ``setup.py`` file. For this tutorial, @@ -34,6 +35,7 @@ In summary: - That package will be part of a *project*. + Objectives ========== @@ -43,6 +45,7 @@ Objectives - Install our ``tutorial`` project in development mode. + Steps ===== @@ -56,8 +59,8 @@ Steps .. literalinclude:: package/setup.py -#. Make the new project installed for development then make a directory - for the actual code: +#. Make the new project installed for development then make a directory for the + actual code: .. code-block:: bash @@ -80,26 +83,27 @@ Steps #. Open http://localhost:6543/ in your browser. + Analysis ======== -Python packages give us an organized unit of project development. -Python projects, via ``setup.py``, gives us special features when -our package is installed (in this case, in local development mode.) +Python packages give us an organized unit of project development. Python +projects, via ``setup.py``, give us special features when our package is +installed (in this case, in local development mode, also called local editable +mode as indicated by ``-e .``). -In this step we have a Python package called ``tutorial``. We use the -same name in each step of the tutorial, to avoid unnecessary retyping. +In this step we have a Python package called ``tutorial``. We use the same name +in each step of the tutorial, to avoid unnecessary retyping. -Above this ``tutorial`` directory we have the files that handle the -packaging of this project. At the moment, all we need is a -bare-bones ``setup.py``. +Above this ``tutorial`` directory we have the files that handle the packaging +of this project. At the moment, all we need is a bare-bones ``setup.py``. -Everything else is the same about our application. We simply made a -Python package with a ``setup.py`` and installed it in development mode. +Everything else is the same about our application. We simply made a Python +package with a ``setup.py`` and installed it in development mode. Note that the way we're running the app (``python tutorial/app.py``) is a bit of an odd duck. We would never do this unless we were writing a tutorial that -tries to capture how this stuff works a step at a time. It's generally a bad +tries to capture how this stuff works one step at a time. It's generally a bad idea to run a Python module inside a package directly as a script. .. seealso:: :ref:`Python Packages ` and `Working in -- cgit v1.2.3 From 8e6520bd91d9b873b5e367176b7c303d7cac429a Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 04:17:36 -0700 Subject: quick_tutorial cleanup - cleanup ini.rst --- docs/quick_tutorial/ini.rst | 92 ++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 46 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/ini.rst b/docs/quick_tutorial/ini.rst index 0aed304df..fba5ce29e 100644 --- a/docs/quick_tutorial/ini.rst +++ b/docs/quick_tutorial/ini.rst @@ -7,28 +7,30 @@ Use Pyramid's ``pserve`` command with a ``.ini`` configuration file for simpler, better application running. + Background ========== -Pyramid has a first-class concept of -:ref:`configuration ` distinct from code. -This approach is optional, but its presence makes it distinct from -other Python web frameworks. It taps into Python's ``setuptools`` -library, which establishes conventions for installing and providing -"entry points" for Python projects. Pyramid uses an entry point to -let a Pyramid application know where to find the WSGI app. +Pyramid has a first-class concept of :ref:`configuration ` +distinct from code. This approach is optional, but its presence makes it +distinct from other Python web frameworks. It taps into Python's ``setuptools`` +library, which establishes conventions for installing and providing "entry +points" for Python projects. Pyramid uses an entry point to let a Pyramid +application know where to find the WSGI app. + Objectives ========== -- Modify our ``setup.py`` to have an entry point telling Pyramid the - location of the WSGI app +- Modify our ``setup.py`` to have an entry point telling Pyramid the location + of the WSGI app. + +- Create an application driven by an ``.ini`` file. -- Create an application driven by a ``.ini`` file +- Start the application with Pyramid's ``pserve`` command. -- Startup the application with Pyramid's ``pserve`` command +- Move code into the package's ``__init__.py``. -- Move code into the package's ``__init__.py`` Steps ===== @@ -39,14 +41,14 @@ Steps $ cd ..; cp -r package ini; cd ini -#. Our ``ini/setup.py`` needs a setuptools "entry point" in the - ``setup()`` function: +#. Our ``ini/setup.py`` needs a setuptools "entry point" in the ``setup()`` + function: .. literalinclude:: ini/setup.py :linenos: -#. We can now install our project, thus generating (or re-generating) an - "egg" at ``ini/tutorial.egg-info``: +#. We can now install our project, thus generating (or re-generating) an "egg" + at ``ini/tutorial.egg-info``: .. code-block:: bash @@ -58,8 +60,8 @@ Steps :language: ini :linenos: -#. We can refactor our startup code from the previous step's ``app.py`` - into ``ini/tutorial/__init__.py``: +#. We can refactor our startup code from the previous step's ``app.py`` into + ``ini/tutorial/__init__.py``: .. literalinclude:: ini/tutorial/__init__.py :linenos: @@ -81,27 +83,26 @@ Steps Analysis ======== -Our ``development.ini`` file is read by ``pserve`` and serves to -bootstrap our application. Processing then proceeds as described in -the Pyramid chapter on +Our ``development.ini`` file is read by ``pserve`` and serves to bootstrap our +application. Processing then proceeds as described in the Pyramid chapter on :ref:`application startup `: -- ``pserve`` looks for ``[app:main]`` and finds ``use = egg:tutorial`` +- ``pserve`` looks for ``[app:main]`` and finds ``use = egg:tutorial``. -- The projects's ``setup.py`` has defined an "entry point" (lines 9-12) - for the project "main" entry point of ``tutorial:main`` +- The projects's ``setup.py`` has defined an "entry point" (lines 9-12) for the + project's "main" entry point of ``tutorial:main``. -- The ``tutorial`` package's ``__init__`` has a ``main`` function +- The ``tutorial`` package's ``__init__`` has a ``main`` function. -- This function is invoked, with the values from certain ``.ini`` - sections passed in +- This function is invoked, with the values from certain ``.ini`` sections + passed in. The ``.ini`` file is also used for two other functions: -- *Configuring the WSGI server*. ``[server:main]`` wires up the choice of - which WSGI *server* for your WSGI *application*. In this case, we are using - ``wsgiref`` bundled in the Python library. It also wires up the *port - number*: ``port = 6543`` tells ``wsgiref`` to listen on port 6543. +- *Configuring the WSGI server*. ``[server:main]`` wires up the choice of which + WSGI *server* for your WSGI *application*. In this case, we are using + ``wsgiref`` bundled in the Python library. It also wires up the *port + number*: ``port = 6543`` tells ``wsgiref`` to listen on port 6543. - *Configuring Python logging*. Pyramid uses Python standard logging, which needs a number of configuration values. The ``.ini`` serves this function. @@ -109,27 +110,27 @@ The ``.ini`` file is also used for two other functions: request. We moved our startup code from ``app.py`` to the package's -``tutorial/__init__.py``. This isn't necessary, -but it is a common style in Pyramid to take the WSGI app bootstrapping -out of your module's code and put it in the package's ``__init__.py``. +``tutorial/__init__.py``. This isn't necessary, but it is a common style in +Pyramid to take the WSGI app bootstrapping out of your module's code and put it +in the package's ``__init__.py``. + +The ``pserve`` application runner has a number of command-line arguments and +options. We are using ``--reload`` which tells ``pserve`` to watch the +filesystem for changes to relevant code (Python files, the INI file, etc.) and, +when something changes, restart the application. Very handy during development. -The ``pserve`` application runner has a number of command-line arguments -and options. We are using ``--reload`` which tells ``pserve`` to watch -the filesystem for changes to relevant code (Python files, the INI file, -etc.) and, when something changes, restart the application. Very handy -during development. Extra Credit ============ -#. If you don't like configuration and/or ``.ini`` files, - could you do this yourself in Python code? +#. If you don't like configuration and/or ``.ini`` files, could you do this + yourself in Python code? -#. Can we have multiple ``.ini`` configuration files for a project? Why - might you want to do that? +#. Can we have multiple ``.ini`` configuration files for a project? Why might + you want to do that? -#. The entry point in ``setup.py`` didn't mention ``__init__.py`` when - it declared ``tutorial:main`` function. Why not? +#. The entry point in ``setup.py`` didn't mention ``__init__.py`` when it + declared ``tutorial:main`` function. Why not? #. What is the purpose of ``**settings``? What does the ``**`` signify? @@ -139,4 +140,3 @@ Extra Credit :ref:`what_is_this_pserve_thing`, :ref:`environment_chapter`, :ref:`paste_chapter` - -- cgit v1.2.3 From 823ef1d9c931106de11e7d383856fcc2fc99c3fa Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 04:26:05 -0700 Subject: quick_tutorial cleanup - cleanup debugtoolbar.rst --- docs/quick_tutorial/debugtoolbar.rst | 53 ++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 24 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/debugtoolbar.rst b/docs/quick_tutorial/debugtoolbar.rst index 1f89cd319..aaf904390 100644 --- a/docs/quick_tutorial/debugtoolbar.rst +++ b/docs/quick_tutorial/debugtoolbar.rst @@ -6,31 +6,34 @@ Error handling and introspection using the ``pyramid_debugtoolbar`` add-on. + Background ========== -As we introduce the basics we also want to show how to be productive in -development and debugging. For example, we just discussed template -reloading and earlier we showed ``--reload`` for application reloading. +As we introduce the basics, we also want to show how to be productive in +development and debugging. For example, we just discussed template reloading, +and earlier we showed ``--reload`` for application reloading. + +``pyramid_debugtoolbar`` is a popular Pyramid add-on which makes several tools +available in your browser. Adding it to your project illustrates several points +about configuration. -``pyramid_debugtoolbar`` is a popular Pyramid add-on which makes -several tools available in your browser. Adding it to your project -illustrates several points about configuration. Objectives ========== -- Install and enable the toolbar to help during development +- Install and enable the toolbar to help during development. + +- Explain Pyramid add-ons. -- Explain Pyramid add-ons +- Show how an add-on gets configured into your application. -- Show how an add-on gets configured into your application Steps ===== -#. First we copy the results of the previous step, as well as install - the ``pyramid_debugtoolbar`` package: +#. First we copy the results of the previous step, as well as install the + ``pyramid_debugtoolbar`` package: .. code-block:: bash @@ -54,6 +57,7 @@ Steps #. Open http://localhost:6543/ in your browser. See the handy toolbar on the right. + Analysis ======== @@ -66,16 +70,16 @@ The ``pyramid_debugtoolbar`` Python package is also a Pyramid add-on, which means we need to include its add-on configuration into our web application. We could do this with imperative configuration in ``tutorial/__init__.py`` by using ``config.include``. Pyramid also supports wiring in add-on configuration -via our ``development.ini`` using ``pyramid.includes``. We use this to load -the configuration for the debugtoolbar. +via our ``development.ini`` using ``pyramid.includes``. We use this to load the +configuration for the debugtoolbar. You'll now see an attractive button on the right side of your browser, which -you may click to provide introspective access to debugging information in a -new browser tab. Even better, if your web application generates an error, you -will see a nice traceback on the screen. When you want to disable this -toolbar, there's no need to change code: you can remove it from -``pyramid.includes`` in the relevant ``.ini`` configuration file (thus showing -why configuration files are handy.) +you may click to provide introspective access to debugging information in a new +rowser tab. Even better, if your web application generates an error, you will +see a nice traceback on the screen. When you want to disable this toolbar, +there's no need to change code: you can remove it from ``pyramid.includes`` in +the relevant ``.ini`` configuration file (thus showing why configuration files +are handy). Note that the toolbar injects a small amount of HTML/CSS into your app just before the closing ```` tag in order to display itself. If you start to @@ -85,13 +89,14 @@ temporarily. .. seealso:: See also :ref:`pyramid_debugtoolbar `. + Extra Credit ============ #. Why don't we add ``pyramid_debugtoolbar`` to the list of ``install_requires`` dependencies in ``debugtoolbar/setup.py``? -#. Introduce a bug into your application: Change: +#. Introduce a bug into your application. Change: .. code-block:: python @@ -105,7 +110,7 @@ Extra Credit def hello_world(request): return xResponse('

Hello World!

') - Save, and visit http://localhost:6543/ again. Notice the nice - traceback display. On the lowest line, click the "screen" icon to the - right, and try typing the variable names ``request`` and ``Response``. - What else can you discover? + Save, and visit http://localhost:6543/ again. Notice the nice traceback + display. On the lowest line, click the "screen" icon to the right, and try + typing the variable names ``request`` and ``Response``. What else can you + discover? -- cgit v1.2.3 From 86e187a734728611bc8bfd5792133502ffd59160 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 04:44:55 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup unit_testing.rst --- docs/quick_tutorial/unit_testing.rst | 114 +++++++++++++++++------------------ 1 file changed, 56 insertions(+), 58 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/unit_testing.rst b/docs/quick_tutorial/unit_testing.rst index 58512d1cc..56fd2b297 100644 --- a/docs/quick_tutorial/unit_testing.rst +++ b/docs/quick_tutorial/unit_testing.rst @@ -1,55 +1,56 @@ .. _qtut_unit_testing: -=========================== -05: Unit Tests and ``nose`` -=========================== +============================= +05: Unit Tests and ``pytest`` +============================= Provide unit testing for our project's Python code. + Background ========== -As the mantra says, "Untested code is broken code." The Python -community has had a long culture of writing test scripts which ensure -that your code works correctly as you write it and maintain it in the -future. Pyramid has always had a deep commitment to testing, -with 100% test coverage from the earliest pre-releases. - -Python includes a -:ref:`unit testing framework ` in its -standard library. Over the years a number of Python projects, such as -`nose `_, have extended this -framework with alternative test runners that provide more convenience -and functionality. The Pyramid developers use ``nose``, which we'll thus -use in this tutorial. - -Don't worry, this tutorial won't be pedantic about "test-driven -development" (TDD). We'll do just enough to ensure that, in each step, -we haven't majorly broken the code. As you're writing your code you -might find this more convenient than changing to your browser -constantly and clicking reload. - -We'll also leave discussion of -`coverage `_ for another section. +As the mantra says, "Untested code is broken code." The Python community has +had a long culture of writing test scripts which ensure that your code works +correctly as you write it and maintain it in the future. Pyramid has always had +a deep commitment to testing, with 100% test coverage from the earliest +pre-releases. + +Python includes a :ref:`unit testing framework +` in its standard library. Over the years a +number of Python projects, such as :ref:`pytest `, have +extended this framework with alternative test runners that provide more +convenience and functionality. The Pyramid developers use ``pytest``, which +we'll use in this tutorial. + +Don't worry, this tutorial won't be pedantic about "test-driven development" +(TDD). We'll do just enough to ensure that, in each step, we haven't majorly +broken the code. As you're writing your code, you might find this more +convenient than changing to your browser constantly and clicking reload. + +We'll also leave discussion of `pytest-cov +`_ for another section. + Objectives ========== -- Write unit tests that ensure the quality of our code +- Write unit tests that ensure the quality of our code. + +- Install a Python package (``pytest``) which helps in our testing. -- Install a Python package (``nose``) which helps in our testing Steps ===== -#. First we copy the results of the previous step, as well as install - the ``nose`` package: +#. First we copy the results of the previous step, as well as install the + ``pytest`` package: .. code-block:: bash $ cd ..; cp -r debugtoolbar unit_testing; cd unit_testing $ $VENV/bin/pip install -e . - $ $VENV/bin/pip install nose + $ $VENV/bin/pip install pytest #. Now we write a simple unit test in ``unit_testing/tutorial/tests.py``: @@ -61,54 +62,51 @@ Steps .. code-block:: bash - $ $VENV/bin/nosetests tutorial + $ $VENV/bin/py.test tutorial/tests.py -q . - ---------------------------------------------------------------------- - Ran 1 test in 0.141s + 1 passed in 0.14 seconds - OK Analysis ======== -Our ``tests.py`` imports the Python standard unit testing framework. To -make writing Pyramid-oriented tests more convenient, Pyramid supplies -some ``pyramid.testing`` helpers which we use in the test setup and -teardown. Our one test imports the view, makes a dummy request, and sees -if the view returns what we expected. +Our ``tests.py`` imports the Python standard unit testing framework. To make +writing Pyramid-oriented tests more convenient, Pyramid supplies some +``pyramid.testing`` helpers which we use in the test setup and teardown. Our +one test imports the view, makes a dummy request, and sees if the view returns +what we expect. -The ``tests.TutorialViewTests.test_hello_world`` test is a small -example of a unit test. First, we import the view inside each test. Why -not import at the top, like in normal Python code? Because imports can -cause effects that break a test. We'd like our tests to be in *units*, -hence the name *unit* testing. Each test should isolate itself to the -correct degree. +The ``tests.TutorialViewTests.test_hello_world`` test is a small example of a +unit test. First, we import the view inside each test. Why not import at the +top, like in normal Python code? Because imports can cause effects that break a +test. We'd like our tests to be in *units*, hence the name *unit* testing. Each +test should isolate itself to the correct degree. -Our test then makes a fake incoming web request, then calls our Pyramid -view. We test the HTTP status code on the response to make sure it -matches our expectations. +Our test then makes a fake incoming web request, then calls our Pyramid view. +We test the HTTP status code on the response to make sure it matches our +expectations. Note that our use of ``pyramid.testing.setUp()`` and ``pyramid.testing.tearDown()`` aren't actually necessary here; they are only necessary when your test needs to make use of the ``config`` object (it's a Configurator) to add stuff to the configuration state before calling the view. + Extra Credit ============ -#. Change the test to assert that the response status code should be - ``404`` (meaning, not found.) Run ``nosetests`` again. Read the - error report and see if you can decipher what it is telling you. +#. Change the test to assert that the response status code should be ``404`` + (meaning, not found). Run ``py.test`` again. Read the error report and see + if you can decipher what it is telling you. -#. As a more realistic example, put the ``tests.py`` back as you found - it and put an error in your view, such as a reference to a - non-existing variable. Run the tests and see how this is more - convenient than reloading your browser and going back to your code. +#. As a more realistic example, put the ``tests.py`` back as you found it, and + put an error in your view, such as a reference to a non-existing variable. + Run the tests and see how this is more convenient than reloading your + browser and going back to your code. #. Finally, for the most realistic test, read about Pyramid ``Response`` - objects and see how to change the response code. Run the tests and - see how testing confirms the "contract" that your code claims to - support. + objects and see how to change the response code. Run the tests and see how + testing confirms the "contract" that your code claims to support. #. How could we add a unit test assertion to test the HTML value of the response body? -- cgit v1.2.3 From ccf3974f81fa0e026fadd42ba5259c838aeab68b Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 04:50:39 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup functional_testing.rst --- docs/quick_tutorial/functional_testing.rst | 52 +++++++++++++++--------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/functional_testing.rst b/docs/quick_tutorial/functional_testing.rst index b8aa7e87d..33793578a 100644 --- a/docs/quick_tutorial/functional_testing.rst +++ b/docs/quick_tutorial/functional_testing.rst @@ -6,30 +6,33 @@ Write end-to-end full-stack testing using ``webtest``. + Background ========== -Unit tests are a common and popular approach to test-driven development -(TDD). In web applications, though, the templating and entire apparatus -of a web site are important parts of the delivered quality. We'd like a -way to test these. +Unit tests are a common and popular approach to test-driven development (TDD). +In web applications, though, the templating and entire apparatus of a web site +are important parts of the delivered quality. We'd like a way to test these. + +`WebTest `_ is a +Python package that does functional testing. With WebTest you can write tests +which simulate a full HTTP request against a WSGI application, then test the +information in the response. For speed purposes, WebTest skips the +setup/teardown of an actual HTTP server, providing tests that run fast enough +to be part of TDD. -WebTest is a Python package that does functional testing. With WebTest -you can write tests which simulate a full HTTP request against a WSGI -application, then test the information in the response. For speed -purposes, WebTest skips the setup/teardown of an actual HTTP server, -providing tests that run fast enough to be part of TDD. Objectives ========== -- Write a test which checks the contents of the returned HTML +- Write a test which checks the contents of the returned HTML. + Steps ===== -#. First we copy the results of the previous step, as well as install - the ``webtest`` package: +#. First we copy the results of the previous step, as well as install the + ``webtest`` package: .. code-block:: bash @@ -43,31 +46,28 @@ Steps .. literalinclude:: functional_testing/tutorial/tests.py :linenos: - Be sure this file is not executable, or ``nosetests`` may not - include your tests. + Be sure this file is not executable, or ``pytest`` may not include your + tests. #. Now run the tests: .. code-block:: bash + $ $VENV/bin/py.test tutorial/tests.py -q + .. + 2 passed in 0.25 seconds - $ $VENV/bin/nosetests tutorial - . - ---------------------------------------------------------------------- - Ran 2 tests in 0.141s - - OK Analysis ======== -We now have the end-to-end testing we were looking for. WebTest lets us -simply extend our existing ``nose``-based test approach with functional -tests that are reported in the same output. These new tests not only -cover our templating, but they didn't dramatically increase the -execution time of our tests. +We now have the end-to-end testing we were looking for. WebTest lets us simply +extend our existing ``pytest``-based test approach with functional tests that +are reported in the same output. These new tests not only cover our templating, +but they didn't dramatically increase the execution time of our tests. + -Extra Credit +Extra credit ============ #. Why do our functional tests use ``b''``? -- cgit v1.2.3 From 8083654303f0f0b3ce5e78979f6b51f7afd6980c Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 04:58:00 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup views.rst --- docs/quick_tutorial/views.rst | 85 +++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 43 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/views.rst b/docs/quick_tutorial/views.rst index 5b6e2960b..edbe4b2ff 100644 --- a/docs/quick_tutorial/views.rst +++ b/docs/quick_tutorial/views.rst @@ -6,12 +6,12 @@ Organize a views module with decorators and multiple views. + Background ========== -For the examples so far, the ``hello_world`` function is a "view". In -Pyramid, views are the primary way to accept web requests and return -responses. +For the examples so far, the ``hello_world`` function is a "view". In Pyramid, +views are the primary way to accept web requests and return responses. So far our examples place everything in one file: @@ -23,22 +23,24 @@ So far our examples place everything in one file: - The WSGI application launcher -Let's move the views out to their own ``views.py`` module and change -our startup code to scan that module, looking for decorators that setup -the views. Let's also add a second view and update our tests. +Let's move the views out to their own ``views.py`` module and change our +startup code to scan that module, looking for decorators that set up the views. +Let's also add a second view and update our tests. + Objectives ========== -- Views in a module that is scanned by the configurator +- Move views into a module that is scanned by the configurator. + +- Create decorators that do declarative configuration. -- Decorators that do declarative configuration Steps ===== -#. Let's begin by using the previous package as a starting point for a - new distribution, then making it active: +#. Let's begin by using the previous package as a starting point for a new + distribution, then making it active: .. code-block:: bash @@ -66,12 +68,9 @@ Steps .. code-block:: bash - $ $VENV/bin/nosetests tutorial - . - ---------------------------------------------------------------------- - Ran 4 tests in 0.141s - - OK + $ $VENV/bin/py.test tutorial/tests.py -q + .... + 4 passed in 0.28 seconds #. Run your Pyramid application with: @@ -82,41 +81,41 @@ Steps #. Open http://localhost:6543/ and http://localhost:6543/howdy in your browser. + Analysis ======== -We added some more URLs, but we also removed the view code from the -application startup code in ``tutorial/__init__.py``. -Our views, and their view registrations (via decorators) are now in a -module ``views.py`` which is scanned via ``config.scan('.views')``. - -We have 2 views, each leading to the other. If you start at -http://localhost:6543/, you get a response with a link to the next -view. The ``hello`` view (available at the URL ``/howdy``) has a link -back to the first view. - -This step also shows that the name appearing in the URL, -the name of the "route" that maps a URL to a view, -and the name of the view, can all be different. More on routes later. - -Earlier we saw ``config.add_view`` as one way to configure a view. This -section introduces ``@view_config``. Pyramid's configuration supports -:term:`imperative configuration`, such as the -``config.add_view`` in the previous example. You can also use -:term:`declarative configuration`, in which a Python -:term:`python:decorator` -is placed on the line above the view. Both approaches result in the -same final configuration, thus usually, it is simply a matter of taste. - -Extra Credit +We added some more URLs, but we also removed the view code from the application +startup code in ``tutorial/__init__.py``. Our views, and their view +registrations (via decorators) are now in a module ``views.py``, which is +scanned via ``config.scan('.views')``. + +We have two views, each leading to the other. If you start at +http://localhost:6543/, you get a response with a link to the next view. The +``hello`` view (available at the URL ``/howdy``) has a link back to the first +view. + +This step also shows that the name appearing in the URL, the name of the +"route" that maps a URL to a view, and the name of the view, can all be +different. More on routes later. + +Earlier we saw ``config.add_view`` as one way to configure a view. This section +introduces ``@view_config``. Pyramid's configuration supports :term:`imperative +configuration`, such as the ``config.add_view`` in the previous example. You +can also use :term:`declarative configuration`, in which a Python +:term:`python:decorator` is placed on the line above the view. Both approaches +result in the same final configuration, thus usually, it is simply a matter of +taste. + + +Extra credit ============ #. What does the dot in ``.views`` signify? -#. Why might ``assertIn`` be a better choice in testing the text in - responses than ``assertEqual``? +#. Why might ``assertIn`` be a better choice in testing the text in responses + than ``assertEqual``? .. seealso:: :ref:`views_chapter`, :ref:`view_config_chapter`, and :ref:`debugging_view_configuration` - -- cgit v1.2.3 From 3dece91a06679f1af98c864160fcd06ec3f15b8c Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 05:02:30 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup templating.rst --- docs/quick_tutorial/templating.rst | 84 ++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 44 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/templating.rst b/docs/quick_tutorial/templating.rst index a975d9ec2..dbcf76a0a 100644 --- a/docs/quick_tutorial/templating.rst +++ b/docs/quick_tutorial/templating.rst @@ -4,50 +4,52 @@ 08: HTML Generation With Templating =================================== -Most web frameworks don't embed HTML in programming code. Instead, -they pass data into a templating system. In this step we look at the -basics of using HTML templates in Pyramid. +Most web frameworks don't embed HTML in programming code. Instead, they pass +data into a templating system. In this step we look at the basics of using HTML +templates in Pyramid. + Background ========== -Ouch. We have been making our own ``Response`` and filling the response -body with HTML. You usually won't embed an HTML string directly in -Python, but instead, will use a templating language. +Ouch. We have been making our own ``Response`` and filling the response body +with HTML. You usually won't embed an HTML string directly in Python, but +instead will use a templating language. + +Pyramid doesn't mandate a particular database system, form library, and so on. +It encourages replaceability. This applies equally to templating, which is +fortunate: developers have strong views about template languages. As of +Pyramid 1.5a2, Pyramid doesn't even bundle a template language! -Pyramid doesn't mandate a particular database system, form library, -etc. It encourages replaceability. This applies equally to templating, -which is fortunate: developers have strong views about template -languages. As of Pyramid 1.5a2, Pyramid doesn't even bundle a template -language! +It does, however, have strong ties to Jinja2, Mako, and Chameleon. In this step +we see how to add ``pyramid_chameleon`` to your project, then change your views +to use templating. -It does, however, have strong ties to Jinja2, Mako, and Chameleon. In -this step we see how to add ``pyramid_chameleon`` to your project, -then change your views to use templating. Objectives ========== -- Enable the ``pyramid_chameleon`` Pyramid add-on +- Enable the ``pyramid_chameleon`` Pyramid add-on. + +- Generate HTML from template files. -- Generate HTML from template files +- Connect the templates as "renderers" for view code. -- Connect the templates as "renderers" for view code +- Change the view code to simply return data. -- Change the view code to simply return data Steps ===== -#. Let's begin by using the previous package as a starting point for a - new project: +#. Let's begin by using the previous package as a starting point for a new + project: .. code-block:: bash $ cd ..; cp -r views templating; cd templating -#. This step depends on ``pyramid_chameleon``, so add it as a dependency - in ``templating/setup.py``: +#. This step depends on ``pyramid_chameleon``, so add it as a dependency in + ``templating/setup.py``: .. literalinclude:: templating/setup.py :linenos: @@ -58,8 +60,8 @@ Steps $ $VENV/bin/pip install -e . -#. We need to connect ``pyramid_chameleon`` as a renderer by making a - call in the setup of ``templating/tutorial/__init__.py``: +#. We need to connect ``pyramid_chameleon`` as a renderer by making a call in + the setup of ``templating/tutorial/__init__.py``: .. literalinclude:: templating/tutorial/__init__.py :linenos: @@ -74,14 +76,13 @@ Steps .. literalinclude:: templating/tutorial/home.pt :language: html -#. For convenience, change ``templating/development.ini`` to reload - templates automatically with ``pyramid.reload_templates``: +#. For convenience, change ``templating/development.ini`` to reload templates + automatically with ``pyramid.reload_templates``: .. literalinclude:: templating/development.ini :language: ini -#. Our unit tests in ``templating/tutorial/tests.py`` can focus on - data: +#. Our unit tests in ``templating/tutorial/tests.py`` can focus on data: .. literalinclude:: templating/tutorial/tests.py :linenos: @@ -90,13 +91,9 @@ Steps .. code-block:: bash - - $ $VENV/bin/nosetests tutorial - . - ---------------------------------------------------------------------- - Ran 4 tests in 0.141s - - OK + $ $VENV/bin/py.test tutorial/tests.py -q + .... + 4 passed in 0.46 seconds #. Run your Pyramid application with: @@ -104,20 +101,19 @@ Steps $ $VENV/bin/pserve development.ini --reload -#. Open http://localhost:6543/ and http://localhost:6543/howdy - in your browser. +#. Open http://localhost:6543/ and http://localhost:6543/howdy in your browser. + Analysis ======== -Ahh, that looks better. We have a view that is focused on Python code. -Our ``@view_config`` decorator specifies a :term:`renderer` that points -to our template file. Our view then simply returns data which is then -supplied to our template. Note that we used the same template for both -views. +Ahh, that looks better. We have a view that is focused on Python code. Our +``@view_config`` decorator specifies a :term:`renderer` that points to our +template file. Our view then simply returns data which is then supplied to our +template. Note that we used the same template for both views. -Note the effect on testing. We can focus on having a data-oriented -contract with our view code. +Note the effect on testing. We can focus on having a data-oriented contract +with our view code. .. seealso:: :ref:`templates_chapter`, :ref:`debugging_templates`, and :ref:`available_template_system_bindings`. -- cgit v1.2.3 From 842a4fa23a8948a31023af0983c874ef45cb1041 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 05:09:14 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup view_classes.rst --- docs/quick_tutorial/templating.rst | 5 +-- docs/quick_tutorial/view_classes.rst | 69 +++++++++++++++++------------------- 2 files changed, 36 insertions(+), 38 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/templating.rst b/docs/quick_tutorial/templating.rst index dbcf76a0a..ec6de98f8 100644 --- a/docs/quick_tutorial/templating.rst +++ b/docs/quick_tutorial/templating.rst @@ -22,8 +22,9 @@ fortunate: developers have strong views about template languages. As of Pyramid 1.5a2, Pyramid doesn't even bundle a template language! It does, however, have strong ties to Jinja2, Mako, and Chameleon. In this step -we see how to add ``pyramid_chameleon`` to your project, then change your views -to use templating. +we see how to add `pyramid_chameleon +`_ to your project, then change +your views to use templating. Objectives diff --git a/docs/quick_tutorial/view_classes.rst b/docs/quick_tutorial/view_classes.rst index cc5337493..05d97a9b1 100644 --- a/docs/quick_tutorial/view_classes.rst +++ b/docs/quick_tutorial/view_classes.rst @@ -4,8 +4,9 @@ 09: Organizing Views With View Classes ====================================== -Change our view functions to be methods on a view class, -then move some declarations to the class level. +Change our view functions to be methods on a view class, then move some +declarations to the class level. + Background ========== @@ -15,27 +16,27 @@ views are related to one another. They may be different ways to look at or work on the same data, or be a REST API that handles multiple operations. Grouping these views together as a :ref:`view class ` makes sense: -- Group views +- Group views. + +- Centralize some repetitive defaults. -- Centralize some repetitive defaults +- Share some state and helpers. -- Share some state and helpers +In this step we just do the absolute minimum to convert the existing views to a +view class. In a later tutorial step, we'll examine view classes in depth. -In this step we just do the absolute minimum to convert the existing -views to a view class. In a later tutorial step we'll examine view -classes in depth. Objectives ========== -- Group related views into a view class +- Group related views into a view class. + +- Centralize configuration with class-level ``@view_defaults``. -- Centralize configuration with class-level ``@view_defaults`` Steps ===== - #. First we copy the results of the previous step: .. code-block:: bash @@ -43,15 +44,15 @@ Steps $ cd ..; cp -r templating view_classes; cd view_classes $ $VENV/bin/pip install -e . -#. Our ``view_classes/tutorial/views.py`` now has a view class with - our two views: +#. Our ``view_classes/tutorial/views.py`` now has a view class with our two + views: .. literalinclude:: view_classes/tutorial/views.py :linenos: -#. Our unit tests in ``view_classes/tutorial/tests.py`` don't run, - so let's modify them to import the view class and make an instance - before getting a response: +#. Our unit tests in ``view_classes/tutorial/tests.py`` don't run, so let's + modify them to import the view class, and make an instance before getting a + response: .. literalinclude:: view_classes/tutorial/tests.py :linenos: @@ -61,12 +62,9 @@ Steps .. code-block:: bash - $ $VENV/bin/nosetests tutorial - . - ---------------------------------------------------------------------- - Ran 4 tests in 0.141s - - OK + $ $VENV/bin/py.test tutorial/tests.py -q + .... + 4 passed in 0.34 seconds #. Run your Pyramid application with: @@ -74,24 +72,23 @@ Steps $ $VENV/bin/pserve development.ini --reload -#. Open http://localhost:6543/ and http://localhost:6543/howdy - in your browser. +#. Open http://localhost:6543/ and http://localhost:6543/howdy in your browser. + Analysis ======== To ease the transition to view classes, we didn't introduce any new -functionality. We simply changed the view functions to methods on a -view class, then updated the tests. - -In our ``TutorialViews`` view class you can see that our two view -classes are logically grouped together as methods on a common class. -Since the two views shared the same template, we could move that to a -``@view_defaults`` decorator at the class level. - -The tests needed to change. Obviously we needed to import the view -class. But you can also see the pattern in the tests of instantiating -the view class with the dummy request first, then calling the view -method being tested. +functionality. We simply changed the view functions to methods on a view class, +then updated the tests. + +In our ``TutorialViews`` view class, you can see that our two view classes are +logically grouped together as methods on a common class. Since the two views +shared the same template, we could move that to a ``@view_defaults`` decorator +at the class level. + +The tests needed to change. Obviously we needed to import the view class. But +you can also see the pattern in the tests of instantiating the view class with +the dummy request first, then calling the view method being tested. .. seealso:: :ref:`class_as_view` -- cgit v1.2.3 From ff68f90859f01658b397e3559dd1eae0feb508f3 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 05:17:04 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup request_response.rst --- docs/quick_tutorial/request_response.rst | 71 +++++++++++++++++--------------- 1 file changed, 37 insertions(+), 34 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/request_response.rst b/docs/quick_tutorial/request_response.rst index f42423de8..0ac9b4f6d 100644 --- a/docs/quick_tutorial/request_response.rst +++ b/docs/quick_tutorial/request_response.rst @@ -5,33 +5,32 @@ ======================================= Web applications handle incoming requests and return outgoing responses. -Pyramid makes working with requests and responses convenient and -reliable. +Pyramid makes working with requests and responses convenient and reliable. + Objectives ========== -- Learn the background on Pyramid's choices for requests and responses +- Learn the background on Pyramid's choices for requests and responses. + +- Grab data out of the request. -- Grab data out of the request +- Change information in the response headers. -- Change information in the response headers Background ========== -Developing for the web means processing web requests. As this is a -critical part of a web application, web developers need a robust, -mature set of software for web requests and returning web -responses. +Developing for the web means processing web requests. As this is a critical +part of a web application, web developers need a robust, mature set of software +for web requests and returning web responses. + +Pyramid has always fit nicely into the existing world of Python web development +(virtual environments, packaging, scaffolding, first to embrace Python 3, and +so on). Pyramid turned to the well-regarded :term:`WebOb` Python library for +request and response handling. In our example above, Pyramid hands +``hello_world`` a ``request`` that is :ref:`based on WebOb `. -Pyramid has always fit nicely into the existing world of Python web -development (virtual environments, packaging, scaffolding, -first to embrace Python 3, etc.) For request handling, Pyramid turned -to the well-regarded :term:`WebOb` Python library for request and -response handling. In our example -above, Pyramid hands ``hello_world`` a ``request`` that is -:ref:`based on WebOb `. Steps ===== @@ -62,7 +61,9 @@ Steps .. code-block:: bash - $ $VENV/bin/nosetests tutorial + $ $VENV/bin/py.test tutorial/tests.py -q + ..... + 5 passed in 0.30 seconds #. Run your Pyramid application with: @@ -70,37 +71,39 @@ Steps $ $VENV/bin/pserve development.ini --reload -#. Open http://localhost:6543/ in your browser. You will be - redirected to http://localhost:6543/plain +#. Open http://localhost:6543/ in your browser. You will be redirected to + http://localhost:6543/plain. #. Open http://localhost:6543/plain?name=alice in your browser. + Analysis ======== -In this view class we have two routes and two views, with the first -leading to the second by an HTTP redirect. Pyramid can -:ref:`generate redirects ` by returning a -special object from a view or raising a special exception. +In this view class, we have two routes and two views, with the first leading to +the second by an HTTP redirect. Pyramid can :ref:`generate redirects +` by returning a special object from a view or raising a special +exception. + +In this Pyramid view, we get the URL being visited from ``request.url``. Also, +if you visited http://localhost:6543/plain?name=alice, the name is included in +the body of the response: -In this Pyramid view, we get the URL being visited from ``request.url``. -Also, if you visited http://localhost:6543/plain?name=alice, -the name is included in the body of the response:: +.. code-block:: text URL http://localhost:6543/plain?name=alice with name: alice -Finally, we set the response's content type and body, then return the -Response. +Finally, we set the response's content type and body, then return the response. + +We updated the unit and functional tests to prove that our code does the +redirection, but also handles sending and not sending ``/plain?name``. -We updated the unit and functional tests to prove that our code -does the redirection, but also handles sending and not sending -``/plain?name``. -Extra Credit +Extra credit ============ -#. Could we also ``raise HTTPFound(location='/plain')`` instead of - returning it? If so, what's the difference? +#. Could we also ``raise HTTPFound(location='/plain')`` instead of returning + it? If so, what's the difference? .. seealso:: :ref:`webob_chapter`, :ref:`generate redirects ` -- cgit v1.2.3 From 72c2196bf0c2bc867e7c13ea93bb6f6ddacd83cb Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 05:22:37 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup routing.rst --- docs/quick_tutorial/routing.rst | 53 ++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 25 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/routing.rst b/docs/quick_tutorial/routing.rst index 7b6d0904d..27c8c2c22 100644 --- a/docs/quick_tutorial/routing.rst +++ b/docs/quick_tutorial/routing.rst @@ -4,22 +4,23 @@ 11: Dispatching URLs To Views With Routing ========================================== -Routing matches incoming URL patterns to view code. Pyramid's routing -has a number of useful features. +Routing matches incoming URL patterns to view code. Pyramid's routing has a +number of useful features. + Background ========== -Writing web applications usually means sophisticated URL design. We -just saw some Pyramid machinery for requests and views. Let's look at -features that help in routing. +Writing web applications usually means sophisticated URL design. We just saw +some Pyramid machinery for requests and views. Let's look at features that help +in routing. Previously we saw the basics of routing URLs to views in Pyramid. -- Your project's "setup" code registers a route name to be used when - matching part of the URL +- Your project's "setup" code registers a route name to be used when matching + part of the URL -- Elsewhere, a view is configured to be called for that route name +- Elsewhere a view is configured to be called for that route name. .. note:: @@ -33,12 +34,14 @@ Previously we saw the basics of routing URLs to views in Pyramid. `_ if you're interested in doing so. + Objectives ========== -- Define a route that extracts part of the URL into a Python dictionary +- Define a route that extracts part of the URL into a Python dictionary. + +- Use that dictionary data in a view. -- Use that dictionary data in a view Steps ===== @@ -76,7 +79,9 @@ Steps .. code-block:: bash - $ $VENV/bin/nosetests tutorial + $ $VENV/bin/$VENV/bin/py.test tutorial/tests.py -q + .. + 2 passed in 0.39 seconds #. Run your Pyramid application with: @@ -86,6 +91,7 @@ Steps #. Open http://localhost:6543/howdy/amy/smith in your browser. + Analysis ======== @@ -95,27 +101,24 @@ In ``__init__.py`` we see an important change in our route declaration: config.add_route('hello', '/howdy/{first}/{last}') -With this we tell the :term:`configurator` that our URL has -a "replacement pattern". With this, URLs such as ``/howdy/amy/smith`` -will assign ``amy`` to ``first`` and ``smith`` to ``last``. We can then -use this data in our view: +With this we tell the :term:`configurator` that our URL has a "replacement +pattern". With this, URLs such as ``/howdy/amy/smith`` will assign ``amy`` to +``first`` and ``smith`` to ``last``. We can then use this data in our view: .. code-block:: python self.request.matchdict['first'] self.request.matchdict['last'] -``request.matchdict`` contains values from the URL that match the -"replacement patterns" (the curly braces) in the route declaration. -This information can then be used anywhere in Pyramid that has access -to the request. +``request.matchdict`` contains values from the URL that match the "replacement +patterns" (the curly braces) in the route declaration. This information can +then be used anywhere in Pyramid that has access to the request. -Extra Credit +Extra credit ============ -#. What happens if you to go the URL - http://localhost:6543/howdy? Is this the result that you - expected? +#. What happens if you to go the URL http://localhost:6543/howdy? Is this the + result that you expected? -.. seealso:: `Weird Stuff You Can Do With URL - Dispatch `_ +.. seealso:: `Weird Stuff You Can Do With URL Dispatch + `_ -- cgit v1.2.3 From d5e6762315458de334896096923abcd3d51a31f5 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 06:43:35 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup jinja2.rst - add pyramid_jinja2 to requirements.rst --- docs/quick_tutorial/jinja2.rst | 55 +++++++++++++++++++----------------- docs/quick_tutorial/requirements.rst | 6 ++-- 2 files changed, 32 insertions(+), 29 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/jinja2.rst b/docs/quick_tutorial/jinja2.rst index 6b9d5feba..2fc68827b 100644 --- a/docs/quick_tutorial/jinja2.rst +++ b/docs/quick_tutorial/jinja2.rst @@ -4,24 +4,26 @@ 12: Templating With ``jinja2`` ============================== -We just said Pyramid doesn't prefer one templating language over -another. Time to prove it. Jinja2 is a popular templating system, -used in Flask and modeled after Django's templates. Let's add -``pyramid_jinja2``, a Pyramid :term:`add-on` which enables Jinja2 as a -:term:`renderer` in our Pyramid applications. +We just said Pyramid doesn't prefer one templating language over another. Time +to prove it. Jinja2 is a popular templating system, used in Flask and modeled +after Django's templates. Let's add ``pyramid_jinja2``, a Pyramid +:term:`add-on` which enables Jinja2 as a :term:`renderer` in our Pyramid +applications. + Objectives ========== -- Show Pyramid's support for different templating systems +- Show Pyramid's support for different templating systems. + +- Learn about installing Pyramid add-ons. -- Learn about installing Pyramid add-ons Steps ===== -#. In this step let's start by copying the ``view_class`` step's - directory, and then installing the ``pyramid_jinja2`` add-on. +#. In this step let's start by copying the ``view_class`` step's directory, + and then installing the ``pyramid_jinja2`` add-on. .. code-block:: bash @@ -29,8 +31,7 @@ Steps $ $VENV/bin/pip install -e . $ $VENV/bin/pip install pyramid_jinja2 -#. We need to include ``pyramid_jinja2`` in - ``jinja2/tutorial/__init__.py``: +#. We need to include ``pyramid_jinja2`` in ``jinja2/tutorial/__init__.py``: .. literalinclude:: jinja2/tutorial/__init__.py :linenos: @@ -49,7 +50,9 @@ Steps .. code-block:: bash - $ $VENV/bin/nosetests tutorial + $ $VENV/bin/py.test tutorial/tests.py -q + .... + 4 passed in 0.40 seconds #. Run your Pyramid application with: @@ -59,30 +62,30 @@ Steps #. Open http://localhost:6543/ in your browser. + Analysis ======== -Getting a Pyramid add-on into Pyramid is simple. First you use normal -Python package installation tools to install the add-on package into -your Python. You then tell Pyramid's configurator to run the setup code +Getting a Pyramid add-on into Pyramid is simple. First you use normal Python +package installation tools to install the add-on package into your Python +virtual environment. You then tell Pyramid's configurator to run the setup code in the add-on. In this case the setup code told Pyramid to make a new "renderer" available that looked for ``.jinja2`` file extensions. -Our view code stayed largely the same. We simply changed the file -extension on the renderer. For the template, the syntax for Chameleon -and Jinja2's basic variable insertion is very similar. +Our view code stayed largely the same. We simply changed the file extension on +the renderer. For the template, the syntax for Chameleon and Jinja2's basic +variable insertion is very similar. + -Extra Credit +Extra credit ============ -#. Our project now depends on ``pyramid_jinja2``. We installed that - dependency manually. What is another way we could have made the - association? +#. Our project now depends on ``pyramid_jinja2``. We installed that dependency + manually. What is another way we could have made the association? #. We used ``config.include`` which is an imperative configuration to get the - :term:`Configurator` to load ``pyramid_jinja2``'s configuration. - What is another way could include it into the config? + :term:`Configurator` to load ``pyramid_jinja2``'s configuration. What is + another way could include it into the config? -.. seealso:: `Jinja2 homepage `_, - and +.. seealso:: `Jinja2 homepage `_, and :ref:`pyramid_jinja2 Overview ` diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index f4c1e70ac..1f2b4da97 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -205,10 +205,10 @@ tutorial. # Mac and Linux $ $VENV/bin/pip install webtest pytest pytest-cov deform sqlalchemy \ - pyramid_chameleon pyramid_debugtoolbar waitress pyramid_tm \ - zope.sqlalchemy + pyramid_chameleon pyramid_debugtoolbar pyramid_jinja2 waitress \ + pyramid_tm zope.sqlalchemy .. code-block:: doscon # Windows - c:\> %VENV%\Scripts\pip install webtest deform sqlalchemy pyramid_chameleon pyramid_debugtoolbar waitress pyramid_tm zope.sqlalchemy + c:\> %VENV%\Scripts\pip install webtest deform sqlalchemy pyramid_chameleon pyramid_debugtoolbar pyramid_jinja2 waitress pyramid_tm zope.sqlalchemy -- cgit v1.2.3 From 41279dddbf5343488542f2629194c68dd3c2142d Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 06:57:21 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup static_assets.rst --- docs/quick_tutorial/static_assets.rst | 45 +++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 21 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/static_assets.rst b/docs/quick_tutorial/static_assets.rst index 61c5fbd50..65b34f8f9 100644 --- a/docs/quick_tutorial/static_assets.rst +++ b/docs/quick_tutorial/static_assets.rst @@ -4,16 +4,17 @@ 13: CSS/JS/Images Files With Static Assets ========================================== -Of course the Web is more than just markup. You need static assets: -CSS, JS, and images. Let's point our web app at a directory where -Pyramid will serve some static assets. +Of course the Web is more than just markup. You need static assets: CSS, JS, +and images. Let's point our web app at a directory where Pyramid will serve +some static assets. Objectives ========== -- Publish a directory of static assets at a URL +- Publish a directory of static assets at a URL. + +- Use Pyramid to help generate URLs to files in that directory. -- Use Pyramid to help generate URLs to files in that directory Steps ===== @@ -37,8 +38,7 @@ Steps .. literalinclude:: static_assets/tutorial/home.pt :language: html -#. Add a CSS file at - ``static_assets/tutorial/static/app.css``: +#. Add a CSS file at ``static_assets/tutorial/static/app.css``: .. literalinclude:: static_assets/tutorial/static/app.css :language: css @@ -47,7 +47,9 @@ Steps .. code-block:: bash - $ $VENV/bin/nosetests tutorial + $ $VENV/bin/$VENV/bin/py.test tutorial/tests.py -q + .... + 4 passed in 0.50 seconds #. Run your Pyramid application with: @@ -57,30 +59,31 @@ Steps #. Open http://localhost:6543/ in your browser and note the new font. + Analysis ======== We changed our WSGI application to map requests under -http://localhost:6543/static/ to files and directories inside a -``static`` directory inside our ``tutorial`` package. This directory -contained ``app.css``. +http://localhost:6543/static/ to files and directories inside a ``static`` +directory inside our ``tutorial`` package. This directory contained +``app.css``. -We linked to the CSS in our template. We could have hard-coded this -link to ``/static/app.css``. But what if the site is later moved under -``/somesite/static/``? Or perhaps the web developer changes the -arrangement on disk? Pyramid gives a helper that provides flexibility -on URL generation: +We linked to the CSS in our template. We could have hard-coded this link to +``/static/app.css``. But what if the site is later moved under +``/somesite/static/``? Or perhaps the web developer changes the arrangement on +disk? Pyramid gives a helper that provides flexibility on URL generation: .. code-block:: html ${request.static_url('tutorial:static/app.css')} -This matches the ``path='tutorial:static'`` in our -``config.add_static_view`` registration. By using ``request.static_url`` -to generate the full URL to the static assets, you both ensure you stay -in sync with the configuration and gain refactoring flexibility later. +This matches the ``path='tutorial:static'`` in our ``config.add_static_view`` +registration. By using ``request.static_url`` to generate the full URL to the +static assets, you both ensure you stay in sync with the configuration and gain +refactoring flexibility later. + -Extra Credit +Extra credit ============ #. There is also a ``request.static_path`` API. How does this differ from -- cgit v1.2.3 From 353268e208451fc302cfd19454cea650b7498af3 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 07:06:17 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup json.rst --- docs/quick_tutorial/json.rst | 87 ++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 43 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/json.rst b/docs/quick_tutorial/json.rst index 49421829b..ff153d2b5 100644 --- a/docs/quick_tutorial/json.rst +++ b/docs/quick_tutorial/json.rst @@ -1,27 +1,28 @@ .. _qtut_json: ======================================== -14: Ajax Development With JSON Renderers +14: AJAX Development With JSON Renderers ======================================== -Modern web apps are more than rendered HTML. Dynamic pages now use -JavaScript to update the UI in the browser by requesting server data as -JSON. Pyramid supports this with a *JSON renderer*. +Modern web apps are more than rendered HTML. Dynamic pages now use JavaScript +to update the UI in the browser by requesting server data as JSON. Pyramid +supports this with a *JSON renderer*. + Background ========== -As we saw in :doc:`templating`, view declarations can specify a -renderer. Output from the view is then run through the renderer, -which generates and returns the ``Response``. We first used a Chameleon -renderer, then a Jinja2 renderer. +As we saw in :doc:`templating`, view declarations can specify a renderer. +Output from the view is then run through the renderer, which generates and +returns the response. We first used a Chameleon renderer, then a Jinja2 +renderer. + +Renderers aren't limited, however, to templates that generate HTML. Pyramid +supplies a JSON renderer which takes Python data, serializes it to JSON, and +performs some other functions such as setting the content type. In fact you can +write your own renderer (or extend a built-in renderer) containing custom logic +for your unique application. -Renderers aren't limited, however, to templates that generate HTML. -Pyramid supplies a JSON renderer which takes Python data, -serializes it to JSON, and performs some other functions such as -setting the content type. In fact, you can write your own renderer (or -extend a built-in renderer) containing custom logic for your unique -application. Steps ===== @@ -33,20 +34,18 @@ Steps $ cd ..; cp -r view_classes json; cd json $ $VENV/bin/pip install -e . -#. We add a new route for ``hello_json`` in - ``json/tutorial/__init__.py``: +#. We add a new route for ``hello_json`` in ``json/tutorial/__init__.py``: .. literalinclude:: json/tutorial/__init__.py :linenos: -#. Rather than implement a new view, we will "stack" another decorator - on the ``hello`` view in ``views.py``: +#. Rather than implement a new view, we will "stack" another decorator on the + ``hello`` view in ``views.py``: .. literalinclude:: json/tutorial/views.py :linenos: -#. We need a new functional test at the end of - ``json/tutorial/tests.py``: +#. We need a new functional test at the end of ``json/tutorial/tests.py``: .. literalinclude:: json/tutorial/tests.py :linenos: @@ -55,7 +54,10 @@ Steps .. code-block:: bash - $ $VENV/bin/nosetests tutorial + $ $VENV/bin/py.test tutorial/tests.py -q + ..... + 5 passed in 0.47 seconds + #. Run your Pyramid application with: @@ -63,40 +65,39 @@ Steps $ $VENV/bin/pserve development.ini --reload -#. Open http://localhost:6543/howdy.json in your browser and you - will see the resulting JSON response. +#. Open http://localhost:6543/howdy.json in your browser and you will see the + resulting JSON response. + Analysis ======== -Earlier we changed our view functions and methods to return Python -data. This change to a data-oriented view layer made test writing -easier, decoupling the templating from the view logic. +Earlier we changed our view functions and methods to return Python data. This +change to a data-oriented view layer made test writing easier, decoupling the +templating from the view logic. -Since Pyramid has a JSON renderer as well as the templating renderers, -it is an easy step to return JSON. In this case we kept the exact same -view and arranged to return a JSON encoding of the view data. We did -this by: +Since Pyramid has a JSON renderer as well as the templating renderers, it is an +easy step to return JSON. In this case we kept the exact same view and arranged +to return a JSON encoding of the view data. We did this by: -- Adding a route to map ``/howdy.json`` to a route name +- Adding a route to map ``/howdy.json`` to a route name. -- Providing a ``@view_config`` that associated that route name with an - existing view +- Providing a ``@view_config`` that associated that route name with an existing + view. -- *overriding* the view defaults in the view config that mentions the - ``hello_json`` route, so that when the route is matched, we use the JSON +- *Overriding* the view defaults in the view config that mentions the + ``hello_json`` route, so that when the route is matched, we use the JSON renderer rather than the ``home.pt`` template renderer that would otherwise be used. -In fact, for pure Ajax-style web applications, we could re-use the existing -route by using Pyramid's view predicates to match on the -``Accepts:`` header sent by modern Ajax implementation. +In fact, for pure AJAX-style web applications, we could re-use the existing +route by using Pyramid's view predicates to match on the ``Accepts:`` header +sent by modern AJAX implementations. -Pyramid's JSON renderer uses the base Python JSON encoder, -thus inheriting its strengths and weaknesses. For example, -Python can't natively JSON encode DateTime objects. There are a number -of solutions for this in Pyramid, including extending the JSON renderer -with a custom renderer. +Pyramid's JSON renderer uses the base Python JSON encoder, thus inheriting its +strengths and weaknesses. For example, Python can't natively JSON encode +DateTime objects. There are a number of solutions for this in Pyramid, +including extending the JSON renderer with a custom renderer. .. seealso:: :ref:`views_which_use_a_renderer`, :ref:`json_renderer`, and -- cgit v1.2.3 From 0fa18e37b5a81a68d70807c1abd90a439dbdb4b7 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 12:19:25 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup more_view_classes.rst --- docs/quick_tutorial/more_view_classes.rst | 131 +++++++++++++++--------------- 1 file changed, 65 insertions(+), 66 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/more_view_classes.rst b/docs/quick_tutorial/more_view_classes.rst index fb97cceb2..30234ea2e 100644 --- a/docs/quick_tutorial/more_view_classes.rst +++ b/docs/quick_tutorial/more_view_classes.rst @@ -6,48 +6,49 @@ Group views into a class, sharing configuration, state, and logic. + Background ========== -As part of its mission to help build more ambitious web applications, -Pyramid provides many more features for views and view classes. +As part of its mission to help build more ambitious web applications, Pyramid +provides many more features for views and view classes. + +The Pyramid documentation discusses views as a Python "callable". This callable +can be a function, an object with a ``__call__``, or a Python class. In this +last case, methods on the class can be decorated with ``@view_config`` to +register the class methods with the :term:`configurator` as a view. -The Pyramid documentation discusses views as a Python "callable". This -callable can be a function, an object with an ``__call__``, -or a Python class. In this last case, methods on the class can be -decorated with ``@view_config`` to register the class methods with the -:term:`configurator` as a view. +At first, our views were simple, free-standing functions. Many times your views +are related: different ways to look at or work on the same data, or a REST API +that handles multiple operations. Grouping these together as a :ref:`view class +` makes sense: -At first, our views were simple, free-standing functions. Many times -your views are related: different ways to look at or work on the same -data or a REST API that handles multiple operations. Grouping these -together as a :ref:`view class ` makes sense: +- Group views. -- Group views +- Centralize some repetitive defaults. -- Centralize some repetitive defaults +- Share some state and helpers. -- Share some state and helpers +Pyramid views have :ref:`view predicates ` that +determine which view is matched to a request, based on factors such as the +request method, the form parameters, and so on. These predicates provide many +axes of flexibility. -Pyramid views have :ref:`view predicates ` -that determine which view is matched to a request, based on factors -such as the request method, the form parameters, etc. These predicates -provide many axes of flexibility. +The following shows a simple example with four operations: view a home page +which leads to a form, save a change, and press the delete button. -The following shows a simple example with four operations: -view a home page which leads to a form, save a change, -and press the delete button. Objectives ========== -- Group related views into a view class +- Group related views into a view class. -- Centralize configuration with class-level ``@view_defaults`` +- Centralize configuration with class-level ``@view_defaults``. -- Dispatch one route/URL to multiple views based on request data +- Dispatch one route/URL to multiple views based on request data. + +- Share states and logic between views and templates via the view class. -- Share states and logic between views and templates via the view class Steps ===== @@ -71,8 +72,7 @@ Steps .. literalinclude:: more_view_classes/tutorial/views.py :linenos: -#. Our primary view needs a template at - ``more_view_classes/tutorial/home.pt``: +#. Our primary view needs a template at ``more_view_classes/tutorial/home.pt``: .. literalinclude:: more_view_classes/tutorial/home.pt :language: html @@ -105,12 +105,9 @@ Steps .. code-block:: bash - $ $VENV/bin/nosetests tutorial - . - ---------------------------------------------------------------------- - Ran 2 tests in 0.248s - - OK + $ $VENV/bin/py.test tutorial/tests.py -q + .. + 2 passed in 0.40 seconds #. Run your Pyramid application with: @@ -118,29 +115,27 @@ Steps $ $VENV/bin/pserve development.ini --reload -#. Open http://localhost:6543/howdy/jane/doe in your browser. Click - the ``Save`` and ``Delete`` buttons and watch the output in the - console window. +#. Open http://localhost:6543/howdy/jane/doe in your browser. Click the + ``Save`` and ``Delete`` buttons, and watch the output in the console window. + Analysis ======== -As you can see, the four views are logically grouped together. -Specifically: +As you can see, the four views are logically grouped together. Specifically: -- We have a ``home`` view available at http://localhost:6543/ with - a clickable link to the ``hello`` view. +- We have a ``home`` view available at http://localhost:6543/ with a clickable + link to the ``hello`` view. -- The second view is returned when you go to ``/howdy/jane/doe``. This - URL is +- The second view is returned when you go to ``/howdy/jane/doe``. This URL is mapped to the ``hello`` route that we centrally set using the optional ``@view_defaults``. -- The third view is returned when the form is submitted with a ``POST`` - method. This rule is specified in the ``@view_config`` for that view. +- The third view is returned when the form is submitted with a ``POST`` method. + This rule is specified in the ``@view_config`` for that view. -- The fourth view is returned when clicking on a button such - as ````. +- The fourth view is returned when clicking on a button such as ````. In this step we show, using the following information as criteria, how to decide which view to use: @@ -149,49 +144,53 @@ decide which view to use: - Parameter information in the request (submitted form field names) -We also centralize part of the view configuration to the class level -with ``@view_defaults``, then in one view, override that default just -for that one view. Finally, we put this commonality between views to -work in the view class by sharing: +We also centralize part of the view configuration to the class level with +``@view_defaults``, then in one view, override that default just for that one +view. Finally, we put this commonality between views to work in the view class +by sharing: - State assigned in ``TutorialViews.__init__`` - A computed value -These are then available both in the view methods but also in the -templates (e.g. ``${view.view_name}`` and ``${view.full_name}``. +These are then available both in the view methods and in the templates (e.g., +``${view.view_name}`` and ``${view.full_name}``). + +As a note, we made a switch in our templates on how we generate URLs. We +previously hardcoded the URLs, such as: -As a note, we made a switch in our templates on how we generate URLs. -We previously hardcode the URLs, such as:: +.. code-block:: html Howdy -In ``home.pt`` we switched to:: +In ``home.pt`` we switched to: + +.. code-block:: xml form -Pyramid has rich facilities to help generate URLs in a flexible, -non-error-prone fashion. +Pyramid has rich facilities to help generate URLs in a flexible, non-error +prone fashion. -Extra Credit +Extra credit ============ #. Why could our template do ``${view.full_name}`` and not have to do ``${view.full_name()}``? -#. The ``edit`` and ``delete`` views are both submitted to with - ``POST``. Why does the ``edit`` view configuration not catch the - ``POST`` used by ``delete``? +#. The ``edit`` and ``delete`` views are both receive ``POST`` requests. Why + does the ``edit`` view configuration not catch the ``POST`` used by + ``delete``? -#. We used Python ``@property`` on ``full_name``. If we reference this - many times in a template or view code, it would re-compute this - every time. Does Pyramid provide something that will cache the initial - computation on a property? +#. We used Python ``@property`` on ``full_name``. If we reference this many + times in a template or view code, it would re-compute this every time. Does + Pyramid provide something that will cache the initial computation on a + property? #. Can you associate more than one route with the same view? -#. There is also a ``request.route_path`` API. How does this differ from +#. There is also a ``request.route_path`` API. How does this differ from ``request.route_url``? .. seealso:: :ref:`class_as_view`, `Weird Stuff You Can Do With -- cgit v1.2.3 From e672bd40b861d763e664992ac0ef6b5b6f84c740 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 12:27:07 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup logging.rst --- docs/quick_tutorial/logging.rst | 52 +++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 23 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/logging.rst b/docs/quick_tutorial/logging.rst index 556a09bf0..cbbf7860e 100644 --- a/docs/quick_tutorial/logging.rst +++ b/docs/quick_tutorial/logging.rst @@ -4,28 +4,30 @@ 16: Collecting Application Info With Logging ============================================ -Capture debugging and error output from your web applications using -standard Python logging. +Capture debugging and error output from your web applications using standard +Python logging. + Background ========== -It's important to know what is going on inside our web application. -In development we might need to collect some output. In production, -we might need to detect problems when other people use the site. We -need *logging*. +It's important to know what is going on inside our web application. In +development we might need to collect some output. In production, we might need +to detect problems when other people use the site. We need *logging*. + +Fortunately Pyramid uses the normal Python approach to logging. The scaffold +generated in your ``development.ini`` has a number of lines that configure the +logging for you to some reasonable defaults. You then see messages sent by +Pyramid, for example, when a new request comes in. -Fortunately Pyramid uses the normal Python approach to logging. The -scaffold generated in your ``development.ini`` has a number of lines that -configure the logging for you to some reasonable defaults. You then see -messages sent by Pyramid, for example, when a new request comes in. Objectives ========== -- Inspect the configuration setup used for logging +- Inspect the configuration setup used for logging. + +- Add logging statements to your view code. -- Add logging statements to your view code Steps ===== @@ -42,8 +44,8 @@ Steps .. literalinclude:: logging/tutorial/views.py :linenos: -#. Finally let's edit ``development.ini`` configuration file - to enable logging for our Pyramid application: +#. Finally let's edit ``development.ini`` configuration file to enable logging + for our Pyramid application: .. literalinclude:: logging/development.ini :language: ini @@ -52,7 +54,9 @@ Steps .. code-block:: bash - $ $VENV/bin/nosetests tutorial + $ $VENV/bin/py.test tutorial/tests.py -q + .... + 4 passed in 0.41 seconds #. Run your Pyramid application with: @@ -60,19 +64,21 @@ Steps $ $VENV/bin/pserve development.ini --reload -#. Open http://localhost:6543/ and http://localhost:6543/howdy - in your browser. Note, both in the console and in the debug - toolbar, the message that you logged. +#. Open http://localhost:6543/ and http://localhost:6543/howdy in your browser. + Note, both in the console and in the debug toolbar, the message that you + logged. + Analysis ======== -In our configuration file ``development.ini``, our ``tutorial`` Python -package is setup as a logger and configured to log messages at a -``DEBUG`` or higher level. When you visit http://localhost:6543 your -console will now show:: +In our configuration file ``development.ini``, our ``tutorial`` Python package +is set up as a logger and configured to log messages at a ``DEBUG`` or higher +level. When you visit http://localhost:6543, your console will now show: + +.. code-block:: text - 2013-08-09 10:42:42,968 DEBUG [tutorial.views][MainThread] In home view + 2013-08-09 10:42:42,968 DEBUG [tutorial.views][MainThread] In home view Also, if you have configured your Pyramid application to use the ``pyramid_debugtoolbar``, logging statements appear in one of its menus. -- cgit v1.2.3 From 3b064fbbd2b9d8c348337f0742899c948862abf6 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 12:33:44 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup sessions.rst --- docs/quick_tutorial/sessions.rst | 70 +++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 33 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/sessions.rst b/docs/quick_tutorial/sessions.rst index 06176f2b6..df4887a4b 100644 --- a/docs/quick_tutorial/sessions.rst +++ b/docs/quick_tutorial/sessions.rst @@ -6,25 +6,28 @@ Store and retrieve non-permanent data in Pyramid sessions. + Background ========== -When people use your web application, they frequently perform a task -that requires semi-permanent data to be saved. For example, a shopping -cart. This is called a :term:`session`. +When people use your web application, they frequently perform a task that +requires semi-permanent data to be saved. For example, a shopping cart. This is +called a :term:`session`. Pyramid has basic built-in support for sessions. Third party packages such as -``pyramid_redis_sessions`` provide richer session support. Or you can create -your own custom sessioning engine. Let's take a look at the -:doc:`built-in sessioning support <../narr/sessions>`. +`pyramid_redis_sessions +`_ provide richer +session support. Or you can create your own custom sessioning engine. Let's +take a look at the :doc:`built-in sessioning support <../narr/sessions>`. + Objectives ========== -- Make a session factory using a built-in, simple Pyramid sessioning - system +- Make a session factory using a built-in, simple Pyramid sessioning system. + +- Change our code to use a session. -- Change our code to use a session Steps ===== @@ -36,14 +39,13 @@ Steps $ cd ..; cp -r view_classes sessions; cd sessions $ $VENV/bin/pip install -e . -#. Our ``sessions/tutorial/__init__.py`` needs a choice of session - factory to get registered with the :term:`configurator`: +#. Our ``sessions/tutorial/__init__.py`` needs a choice of session factory to + get registered with the :term:`configurator`: .. literalinclude:: sessions/tutorial/__init__.py :linenos: -#. Our views in ``sessions/tutorial/views.py`` can now use - ``request.session``: +#. Our views in ``sessions/tutorial/views.py`` can now use ``request.session``: .. literalinclude:: sessions/tutorial/views.py :linenos: @@ -58,7 +60,9 @@ Steps .. code-block:: bash - $ $VENV/bin/nosetests tutorial + $ $VENV/bin/py.test tutorial/tests.py -q + .... + 4 passed in 0.42 seconds #. Run your Pyramid application with: @@ -66,33 +70,33 @@ Steps $ $VENV/bin/pserve development.ini --reload -#. Open http://localhost:6543/ and http://localhost:6543/howdy - in your browser. As you reload and switch between those URLs, note - that the counter increases and is *not* specific to the URL. +#. Open http://localhost:6543/ and http://localhost:6543/howdy in your browser. + As you reload and switch between those URLs, note that the counter increases + and is *not* specific to the URL. + +#. Restart the application and revisit the page. Note that counter still + increases from where it left off. -#. Restart the application and revisit the page. Note that counter - still increases from where it left off. Analysis ======== -Pyramid's :term:`request` object now has a ``session`` attribute -that we can use in our view code. It acts like a dictionary. +Pyramid's :term:`request` object now has a ``session`` attribute that we can +use in our view code. It acts like a dictionary. -Since all the views are using the same counter, we made the counter a -Python property at the view class level. With this, each reload will -increase the counter displayed in our template. +Since all the views are using the same counter, we made the counter a Python +property at the view class level. With this, each reload will increase the +counter displayed in our template. -In web development, "flash messages" are notes for the user that need -to appear on a screen after a future web request. For example, -when you add an item using a form ``POST``, the site usually issues a -second HTTP Redirect web request to view the new item. You might want a -message to appear after that second web request saying "Your item was -added." You can't just return it in the web response for the POST, -as it will be tossed out during the second web request. +In web development, "flash messages" are notes for the user that need to appear +on a screen after a future web request. For example, when you add an item using +a form ``POST``, the site usually issues a second HTTP Redirect web request to +view the new item. You might want a message to appear after that second web +request saying "Your item was added." You can't just return it in the web +response for the POST, as it will be tossed out during the second web request. -Flash messages are a technique where messages can be stored between -requests, using sessions, then removed when they finally get displayed. +Flash messages are a technique where messages can be stored between requests, +using sessions, then removed when they finally get displayed. .. seealso:: :ref:`sessions_chapter`, -- cgit v1.2.3 From 59c8fc7919730c3f3100ad84250a788e2d0a3bb0 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 12:55:28 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup forms.rst --- docs/quick_tutorial/forms.rst | 127 ++++++++++++++++++++++-------------------- 1 file changed, 66 insertions(+), 61 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/forms.rst b/docs/quick_tutorial/forms.rst index 023e7127f..6b29833bd 100644 --- a/docs/quick_tutorial/forms.rst +++ b/docs/quick_tutorial/forms.rst @@ -6,30 +6,30 @@ Schema-driven, autogenerated forms with validation. + Background ========== -Modern web applications deal extensively with forms. Developers, -though, have a wide range of philosophies about how frameworks should -help them with their forms. As such, Pyramid doesn't directly bundle -one particular form library. Instead there are a variety of form -libraries that are easy to use in Pyramid. +Modern web applications deal extensively with forms. Developers, though, have a +wide range of philosophies about how frameworks should help them with their +forms. As such, Pyramid doesn't directly bundle one particular form library. +Instead there are a variety of form libraries that are easy to use in Pyramid. -:ref:`Deform ` -is one such library. In this step, we introduce Deform for our -forms and validation. This also gives us :ref:`Colander ` +:ref:`Deform ` is one such library. In this step, we introduce +Deform for our forms. This also gives us :ref:`Colander ` for schemas and validation. -Deform is getting a facelift, with styling from Twitter Bootstrap and -advanced widgets from popular JavaScript projects. The work began in -``deform_bootstrap`` and is being merged into an update to Deform. +Deform uses styling from Twitter Bootstrap and advanced widgets from popular +JavaScript projects. + Objectives ========== -- Make a schema using Colander, the companion to Deform +- Make a schema using Colander, the companion to Deform. + +- Create a form with Deform and change our views to handle validation. -- Create a form with Deform and change our views to handle validation Steps ===== @@ -40,8 +40,8 @@ Steps $ cd ..; cp -r view_classes forms; cd forms -#. Let's edit ``forms/setup.py`` to declare a dependency on Deform - (which then pulls in Colander as a dependency: +#. Let's edit ``forms/setup.py`` to declare a dependency on Deform (which then + pulls in Colander as a dependency: .. literalinclude:: forms/setup.py :linenos: @@ -52,21 +52,19 @@ Steps $ $VENV/bin/pip install -e . -#. Register a static view in ``forms/tutorial/__init__.py`` for - Deform's CSS/JS etc. as well as our demo wikipage scenario's - views: +#. Register a static view in ``forms/tutorial/__init__.py`` for Deform's CSS, + JavaScript, etc., as well as our demo wiki page's views: .. literalinclude:: forms/tutorial/__init__.py :linenos: -#. Implement the new views, as well as the form schemas and some - dummy data, in ``forms/tutorial/views.py``: +#. Implement the new views, as well as the form schemas and some dummy data, in + ``forms/tutorial/views.py``: .. literalinclude:: forms/tutorial/views.py :linenos: -#. A template for the top of the "wiki" in - ``forms/tutorial/wiki_view.pt``: +#. A template for the top of the "wiki" in ``forms/tutorial/wiki_view.pt``: .. literalinclude:: forms/tutorial/wiki_view.pt :language: html @@ -79,13 +77,21 @@ Steps :language: html :linenos: -#. Finally, a template at ``forms/tutorial/wikipage_view.pt`` - for viewing a wiki page: +#. Finally, a template at ``forms/tutorial/wikipage_view.pt`` for viewing a + wiki page: .. literalinclude:: forms/tutorial/wikipage_view.pt :language: html :linenos: +#. Run the tests: + + .. code-block:: bash + + $ $VENV/bin/py.test tutorial/tests.py -q + .. + 2 passed in 0.45 seconds + #. Run your Pyramid application with: .. code-block:: bash @@ -98,51 +104,50 @@ Steps Analysis ======== -This step helps illustrate the utility of asset specifications for -static assets. We have an outside package called Deform with static -assets which need to be published. We don't have to know where on disk -it is located. We point at the package, then the path inside the package. - -We just need to include a call to ``add_static_view`` to make that -directory available at a URL. For Pyramid-specific packages, -Pyramid provides a facility (``config.include()``) which even makes -that unnecessary for consumers of a package. (Deform is not specific to -Pyramid.) - -Our forms have rich widgets which need the static CSS and JS just -mentioned. Deform has a :term:`resource registry` which allows widgets -to specify which JS and CSS are needed. Our ``wikipage_addedit.pt`` -template shows how we iterated over that data to generate markup that -includes the needed resources. - -Our add and edit views use a pattern called *self-posting forms*. -Meaning, the same URL is used to ``GET`` the form as is used to -``POST`` the form. The route, the view, and the template are the same -whether you are walking up to it the first time or you clicked a button. - -Inside the view we do ``if 'submit' in self.request.params:`` to see if -this form was a ``POST`` where the user clicked on a particular button +This step helps illustrate the utility of asset specifications for static +assets. We have an outside package called Deform with static assets which need +to be published. We don't have to know where on disk it is located. We point at +the package, then the path inside the package. + +We just need to include a call to ``add_static_view`` to make that directory +available at a URL. For Pyramid-specific packages, Pyramid provides a facility +(``config.include()``) which even makes that unnecessary for consumers of a +package. (Deform is not specific to Pyramid.) + +Our forms have rich widgets which need the static CSS and JavaScript just +mentioned. Deform has a :term:`resource registry` which allows widgets to +specify which JavaScript and CSS are needed. Our ``wikipage_addedit.pt`` +template shows how we iterated over that data to generate markup that includes +the needed resources. + +Our add and edit views use a pattern called *self-posting forms*. Meaning, the +same URL is used to ``GET`` the form as is used to ``POST`` the form. The +route, the view, and the template are the same URL whether you are walking up +to it for the first time or you clicked a button. + +Inside the view we do ``if 'submit' in self.request.params:`` to see if this +form was a ``POST`` where the user clicked on a particular button ````. The form controller then follows a typical pattern: -- If you are doing a GET, skip over and just return the form +- If you are doing a ``GET``, skip over and just return the form. + +- If you are doing a ``POST``, validate the form contents. -- If you are doing a POST, validate the form contents +- If the form is invalid, bail out by re-rendering the form with the supplied + ``POST`` data. -- If the form is invalid, bail out by re-rendering the form with the - supplied ``POST`` data +- If the validation succeeded, perform some action and issue a redirect via + ``HTTPFound``. -- If the validation succeeded, perform some action and issue a - redirect via ``HTTPFound``. +We are, in essence, writing our own form controller. Other Pyramid-based +systems, including ``pyramid_deform``, provide a form-centric view class which +automates much of this branching and routing. -We are, in essence, writing our own form controller. Other -Pyramid-based systems, including ``pyramid_deform``, provide a -form-centric view class which automates much of this branching and -routing. -Extra Credit +Extra credit ============ -#. Give a try at a button that goes to a delete view for a - particular wiki page. +#. Give a try at a button that goes to a delete view for a particular wiki + page. -- cgit v1.2.3 From 8bca48a37f5a0f79976d975aa3afd5760688a89c Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 13:22:31 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup databases.rst --- docs/quick_tutorial/databases.rst | 186 +++++++++++------------ docs/quick_tutorial/databases/sqltutorial.sqlite | Bin 12288 -> 0 bytes 2 files changed, 92 insertions(+), 94 deletions(-) delete mode 100644 docs/quick_tutorial/databases/sqltutorial.sqlite (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index f9f548585..c8d87c180 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -4,37 +4,39 @@ 19: Databases Using SQLAlchemy ============================== -Store/retrieve data using the SQLAlchemy ORM atop the SQLite database. +Store and retrieve data using the SQLAlchemy ORM atop the SQLite database. + Background ========== -Our Pyramid-based wiki application now needs database-backed storage of -pages. This frequently means a SQL database. The Pyramid community -strongly supports the -:ref:`SQLAlchemy ` project and its -:ref:`object-relational mapper (ORM) ` -as a convenient, Pythonic way to interface to databases. +Our Pyramid-based wiki application now needs database-backed storage of pages. +This frequently means an SQL database. The Pyramid community strongly supports +the :ref:`SQLAlchemy ` project and its +:ref:`object-relational mapper (ORM) ` as a +convenient, Pythonic way to interface to databases. -In this step we hook up SQLAlchemy to a SQLite database table, -providing storage and retrieval for the wikipages in the previous step. +In this step we hook up SQLAlchemy to a SQLite database table, providing +storage and retrieval for the wiki pages in the previous step. .. note:: - The ``alchemy`` scaffold is really helpful for getting a - SQLAlchemy project going, including generation of the console - script. Since we want to see all the decisions, we will forgo - convenience in this tutorial and wire it up ourselves. + The ``alchemy`` scaffold is really helpful for getting an SQLAlchemy + project going, including generation of the console script. Since we want to + see all the decisions, we will forgo convenience in this tutorial, and wire + it up ourselves. + Objectives ========== -- Store pages in SQLite by using SQLAlchemy models +- Store pages in SQLite by using SQLAlchemy models. -- Use SQLAlchemy queries to list/add/view/edit pages +- Use SQLAlchemy queries to list/add/view/edit pages. + +- Provide a database-initialize command by writing a Pyramid *console script* + which can be run from the command line. -- Provide a database-initialize command by writing a Pyramid *console - script* which can be run from the command line Steps ===== @@ -45,31 +47,31 @@ Steps $ cd ..; cp -r forms databases; cd databases -#. We need to add some dependencies in ``databases/setup.py`` as well - as an "entry point" for the command-line script: +#. We need to add some dependencies in ``databases/setup.py`` as well as an + "entry point" for the command-line script: .. literalinclude:: databases/setup.py :linenos: .. note:: - We aren't yet doing ``$VENV/bin/pip install -e .`` as we - will change it later. + We aren't yet doing ``$VENV/bin/pip install -e .`` as we will change it + later. -#. Our configuration file at ``databases/development.ini`` wires - together some new pieces: +#. Our configuration file at ``databases/development.ini`` wires together some + new pieces: .. literalinclude:: databases/development.ini :language: ini -#. This engine configuration now needs to be read into the application - through changes in ``databases/tutorial/__init__.py``: +#. This engine configuration now needs to be read into the application through + changes in ``databases/tutorial/__init__.py``: .. literalinclude:: databases/tutorial/__init__.py :linenos: -#. Make a command-line script at ``databases/tutorial/initialize_db.py`` - to initialize the database: +#. Make a command-line script at ``databases/tutorial/initialize_db.py`` to + initialize the database: .. literalinclude:: databases/tutorial/initialize_db.py :linenos: @@ -90,51 +92,49 @@ Steps .. code-block:: bash $ $VENV/bin/initialize_tutorial_db development.ini - 2015-06-01 11:22:52,650 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1 - 2015-06-01 11:22:52,650 INFO [sqlalchemy.engine.base.Engine][MainThread] () - 2015-06-01 11:22:52,651 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1 - 2015-06-01 11:22:52,651 INFO [sqlalchemy.engine.base.Engine][MainThread] () - 2015-06-01 11:22:52,652 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages") - 2015-06-01 11:22:52,652 INFO [sqlalchemy.engine.base.Engine][MainThread] () - 2015-06-01 11:22:52,653 INFO [sqlalchemy.engine.base.Engine][MainThread] + + 2016-04-16 13:01:33,055 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1 + 2016-04-16 13:01:33,055 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2016-04-16 13:01:33,056 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1 + 2016-04-16 13:01:33,056 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2016-04-16 13:01:33,057 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages") + 2016-04-16 13:01:33,057 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2016-04-16 13:01:33,058 INFO [sqlalchemy.engine.base.Engine][MainThread] CREATE TABLE wikipages ( - uid INTEGER NOT NULL, - title TEXT, - body TEXT, - PRIMARY KEY (uid), - UNIQUE (title) + uid INTEGER NOT NULL, + title TEXT, + body TEXT, + PRIMARY KEY (uid), + UNIQUE (title) ) - 2015-06-01 11:22:52,653 INFO [sqlalchemy.engine.base.Engine][MainThread] () - 2015-06-01 11:22:52,655 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT - 2015-06-01 11:22:52,658 INFO [sqlalchemy.engine.base.Engine][MainThread] BEGIN (implicit) - 2015-06-01 11:22:52,659 INFO [sqlalchemy.engine.base.Engine][MainThread] INSERT INTO wikipages (title, body) VALUES (?, ?) - 2015-06-01 11:22:52,659 INFO [sqlalchemy.engine.base.Engine][MainThread] ('Root', '

Root

') - 2015-06-01 11:22:52,659 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT + 2016-04-16 13:01:33,058 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2016-04-16 13:01:33,059 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT + 2016-04-16 13:01:33,062 INFO [sqlalchemy.engine.base.Engine][MainThread] BEGIN (implicit) + 2016-04-16 13:01:33,062 INFO [sqlalchemy.engine.base.Engine][MainThread] INSERT INTO wikipages (title, body) VALUES (?, ?) + 2016-04-16 13:01:33,063 INFO [sqlalchemy.engine.base.Engine][MainThread] ('Root', '

Root

') + 2016-04-16 13:01:33,063 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT -#. With our data now driven by SQLAlchemy queries, we need to update - our ``databases/tutorial/views.py``: +#. With our data now driven by SQLAlchemy queries, we need to update our + ``databases/tutorial/views.py``: .. literalinclude:: databases/tutorial/views.py :linenos: -#. Our tests in ``databases/tutorial/tests.py`` changed to include - SQLAlchemy bootstrapping: +#. Our tests in ``databases/tutorial/tests.py`` changed to include SQLAlchemy + bootstrapping: .. literalinclude:: databases/tutorial/tests.py :linenos: -#. Run the tests in your package using ``nose``: +#. Run the tests in your package using ``py.test``: - .. code-block:: bash - - $ $VENV/bin/nosetests tutorial - .. - ----------------------------------------------------------------- - Ran 2 tests in 1.141s + .. code-block:: bash - OK + $ $VENV/bin/py.test tutorial/tests.py -q + .. + 2 passed in 1.41 seconds #. Run your Pyramid application with: @@ -144,57 +144,55 @@ Steps #. Open http://localhost:6543/ in a browser. + Analysis ======== -Let's start with the dependencies. We made the decision to use -``SQLAlchemy`` to talk to our database. We also, though, installed -``pyramid_tm`` and ``zope.sqlalchemy``. Why? +Let's start with the dependencies. We made the decision to use ``SQLAlchemy`` +to talk to our database. We also, though, installed ``pyramid_tm`` and +``zope.sqlalchemy``. Why? Pyramid has a strong orientation towards support for ``transactions``. -Specifically, you can install a transaction manager into your -application either as middleware or a Pyramid "tween". Then, -just before you return the response, all transaction-aware parts of -your application are executed. +Specifically, you can install a transaction manager into your application +either as middleware or a Pyramid "tween". Then, just before you return the +response, all transaction-aware parts of your application are executed. -This means Pyramid view code usually doesn't manage transactions. If -your view code or a template generates an error, the transaction manager -aborts the transaction. This is a very liberating way to write code. +This means Pyramid view code usually doesn't manage transactions. If your view +code or a template generates an error, the transaction manager aborts the +transaction. This is a very liberating way to write code. The ``pyramid_tm`` package provides a "tween" that is configured in the -``development.ini`` configuration file. That installs it. We then need -a package that makes SQLAlchemy, and thus the RDBMS transaction manager, -integrate with the Pyramid transaction manager. That's what -``zope.sqlalchemy`` does. +``development.ini`` configuration file. That installs it. We then need a +package that makes SQLAlchemy, and thus the RDBMS transaction manager, +integrate with the Pyramid transaction manager. That's what ``zope.sqlalchemy`` +does. Where do we point at the location on disk for the SQLite file? In the -configuration file. This lets consumers of our package change the -location in a safe (non-code) way. That is, in configuration. This -configuration-oriented approach isn't required in Pyramid; you can -still make such statements in your ``__init__.py`` or some companion -module. - -The ``initialize_tutorial_db`` is a nice example of framework support. -You point your setup at the location of some ``[console_scripts]`` and -these get generated into your virtual environment's ``bin`` directory. Our -console script follows the pattern of being fed a configuration file -with all the bootstrapping. It then opens SQLAlchemy and creates the -root of the wiki, which also makes the SQLite file. Note the -``with transaction.manager`` part that puts the work in the scope of a -transaction, as we aren't inside a web request where this is done -automatically. - -The ``models.py`` does a little bit extra work to hook up SQLAlchemy -into the Pyramid transaction manager. It then declares the model for a -``Page``. +configuration file. This lets consumers of our package change the location in a +safe (non-code) way. That is, in configuration. This configuration-oriented +approach isn't required in Pyramid; you can still make such statements in your +``__init__.py`` or some companion module. + +The ``initialize_tutorial_db`` is a nice example of framework support. You +point your setup at the location of some ``[console_scripts]``, and these get +generated into your virtual environment's ``bin`` directory. Our console script +follows the pattern of being fed a configuration file with all the +bootstrapping. It then opens SQLAlchemy and creates the root of the wiki, which +also makes the SQLite file. Note the ``with transaction.manager`` part that +puts the work in the scope of a transaction, as we aren't inside a web request +where this is done automatically. + +The ``models.py`` does a little bit of extra work to hook up SQLAlchemy into +the Pyramid transaction manager. It then declares the model for a ``Page``. Our views have changes primarily around replacing our dummy -dictionary-of-dictionaries data with proper database support: list the -rows, add a row, edit a row, and delete a row. +dictionary-of-dictionaries data with proper database support: list the rows, +add a row, edit a row, and delete a row. + -Extra Credit +Extra credit ============ -#. Why all this code? Why can't I just type 2 lines and have magic ensue? +#. Why all this code? Why can't I just type two lines and have magic ensue? #. Give a try at a button that deletes a wiki page. diff --git a/docs/quick_tutorial/databases/sqltutorial.sqlite b/docs/quick_tutorial/databases/sqltutorial.sqlite deleted file mode 100644 index b8bd856fd..000000000 Binary files a/docs/quick_tutorial/databases/sqltutorial.sqlite and /dev/null differ -- cgit v1.2.3 From b92a5f6f44df3490c61ab9436e51c043299e9097 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 13:50:02 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup authentication.rst --- docs/quick_tutorial/authentication.rst | 89 ++++++++++++++++------------------ 1 file changed, 42 insertions(+), 47 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/authentication.rst b/docs/quick_tutorial/authentication.rst index cb3839b08..acff97f3b 100644 --- a/docs/quick_tutorial/authentication.rst +++ b/docs/quick_tutorial/authentication.rst @@ -4,28 +4,27 @@ 20: Logins With Authentication ============================== -Login views that authenticate a username/password against a list of -users. +Login views that authenticate a username and password against a list of users. + Background ========== -Most web applications have URLs that allow people to add/edit/delete -content via a web browser. Time to add -:ref:`security ` -to the application. In this first step we introduce authentication. -That is, logging in and logging out using Pyramid's rich facilities for -pluggable user storages. +Most web applications have URLs that allow people to add/edit/delete content +via a web browser. Time to add :ref:`security ` to the +application. In this first step we introduce authentication. That is, logging +in and logging out, using Pyramid's rich facilities for pluggable user storage. + +In the next step we will introduce protection of resources with authorization +security statements. -In the next step we will introduce protection resources with -authorization security statements. Objectives ========== -- Introduce the Pyramid concepts of authentication +- Introduce the Pyramid concepts of authentication. -- Create login/logout views +- Create login and logout views. Steps ===== @@ -38,22 +37,20 @@ Steps $ $VENV/bin/pip install -e . #. Put the security hash in the ``authentication/development.ini`` - configuration file as ``tutorial.secret`` instead of putting it in - the code: + configuration file as ``tutorial.secret`` instead of putting it in the code: .. literalinclude:: authentication/development.ini :language: ini :linenos: -#. Get authentication (and for now, authorization policies) and login - route into the :term:`configurator` in - ``authentication/tutorial/__init__.py``: +#. Get authentication (and for now, authorization policies) and login route + into the :term:`configurator` in ``authentication/tutorial/__init__.py``: .. literalinclude:: authentication/tutorial/__init__.py :linenos: -#. Create a ``authentication/tutorial/security.py`` module that can find - our user information by providing an *authentication policy callback*: +#. Create an ``authentication/tutorial/security.py`` module that can find our + user information by providing an *authentication policy callback*: .. literalinclude:: authentication/tutorial/security.py :linenos: @@ -69,7 +66,7 @@ Steps :language: html :linenos: -#. Provide a login/logout box in ``authentication/tutorial/home.pt`` +#. Provide a login/logout box in ``authentication/tutorial/home.pt``: .. literalinclude:: authentication/tutorial/home.pt :language: html @@ -95,39 +92,37 @@ Steps Analysis ======== -Unlike many web frameworks, Pyramid includes a built-in but optional -security model for authentication and authorization. This security -system is intended to be flexible and support many needs. In this -security model, authentication (who are you) and authorization (what -are you allowed to do) are not just pluggable, but de-coupled. To learn -one step at a time, we provide a system that identifies users and lets -them log out. - -In this example we chose to use the bundled -:ref:`AuthTktAuthenticationPolicy ` -policy. We enabled it in our configuration and provided a -ticket-signing secret in our INI file. - -Our view class grew a login view. When you reached it via a GET, -it returned a login form. When reached via POST, it processed the -username and password against the "groupfinder" callable that we -registered in the configuration. - -In our template, we fetched the ``logged_in`` value from the view -class. We use this to calculate the logged-in user, -if any. In the template we can then choose to show a login link to -anonymous visitors or a logout link to logged-in users. - -Extra Credit +Unlike many web frameworks, Pyramid includes a built-in but optional security +model for authentication and authorization. This security system is intended to +be flexible and support many needs. In this security model, authentication (who +are you) and authorization (what are you allowed to do) are not just pluggable, +but de-coupled. To learn one step at a time, we provide a system that +identifies users and lets them log out. + +In this example we chose to use the bundled :ref:`AuthTktAuthenticationPolicy +` policy. We enabled it in our configuration and +provided a ticket-signing secret in our INI file. + +Our view class grew a login view. When you reached it via a ``GET`` request, it +returned a login form. When reached via ``POST``, it processed the submitted +username and password against the "groupfinder" callable that we registered in +the configuration. + +In our template, we fetched the ``logged_in`` value from the view class. We use +this to calculate the logged-in user, if any. In the template we can then +choose to show a login link to anonymous visitors or a logout link to logged-in +users. + + +Extra credit ============ #. What is the difference between a user and a principal? #. Can I use a database behind my ``groupfinder`` to look up principals? -#. Once I am logged in, does any user-centric information get jammed - onto each request? Use ``import pdb; pdb.set_trace()`` to answer - this. +#. Once I am logged in, does any user-centric information get jammed onto each + request? Use ``import pdb; pdb.set_trace()`` to answer this. .. seealso:: See also :ref:`security_chapter`, :ref:`AuthTktAuthenticationPolicy `. -- cgit v1.2.3 From a5e89f07e4c97849f0a36069d4272c6e2efe8539 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 13:57:14 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup authorization.rst --- docs/quick_tutorial/authorization.rst | 86 +++++++++++++++++------------------ 1 file changed, 43 insertions(+), 43 deletions(-) (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/authorization.rst b/docs/quick_tutorial/authorization.rst index a4a12774b..58c1d2582 100644 --- a/docs/quick_tutorial/authorization.rst +++ b/docs/quick_tutorial/authorization.rst @@ -4,33 +4,35 @@ 21: Protecting Resources With Authorization =========================================== -Assign security statements to resources describing the permissions -required to perform an operation. +Assign security statements to resources describing the permissions required to +perform an operation. + Background ========== -Our application has URLs that allow people to add/edit/delete content -via a web browser. Time to add security to the application. Let's -protect our add/edit views to require a login (username of -``editor`` and password of ``editor``). We will allow the other views -to continue working without a password. +Our application has URLs that allow people to add/edit/delete content via a web +browser. Time to add security to the application. Let's protect our add/edit +views to require a login (username of ``editor`` and password of ``editor``). +We will allow the other views to continue working without a password. + Objectives ========== -- Introduce the Pyramid concepts of authentication, authorization, - permissions, and access control lists (ACLs) +- Introduce the Pyramid concepts of authentication, authorization, permissions, + and access control lists (ACLs). + +- Make a :term:`root factory` that returns an instance of our class for the top + of the application. -- Make a :term:`root factory` that returns an instance of our - class for the top of the application +- Assign security statements to our root resource. -- Assign security statements to our root resource +- Add a permissions predicate on a view. -- Add a permissions predicate on a view +- Provide a :term:`Forbidden view` to handle visiting a URL without adequate + permissions. -- Provide a :term:`Forbidden view` to handle visiting a URL without - adequate permissions Steps ===== @@ -42,14 +44,13 @@ Steps $ cd ..; cp -r authentication authorization; cd authorization $ $VENV/bin/pip install -e . -#. Start by changing ``authorization/tutorial/__init__.py`` to - specify a root factory to the :term:`configurator`: +#. Start by changing ``authorization/tutorial/__init__.py`` to specify a root + factory to the :term:`configurator`: .. literalinclude:: authorization/tutorial/__init__.py :linenos: -#. That means we need to implement - ``authorization/tutorial/resources.py`` +#. That means we need to implement ``authorization/tutorial/resources.py``: .. literalinclude:: authorization/tutorial/resources.py :linenos: @@ -70,48 +71,47 @@ Steps #. If you are still logged in, click the "Log Out" link. -#. Visit http://localhost:6543/howdy in a browser. You should be - asked to login. +#. Visit http://localhost:6543/howdy in a browser. You should be asked to + login. + Analysis ======== This simple tutorial step can be boiled down to the following: -- A view can require a *permission* (``edit``) +- A view can require a *permission* (``edit``). -- The context for our view (the ``Root``) has an access control list - (ACL) +- The context for our view (the ``Root``) has an access control list (ACL). -- This ACL says that the ``edit`` permission is available on ``Root`` - to the ``group:editors`` *principal* +- This ACL says that the ``edit`` permission is available on ``Root`` to the + ``group:editors`` *principal*. -- The registered ``groupfinder`` answers whether a particular user - (``editor``) has a particular group (``group:editors``) +- The registered ``groupfinder`` answers whether a particular user (``editor``) + has a particular group (``group:editors``). -In summary: ``hello`` wants ``edit`` permission, ``Root`` says +In summary, ``hello`` wants ``edit`` permission, ``Root`` says ``group:editors`` has ``edit`` permission. -Of course, this only applies on ``Root``. Some other part of the site -(a.k.a. *context*) might have a different ACL. +Of course, this only applies on ``Root``. Some other part of the site (a.k.a. +*context*) might have a different ACL. + +If you are not logged in and visit ``/howdy``, you need to get shown the login +screen. How does Pyramid know what is the login page to use? We explicitly told +Pyramid that the ``login`` view should be used by decorating the view with +``@forbidden_view_config``. -If you are not logged in and visit ``/howdy``, you need to get -shown the login screen. How does Pyramid know what is the login page to -use? We explicitly told Pyramid that the ``login`` view should be used -by decorating the view with ``@forbidden_view_config``. -Extra Credit +Extra credit ============ -#. Do I have to put a ``renderer`` in my ``@forbidden_view_config`` - decorator? +#. Do I have to put a ``renderer`` in my ``@forbidden_view_config`` decorator? #. Perhaps you would like the experience of not having enough permissions (forbidden) to be richer. How could you change this? -#. Perhaps we want to store security statements in a database and - allow editing via a browser. How might this be done? +#. Perhaps we want to store security statements in a database and allow editing + via a browser. How might this be done? -#. What if we want different security statements on different kinds of - objects? Or on the same kinds of objects, but in different parts of a - URL hierarchy? +#. What if we want different security statements on different kinds of objects? + Or on the same kinds of objects, but in different parts of a URL hierarchy? -- cgit v1.2.3