Merge remote-tracking branch 'origin/master'

This commit is contained in:
Jonathan LaCour
2011-09-02 12:59:12 -04:00
11 changed files with 163 additions and 188 deletions

View File

View File

@@ -26,7 +26,16 @@ By default, this module contains a special method, ``init_model``::
from pecan import conf from pecan import conf
def init_model(): def init_model():
# Read and parse database bindings from pecan.conf """
This is a stub method which is called at application startup time.
If you need to bind to a parse database configuration, set up tables or
ORM classes, or perform any database initialization, this is the
recommended place to do it.
For more information working with databases, and some common recipes,
see http://pecan.readthedocs.org/en/latest/databases.html
"""
pass pass
The purpose of this method is to determine bindings from your configuration file and create The purpose of this method is to determine bindings from your configuration file and create
@@ -91,7 +100,7 @@ Binding Within the Application
There are several approaches that can be taken to wrap your application's requests with calls There are several approaches that can be taken to wrap your application's requests with calls
to appropriate model function calls. One approach is WSGI middleware. We also recommend to appropriate model function calls. One approach is WSGI middleware. We also recommend
Pecan :ref:`hooks`. Pecan comes with ``TransactionHook``, a hook which can Pecan :ref:`hooks`. Pecan comes with ``TransactionHook``, a hook which can
be used to wrap requests in transactions for you. To use it, simply include it in your be used to wrap requests in database transactions for you. To use it, simply include it in your
project's ``app.py`` file and pass it a set of functions related to database binding:: project's ``app.py`` file and pass it a set of functions related to database binding::
from pecan import conf, make_app from pecan import conf, make_app

View File

@@ -0,0 +1,4 @@
.. _deployment:
Deployment Recipes
=============

View File

@@ -63,10 +63,8 @@ tutorial on App Engine.
app_engine.rst app_engine.rst
sessions.rst sessions.rst
celery.rst
databases.rst databases.rst
deployment.rst deployment.rst
reporting.rst
API Documentation API Documentation

View File

@@ -3,40 +3,40 @@
Installation Installation
============ ============
.. warning:: Stable Version
This section is out of date. Please do not refer to it directly. ------------------------------
We recommend installing Pecan with ``pip`` but you can also try with We recommend installing Pecan with ``pip`` but you can also try with
``easy_install`` and ``virtualenv``. Creating a spot in your environment where ``easy_install`` and ``virtualenv``. Creating a spot in your environment where
Pecan can be isolated from other packages is best practice. Pecan can be isolated from other packages is best practice.
To get started with an environment for Pecan, create a virtual environment for To get started with an environment for Pecan, create a new
it without any site-packages that might pollute:: `virtual environment <http://www.virtualenv.org>`_::
virtualenv --no-site-packages pecan-env virtualenv --no-site-packages pecan-env
cd pecan-env cd pecan-env
source bin/activate source bin/activate
The above commands created a virtual environment and *activated* it. Those The above commands create a virtual environment and *activate* it. Those
actions will encapsulate anything that we do with the framework, making it actions will encapsulate any dependency installations for the framework,
easier to debug problems if needed. making it easier to debug problems if needed.
But we do not have Pecan yet, so let's grab it from PYPI:: Next, let's install Pecan::
pip install pecan pip install pecan
After a lot of output, you should have Pecan successfully installed and ready After a lot of output, you should have Pecan successfully installed.
to use.
Development (Unstable) Version Development (Unstable) Version
------------------------------ ------------------------------
If you want to run the development version of Pecan you will If you want to run the development version of Pecan you will
need GIT installed and clone the repo from github:: need to install git and clone the repo from github::
git clone https://github.com/pecan/pecan.git git clone https://github.com/pecan/pecan.git
If you are still in the *pecan-dev* virtual environment that we created before, If your virtual environment is still activated, call ``setup.py`` to install
you should call ``setup.py`` to install:: the development version::
cd pecan
python setup.py develop python setup.py develop

View File

@@ -3,69 +3,33 @@
Quick Start Quick Start
=========== ===========
Here we will cover the basics for a small project in Pecan. More advanced Let's create a small sample project with Pecan.
examples and methods are not covered here.
.. note:: .. note::
We will not cover how to get Pecan installed here. If you need installation This guide does not cover the installation of Pecan. If you need
details please go to :ref:`installation` which includes the recommended way instructions for installing Pecan, go to :ref:`installation`.
of setting up a proper development environment.
Base Application Template Base Application Template
------------------------- -------------------------
We include a basic template to have a good layout for a Pecan project. This is A basic template for getting started is included with Pecan. From
accomplished by the ``pecan`` command line script bundled with the framework. your shell, type::
Invoking the command to create a project is trivial::
$ pecan create -t base $ pecan create
The above command will prompt you for a project name. I chose *test_project*, The above command will prompt you for a project name. I chose *test_project*,
but you can also provided as an argument at the end of the example command but you can also provided as an argument at the end of the example command
above, like:: above, like::
$ pecan create -t base test_project $ pecan create test_project
This is how it looks like when we run the whole command:: Go ahead and change into your newly created project directory::
$ pecan create -t base $ cd test_project
Selected and implied templates: $ ls
pecan#pecan-base Template for creating a basic Framework package
Enter project name: test_project This is how the layout of your new project should look::
Variables:
egg: test_project
package: test_project
project: test_project
Creating template pecan-base
Creating directory ./test_project
Recursing into +egg+
Creating ./test_project/test_project/
Copying __init__.py to ./test_project/test_project/__init__.py
Recursing into controllers
Creating ./test_project/test_project/controllers/
Copying __init__.py to ./test_project/test_project/controllers/__init__.py
Copying root.py to ./test_project/test_project/controllers/root.py
Recursing into model
Creating ./test_project/test_project/model/
Copying __init__.py to ./test_project/test_project/model/__init__.py
Recursing into templates
Creating ./test_project/test_project/templates/
Copying index.html to ./test_project/test_project/templates/index.html
Copying layout.html to ./test_project/test_project/templates/layout.html
Copying success.html to ./test_project/test_project/templates/success.html
Recursing into public
Creating ./test_project/public/
Recursing into css
Creating ./test_project/public/css/
Copying style.css to ./test_project/public/css/style.css
Recursing into javascript
Creating ./test_project/public/javascript/
Copying shared.js to ./test_project/public/javascript/shared.js
This is how the structure of your new project should look like::
├── MANIFEST.in ├── MANIFEST.in
├── config.py ├── config.py
@@ -74,77 +38,67 @@ This is how the structure of your new project should look like::
│   │   └── style.css │   │   └── style.css
│   └── javascript │   └── javascript
│   └── shared.js │   └── shared.js
├── setup.cfg
├── setup.py ├── setup.py
── test_project ── test_project
   ├── __init__.py    ├── __init__.py
   ├── app.py    ├── app.py
   ├── controllers    ├── controllers
   │   ├── __init__.py    │   ├── __init__.py
   │   └── root.py    │   └── root.py
   ├── model    ├── model
   │   └── __init__.py    │   └── __init__.py
   ├── templates    ├── templates
   │   ├── error.html    │   ├── error.html
   │   ├── index.html    │   ├── index.html
   │   ├── layout.html    │   ├── layout.html
   │   └── success.html    │   └── success.html
   └── tests    └── tests
   ├── __init__.py    ├── __init__.py
   ├── test_config.py    ├── test_config.py
   └── test_root.py    └── test_root.py
└── test_project.egg-info
├── PKG-INFO
├── SOURCES.txt
├── dependency_links.txt
├── not-zip-safe
├── paster_plugins.txt
├── requires.txt
└── top_level.txt
9 directories, 25 files The amount of files and directories may vary, but the above structure should
give you an idea of what you should expect.
The amount of files and directories may vary from time to time, but the above A few things have been created for you, so let's review them one by one:
structure should give you an idea of what you should expect.
A few things have been set for you, let's review them one by one: * **public**: All your static files (like CSS and Javascript) live here. If you
have any images (this example app doesn't) they would live here too.
* **public**: All your public static files like CSS and Javascript are placed
here. If you have some images (this example app doesn't) it would make sense
to get them here as well.
Inside the project name you chose you have a few directories, and for the The remaining directories encompass your models, controllers and templates, and
most part, it will contain your models, controllers and templates: tests:
* **controllers**: The container directory for your controller files. * **test_project/controllers**: The container directory for your controller files.
* **templates**: All your templates would go in here. * **test_project/templates**: All your templates go in here.
* **model**: Container for your model files. * **test_project/model**: Container for your model files.
* **tests**: All your application test files. * **test_project/tests**: All of the tests for your application.
To avoid unneeded dependencies and to remain as flexible as possible, Pecan doesn't impose any database or To avoid unneeded dependencies and to remain as flexible as possible, Pecan
ORM (Object Relational Mapper) out of the box. You may notice that **model/__init__.py** is mostly empty. doesn't impose any database or ORM (Object Relational Mapper) out of the box.
Its contents generally contain any code necessary to define tables, ORM definitions, and parse bindings from You may notice that **model/__init__.py** is mostly empty. You may wish to add
your configuration file. code here to define tables, ORM definitions, and parse bindings from your
configuration file.
.. note:: .. note::
With your base project you also got some ready-to-run tests. Try running The base project contains some ready-to-run tests. Try running
``py.test`` (the recommended test runner for Pecan) and see them passing! ``py.test`` (the recommended test runner for Pecan) and watch them pass!
.. _running_application: .. _running_application:
Running the application Running the application
----------------------- -----------------------
The most important file to run your application is your configuration file, the Before starting up your Pecan app, you'll need a configuration file. The
base project template should have created one for you already and it should be base project template should have created one for you already, ``config.py``.
named ``config.py``.
This file already contains the necessary information to run a Pecan app, like This file already contains the necessary information to run a Pecan app, like
ports, static paths and so forth. ports, static paths and so forth.
If you just run ``pecan serve`` passing ``config.py`` as an argument for If you just run ``pecan serve``, passing ``config.py`` as an argument for
configuration it will bring up the development server and serve the app:: configuration, it will bring up the development server and serve the app::
$ pecan serve config.py $ pecan serve config.py
Starting subprocess with file monitor Starting subprocess with file monitor
@@ -152,27 +106,15 @@ configuration it will bring up the development server and serve the app::
serving on 0.0.0.0:8080 view at http://127.0.0.1:8080 serving on 0.0.0.0:8080 view at http://127.0.0.1:8080
To get up and running in no time the template helps a lot! The location for the config file and the argument itself are very flexible -
you can pass an absolute or relative path to the file.
.. note::
If you fail to pass an argument you will get a small error message asking
for a configuration file.
The location for the config file and the argument itself are very flexible. You
can pass an absolute path or just the name of the file without an extension,
like::
$ pecan serve config
Simple Configuration Simple Configuration
-------------------- --------------------
We mentioned that you get a Python file with some configurations. The only For ease of use, Pecan configuration files are pure Python.
Python syntax that you will see is the first line that imports the
RootController that is in turn placed as the application root. Everything else,
including possible custom configurations are set as Python dictionaries.
This is how your default configuration file should look like:: This is how your default configuration file should look::
from test_project.controllers.root import RootController from test_project.controllers.root import RootController
@@ -188,8 +130,8 @@ This is how your default configuration file should look like::
app = { app = {
'root' : RootController(), 'root' : RootController(),
'modules' : [test_project], 'modules' : [test_project],
'static_root' : 'public', 'static_root' : '%(confdir)s/public',
'template_path' : 'test_project/templates', 'template_path' : '%(confdir)s/test_project/templates',
'reload': True, 'reload': True,
'debug' : True, 'debug' : True,
'errors' : { 'errors' : {
@@ -206,28 +148,21 @@ This is how your default configuration file should look like::
# pecan.conf # pecan.conf
.. note::
If you named your project something other than *test_project*
you should see that same name above instead.
**Nothing** in the configuration file above is actually required for Pecan to **Nothing** in the configuration file above is actually required for Pecan to
be able to run. If you fail to provide some values Pecan will fill in the run. If you fail to provide some values, Pecan will fill in the missing things
missing things it needs to run. it needs to run.
You also get the ability to set your own configurations as dictionaries and you You can also add your own configuration as dictionaries.
get a commented out example on how to do that.
We are not going to explain much more about configuration here, if you need For more specific documentation on configuration, see the :ref:`Configuration`
more specific details, go to the :ref:`Configuration` section. section.
Root Controller Root Controller
--------------- ---------------
The Root Controller is the main point of contact between your application and The Root Controller is the root of your application.
the framework.
This is how it looks from the project template:: This is how it looks in the project template::
from pecan import expose, request from pecan import expose, request
from formencode import Schema, validators as v from formencode import Schema, validators as v
@@ -259,35 +194,33 @@ This is how it looks from the project template::
Here you can specify other classes if you need to do so later on your project, You can specify additional classes if you need to do so, but for now we have an
but for now we have an *index* method and a *handle_form* one. *index* and *handle_form* method.
**index**: Is *exposed* via the decorator ``@expose`` (that in turn uses the **index**: is *exposed* via the decorator ``@expose`` (which in turn uses the
``index.html`` file) as the root of the application, so anything that hits ``index.html`` template) at the root of the application (http://127.0.0.1:8080/),
the root of you application will touch this method. so anything that hits the root of your application will touch this method.
What your index method returns is a dictionary that is received by the template Notice that the index method returns a dictionary - this dictionary is used as
engine and translated into valid HTML. a namespace to render the specified template (``index.html``) into HTML.
Since we are doing some validation and want to pass any errors we might get to Since we are performing form validation and want to pass any errors we might
the template, we set ``errors`` to receive anything that get to the template, we set ``errors`` to receive form validation errors that
``request.validation_errors`` returns. may exist in ``request.validation_errors``.
**handle_form**: It receives 2 arguments (*name* and *age*) that are validated **handle_form**: receives 2 arguments (*name* and *age*) that are validated
through the *SampleForm* schema class. through the *SampleForm* schema.
The ``error_handler`` has been set to index, this means that when errors are raised The ``error_handler`` has been set to index. This means that when errors are
they will be sent to the index controller so it returns them to the template. raised, they will be sent to the index controller and rendered through its
template.
**error**: Finally, we have the error controller that allows you application to **error**: Finally, we have the error controller that allows your application to
custom display any possible errors that you might want to display. display custom pages for certain HTTP errors (404, etc...).
Application Interaction Application Interaction
----------------------- -----------------------
If you still have your application running and you visit your browser, you should If you still have your application running and you visit it in your browser,
see a nice page with some information about Pecan and a form so you can play a bit you should see a page with some information about Pecan and a form so you can
with. play a bit.
This is very basic but it will give you the grounds necessary to build your application
and understand some of the features the framework packs.

View File

@@ -0,0 +1,36 @@
.. _session:
Working with Sessions and User Authentication
=============
Out of the box, Pecan provides no opinionated support for managing user sessions,
but it's easy to hook into your session framework of choice with minimal
effort.
This article details best practices for integrating the popular session
framework, `Beaker <http://beaker.groovie.org>`_, into your Pecan project.
Setting up Session Management
----------------
There are several approaches that can be taken to set up session management.
One approach is WSGI middleware. Another is Pecan :ref:`hooks`.
Here's an example of wrapping your WSGI application with Beaker's
``SessionMiddleware`` in your project's `app.py`::
from pecan import conf, make_app
from beaker import SessionMiddleware
from test_project import model
app = make_app(
...
)
app = SessionMiddleware(app, conf.beaker)
...and a corresponding dictionary in your configuration file::
beaker = {
'session.key' : 'sessionkey',
'session.type' : 'cookie',
'session.validate_key' : '05d2175d1090e31f42fa36e63b8d2aad',
'__force_dict__' : True
}

View File

@@ -175,9 +175,6 @@ def import_module(conf):
:param conf: The string to the configuration. Automatically strips off ".py" file extensions. :param conf: The string to the configuration. Automatically strips off ".py" file extensions.
''' '''
if conf.endswith('.py'):
conf = conf[:-3]
if '.' in conf: if '.' in conf:
parts = conf.split('.') parts = conf.split('.')
name = '.'.join(parts[:-1]) name = '.'.join(parts[:-1])
@@ -207,15 +204,12 @@ def initconf():
def set_config(name): def set_config(name):
''' '''
Updates the global configuration from a path or filename. Updates the global configuration a filename.
:param name: Path or filename, as a string. :param name: filename, as a string.
''' '''
if '/' in name:
_runtime_conf.update(conf_from_file(name)) _runtime_conf.update(conf_from_file(name))
else:
_runtime_conf.update_with_module(name)
_runtime_conf = initconf() _runtime_conf = initconf()

View File

@@ -1,5 +1,14 @@
from pecan import conf from pecan import conf
def init_model(): def init_model():
# Read and parse database bindings from pecan.conf """
This is a stub method which is called at application startup time.
If you need to bind to a parse database configuration, set up tables or
ORM classes, or perform any database initialization, this is the
recommended place to do it.
For more information working with databases, and some common recipes,
see http://pecan.readthedocs.org/en/latest/databases.html
"""
pass pass

View File

@@ -108,14 +108,6 @@ class TestConf(TestCase):
configuration.set_config(path) configuration.set_config(path)
assert list(_runtime_conf.server) == list(configuration.initconf().server) assert list(_runtime_conf.server) == list(configuration.initconf().server)
def test_config_set_from_module(self):
configuration.set_config('config')
self.assertEqual(_runtime_conf.server.host, '1.1.1.1')
def test_config_set_from_module_with_extension(self):
configuration.set_config('config.py')
self.assertEqual(_runtime_conf.server.host, '1.1.1.1')
def test_config_dir(self): def test_config_dir(self):
if sys.version_info >= (2, 6): if sys.version_info >= (2, 6):
conf = configuration.Config({}) conf = configuration.Config({})