diff options
| author | Chris McDonough <chrism@plope.com> | 2011-12-15 21:36:19 -0500 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-12-15 21:36:19 -0500 |
| commit | 63f7a19b58738b8fe5fbe82f362825fa53ddc0d2 (patch) | |
| tree | ae76a8285e901994ba62802b639802d2de2e0b0e /docs | |
| parent | 8e615c4f433c4df9b694c6452f793ed4763434ff (diff) | |
| parent | 61838b76639d6dcf9facd549841a2ed0d07ea012 (diff) | |
| download | pyramid-63f7a19b58738b8fe5fbe82f362825fa53ddc0d2.tar.gz pyramid-63f7a19b58738b8fe5fbe82f362825fa53ddc0d2.tar.bz2 pyramid-63f7a19b58738b8fe5fbe82f362825fa53ddc0d2.zip | |
Merge branch '1.3-branch'
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/api.rst | 1 | ||||
| -rw-r--r-- | docs/api/scaffolds.rst | 13 | ||||
| -rw-r--r-- | docs/conf.py | 7 | ||||
| -rw-r--r-- | docs/index.rst | 6 | ||||
| -rw-r--r-- | docs/narr/commandline.rst | 296 | ||||
| -rw-r--r-- | docs/narr/hooks.rst | 2 | ||||
| -rw-r--r-- | docs/narr/scaffolding.rst | 171 | ||||
| -rw-r--r-- | docs/whatsnew-1.3.rst | 26 |
8 files changed, 507 insertions, 15 deletions
diff --git a/docs/api.rst b/docs/api.rst index 979e8f490..d510c0d27 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -26,6 +26,7 @@ documentation is organized alphabetically by module name. api/renderers api/request api/response + api/scaffolds api/scripting api/security api/session diff --git a/docs/api/scaffolds.rst b/docs/api/scaffolds.rst new file mode 100644 index 000000000..827962e19 --- /dev/null +++ b/docs/api/scaffolds.rst @@ -0,0 +1,13 @@ +.. _scaffolds_module: + +:mod:`pyramid.scaffolds` +------------------------ + +.. automodule:: pyramid.scaffolds + + .. autoclass:: pyramid.scaffolds.Template + :members: + + .. autoclass:: pyramid.scaffolds.PyramidTemplate + :members: + diff --git a/docs/conf.py b/docs/conf.py index 9be5db325..5281017e7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -80,7 +80,8 @@ copyright = '%s, Agendaless Consulting' % datetime.datetime.now().year # other places throughout the built documents. # # The short X.Y version. -version = '1.4dev' +version = '1.3a2' + # The full version, including alpha/beta/rc tags. release = version @@ -475,7 +476,7 @@ def resig(app, what, name, obj, options, signature, return_annotation): # -- Options for Epub output --------------------------------------------------- # Bibliographic Dublin Core info. -epub_title = 'The Pyramid Web Application Development Framework, Version 1.4dev' +epub_title = 'The Pyramid Web Application Development Framework, Version 1.3' epub_author = 'Chris McDonough' epub_publisher = 'Agendaless Consulting' epub_copyright = '2008-2011' @@ -492,7 +493,7 @@ epub_scheme = 'ISBN' epub_identifier = '0615445675' # A unique identification for the text. -epub_uid = 'The Pyramid Web Application Development Framework, Version 1.4dev' +epub_uid = 'The Pyramid Web Application Development Framework, Version 1.3' # HTML files that should be inserted before the pages created by sphinx. # The format is a list of tuples containing the path and title. diff --git a/docs/index.rst b/docs/index.rst index df7a422d4..21e587992 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -19,10 +19,9 @@ When saved to ``helloworld.py``, the above application can be run via: $ easy_install pyramid $ python helloworld.py - serving on 0.0.0.0:8080 view at http://127.0.0.1:8080 -And when you visit ``http://localhost:8080/hello/world`` in a browser, you -will see the text ``Hello, world!``. +When you visit ``http://localhost:8080/hello/world`` in a browser, you will +see the text ``Hello, world!``. See :ref:`firstapp_chapter` for a full explanation of how this application works. Read the :ref:`html_narrative_documentation` to understand how @@ -93,6 +92,7 @@ Narrative documentation in chapter form explaining how to use narr/extending narr/advconfig narr/extconfig + narr/scaffolding narr/threadlocals narr/zca diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst index 66ef46671..dc3cff8ac 100644 --- a/docs/narr/commandline.rst +++ b/docs/narr/commandline.rst @@ -121,7 +121,8 @@ The Interactive Shell Once you've installed your program for development using ``setup.py develop``, you can use an interactive Python shell to execute expressions in a Python environment exactly like the one that will be used when your -application runs "for real". To do so, use the ``pshell`` command. +application runs "for real". To do so, use the ``pshell`` command line +utility. The argument to ``pshell`` follows the format ``config_file#section_name`` where ``config_file`` is the path to your application's ``.ini`` file and @@ -311,7 +312,7 @@ For example: .. code-block:: text :linenos: - [chrism@thinko MyProject]$ ../bin/proutes development.ini#MyProject + [chrism@thinko MyProject]$ ../bin/proutes development.ini Name Pattern View ---- ------- ---- home / <function my_view> @@ -354,7 +355,7 @@ configured without any explicit tweens: .. code-block:: text :linenos: - [chrism@thinko pyramid]$ ptweens development.ini + [chrism@thinko pyramid]$ myenv/bin/ptweens development.ini "pyramid.tweens" config value NOT set (implicitly ordered tweens used) Implicit Tween Chain @@ -416,6 +417,64 @@ is used: See :ref:`registering_tweens` for more information about tweens. +.. index:: + single: invoking a request + single: prequest + +.. _invoking_a_request: + +Invoking a Request +------------------ + +You can use the ``prequest`` command-line utility to send a request to your +application and see the response body without starting a server. + +There are two required arguments to ``prequest``: + +- The config file/section: follows the format ``config_file#section_name`` + where ``config_file`` is the path to your application's ``.ini`` file and + ``section_name`` is the ``app`` section name inside the ``.ini`` file. The + ``section_name`` is optional, it defaults to ``main``. For example: + ``development.ini``. + +- The path: this should be the non-url-quoted path element of the URL to the + resource you'd like to be rendered on the server. For example, ``/``. + +For example:: + + $ bin/prequest development.ini / + +This will print the body of the response to the console on which it was +invoked. + +Several options are supported by ``prequest``. These should precede any +config file name or URL. + +``prequest`` has a ``-d`` (aka ``--display-headers``) option which prints the +status and headers returned by the server before the output:: + + $ bin/prequest -d development.ini / + +This will print the status, then the headers, then the body of the response +to the console. + +You can add request header values by using the ``--header`` option:: + + $ bin/prequest --header=Host=example.com development.ini / + +Headers are added to the WSGI environment by converting them to their +CGI/WSGI equivalents (e.g. ``Host=example.com`` will insert the ``HTTP_HOST`` +header variable as the value ``example.com``). Multiple ``--header`` options +can be supplied. The special header value ``content-type`` sets the +``CONTENT_TYPE`` in the WSGI environment. + +By default, ``prequest`` sends a ``GET`` request. You can change this by +using the ``-m`` (aka ``--method``) option. ``GET``, ``HEAD``, ``POST`` and +``DELETE`` are currently supported. When you use ``POST``, the standard +input of the ``prequest`` process is used as the ``POST`` body:: + + $ bin/prequest -mPOST development.ini / < somefile + .. _writing_a_script: Writing a Script @@ -595,3 +654,234 @@ use the following command: import logging.config logging.config.fileConfig('/path/to/my/development.ini') + +.. index:: + single: console script + +.. _making_a_console_script: + +Making Your Script into a Console Script +---------------------------------------- + +A "console script" is :term:`setuptools` terminology for a script that gets +installed into the ``bin`` directory of a Python :term:`virtualenv` (or +"base" Python environment) when a :term:`distribution` which houses that +script is installed. Because it's installed into the ``bin`` directory of a +virtualenv when the distribution is installed, it's a convenient way to +package and distribute functionality that you can call from the command-line. +It's often more convenient to create a console script than it is to create a +``.py`` script and instruct people to call it with "the right Python +interpreter": because it generates a file that lives in ``bin``, when it's +invoked, it will always use "the right" Python environment, which means it +will always be invoked in an environment where all the libraries it needs +(such as Pyramid) are available. + +In general, you can make your script into a console script by doing the +following: + +- Use an existing distribution (such as one you've already created via + ``pcreate``) or create a new distribution that possesses at least one + package or module. It should, within any module within the distribution, + house a callable (usually a function) that takes no arguments and which + runs any of the code you wish to run. + +- Add a ``[console_scripts]`` section to the ``entry_points`` argument of the + distribution which creates a mapping between a script name and a dotted + name representing the callable you added to your distribution. + +- Run ``setup.py develop``, ``setup.py install``, or ``easy_install`` to get + your distribution reinstalled. When you reinstall your distribution, a + file representing the script that you named in the last step will be in the + ``bin`` directory of the virtualenv in which you installed the + distribution. It will be executable. Invoking it from a terminal will + execute your callable. + +As an example, let's create some code that can be invoked by a console script +that prints the deployment settings of a Pyramid application. To do so, +we'll pretend you have a distribution with a package in it named +``myproject``. Within this package, we'll pretend you've added a +``scripts.py`` module which contains the following code: + +.. code-block:: python + :linenos: + + # myproject.scripts module + + import optparse + import sys + import textwrap + + from pyramid.paster import bootstrap + + def settings_show(): + description = """\ + Print the deployment settings for a Pyramid application. Example: + 'psettings deployment.ini' + """ + usage = "usage: %prog config_uri" + parser = optparse.OptionParser( + usage=usage, + description=textwrap.dedent(description) + ) + parser.add_option( + '-o', '--omit', + dest='omit', + metavar='PREFIX', + type='string', + action='append', + help=("Omit settings which start with PREFIX (you can use this " + "option multiple times)") + ) + + options, args = parser.parse_args(sys.argv[1:]) + if not len(args) >= 1: + print('You must provide at least one argument') + return 2 + config_uri = args[0] + omit = options.omit + if omit is None: + omit = [] + env = bootstrap(config_uri) + settings, closer = env['registry'].settings, env['closer'] + try: + for k, v in settings.items(): + if any([k.startswith(x) for x in omit]): + continue + print('%-40s %-20s' % (k, v)) + finally: + closer() + +This script uses the Python ``optparse`` module to allow us to make sense out +of extra arguments passed to the script. It uses the +:func:`pyramid.paster.bootstrap` function to get information about the the +application defined by a config file, and prints the deployment settings +defined in that config file. + +After adding this script to the package, you'll need to tell your +distribution's ``setup.py`` about its existence. Within your distribution's +top-level directory your ``setup.py`` file will look something like this: + +.. code-block:: python + :linenos: + + import os + + from setuptools import setup, find_packages + + here = os.path.abspath(os.path.dirname(__file__)) + README = open(os.path.join(here, 'README.txt')).read() + CHANGES = open(os.path.join(here, 'CHANGES.txt')).read() + + requires = ['pyramid', 'pyramid_debugtoolbar'] + + setup(name='MyProject', + version='0.0', + description='My project', + long_description=README + '\n\n' + CHANGES, + classifiers=[ + "Programming Language :: Python", + "Framework :: Pylons", + "Topic :: Internet :: WWW/HTTP", + "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", + ], + author='', + author_email='', + url='', + keywords='web pyramid pylons', + packages=find_packages(), + include_package_data=True, + zip_safe=False, + install_requires=requires, + tests_require=requires, + test_suite="wiggystatic", + entry_points = """\ + [paste.app_factory] + main = wiggystatic:main + """, + ) + +We're going to change the setup.py file to add an ``[console_scripts]`` +section with in the ``entry_points`` string. Within this section, you should +specify a ``scriptname = dotted.path.to:yourfunction`` line. For example:: + + [console_scripts] + show_settings = myproject.scripts:settings_show + +The ``show_settings`` name will be the name of the script that is installed +into ``bin``. The colon (``:``) between ``myproject.scripts`` and +``settings_show`` above indicates that ``myproject.scripts`` is a Python +module, and ``settings_show`` is the function in that module which contains +the code you'd like to run as the result of someone invoking the +``show_settings`` script from their command line. + +The result will be something like: + +.. code-block:: python + :linenos: + + import os + + from setuptools import setup, find_packages + + here = os.path.abspath(os.path.dirname(__file__)) + README = open(os.path.join(here, 'README.txt')).read() + CHANGES = open(os.path.join(here, 'CHANGES.txt')).read() + + requires = ['pyramid', 'pyramid_debugtoolbar'] + + setup(name='MyProject', + version='0.0', + description='My project', + long_description=README + '\n\n' + CHANGES, + classifiers=[ + "Programming Language :: Python", + "Framework :: Pylons", + "Topic :: Internet :: WWW/HTTP", + "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", + ], + author='', + author_email='', + url='', + keywords='web pyramid pylons', + packages=find_packages(), + include_package_data=True, + zip_safe=False, + install_requires=requires, + tests_require=requires, + test_suite="wiggystatic", + entry_points = """\ + [paste.app_factory] + main = wiggystatic:main + [console_scripts] + show_settings = myproject.scripts:settings_show + """, + ) + +Once you've done this, invoking ``$somevirtualenv/bin/python setup.py +develop`` will install a file named ``show_settings`` into the +``$somevirtualenv/bin`` directory with a small bit of Python code that points +to your entry point. It will be executable. Running it without any +arguments will print an error and exit. Running it with a single argument +that is the path of a config file will print the settings. Running it with +an ``--omit=foo`` argument will omit the settings that have keys that start +with ``foo``. Running it with two "omit" options (e.g. ``--omit=foo +--omit=bar``) will omit all settings that have keys that start with either +``foo`` or ``bar``:: + + [chrism@thinko somevenv]$ bin/show_settings development.ini \ + --omit=pyramid \ + --omit=debugtoolbar + debug_routematch False + debug_templates True + reload_templates True + mako.directories [] + debug_notfound False + default_locale_name en + reload_resources False + debug_authorization False + reload_assets False + prevent_http_cache False + +Pyramid's ``pserve``, ``pcreate``, ``pshell``, ``prequest``, ``ptweens`` and +other ``p*`` scripts are implemented as console scripts. When you invoke one +of those, you are using a console script. diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 3c6799afb..a1ed6c7ff 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -119,7 +119,7 @@ Here's some sample code that implements a minimal forbidden view: .. code-block:: python :linenos: - from pyramid.views import view_config + from pyramid.view import view_config from pyramid.response import Response def forbidden_view(request): diff --git a/docs/narr/scaffolding.rst b/docs/narr/scaffolding.rst new file mode 100644 index 000000000..3e7b102fd --- /dev/null +++ b/docs/narr/scaffolding.rst @@ -0,0 +1,171 @@ +.. _scaffolding_chapter: + +Creating Pyramid Scaffolds +========================== + +You can extend Pyramid by creating a :term:`scaffold` template. A scaffold +template is useful if you'd like to distribute a customizable configuration +of Pyramid to other users. Once you've created a scaffold, and someone has +installed the distribution that houses the scaffold, they can use the +``pcreate`` script to create a custom version of your scaffold's template. +Pyramid itself uses scaffolds to allow people to bootstrap new projects. For +example, ``pcreate -s alchemy MyStuff`` causes Pyramid to render the +``alchemy`` scaffold template to the ``MyStuff`` directory. + +Basics +------ + +A scaffold template is just a bunch of source files and directories on disk. +A small definition class points at this directory; it is in turn pointed at +by a :term:`setuptools` "entry point" which registers the scaffold so it can +be found by the ``pcreate`` command. + +To create a scaffold template, create a Python :term:`distribution` to house +the scaffold which includes a ``setup.py`` that relies on the ``setuptools`` +package. See `Creating a Package +<http://guide.python-distribute.org/creation.html>`_ for more information +about how to do this. For the sake of example, we'll pretend the +distribution you create is named ``CoolExtension``, and it has a package +directory within it named ``coolextension`` + +Once you've created the distribution put a "scaffolds" directory within your +distribution's package directory, and create a file within that directory +named ``__init__.py`` with something like the following: + +.. code-block:: python + :linenos: + + # CoolExtension/coolextension/scaffolds/__init__.py + + from pyramid.scaffolds import PyramidTemplate + + class CoolExtensionTemplate(PyramidTemplate): + _template_dir = 'coolextension_scaffold' + summary = 'My cool extension' + +Once this is done, within the ``scaffolds`` directory, create a template +directory. Our example used a template directory named +``coolextension_scaffold``. + +As you create files and directories within the template directory, note that: + +- Files which have a name which are suffixed with the value ``_tmpl`` will be + rendered, and replacing any instance of the literal string ``{{var}}`` with + the string value of the variable named ``var`` provided to the scaffold. + +- Files and directories with filenames that contain the string ``+var+`` will + have that string replaced with the value of the ``var`` variable provided + to the scaffold. + +Otherwise, files and directories which live in the template directory will be +copied directly without modification to the ``pcreate`` output location. + +The variables provided by the default ``PyramidTemplate`` include ``project`` +(the project name provided by the user as an argument to ``pcreate``), +``package`` (a lowercasing and normalizing of the project name provided by +the user), ``random_string`` (a long random string), and ``package_logger`` +(the name of the package's logger). + +See Pyramid's "scaffolds" package +(https://github.com/Pylons/pyramid/tree/master/pyramid/scaffolds) for +concrete examples of scaffold directories (``zodb``, ``alchemy``, and +``starter``, for example). + +After you've created the template directory, add the following to the +``entry_points`` value of your distribution's ``setup.py``: + + [pyramid.scaffold] + coolextension=coolextension.scaffolds:CoolExtensionTemplate + +For example:: + + def setup( + ..., + entry_points = """\ + [pyramid.scaffold] + coolextension=coolextension.scaffolds:CoolExtensionTemplate + """ + ) + +Run your distribution's ``setup.py develop`` or ``setup.py install`` +command. After that, you should be able to see your scaffolding template +listed when you run ``pcreate -l``. It will be named ``coolextension`` +because that's the name we gave it in the entry point setup. Running +``pcreate -s coolextension MyStuff`` will then render your scaffold to an +output directory named ``MyStuff``. + +See the module documentation for :mod:`pyramid.scaffolds` for information +about the API of the :class:`pyramid.scaffolds.PyramidScaffold` class and +related classes. You can override methods of this class to get special +behavior. + +Supporting Older Pyramid Versions +--------------------------------- + +Because different versions of Pyramid handled scaffolding differently, if you +want to have extension scaffolds that can work across Pyramid 1.0.X, 1.1.X, +1.2.X and 1.3.X, you'll need to use something like this bit of horror while +defining your scaffold template: + +.. code-block:: python + :linenos: + + try: # pyramid 1.0.X + # "pyramid.paster.paste_script..." doesn't exist past 1.0.X + from pyramid.paster import paste_script_template_renderer + from pyramid.paster import PyramidTemplate + except ImportError: + try: # pyramid 1.1.X, 1.2.X + # trying to import "paste_script_template_renderer" fails on 1.3.X + from pyramid.scaffolds import paste_script_template_renderer + from pyramid.scaffolds import PyramidTemplate + except ImportError: # pyramid >=1.3a2 + paste_script_template_renderer = None + from pyramid.scaffolds import PyramidTemplate + + class CoolExtensionTemplateTemplate(PyramidTemplate): + _template_dir = 'coolextension_scaffold' + summary = 'My cool extension' + template_renderer = staticmethod(paste_script_template_renderer) + +And then in the setup.py of the package that contains your scaffold, define +the template as a target of both ``paste.paster_create_template`` (for +``paster create``) and ``pyramid.scaffold`` (for ``pcreate``):: + + [paste.paster_create_template] + coolextension=coolextension.scaffolds:CoolExtensionTemplate + [pyramid.scaffold] + coolextension=coolextension.scaffolds:CoolExtensionTemplate + +Doing this hideousness will allow your scaffold to work as a ``paster +create`` target (under 1.0, 1.1, or 1.2) or as a ``pcreate`` target (under +1.3). If an invoker tries to run ``paster create`` against a scaffold +defined this way under 1.3, an error is raised instructing them to use +``pcreate`` instead. + +If you want only to support Pyramid 1.3 only, it's much cleaner, and the API +is stable: + +.. code-block:: python + :linenos: + + from pyramid.scaffolds import PyramidTemplate + + class CoolExtensionTemplate(PyramidTemplate): + _template_dir = 'coolextension_scaffold' + summary = 'My cool_extension' + +You only need to specify a ``paste.paster_create_template`` entry point +target in your ``setup.py`` if you want your scaffold to be consumable by +users of Pyramid 1.0, 1.1, or 1.2. To support only 1.3, specifying only the +``pyramid.scaffold`` entry point is good enough. If you want to support both +``paster create`` and ``pcreate`` (meaning you want to support Pyramid 1.2 +and some older version), you'll need to define both. + +Examples +-------- + +Existing third-party distributions which house scaffolding are available via +:term:`PyPI`. The ``pyramid_jqm``, ``pyramid_zcml`` and ``pyramid_jinja2`` +packages house scaffolds. You can install and examine these packages to see +how they work in the quest to develop your own scaffolding. diff --git a/docs/whatsnew-1.3.rst b/docs/whatsnew-1.3.rst index 28c161ad0..8dd3c3cdb 100644 --- a/docs/whatsnew-1.3.rst +++ b/docs/whatsnew-1.3.rst @@ -76,12 +76,14 @@ command:: The ``ini`` configuration file format supported by Pyramid has not changed. As a result, Python 2-only users can install PasteScript manually and use -``paster serve`` and ``paster create`` instead if they like. However, using -``pserve`` and ``pcreate`` will work under both Python 2 and Python 3. +``paster serve`` instead if they like. However, using ``pserve`` will work +under both Python 2 and Python 3. ``pcreate`` is required to be used for +internal Pyramid scaffolding; externally distributed scaffolding may allow +for both ``pcreate`` and/or ``paster create``. -Analogues of ``paster pshell``, ``paster pviews`` and ``paster ptweens`` also -exist under the respective console script names ``pshell``, ``pviews``, and -``ptweens``. +Analogues of ``paster pshell``, ``paster pviews``, ``paster request`` and +``paster ptweens`` also exist under the respective console script names +``pshell``, ``pviews``, ``prequest`` and ``ptweens``. We've replaced use of the Paste ``httpserver`` with the ``wsgiref`` server in the scaffolds, so once you create a project from a scaffold, its @@ -101,6 +103,10 @@ actually recommended if you rely on proxying from Apache or Nginx to a ``pserve`` -invoked application. **The wsgiref server is not a production quality server.** See :ref:`alternate_wsgi_server` for more information. +New releases in every older major Pyramid series (1.0.2, 1.1.3, 1.2.5) also +have the ``egg:pyramid#wsgiref`` entry point, so scaffold-writers can depend +on it being there even in older major Pyramid versions. + .. warning:: Previously, paste.httpserver "helped" by converting header values that weren't @@ -286,6 +292,16 @@ Documentation Enhancements - A narrative documentation chapter named :ref:`using_introspection` was added. It describes how to query the introspection system. +- Added an API docs chapter for :mod:`pyramid.scaffolds`. + +- Added a narrative docs chapter named :ref:`scaffolding_chapter`. + +- Added a description of the ``prequest`` command-line script at + :ref:`invoking_a_request`. + +- Added a section to the "Command-Line Pyramid" chapter named + :ref:`making_a_console_script`. + Dependency Changes ------------------ |
