diff options
| author | Ben Bangert <ben@groovie.org> | 2010-10-29 11:14:41 -0700 |
|---|---|---|
| committer | Ben Bangert <ben@groovie.org> | 2010-10-29 11:14:41 -0700 |
| commit | 17e70c8db9140c0b4062f46ef5eb4527d678b793 (patch) | |
| tree | 38b6b8de2a57db4debec477bc4fda27db82c4c5a | |
| parent | d39e99e1f6f06a02a275a8a30f154e0f292d7dff (diff) | |
| parent | 5038994ea9e053b16fca74ea8fa022871e630883 (diff) | |
| download | pyramid-17e70c8db9140c0b4062f46ef5eb4527d678b793.tar.gz pyramid-17e70c8db9140c0b4062f46ef5eb4527d678b793.tar.bz2 pyramid-17e70c8db9140c0b4062f46ef5eb4527d678b793.zip | |
Merge branch 'master' of github.com:Pylons/pyramid
104 files changed, 3120 insertions, 368 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 1e4d73c6c..8d3bfe3a0 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -31,11 +31,28 @@ Features (delta from BFG 1.3.X) - Using ``request.session`` now returns a (dictionary-like) session object if a session factory has been configured. +- New module: ``pyramid.personality.pylons``: contains Pylons-specific + features. + +- The request now has a new attribute: ``tmpl_context`` for benefit of + Pylons users. + +- The decorator previously known as ``pyramid.view.bfg_view`` is now + known most formally as ``pyramid.view.view_config`` in docs and + paster templates. An import of ``pyramid.view.bfg_view``, however, + will continue to work "forever". + Documentation (delta from BFG 1.3) ----------------------------------- - Added a ``pyramid.httpexceptions`` API documentation chapter. +- Added a ``pyramid.session`` API documentation chapter. + +- Added a ``Session Objects`` narrative documentation chapter. + +- Added an API chapter for the ``pyramid.personality`` module. + Backwards Incompatibilities (with BFG 1.3.X) -------------------------------------------- diff --git a/HACKING.txt b/HACKING.txt index 7de34bed6..464b653c1 100644 --- a/HACKING.txt +++ b/HACKING.txt @@ -1,7 +1,15 @@ -In order to add a feature to this package: +Hacking on Pyramid +================== + +Here are some guidelines about hacking on Pyramid. + +Adding Features +--------------- + +In order to add a feature to Pyramid: - The feature must be documented in both the API and narrative - documentation (in docs/). + documentation (in ``docs/``). - The feature must work fully on the following CPython versions: 2.4, 2.5, 2.6, and 2.7 on both UNIX and Windows. @@ -19,6 +27,38 @@ In order to add a feature to this package: be discussed). The above requirements are relaxed for paster template dependencies. -If a paster template has a dependency on something that doesn't work -on a particular platform, that caveat should be spelled out clearly in -*its* documentation (within docs/). +If a paster template has an install-time dependency on something that +doesn't work on a particular platform, that caveat should be spelled +out clearly in *its* documentation (within its ``docs/`` directory). + +Coding Style +------------ + +- PEP8 compliance. Whitespace rules are relaxed: not necessary to put + 2 newlines between classes. But 80-column lines, in particular, are + mandatory. + +Test Coverage +------------- + +- The codebase *must* have 100% test statement coverage after each + commit. You can test coverage via ``python setup.py nosetests + --with-coverage`` (requires the ``nose`` and ``coverage`` packages). + +Documentation Coverage +---------------------- + +- If you fix a bug, and the bug requires an API or behavior + modification, all documentation in this package which references + that API or behavior must change to reflect the bug fix, ideally in + the same commit that fixes the bug or adds the feature. + +Change Log +---------- + +- Feature additions and bugfixes must be added to the ``CHANGES.txt`` + file in the prevailing style. Changelog entries should be long and + descriptive, not cryptic. Other developers should be able to know + what your changelog entry means. + + @@ -62,13 +62,9 @@ - Update App engine chapter. -- Add SessionFactory interface +- Browser id? -- Create session interface (flash() is part of it, figure out granularity) - -- Add CacheFactory interface - -- Browser id +- .flash API on session. - Signed_signature method of the request and response from pylons2. @@ -84,10 +80,12 @@ - ``handler`` ZCML directive. -- ``bfg_view`` alias. - - ``repoze.bfg.message`` alias. - Try to get rid of Mako Beaker dependency. - Maybe make renderer globals lookup send an event? + +- bfgshell + +- ``docs`` directory for each paster template. diff --git a/docs/api.rst b/docs/api.rst index 8e7c0c283..e457d28f0 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -20,6 +20,7 @@ documentation is organized alphabetically by module name. api/interfaces api/location api/paster + api/personality api/renderers api/request api/router diff --git a/docs/api/personality.rst b/docs/api/personality.rst new file mode 100644 index 000000000..7eb964e76 --- /dev/null +++ b/docs/api/personality.rst @@ -0,0 +1,9 @@ +.. _personality_module: + +:mod:`pyramid.personality.pylons` +--------------------------------- + +.. module:: pyramid.personality.pylons + +.. function:: renderer_globals_factory_config + diff --git a/docs/api/request.rst b/docs/api/request.rst index 9e851ba8d..97b164428 100644 --- a/docs/api/request.rst +++ b/docs/api/request.rst @@ -93,3 +93,8 @@ ``request.session`` attribute will cause a :class:`pyramid.exceptions.ConfigurationError` to be raised. + .. attribute:: tmpl_context + + The template context for Pylons-style applications. + + diff --git a/docs/api/view.rst b/docs/api/view.rst index 5e884656c..0057cca4a 100644 --- a/docs/api/view.rst +++ b/docs/api/view.rst @@ -13,7 +13,7 @@ .. autofunction:: is_response - .. autoclass:: bfg_view + .. autoclass:: view_config :members: .. autoclass:: static diff --git a/docs/designdefense.rst b/docs/designdefense.rst index 0e4784c66..c437f18d9 100644 --- a/docs/designdefense.rst +++ b/docs/designdefense.rst @@ -374,14 +374,14 @@ which don't use interfaces. Instead, each predicate uses a domain-specific string as a match value. For example, to write a view configuration which matches only requests -with the ``POST`` HTTP request method, you might write a ``@bfg_view`` +with the ``POST`` HTTP request method, you might write a ``@view_config`` decorator which mentioned the ``request_method`` predicate: .. code-block:: python :linenos: - from pyramid.view import bfg_view - @bfg_view(name='post_view', request_method='POST', renderer='json') + from pyramid.view import view_config + @view_config(name='post_view', request_method='POST', renderer='json') def post_view(request): return 'POSTed' @@ -392,8 +392,8 @@ response: .. code-block:: python :linenos: - from pyramid.view import bfg_view - @bfg_view(name='post_view', request_method='POST', accept='application/json', + from pyramid.view import view_config + @view_config(name='post_view', request_method='POST', accept='application/json', renderer='json') def post_view(request): return 'POSTed' @@ -417,13 +417,13 @@ acommodate this by allowing people to define "custom" view predicates: .. code-block:: python :linenos: - from pyramid.view import bfg_view + from pyramid.view import view_config from webob import Response def subpath(context, request): return request.subpath and request.subpath[0] == 'abc' - @bfg_view(custom_predicates=(subpath,)) + @view_config(custom_predicates=(subpath,)) def aview(request): return Response('OK') @@ -760,7 +760,7 @@ code. Pyramid Is Too Big ------------------ -"The :mod:`pyramid` compressed tarball is 1MB. It must be +"The :mod:`pyramid` compressed tarball is almost 2MB. It must be enormous!" No. We just ship it with test code and helper templates. Here's a @@ -768,26 +768,26 @@ breakdown of what's included in subdirectories of the package tree: docs/ - 2.2MB + 3.0MB -repoze/bfg/tests +pyramid/tests/ - 580KB + 1.1MB -repoze/bfg/paster_templates +pyramid/paster_templates/ - 372KB + 804KB -repoze/bfg (except for ``repoze/bfg/tests and repoze/bfg/paster_templates``) +pyramid/ (except for ``pyramd/tests and pyramid/paster_templates``) - 316K + 539K -The actual :mod:`pyramid` runtime code is about 10% of the total -size of the tarball omitting docs, helper templates used for package +The actual :mod:`pyramid` runtime code is about 10% of the total size +of the tarball omitting docs, helper templates used for package generation, and test code. Of the approximately 13K lines of Python code in the package, the code that actually has a chance of executing during normal operation, excluding tests and paster template Python -files, accounts for approximately 3K lines of Python code. This is +files, accounts for approximately 5K lines of Python code. This is comparable to Pylons, which ships with a little over 2K lines of Python code, excluding tests. diff --git a/docs/glossary.rst b/docs/glossary.rst index 93d86b664..9259fed0a 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -97,20 +97,20 @@ Glossary which will be an instance of a :term:`request` object. An alternate calling convention allows a view to be defined as a callable which accepts a pair of arguments: ``context`` and - ``request``: this calling convention is useful for traversal-based - applications in which a :term:`context` is always very important. A - view callable is the primary mechanism by which a developer writes - user interface code within :mod:`repoze.bfg`. See - :ref:`views_chapter` for more information about :mod:`repoze.bfg` - view callables. + ``request``: this calling convention is useful for + traversal-based applications in which a :term:`context` is always + very important. A view callable is the primary mechanism by + which a developer writes user interface code within + :mod:`pyramid`. See :ref:`views_chapter` for more information + about :mod:`pyramid` view callables. view configuration View configuration is the act of associating a :term:`view callable` with configuration information. This configuration information helps map a given :term:`request` to a particular view callable and it can influence the response of a view callable. - :mod:`repoze.bfg` views can be configured via :term:`imperative - configuration`, :term:`ZCML` or by a special ``@bfg_view`` + :mod:`pyramid` views can be configured via :term:`imperative + configuration`, :term:`ZCML` or by a special ``@view_config`` decorator coupled with a :term:`scan`. See :ref:`views_chapter` for more information about view configuration. @@ -138,12 +138,12 @@ Glossary :term:`context` of a :term:`view`. If :mod:`url dispatch` is used, a single :term:`context` is generated for each request and is used as the context of a view: this object is also technically - a "model" in :mod:`repoze.bfg` terms, although this terminology + a "model" in :mod:`pyramid` terms, although this terminology can be a bit confusing: see :ref:`model_traversal_confusion`. traversal The act of descending "down" a graph of model objects from a root - model in order to find a :term:`context`. The :mod:`repoze.bfg` + model in order to find a :term:`context`. The :mod:`pyramid` :term:`router` performs traversal of model objects when a :term:`root factory` is specified. See the :ref:`traversal_chapter` chapter for more information. Traversal @@ -153,15 +153,15 @@ Glossary router The :term:`WSGI` application created when you start a - :mod:`repoze.bfg` application. The router intercepts requests, + :mod:`pyramid` application. The router intercepts requests, invokes traversal and/or URL dispatch, calls view functions, and returns responses to the WSGI server on behalf of your - :mod:`repoze.bfg` application. + :mod:`pyramid` application. URL dispatch An alternative to graph traversal as a mechanism for locating a :term:`context` for a :term:`view`. When you use a :term:`route` - in your :mod:`repoze.bfg` application via a :term:`route + in your :mod:`pyramid` application via a :term:`route configuration`, you are using URL dispatch. See the :ref:`urldispatch_chapter` for more information. @@ -178,10 +178,10 @@ Glossary application registry A registry of configuration information consulted by - :mod:`repoze.bfg` while servicing an application. An application + :mod:`pyramid` while servicing an application. An application registry maps model types to views, as well as housing other application-specific component registrations. Every - :mod:`repoze.bfg` application has one (and only one) application + :mod:`pyramid` application has one (and only one) application registry. template @@ -235,7 +235,7 @@ Glossary authentication The act of determining that the credentials a user presents during a particular request are "good". Authentication in - :mod:`repoze.bfg` is performed via an :term:`authentication + :mod:`pyramid` is performed via an :term:`authentication policy`. authorization @@ -243,7 +243,7 @@ Glossary action. In bfg terms, this means determining whether, for a given context, any :term:`principal` (or principals) associated with the request have the requisite :term:`permission` to allow the request - to continue. Authorization in :mod:`repoze.bfg` is performed via + to continue. Authorization in :mod:`pyramid` is performed via its :term:`authorization policy`. principal @@ -256,21 +256,21 @@ Glossary "group foo" and "group bar". authorization policy - An authorization policy in :mod:`repoze.bfg` terms is a bit of + An authorization policy in :mod:`pyramid` terms is a bit of code which has an API which determines whether or not the principals associated with the request can perform an action associated with a permission, based on the information found on the :term:`context`. authentication policy - An authentication policy in :mod:`repoze.bfg` terms is a bit of + An authentication policy in :mod:`pyramid` terms is a bit of code which has an API which determines the current :term:`principal` (or principals) associated with a request. WSGI `Web Server Gateway Interface <http://wsgi.org/>`_. This is a Python standard for connecting web applications to web servers, - similar to the concept of Java Servlets. ``repoze.bfg`` requires + similar to the concept of Java Servlets. ``pyramid`` requires that your application be served as a WSGI application. middleware @@ -318,7 +318,7 @@ Glossary PasteDeploy `PasteDeploy <http://pythonpaste.org>`_ is a library used by - :mod:`repoze.bfg` which makes it possible to configure + :mod:`pyramid` which makes it possible to configure :term:`WSGI` components together declaratively within an ``.ini`` file. It was developed by Ian Bicking as part of :term:`Paste`. @@ -329,7 +329,7 @@ Glossary maintained by Malthe Borch. It has several extensions, such as the ability to use bracketed (Genshi-style) ``${name}`` syntax, even within ZPT. It is also much faster than the reference - implementations of both ZPT and Genshi. :mod:`repoze.bfg` offers + implementations of both ZPT and Genshi. :mod:`pyramid` offers Chameleon templating out of the box in ZPT and text flavors. ZPT @@ -352,7 +352,7 @@ Glossary Routes A `system by Ben Bangert <http://routes.groovie.org/>`_ which parses URLs and compares them against a number of user defined - mappings. The URL pattern matching syntax in :mod:`repoze.bfg` is + mappings. The URL pattern matching syntax in :mod:`pyramid` is inspired by the Routes syntax (which was inspired by Ruby On Rails pattern syntax). @@ -372,11 +372,11 @@ Glossary ZCML `Zope Configuration Markup Language <http://www.muthukadan.net/docs/zca.html#zcml>`_, an XML dialect - used by Zope and :mod:`repoze.bfg` for configuration tasks. ZCML + used by Zope and :mod:`pyramid` for configuration tasks. ZCML is capable of performing different types of :term:`configuration - declaration`, but its primary purpose in :mod:`repoze.bfg` is to + declaration`, but its primary purpose in :mod:`pyramid` is to perform :term:`view configuration` and :term:`route configuration` - within the ``configure.zcml`` file in a :mod:`repoze.bfg` + within the ``configure.zcml`` file in a :mod:`pyramid` application. You can use ZCML as an alternative to :term:`imperative configuration`. @@ -391,7 +391,7 @@ Glossary <http://www.muthukadan.net/docs/zca.html>`_ (aka ZCA) is a system which allows for application pluggability and complex dispatching based on objects which implement an :term:`interface`. - :mod:`repoze.bfg` uses the ZCA "under the hood" to perform view + :mod:`pyramid` uses the ZCA "under the hood" to perform view dispatching and other application configuration tasks. reStructuredText @@ -402,7 +402,7 @@ Glossary root The object at which :term:`traversal` begins when - :mod:`repoze.bfg` searches for a :term:`context` (for :term:`URL + :mod:`pyramid` searches for a :term:`context` (for :term:`URL Dispatch`, the root is *always* the context). subpath @@ -415,26 +415,26 @@ Glossary interface A `Zope interface <http://pypi.python.org/pypi/zope.interface>`_ - object. In :mod:`repoze.bfg`, an interface may be attached to a + object. In :mod:`pyramid`, an interface may be attached to a :term:`model` object or a :term:`request` object in order to identify that the object is "of a type". Interfaces are used - internally by :mod:`repoze.bfg` to perform view lookups and other + internally by :mod:`pyramid` to perform view lookups and other policy lookups. The ability to make use of an interface is exposed to an application programmers during :term:`view configuration` via the ``context`` argument, the ``request_type`` argument and the ``containment`` argument. Interfaces are also exposed to application developers when they make use of the - :term:`event` system. Fundamentally, :mod:`repoze.bfg` + :term:`event` system. Fundamentally, :mod:`pyramid` programmers can think of an interface as something that they can attach to an object that stamps it with a "type" unrelated to its underlying Python type. Interfaces can also be used to describe the behavior of an object (its methods and attributes), but - unless they choose to, :mod:`repoze.bfg` programmers do not need + unless they choose to, :mod:`pyramid` programmers do not need to understand or use this feature of interfaces. event An object broadcast to zero or more :term:`subscriber` callables - during normal :mod:`repoze.bfg` system operations during the + during normal :mod:`pyramid` system operations during the lifetime of an application. Application code can subscribe to these events by using the subscriber functionality described in :ref:`events_chapter`. @@ -448,32 +448,32 @@ Glossary request type An attribute of a :term:`request` that allows for specialization of view invocation based on arbitrary categorization. The every - :term:`request` object that :mod:`repoze.bfg` generates and + :term:`request` object that :mod:`pyramid` generates and manipulates has one or more :term:`interface` objects attached to it. The default interface attached to a request object is - ``repoze.bfg.interfaces.IRequest``. + ``pyramid.interfaces.IRequest``. repoze.lemonade Zope2 CMF-like `data structures and helper facilities <http://docs.repoze.org/lemonade>`_ for CA-and-ZODB-based - applications useful within :mod:`repoze.bfg` applications. + applications useful within :mod:`pyramid` applications. repoze.catalog An indexing and search facility (fielded and full-text) based on `zope.index <http://pypi.python.org/pypi/zope.index>`_. See `the documentation <http://docs.repoze.org/catalog>`_ for more - information. A tutorial for its usage in :mod:`repoze.bfg` + information. A tutorial for its usage in :mod:`pyramid` exists in :ref:`catalog_tutorial`. repoze.who `Authentication middleware <http://docs.repoze.org/who>`_ for - :term:`WSGI` applications. It can be used by :mod:`repoze.bfg` to + :term:`WSGI` applications. It can be used by :mod:`pyramid` to provide authentication information. repoze.workflow `Barebones workflow for Python apps <http://docs.repoze.org/workflow>`_ . It can be used by - :mod:`repoze.bfg` to form a workflow system. + :mod:`pyramid` to form a workflow system. virtual root A model object representing the "virtual" root of a request; this @@ -490,11 +490,11 @@ Glossary object in a lineage is available as its ``__parent__`` attribute. root factory - The "root factory" of an :mod:`repoze.bfg` application is called + The "root factory" of an :mod:`pyramid` application is called on every request sent to the application. The root factory returns the traversal root of an application. It is conventionally named ``get_root``. An application may supply a - root factory to :mod:`repoze.bfg` during the construction of a + root factory to :mod:`pyramid` during the construction of a :term:`Configurator`. If a root factory is not supplied, the application uses a default root object. Use of the default root object is useful in application which use :term:`URL dispatch` for @@ -524,7 +524,7 @@ Glossary `mod_wsgi <http://code.google.com/p/modwsgi/>`_ is an Apache module developed by Graham Dumpleton. It allows :term:`WSGI` applications (such as applications developed using - :mod:`repoze.bfg`) to be served using the Apache web server. + :mod:`pyramid`) to be served using the Apache web server. view predicate An argument to a :term:`view configuration` which evaluates to @@ -548,7 +548,7 @@ Glossary predicate A test which returns ``True`` or ``False``. Two different types - of predicates exist in :mod:`repoze.bfg`: a :term:`view predicate` + of predicates exist in :mod:`pyramid`: a :term:`view predicate` and a :term:`route predicate`. View predicates are attached to :term:`view configuration` and route predicates are attached to :term:`route configuration`. @@ -556,13 +556,13 @@ Glossary decorator A wrapper around a Python function or class which accepts the function or class as its first argument and which returns an - arbitrary object. :mod:`repoze.bfg` provides several decorators, + arbitrary object. :mod:`pyramid` provides several decorators, used for configuration and return value modification purposes. See also `PEP 318 <http://www.python.org/dev/peps/pep-0318/>`_. configuration declaration An individual method call made to an instance of a - :mod:`repoze.bfg` :term:`Configurator` object which performs an + :mod:`pyramid` :term:`Configurator` object which performs an arbitrary action, such as registering a :term:`view configuration` (via the ``view`` method of the configurator) or :term:`route configuration` (via the ``route`` method of the configurator). A @@ -572,19 +572,21 @@ Glossary of code in a package. configuration decoration + Metadata implying one or more :term:`configuration declaration` invocations. Often set by configuration Python :term:`decorator` - attributes, such as ``repoze.bfg.view.bfg_view``, aka ``@bfg_view``. + attributes, such as :class:`pyramid.view.view_config`, aka + ``@view_config``. scan - The term used by :mod:`repoze.bfg` to define the process of + The term used by :mod:`pyramid` to define the process of importing and examining all code in a Python package or module for :term:`configuration decoration`. configurator An object used to do :term:`configuration declaration` within an application. The most common configurator is an instance of the - ``repoze.bfg.configuration.Configurator`` class. + ``pyramid.configuration.Configurator`` class. imperative configuration The configuration mode in which you use Python to call methods on @@ -596,28 +598,28 @@ Glossary a set of :term:`configuration declaration` statements. Not Found view - An :term:`exception view` invoked by :mod:`repoze.bfg` when the - developer explicitly raises a ``repoze.bfg.exceptions.NotFound`` + An :term:`exception view` invoked by :mod:`pyramid` when the + developer explicitly raises a ``pyramid.exceptions.NotFound`` exception from within :term:`view` code or :term:`root factory` code, or when the current request doesn't match any :term:`view - configuration`. :mod:`repoze.bfg` provides a default + configuration`. :mod:`pyramid` provides a default implementation of a not found view; it can be overridden. See :ref:`changing_the_notfound_view`. Forbidden view - An :term:`exception view` invoked by :mod:`repoze.bfg` when the + An :term:`exception view` invoked by :mod:`pyramid` when the developer explicitly raises a - ``repoze.bfg.exceptions.Forbidden`` exception from within + ``pyramid.exceptions.Forbidden`` exception from within :term:`view` code or :term:`root factory` code, or when the :term:`view configuration` and :term:`authorization policy` found for a request disallows a particular view invocation. - :mod:`repoze.bfg` provides a default implementation of a + :mod:`pyramid` provides a default implementation of a forbidden view; it can be overridden. See :ref:`changing_the_forbidden_view`. Exception view An exception view is a :term:`view callable` which may be - invoked by :mod:`repoze.bfg` when an exception is raised during + invoked by :mod:`pyramid` when an exception is raised during request processing. See :ref:`exception_views` for more information. @@ -627,7 +629,7 @@ Glossary each `thread <http://en.wikipedia.org/wiki/Thread_(computer_science)>` used by the application may have a different value for this same "global" - variable. :mod:`repoze.bfg` uses a small number of thread local + variable. :mod:`pyramid` uses a small number of thread local variables, as described in :ref:`threadlocals_chapter`. See also the `threading.local documentation <http://docs.python.org/library/threading.html#threading.local>` @@ -653,7 +655,7 @@ Glossary Python The `programming language <http://python.org>` in which - :mod:`repoze.bfg` is written. + :mod:`pyramid` is written. CPython The C implementation of the Python language. This is the @@ -671,7 +673,7 @@ Glossary The act of locating a :term:`context` and a :term:`view name` given a :term:`request`. :term:`Traversal` and :term:`URL dispatch` are the context finding subsystems used by - :mod:`repoze.bfg`. + :mod:`pyramid`. Triad The three bits of information used by :term:`view lookup` to find @@ -681,18 +683,18 @@ Glossary Google App Engine `Google App Engine <http://code.google.com/appengine/>`_ (aka "GAE") is a Python application hosting service offered by Google. - :mod:`repoze.bfg` runs on GAE. + :mod:`pyramid` runs on GAE. Venusian `Venusian <http://docs.repoze.org/venusian>`_ is a library which allows framework authors to defer decorator actions. Instead of taking actions when a function (or class) decorator is executed at import time, the action usually taken by the decorator is - deferred until a separate "scan" phase. :mod:`repoze.bfg` relies + deferred until a separate "scan" phase. :mod:`pyramid` relies on Venusian to provide a basis for its :term:`scan` feature. Translation String - An instance of :class:`repoze.bfg.i18n.TranslationString`, which + An instance of :class:`pyramid.i18n.TranslationString`, which is a class that behaves like a Unicode string, but has several extra attributes such as ``domain``, ``msgid``, and ``mapping`` for use during translation. Translation strings are usually @@ -712,7 +714,7 @@ Glossary A callable which receives a :term:`translation string` and returns a translated Unicode object for the purposes of internationalization. A :term:`localizer` supplies a - translator to a :mod:`repoze.bfg` application accessible via its + translator to a :mod:`pyramid` application accessible via its ``translate`` method. Translation Directory @@ -724,10 +726,10 @@ Glossary (minus the .mo extension) is the translation domain name. Localizer - An instance of the class :class:`repoze.bfg.i18n.Localizer` which + An instance of the class :class:`pyramid.i18n.Localizer` which provides translation and pluralization services to an application. It is retrieved via the - :func:`repoze.bfg.i18n.get_localizer` function. + :func:`pyramid.i18n.get_localizer` function. Locale Name A string like ``en``, ``en_US``, ``de``, or ``de_AT`` which @@ -740,19 +742,19 @@ Glossary Locale Negotiator An object supplying a policy determining which :term:`locale name` best represents a given :term:`request`. It is used by the - :func:`repoze.bfg.i18n.get_locale_name`, and - :func:`repoze.bfg.i18n.negotiate_locale_name` functions, and - indirectly by :func:`repoze.bfg.i18n.get_localizer`. The - :func:`repoze.bfg.i18n.default_locale_negotiator` function + :func:`pyramid.i18n.get_locale_name`, and + :func:`pyramid.i18n.negotiate_locale_name` functions, and + indirectly by :func:`pyramid.i18n.get_localizer`. The + :func:`pyramid.i18n.default_locale_negotiator` function is an example of a locale negotiator. Gettext The GNU `gettext <http://www.gnu.org/software/gettext/>`_ - library, used by the :mod:`repoze.bfg` translation machinery. + library, used by the :mod:`pyramid` translation machinery. Babel A `collection of tools <http://babel.edgewall.org/>`_ for - internationalizing Python applications. :mod:`repoze.bfg` does + internationalizing Python applications. :mod:`pyramid` does not depend on Babel to operate, but if Babel is installed, additional locale functionality becomes available to your application. @@ -797,11 +799,11 @@ Glossary pregenerator A pregenerator is a function associated by a developer with a - :term:`route`. It is called by :func:`repoze.bfg.url.route_url` + :term:`route`. It is called by :func:`pyramid.url.route_url` in order to adjust the set of arguments passed to it by the user for special purposes. It will influence the URL returned by ``route_url``. See - :class:`repoze.bfg.interfaces.IRoutePregenerator` for more + :class:`pyramid.interfaces.IRoutePregenerator` for more information. session diff --git a/docs/narr/configuration.rst b/docs/narr/configuration.rst index fe55705bb..a62cf76ff 100644 --- a/docs/narr/configuration.rst +++ b/docs/narr/configuration.rst @@ -254,7 +254,7 @@ application. This error will contain information about which tags might have conflicted. .. index:: - single: bfg_view + single: view_config single: ZCML view directive single: configuration decoration single: code scanning @@ -277,10 +277,10 @@ referred to by the declaration itself. For example: .. code-block:: python :linenos: - from pyramid.view import bfg_view + from pyramid.view import view_config from webob import Response - @bfg_view(name='hello', request_method='GET') + @view_config(name='hello', request_method='GET') def hello(request): return Response('Hello') @@ -290,7 +290,7 @@ the configuration of a :mod:`pyramid` application, a configuration decoration within application code must be found through a process known as a :term:`scan`. -The :class:`pyramid.view.bfg_view` decorator above adds an +The :class:`pyramid.view.view_config` decorator above adds an attribute to the ``hello`` function, making it available for a :term:`scan` to find it later. @@ -306,10 +306,10 @@ and its subpackages. For example: :linenos: from paste.httpserver import serve - from pyramid.view import bfg_view + from pyramid.view import view_config from webob import Response - @bfg_view() + @view_config() def hello(request): return Response('Hello') @@ -334,10 +334,10 @@ directive, the package the ZCML file points to is scanned. # helloworld.py from paste.httpserver import serve - from pyramid.view import bfg_view + from pyramid.view import view_config from webob import Response - @bfg_view() + @view_config() def hello(request): return Response('Hello') @@ -366,7 +366,7 @@ The scanning machinery imports each module and subpackage in a package or module recursively, looking for special attributes attached to objects defined within a module. These special attributes are typically attached to code via the use of a :term:`decorator`. For -example, the :class:`pyramid.view.bfg_view` decorator can be +example, the :class:`pyramid.view.view_config` decorator can be attached to a function or instance method. Once scanning is invoked, and :term:`configuration decoration` is @@ -375,7 +375,7 @@ found by the scanner, a set of calls are made to a the intent of the configuration decoration. In the example above, this is best represented as the scanner -translating the arguments to :class:`pyramid.view.bfg_view` into a +translating the arguments to :class:`pyramid.view.view_config` into a call to the :meth:`pyramid.configuration.Configurator.add_view` method, effectively: diff --git a/docs/narr/extending.rst b/docs/narr/extending.rst index 490d0733f..88b42eabf 100644 --- a/docs/narr/extending.rst +++ b/docs/narr/extending.rst @@ -39,7 +39,7 @@ The fundamental "plug points" of an application developed using :mod:`pyramid` are *routes*, *views*, and *resources*. Routes are declarations made using the ZCML ``<route>`` directive. Views are declarations made using the ZCML ``<view>`` directive (or the -``@bfg_view`` decorator). Resources are files that are accessed by +``@view_config`` decorator). Resources are files that are accessed by :mod:`pyramid` using the :term:`pkg_resources` API such as static files and templates. @@ -89,7 +89,7 @@ Extending an Application Which Possesses Configuration Decorators Or Which Does ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you've inherited a :mod:`pyramid` application which uses -:class:`pyramid.view.bfg_view` decorators or which performs +:class:`pyramid.view.view_config` decorators or which performs configuration imperatively, one of two things may be true: - If you just want to *extend* the application, you can write @@ -101,7 +101,7 @@ configuration imperatively, one of two things may be true: *may* need to change the source code of the original application. If the only source of trouble is the existence of - :class:`pyramid.view.bfg_view` decorators, you can just prevent a + :class:`pyramid.view.view_config` decorators, you can just prevent a :term:`scan` from happening (by omitting the ``<scan>`` declaration from ZCML or omitting any call to the :meth:`pyramid.configuration.Configurator.scan` method). This diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index db933c525..12c1cd0aa 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -556,7 +556,7 @@ subscriber of a :class:`pyramid.interfaces.INewRequest` event). Registering Configuration Decorators ------------------------------------ -Decorators such as :class:`pyramid.view.bfg_view` don't change the +Decorators such as :class:`pyramid.view.view_config` don't change the behavior of the functions or classes they're decorating. Instead, when a :term:`scan` is performed, a modified version of the function or class is registered with :mod:`pyramid`. diff --git a/docs/narr/project.rst b/docs/narr/project.rst index 0e18f0924..f88496fcc 100644 --- a/docs/narr/project.rst +++ b/docs/narr/project.rst @@ -21,6 +21,9 @@ templates". single: pyramid_zodb paster template single: pyramid_alchemy paster template single: pyramid_routesalchemy paster template + single: pylons_minimal paster template + single: pylons_basic paster template + single: pylons_sqla paster template .. _additional_paster_templates: @@ -52,6 +55,18 @@ The included templates are these: URL mapping via :term:`traversal` and persistence via :term:`SQLAlchemy` +``pylons_minimal`` + URL mapping via :term:`URL dispatch` and Pylons-style view handlers, + minimal setup. + +``pylons_basic`` + URL mapping via :term:`URL dispatch` and Pylons-style view handlers, + and some extra functionality. + +``pylons_sqla`` + URL mapping via :term:`URL dispatch` and Pylons-style view handlers, + some extra functionality, and SQLAlchemy set up. + Each of these project templates uses :term:`ZCML` instead of :term:`imperative configuration`. Each also makes the assumption that you want your code to live in a Python :term:`package`. Even if your diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 5782837aa..63d1cad25 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -181,16 +181,16 @@ For example, the following declaration protects the view named /> The equivalent view registration including the ``add`` permission name -may be performed via the ``@bfg_view`` decorator: +may be performed via the ``@view_config`` decorator: .. ignore-next-block .. code-block:: python :linenos: - from pyramid.view import bfg_view + from pyramid.view import view_config from models import Blog - @bfg_view(context=Blog, name='add_entry.html', permission='add') + @view_config(context=Blog, name='add_entry.html', permission='add') def blog_entry_add_view(request): """ Add blog entry code goes here """ pass diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index e460e2d74..df164e684 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -88,9 +88,6 @@ two extra methods. Extra attributes: -``modified`` - An integer timestamp indicating the last time the session was modified. - ``created`` An integer timestamp indicating the time that this session was created. @@ -130,13 +127,24 @@ Some gotchas: When in doubt, call ``changed()`` after you've changed sessioning data. +.. index:: + single: pyramid_beaker + single: Beaker + Using Alternate Session Factories --------------------------------- -At the time of this writing, alternate session factories don't yet -exist. It is our intent that we will soon provide at least one other -session factory which will be easily installable: one that uses the -`Beaker <http://beaker.groovie.org/>`_ library as a backend. +At the time of this writing, exactly one alternate session factory +implementation exists, named ``pyramid_beaker``. This is a session +factory that uses the `Beaker <http://beaker.groovie.org/>`_ library +as a backend. Beaker has support for file-based sessions, database +based sessions, and encrypted cookie-based sessions. See +`http://github.com/Pylons/pyramid_beaker +<http://github.com/Pylons/pyramid_beaker>`_ for more information about +``pyramid_beaker``. + +.. index:: + single: session factory Creating Your Own Session Factory --------------------------------- diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst index 0650480af..57d1bc3b9 100644 --- a/docs/narr/templates.rst +++ b/docs/narr/templates.rst @@ -285,16 +285,16 @@ The association of a template as a renderer for a :term:`view configuration` makes it possible to replace code within a :term:`view callable` that handles the rendering of a template. -Here's an example of using a :class:`pyramid.view.bfg_view` +Here's an example of using a :class:`pyramid.view.view_config` decorator to specify a :term:`view configuration` that names a template renderer: .. code-block:: python :linenos: - from pyramid.view import bfg_view + from pyramid.view import view_config - @bfg_view(renderer='templates/foo.pt') + @view_config(renderer='templates/foo.pt') def my_view(request): return {'foo':1, 'bar':2} @@ -310,7 +310,7 @@ Similar renderer configuration can be done imperatively and via :term:`ZCML`. See :ref:`views_which_use_a_renderer`. See also :ref:`built_in_renderers`. -The ``renderer`` argument to the ``@bfg_view`` configuration decorator +The ``renderer`` argument to the ``@view_config`` configuration decorator shown above is the template *path*. In the example above, the path ``templates/foo.pt`` is *relative*. Relative to what, you ask? Relative to the directory in which the file which defines the view @@ -347,7 +347,7 @@ of :term:`Jinja2` templates as renderers. See configuration typically return a dictionary, and making assertions about the information is almost always more direct than needing to parse HTML. Specifying a renderer from within :term:`ZCML` (as - opposed to imperatively or via a ``bfg_view`` decorator, or using a + opposed to imperatively or via a ``view_config`` decorator, or using a template directly from within a view callable) also makes it possible for someone to modify the template used to render a view without needing to fork your code to do so. See @@ -401,9 +401,9 @@ the template as a :term:`renderer` like so: .. code-block:: python :linenos: - from pyramid.view import bfg_view + from pyramid.view import view_config - @bfg_view(renderer='templates/foo.pt') + @view_config(renderer='templates/foo.pt') def my_view(request): return {'foo':1, 'bar':2} @@ -467,16 +467,16 @@ the macro itself) *into* the rendered template. To make a macro available to the rendered template, you can retrieve a different template using the :func:`pyramid.renderers.get_renderer` API, and pass it in to the template being rendered. For example, using a -:term:`view configuration` via a :class:`pyramid.view.bfg_view` +:term:`view configuration` via a :class:`pyramid.view.view_config` decorator that uses a :term:`renderer`: .. code-block:: python :linenos: from pyramid.renderers import get_renderer - from pyramid.view import bfg_view + from pyramid.view import view_config - @bfg_view(renderer='templates/mytemplate.pt') + @view_config(renderer='templates/mytemplate.pt') def my_view(request): main = get_renderer('templates/master.pt').implementation() return {'main':main} @@ -534,9 +534,9 @@ which renders this template: .. code-block:: python :linenos: - from pyramid.view import bfg_view + from pyramid.view import view_config - @bfg_view(renderer='templates/mytemplate.txt') + @view_config(renderer='templates/mytemplate.txt') def my_view(request): return {'name':'world'} diff --git a/docs/narr/views.rst b/docs/narr/views.rst index 2969487d3..39115a493 100644 --- a/docs/narr/views.rst +++ b/docs/narr/views.rst @@ -255,9 +255,9 @@ Response interface, :mod:`pyramid` will attempt to use a :linenos: from webob import Response - from pyramid.view import bfg_view + from pyramid.view import view_config - @bfg_view(renderer='json') + @view_config(renderer='json') def hello_world(request): return {'content':'Hello!'} @@ -266,7 +266,7 @@ dictionary does not implement the :term:`WebOb` response interface, so you might believe that this example would fail. However, since a ``renderer`` is associated with the view callable through its :term:`view configuration` (in this case, using a ``renderer`` -argument passed to :func:`pyramid.view.bfg_view`), if the view does +argument passed to :func:`pyramid.view.view_config`), if the view does *not* return a Response object, the renderer will attempt to convert the result of the view to a response on the developer's behalf. Of course, if no renderer is associated with a view's configuration, @@ -411,9 +411,9 @@ representation of the dictionary: :linenos: from webob import Response - from pyramid.view import bfg_view + from pyramid.view import view_config - @bfg_view(renderer='string') + @view_config(renderer='string') def hello_world(request): return {'content':'Hello!'} @@ -450,9 +450,9 @@ view will render the returned dictionary to a JSON serialization: :linenos: from webob import Response - from pyramid.view import bfg_view + from pyramid.view import view_config - @bfg_view(renderer='json') + @view_config(renderer='json') def hello_world(request): return {'content':'Hello!'} @@ -610,9 +610,9 @@ attribute to the request before returning a result: .. code-block:: python :linenos: - from pyramid.view import bfg_view + from pyramid.view import view_config - @bfg_view(name='gone', renderer='templates/gone.pt') + @view_config(name='gone', renderer='templates/gone.pt') def myview(request): request.response_status = '404 Not Found' return {'URL':request.URL} @@ -737,9 +737,9 @@ attribute of a :term:`view configuration`: .. code-block:: python :linenos: - from pyramid.view import bfg_view + from pyramid.view import view_config - @bfg_view(renderer='amf') + @view_config(renderer='amf') def myview(request): return {'Hello':'world'} @@ -771,9 +771,9 @@ configuration`: .. code-block:: python :linenos: - from pyramid.view import bfg_view + from pyramid.view import view_config - @bfg_view(renderer='templates/mytemplate.jinja2') + @view_config(renderer='templates/mytemplate.jinja2') def myview(request): return {'Hello':'world'} @@ -928,7 +928,7 @@ code raises a ``hellworld.exceptions.ValidationFailure`` exception: from helloworld.exceptions import ValidationFailure - @bfg_view(context=ValidationFailure) + @view_config(context=ValidationFailure) def failed_validation(exc, request): response = Response('Failed validation: %s' % exc.msg) response.status_int = 500 @@ -946,11 +946,11 @@ exception view registration: .. code-block:: python :linenos: - from pyramid.view import bfg_view + from pyramid.view import view_config from pyramid.exceptions import NotFound from webob.exc import HTTPNotFound - @bfg_view(context=NotFound, route_name='home') + @view_config(context=NotFound, route_name='home') def notfound_view(request): return HTTPNotFound() @@ -976,7 +976,7 @@ registered as exception views which have a name will be ignored. normal view. The feature can be used with any view registration mechanism -(``@bfg_view`` decorator, ZCML, or imperative ``add_view`` styles). +(``@view_config`` decorator, ZCML, or imperative ``add_view`` styles). .. index:: single: unicode, views, and forms @@ -1120,8 +1120,8 @@ View configuration is performed in one of three ways: :ref:`view_directive`. - by running a :term:`scan` against application source code which has - a :class:`pyramid.view.bfg_view` decorator attached to a Python - object as per :class:`pyramid.view.bfg_view` and + a :class:`pyramid.view.view_config` decorator attached to a Python + object as per :class:`pyramid.view.view_config` and :ref:`mapping_views_using_a_decorator_section`. - by using the :meth:`pyramid.configuration.Configurator.add_view` @@ -1497,15 +1497,15 @@ apply for the class which is named. See :ref:`view_directive` for complete ZCML directive documentation. .. index:: - single: bfg_view decorator + single: view_config decorator .. _mapping_views_using_a_decorator_section: -View Configuration Using the ``@bfg_view`` Decorator +View Configuration Using the ``@view_config`` Decorator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For better locality of reference, you may use the -:class:`pyramid.view.bfg_view` decorator to associate your view +:class:`pyramid.view.view_config` decorator to associate your view functions with URLs instead of using :term:`ZCML` or imperative configuration for the same purpose. @@ -1520,15 +1520,15 @@ configuration for the same purpose. See :ref:`extending_chapter` for more information about building extensible applications. -Usage of the ``bfg_view`` decorator is a form of :term:`declarative +Usage of the ``view_config`` decorator is a form of :term:`declarative configuration`, like ZCML, but in decorator form. -:class:`pyramid.view.bfg_view` can be used to associate :term:`view +:class:`pyramid.view.view_config` can be used to associate :term:`view configuration` information -- as done via the equivalent ZCML -- with a function that acts as a :mod:`pyramid` view callable. All ZCML :ref:`view_directive` attributes (save for the ``view`` attribute) are available in decorator form and mean precisely the same thing. -An example of the :class:`pyramid.view.bfg_view` decorator might +An example of the :class:`pyramid.view.view_config` decorator might reside in a :mod:`pyramid` application module ``views.py``: .. ignore-next-block @@ -1536,10 +1536,10 @@ reside in a :mod:`pyramid` application module ``views.py``: :linenos: from models import MyModel - from pyramid.view import bfg_view + from pyramid.view import view_config from pyramid.chameleon_zpt import render_template_to_response - @bfg_view(name='my_view', request_method='POST', context=MyModel, + @view_config(name='my_view', request_method='POST', context=MyModel, permission='read', renderer='templates/my.pt') def my_view(request): return {'a':1} @@ -1567,15 +1567,15 @@ Or replaces the need to add this imperative configuration stanza: config.add_view('.views.my_view', name='my_view', request_method='POST', context=MyModel, permission='read') -All arguments to ``bfg_view`` may be omitted. For example: +All arguments to ``view_config`` may be omitted. For example: .. code-block:: python :linenos: from webob import Response - from pyramid.view import bfg_view + from pyramid.view import view_config - @bfg_view() + @view_config() def my_view(request): """ My view """ return Response() @@ -1586,9 +1586,9 @@ matches any model type, using no permission, registered against requests with any request method / request type / request param / route name / containment. -The mere existence of a ``@bfg_view`` decorator doesn't suffice to +The mere existence of a ``@view_config`` decorator doesn't suffice to perform view configuration. To make :mod:`pyramid` process your -:class:`pyramid.view.bfg_view` declarations, you *must* do one of +:class:`pyramid.view.view_config` declarations, you *must* do one of the following: - If you are using :term:`ZCML`, insert the following boilerplate into @@ -1610,7 +1610,7 @@ the following: Please see :ref:`decorations_and_code_scanning` for detailed information about what happens when code is scanned for configuration declarations resulting from use of decorators like -:class:`pyramid.view.bfg_view`. +:class:`pyramid.view.view_config`. See :ref:`configuration_module` for additional API arguments to the :meth:`pyramid.configuration.Configurator.scan` method. For @@ -1619,10 +1619,10 @@ better control exactly *which* code will be scanned. This is the same value implied by the ``package`` attribute of the ZCML ``<scan>`` directive (see :ref:`scan_directive`). -``@bfg_view`` Placement -+++++++++++++++++++++++ +``@view_config`` Placement +++++++++++++++++++++++++++ -A :class:`pyramid.view.bfg_view` decorator can be placed in various +A :class:`pyramid.view.view_config` decorator can be placed in various points in your application. If your view callable is a function, it may be used as a function @@ -1631,10 +1631,10 @@ decorator: .. code-block:: python :linenos: - from pyramid.view import bfg_view + from pyramid.view import view_config from webob import Response - @bfg_view(name='edit') + @view_config(name='edit') def edit(request): return Response('edited!') @@ -1648,9 +1648,9 @@ function. For example: :linenos: from webob import Response - from pyramid.view import bfg_view + from pyramid.view import view_config - @bfg_view() + @view_config() class MyView(object): def __init__(self, request): self.request = request @@ -1658,7 +1658,7 @@ function. For example: def __call__(self): return Response('hello') -You can use the :class:`pyramid.view.bfg_view` decorator as a +You can use the :class:`pyramid.view.view_config` decorator as a simple callable to manually decorate classes in Python 2.5 and below without the decorator syntactic sugar, if you wish: @@ -1666,7 +1666,7 @@ without the decorator syntactic sugar, if you wish: :linenos: from webob import Response - from pyramid.view import bfg_view + from pyramid.view import view_config class MyView(object): def __init__(self, request): @@ -1675,20 +1675,20 @@ without the decorator syntactic sugar, if you wish: def __call__(self): return Response('hello') - my_view = bfg_view()(MyView) + my_view = view_config()(MyView) -More than one :class:`pyramid.view.bfg_view` decorator can be +More than one :class:`pyramid.view.view_config` decorator can be stacked on top of any number of others. Each decorator creates a separate view registration. For example: .. code-block:: python :linenos: - from pyramid.view import bfg_view + from pyramid.view import view_config from webob import Response - @bfg_view(name='edit') - @bfg_view(name='change') + @view_config(name='edit') + @view_config(name='change') def edit(request): return Response('edited!') @@ -1700,13 +1700,13 @@ The decorator can also be used against class methods: :linenos: from webob import Response - from pyramid.view import bfg_view + from pyramid.view import view_config class MyView(object): def __init__(self, request): self.request = request - @bfg_view(name='hello') + @view_config(name='hello') def amethod(self): return Response('hello') @@ -1729,9 +1729,9 @@ equivalently as the below: :linenos: from webob import Response - from pyramid.view import bfg_view + from pyramid.view import view_config - @bfg_view(attr='amethod', name='hello') + @view_config(attr='amethod', name='hello') class MyView(object): def __init__(self, request): self.request = request @@ -1750,7 +1750,7 @@ View Configuration Using the ``add_view`` Method of a Configurator The :meth:`pyramid.configuration.Configurator.add_view` method within :ref:`configuration_module` is used to configure a view imperatively. The arguments to this method are very similar to the -arguments that you provide to the ``@bfg_view`` decorator. For +arguments that you provide to the ``@view_config`` decorator. For example: .. code-block:: python diff --git a/docs/narr/webob.rst b/docs/narr/webob.rst index 15f8da9cf..b41979a1f 100644 --- a/docs/narr/webob.rst +++ b/docs/narr/webob.rst @@ -112,9 +112,9 @@ Special Attributes Added to the Request by :mod:`pyramid` In addition to the standard :term:`WebOb` attributes, :mod:`pyramid` adds special attributes to every request: ``context``, ``registry``, ``root``, ``subpath``, ``traversed``, ``view_name``, ``virtual_root`` -, ``virtual_root_path``, and ``session``. These attributes are -documented further within the :class:`pyramid.request.Request` API -documentation. +, ``virtual_root_path``, ``session``, and ``tmpl_context``. These +attributes are documented further within the +:class:`pyramid.request.Request` API documentation. .. index:: single: request URLs diff --git a/docs/tutorials/catalog/index.rst b/docs/tutorials/catalog/index.rst index 9a5bbfb2f..424286bd9 100644 --- a/docs/tutorials/catalog/index.rst +++ b/docs/tutorials/catalog/index.rst @@ -1,7 +1,7 @@ .. _catalog_tutorial: -Using :mod:`repoze.catalog` Within :mod:`repoze.bfg` -==================================================== +Using :mod:`repoze.catalog` Within :mod:`pyramid` +================================================= :mod:`repoze.catalog` is a ZODB-based system that can be used to index Python objects. It also offers a query interface for retrieving @@ -83,12 +83,12 @@ want the application to be based on :term:`traversal`. .. code-block:: text - [chrism@snowpro sess]$ ../bin/paster --plugin=repoze.bfg bfgshell \ + [chrism@snowpro sess]$ ../bin/paster --plugin=pyramid bfgshell \ myapp.ini myapp Python 2.5.4 (r254:67916, Sep 4 2009, 02:12:16) [GCC 4.2.1 (Apple Inc. build 5646)] on darwin Type "help" for more information. "root" is the BFG app root object. - >>> from repoze.bfg.traversal import model_path + >>> from pyramid.traversal import model_path >>> from myapp.models import Document >>> root['name'] = Document('title') >>> doc = root['name'] @@ -107,7 +107,7 @@ or from within a ``bfgshell`` session to update the set of indexes used by your application. In :term:`view` code, you should be able to get a hold of the root -object via the :func:`repoze.bfg.traversal.find_root` API. The +object via the :func:`pyramid.traversal.find_root` API. The ``catalog`` attribute of that root object will represent the catalog previously added. diff --git a/docs/tutorials/modwsgi/index.rst b/docs/tutorials/modwsgi/index.rst index 5572e300b..8b429a0c8 100644 --- a/docs/tutorials/modwsgi/index.rst +++ b/docs/tutorials/modwsgi/index.rst @@ -54,7 +54,7 @@ commands and files. .. code-block:: text $ cd ~/modwsgi/env - $ bin/easy_install repoze.bfg + $ bin/easy_install pyramid #. Create and install your :mod:`pyramid` application. For the purposes of this tutorial, we'll just be using the ``bfg_starter`` diff --git a/docs/tutorials/wiki/authorization.rst b/docs/tutorials/wiki/authorization.rst index 0d135f5e2..189401a45 100644 --- a/docs/tutorials/wiki/authorization.rst +++ b/docs/tutorials/wiki/authorization.rst @@ -182,12 +182,12 @@ Our resulting ``models.py`` file will now look like so: :linenos: :language: python -Adding ``permission`` Declarations to our ``bfg_view`` Decorators ------------------------------------------------------------------ +Adding ``permission`` Declarations to our ``view_config`` Decorators +-------------------------------------------------------------------- To protect each of our views with a particular permission, we need to pass a ``permission`` argument to each of our -:class:`pyramid.view.bfg_view` decorators. To do so, within +:class:`pyramid.view.view_config` decorators. To do so, within ``views.py``: - We add ``permission='view'`` to the decorator attached to the @@ -220,10 +220,10 @@ pass a ``permission`` argument to each of our consults the ``GROUPS`` data structure. This means that the ``editor`` user can add pages. -- We add ``permission='edit'`` to the ``bfg_view`` decorator attached - to the ``edit_page`` view function. This makes the assertion that - only users who possess the effective ``edit`` permission at the time - of the request may invoke this view. We've granted the +- We add ``permission='edit'`` to the decorator attached to the + ``edit_page`` view function. This makes the assertion that only + users who possess the effective ``edit`` permission at the time of + the request may invoke this view. We've granted the ``group:editors`` principal the ``edit`` permission at the root model via its ACL, so only the a user whom is a member of the group named ``group:editors`` will able to invoke the ``edit_page`` view. diff --git a/docs/tutorials/wiki/src/authorization/tutorial/login.py b/docs/tutorials/wiki/src/authorization/tutorial/login.py index ee67d9a5e..60e69fddf 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/login.py +++ b/docs/tutorials/wiki/src/authorization/tutorial/login.py @@ -1,6 +1,6 @@ from pyramid.httpexceptions import HTTPFound -from pyramid.view import bfg_view +from pyramid.view import view_config from pyramid.url import model_url from pyramid.security import remember @@ -9,7 +9,7 @@ from pyramid.security import forget from tutorial.models import Wiki from tutorial.security import USERS -@bfg_view(context=Wiki, name='login', renderer='templates/login.pt') +@view_config(context=Wiki, name='login', renderer='templates/login.pt') def login(request): login_url = model_url(request.context, request, 'login') referrer = request.url @@ -36,7 +36,7 @@ def login(request): password = password, ) -@bfg_view(context=Wiki, name='logout') +@view_config(context=Wiki, name='logout') def logout(request): headers = forget(request) return HTTPFound(location = model_url(request.context, request), diff --git a/docs/tutorials/wiki/src/authorization/tutorial/views.py b/docs/tutorials/wiki/src/authorization/tutorial/views.py index 8c35afcd6..48e4e2b43 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/views.py +++ b/docs/tutorials/wiki/src/authorization/tutorial/views.py @@ -6,7 +6,7 @@ from pyramid.url import model_url from pyramid.security import authenticated_userid -from pyramid.view import bfg_view +from pyramid.view import view_config from tutorial.models import Page from tutorial.models import Wiki @@ -14,11 +14,11 @@ from tutorial.models import Wiki # regular expression used to find WikiWords wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)") -@bfg_view(context=Wiki, permission='view') +@view_config(context=Wiki, permission='view') def view_wiki(context, request): return HTTPFound(location = model_url(context, request, 'FrontPage')) -@bfg_view(context=Page, renderer='templates/view.pt', permission='view') +@view_config(context=Page, renderer='templates/view.pt', permission='view') def view_page(context, request): wiki = context.__parent__ @@ -41,8 +41,8 @@ def view_page(context, request): return dict(page = context, content = content, edit_url = edit_url, logged_in = logged_in) -@bfg_view(context=Wiki, name='add_page', renderer='templates/edit.pt', - permission='edit') +@view_config(context=Wiki, name='add_page', renderer='templates/edit.pt', + permission='edit') def add_page(context, request): name = request.subpath[0] if 'form.submitted' in request.params: @@ -61,8 +61,8 @@ def add_page(context, request): return dict(page = page, save_url = save_url, logged_in = logged_in) -@bfg_view(context=Page, name='edit_page', renderer='templates/edit.pt', - permission='edit') +@view_config(context=Page, name='edit_page', renderer='templates/edit.pt', + permission='edit') def edit_page(context, request): if 'form.submitted' in request.params: context.data = request.params['body'] diff --git a/docs/tutorials/wiki/src/viewdecorators/tutorial/views.py b/docs/tutorials/wiki/src/viewdecorators/tutorial/views.py index 937a67344..168965db2 100644 --- a/docs/tutorials/wiki/src/viewdecorators/tutorial/views.py +++ b/docs/tutorials/wiki/src/viewdecorators/tutorial/views.py @@ -3,7 +3,7 @@ import re from pyramid.httpexceptions import HTTPFound from pyramid.url import model_url -from pyramid.view import bfg_view +from pyramid.view import view_config from tutorial.models import Page from tutorial.models import Wiki @@ -11,11 +11,11 @@ from tutorial.models import Wiki # regular expression used to find WikiWords wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)") -@bfg_view(context=Wiki) +@view_config(context=Wiki) def view_wiki(context, request): return HTTPFound(location = model_url(context, request, 'FrontPage')) -@bfg_view(context=Page, renderer='templates/view.pt') +@view_config(context=Page, renderer='templates/view.pt') def view_page(context, request): wiki = context.__parent__ @@ -34,7 +34,7 @@ def view_page(context, request): edit_url = model_url(context, request, 'edit_page') return dict(page = context, content = content, edit_url = edit_url) -@bfg_view(context=Wiki, name='add_page', renderer='templates/edit.pt') +@view_config(context=Wiki, name='add_page', renderer='templates/edit.pt') def add_page(context, request): name = request.subpath[0] if 'form.submitted' in request.params: @@ -50,7 +50,7 @@ def add_page(context, request): page.__parent__ = context return dict(page = page, save_url = save_url) -@bfg_view(context=Page, name='edit_page', renderer='templates/edit.pt') +@view_config(context=Page, name='edit_page', renderer='templates/edit.pt') def edit_page(context, request): if 'form.submitted' in request.params: context.data = request.params['body'] diff --git a/docs/tutorials/wiki/viewdecorators.rst b/docs/tutorials/wiki/viewdecorators.rst index 7d202ee6d..2d58890e4 100644 --- a/docs/tutorials/wiki/viewdecorators.rst +++ b/docs/tutorials/wiki/viewdecorators.rst @@ -3,25 +3,26 @@ Using View Decorators Rather than ZCML ``view`` directives ========================================================== So far we've been using :term:`ZCML` to map model types to views. -It's often easier to use the ``bfg_view`` view decorator to do this -mapping. Using view decorators provides better locality of reference -for the mapping, because you can see which model types and view names -the view will serve right next to the view function itself. In this -mode, however, you lose the ability for some views to be overridden -"from the outside" (by someone using your application as a framework, -as explained in the :ref:`extending_chapter`). Since this application -is not meant to be a framework, it makes sense for us to switch over -to using view decorators. +It's often easier to use the :class:`pyramid.view.view_config` view +decorator to do this mapping. Using view decorators provides better +locality of reference for the mapping, because you can see which model +types and view names the view will serve right next to the view +function itself. In this mode, however, you lose the ability for some +views to be overridden "from the outside" (by someone using your +application as a framework, as explained in the +:ref:`extending_chapter`). Since this application is not meant to be +a framework, it makes sense for us to switch over to using view +decorators. Adding View Decorators ====================== -We're going to import the :class:`pyramid.view.bfg_view` callable. +We're going to import the :class:`pyramid.view.view_config` callable. This callable can be used as a function, class, or method decorator. We'll use it to decorate our ``view_wiki``, ``view_page``, ``add_page`` and ``edit_page`` view functions. -The :class:`pyramid.view.bfg_view` callable accepts a number of +The :class:`pyramid.view.view_config` callable accepts a number of arguments: ``context`` @@ -50,7 +51,7 @@ The decorator above the ``view_wiki`` function will be: .. code-block:: python :linenos: - @bfg_view(context=Wiki) + @view_config(context=Wiki) This indicates that the view is for the Wiki class and has the *empty* view_name (indicating the :term:`default view` for the Wiki class). @@ -76,7 +77,7 @@ The decorator above the ``view_page`` function will be: .. code-block:: python :linenos: - @bfg_view(context=Page, renderer='templates/view.pt') + @view_config(context=Page, renderer='templates/view.pt') This indicates that the view is for the Page class and has the *empty* view_name (indicating the :term:`default view` for the Page class). @@ -103,7 +104,7 @@ The decorator above the ``add_page`` function will be: .. code-block:: python :linenos: - @bfg_view(context=Wiki, name='add_page', renderer='templates/edit.pt') + @view_config(context=Wiki, name='add_page', renderer='templates/edit.pt') This indicates that the view is for the Wiki class and has the ``add_page`` view_name. After injecting this decorator, we can now @@ -130,7 +131,7 @@ The decorator above the ``edit_page`` function will be: .. code-block:: python :linenos: - @bfg_view(context=Page, name='edit_page', renderer='templates/edit.pt') + @view_config(context=Page, name='edit_page', renderer='templates/edit.pt') This indicates that the view is for the Page class and has the ``edit_page`` view_name. After injecting this decorator, we can now diff --git a/docs/zcml/forbidden.rst b/docs/zcml/forbidden.rst index ca5b2cca1..330df3c2e 100644 --- a/docs/zcml/forbidden.rst +++ b/docs/zcml/forbidden.rst @@ -43,7 +43,7 @@ Attributes ``wrapper`` The :term:`view name` (*not* an object dotted name) of another view - declared elsewhere in ZCML (or via the ``@bfg_view`` decorator) + declared elsewhere in ZCML (or via the ``@view_config`` decorator) which will receive the response body of this view as the ``request.wrapped_body`` attribute of its own request, and the response returned by this view as the ``request.wrapped_response`` diff --git a/docs/zcml/notfound.rst b/docs/zcml/notfound.rst index 59263db34..0e1652708 100644 --- a/docs/zcml/notfound.rst +++ b/docs/zcml/notfound.rst @@ -6,7 +6,7 @@ .. warning:: The ``notfound`` ZCML directive is deprecated in :mod:`pyramid` - version 1.3. Instead, you should use the :ref:`view_directive` + version 1.0. Instead, you should use the :ref:`view_directive` directive with a ``context`` that names the :exc:`pyramid.exceptions.NotFound` class. See :ref:`changing_the_notfound_view` form more information. @@ -42,7 +42,7 @@ Attributes ``wrapper`` The :term:`view name` (*not* an object dotted name) of another view - declared elsewhere in ZCML (or via the ``@bfg_view`` decorator) + declared elsewhere in ZCML (or via the ``@view_config`` decorator) which will receive the response body of this view as the ``request.wrapped_body`` attribute of its own request, and the response returned by this view as the ``request.wrapped_response`` diff --git a/docs/zcml/view.rst b/docs/zcml/view.rst index 041e35af5..392e84430 100644 --- a/docs/zcml/view.rst +++ b/docs/zcml/view.rst @@ -83,7 +83,7 @@ Non-Predicate Attributes ``wrapper`` The :term:`view name` (*not* an object dotted name) of another view - declared elsewhere in ZCML (or via the ``@bfg_view`` decorator) + declared elsewhere in ZCML (or via the ``@view_config`` decorator) which will receive the response body of this view as the ``request.wrapped_body`` attribute of its own request, and the response returned by this view as the ``request.wrapped_response`` @@ -246,7 +246,7 @@ Alternatives You can also add a :term:`view configuration` via: -- Using the :class:`pyramid.view.bfg_view` class as a decorator. +- Using the :class:`pyramid.view.view_config` class as a decorator. - Using the :meth:`pyramid.configuration.Configurator.add_view` method. diff --git a/pyramid/configuration.py b/pyramid/configuration.py index f159a342f..b877441ec 100644 --- a/pyramid/configuration.py +++ b/pyramid/configuration.py @@ -1557,7 +1557,7 @@ class Configurator(object): def scan(self, package=None, categories=None, _info=u''): """ Scan a Python package and any of its subpackages for objects marked with :term:`configuration decoration` such as - :class:`pyramid.view.bfg_view`. Any decorated object found + :class:`pyramid.view.view_config`. Any decorated object found will influence the current configuration state. The ``package`` argument should be a Python :term:`package` or @@ -1572,15 +1572,15 @@ class Configurator(object): By default, ``categories`` is ``None`` which will execute *all* Venusian decorator callbacks including - :mod:`pyramid`-related decorators such as ``bfg_view``. If - this is not desirable because the codebase has other - Venusian-using decorators that aren't meant to be invoked - during a particular scan, use ``('bfg',)`` as a ``categories`` - value to limit the execution of decorator callbacks to only - those registered by :mod:`pyramid` itself. Or pass a - sequence of Venusian scan categories as necessary - (e.g. ``('bfg', 'myframework')``) to limit the decorators - called to the set of categories required. + :mod:`pyramid`-related decorators such as + :class:`pyramid.view.view_config``. If this is not desirable + because the codebase has other Venusian-using decorators that + aren't meant to be invoked during a particular scan, use + ``('bfg',)`` as a ``categories`` value to limit the execution + of decorator callbacks to only those registered by + :mod:`pyramid` itself. Or pass a sequence of Venusian scan + categories as necessary (e.g. ``('bfg', 'myframework')``) to + limit the decorators called to the set of categories required. """ package = self.maybe_dotted(package) if package is None: # pragma: no cover diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py index e1d7491b5..56486307a 100644 --- a/pyramid/interfaces.py +++ b/pyramid/interfaces.py @@ -392,10 +392,6 @@ class ISession(Interface): # attributes created = Attribute('Integer representing Epoch time when created.') - modified = Attribute( - 'Integer representing Epoch time of last modification. If the ' - 'session has not yet been modified (it is new), this time will ' - 'be the created time.') new = Attribute('Boolean attribute. If ``True``, the session is new.') # special methods diff --git a/pyramid/paster.py b/pyramid/paster.py index 0b7a4f7c7..1a0e3f6cb 100644 --- a/pyramid/paster.py +++ b/pyramid/paster.py @@ -9,7 +9,6 @@ from paste.util.template import paste_script_template_renderer from pyramid.scripting import get_root - class StarterProjectTemplate(Template): _template_dir = 'paster_templates/starter' summary = 'pyramid starter project' @@ -30,6 +29,21 @@ class AlchemyProjectTemplate(Template): summary = 'pyramid SQLAlchemy project using traversal' template_renderer = staticmethod(paste_script_template_renderer) +class PylonsBasicProjectTemplate(Template): + _template_dir = 'paster_templates/pylons_basic' + summary = 'Pylons basic project' + template_renderer = staticmethod(paste_script_template_renderer) + +class PylonsMinimalProjectTemplate(Template): + _template_dir = 'paster_templates/pylons_minimal' + summary = 'Pylons minimal project' + template_renderer = staticmethod(paste_script_template_renderer) + +class PylonsSQLAlchemyProjectTemplate(Template): + _template_dir = 'paster_templates/pylons_sqla' + summary = 'Pylons SQLAlchemy project' + template_renderer = staticmethod(paste_script_template_renderer) + def get_app(config_file, name, loadapp=loadapp): """ Return the WSGI application named ``name`` in the PasteDeploy config file ``config_file``""" diff --git a/pyramid/paster_templates/pylons_basic/+package+/__init__.py_tmpl b/pyramid/paster_templates/pylons_basic/+package+/__init__.py_tmpl new file mode 100644 index 000000000..b8f5219a7 --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/+package+/__init__.py_tmpl @@ -0,0 +1,22 @@ +from pyramid_beaker import session_factory_from_settings +from pyramid.personality.pylons import renderer_globals_factory_config +from {{package}}.lib import helpers + +def main(global_config, **settings): + """ This function returns a Pyramid WSGI application. + """ + from pyramid.configuration import Configurator + config = Configurator(settings=settings) + config.begin() + session_factory = session_factory_from_settings(settings) + config.set_session_factory(session_factory) + globals_factory = renderer_globals_factory_config(helpers) + config.set_renderer_globals_factory(globals_factory) + # XXX add caching setup + config.add_static_view('static', '{{package}}:static/') + config.add_handler('action', '/{action}', + '{{package}}.handlers.hello:HelloHandler') + config.add_handler('home', '/', '{{package}}.handlers.hello:HelloHandler', + action='index') + config.end() + return config.make_wsgi_app() diff --git a/pyramid/paster_templates/pylons_basic/+package+/handlers/__init__.py b/pyramid/paster_templates/pylons_basic/+package+/handlers/__init__.py new file mode 100644 index 000000000..5bb534f79 --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/+package+/handlers/__init__.py @@ -0,0 +1 @@ +# package diff --git a/pyramid/paster_templates/pylons_basic/+package+/handlers/hello.py_tmpl b/pyramid/paster_templates/pylons_basic/+package+/handlers/hello.py_tmpl new file mode 100644 index 000000000..696772798 --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/+package+/handlers/hello.py_tmpl @@ -0,0 +1,9 @@ +from pyramid.view import action + +class HelloHandler(object): + def __init__(self, request): + self.request = request + + @action(renderer='mytemplate.mak') + def index(self): + return {'project':'{{project}}'} diff --git a/pyramid/paster_templates/pylons_basic/+package+/lib/__init__.py b/pyramid/paster_templates/pylons_basic/+package+/lib/__init__.py new file mode 100644 index 000000000..4287ca861 --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/+package+/lib/__init__.py @@ -0,0 +1 @@ +#
\ No newline at end of file diff --git a/pyramid/paster_templates/pylons_basic/+package+/lib/helpers.py b/pyramid/paster_templates/pylons_basic/+package+/lib/helpers.py new file mode 100644 index 000000000..878b8882f --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/+package+/lib/helpers.py @@ -0,0 +1,7 @@ +"""Helper functions + +Consists of functions to typically be used within templates, but also +available to Controllers. This module is available to templates as 'h'. +""" +# Import helpers as desired, or define your own, ie: +#from webhelpers.html.tags import checkbox, password diff --git a/pyramid/paster_templates/pylons_basic/+package+/static/default.css b/pyramid/paster_templates/pylons_basic/+package+/static/default.css new file mode 100644 index 000000000..41b3debde --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/+package+/static/default.css @@ -0,0 +1,380 @@ +/* +Design by Free CSS Templates +http://www.freecsstemplates.org +Released for free under a Creative Commons Attribution 2.5 License +*/ + +body { + margin: 0; + padding: 0; + background: url(images/img01.gif) repeat-x left top; + font-size: 13px; + font-family: "Trebuchet MS", Georgia, "Times New Roman", Times, serif; + text-align: justify; + color: #FFFFFF; +} + +h1, h2, h3 { + margin: 0; + text-transform: lowercase; + font-weight: normal; + color: #FFFFFF; +} + +h1 { + letter-spacing: -1px; + font-size: 32px; +} + +h2 { + font-size: 23px; +} + +p, ul, ol { + margin: 0 0 2em 0; + text-align: justify; + line-height: 26px; +} + +a:link { + color: #8BD80E; +} + +a:hover, a:active { + text-decoration: none; + color: #8BD80E; +} + +a:visited { + color: #8BD80E; +} + +img { + border: none; +} + +img.left { + float: left; + margin-right: 15px; +} + +img.right { + float: right; + margin-left: 15px; +} + +/* Form */ + +form { + margin: 0; + padding: 0; +} + +fieldset { + margin: 0; + padding: 0; + border: none; +} + +legend { + display: none; +} + +input, textarea, select { + font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; + font-size: 13px; + color: #333333; +} + +#wrapper { + margin: 0; + padding: 0; + background: #000000; +} + +/* Header */ + +#header { + width: 713px; + margin: 0 auto; + height: 42px; +} + +/* Menu */ + +#menu { + float: left; + width: 713px; + height: 50px; + background: url(images/img02.gif) no-repeat left top; +} + +#menu ul { + margin: 0; + padding: 0px 0 0 10px; + list-style: none; + line-height: normal; +} + +#menu li { + display: block; + float: left; +} + +#menu a { + display: block; + float: left; + background: url(images/img04.gif) no-repeat right 55%; + margin-top: 5px; + margin-right: 3px; + padding: 8px 17px; + text-decoration: none; + font-size: 13px; + color: #000000; +} + +#menu a:hover { + color: #000000; +} + +#menu .current_page_item a { + color: #000000; +} + +/** LOGO */ + +#logo { + width: 713px; + height: 80px; + margin: 0 auto; +} + +#logo h1, #logo h2 { + float: left; + margin: 0; + padding: 30px 0 0 0px; + line-height: normal; +} + +#logo h1 { + font-family: Georgia, "Times New Roman", Times, serif; + font-size:40px; +} + +#logo h1 a { + text-decoration: none; + color: #4C4C4C; +} + +#logo h1 a:hover { text-decoration: underline; } + +#logo h2 { + float: left; + padding: 45px 0 0 18px; + font: 18px Georgia, "Times New Roman", Times, serif; + color: #8BD80E; +} + +#logo p a { + text-decoration: none; + color: #8BD80E; +} + +#logo p a:hover { text-decoration: underline; } + + + +/* Page */ + +#page { + width: 663px; + margin: 0 auto; + background: #4C4C4C url(images/img03.gif) no-repeat left bottom; + padding: 0 25px; +} + +/* Content */ + +#content { + float: left; + width: 410px; + +} + +/* Post */ + +.post { + padding: 15px 0px; + margin-bottom: 20px; +} + +.post .title { + margin-bottom: 20px; + padding-bottom: 5px; +} + +.post h1 { + padding: 0px 0 0 0px; + background: url(images/img08.jpg) no-repeat left top; + font-size: 24px; + color: #FFFFFF; +} + +.post h2 { + padding: 0px 0 0 0px; + font-size: 22px; + color: #FFFFFF; +} + +.post .entry { +} + +.post .meta { + padding: 15px 15px 30px 0px; + font-family: Arial, Helvetica, sans-serif; + font-size: 11px; +} + +.post .meta p { + margin: 0; + padding-top: 15px; + line-height: normal; + color: #FFFFFF; +} + +.post .meta .byline { + float: left; +} + +.post .meta .links { + float: right; +} + +.post .meta .more { + padding: 0 10px 0 18px; +} + +.post .meta .comments { +} + +.post .meta b { + display: none; +} + + +/* Sidebar */ + +#sidebar { + width: 210px; + float: right; + margin: 0; + padding: 0; +} + +#sidebar ul { + margin: 0; + padding: 0; + list-style: none; +} + +#sidebar li { + margin-bottom: 40px; +} + +#sidebar li ul { +} + +#sidebar li li { + margin: 0; +} + +#sidebar h2 { + width: 250px; + padding: 8px 0 0 0px; + margin-bottom: 10px; + background: url(images/img07.jpg) no-repeat left top; + font-size: 20px; + color: #FFFFFF; +} + +/* Search */ + +#search { + +} + +#search h2 { + margin-bottom: 20px; +} + +#s { + width: 140px; + margin-right: 5px; + padding: 3px; + border: 1px solid #BED99C; +} + +#x { + padding: 3px; + border: none; + background: #8BD80E; + text-transform: lowercase; + font-size: 11px; + color: #FFFFFF; +} + +/* Boxes */ + +.box1 { + padding: 20px; +} + +.box2 { + color: #BABABA; +} + +.box2 h2 { + margin-bottom: 15px; + font-size: 16px; + color: #FFFFFF; +} + +.box2 ul { + margin: 0; + padding: 0; + list-style: none; +} + +.box2 a:link, .box2 a:hover, .box2 a:active, .box2 a:visited { + color: #EDEDED; +} + +/* Footer */ +#footer-wrap { +} + +#footer { + margin: 0 auto; + padding: 20px 0 10px 0; + background: #000000; +} + +html>body #footer { + height: auto; +} + +#footer p { + font-size: 11px; +} + +#legal { + clear: both; + padding-top: 17px; + text-align: center; + color: #FFFFFF; +} + +#legal a { + font-weight: normal; + color: #FFFFFF; +} diff --git a/pyramid/paster_templates/pylons_basic/+package+/static/images/img01.gif b/pyramid/paster_templates/pylons_basic/+package+/static/images/img01.gif Binary files differnew file mode 100644 index 000000000..5f082bd99 --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/+package+/static/images/img01.gif diff --git a/pyramid/paster_templates/pylons_basic/+package+/static/images/img02.gif b/pyramid/paster_templates/pylons_basic/+package+/static/images/img02.gif Binary files differnew file mode 100644 index 000000000..45a3ae976 --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/+package+/static/images/img02.gif diff --git a/pyramid/paster_templates/pylons_basic/+package+/static/images/img03.gif b/pyramid/paster_templates/pylons_basic/+package+/static/images/img03.gif Binary files differnew file mode 100644 index 000000000..d92ea38f9 --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/+package+/static/images/img03.gif diff --git a/pyramid/paster_templates/pylons_basic/+package+/static/images/img04.gif b/pyramid/paster_templates/pylons_basic/+package+/static/images/img04.gif Binary files differnew file mode 100644 index 000000000..950c4af9d --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/+package+/static/images/img04.gif diff --git a/pyramid/paster_templates/pylons_basic/+package+/static/images/spacer.gif b/pyramid/paster_templates/pylons_basic/+package+/static/images/spacer.gif Binary files differnew file mode 100644 index 000000000..5bfd67a2d --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/+package+/static/images/spacer.gif diff --git a/pyramid/paster_templates/pylons_basic/+package+/static/templatelicense.txt b/pyramid/paster_templates/pylons_basic/+package+/static/templatelicense.txt new file mode 100644 index 000000000..ccb6b06ab --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/+package+/static/templatelicense.txt @@ -0,0 +1,243 @@ +Creative Commons </> + +Creative Commons Legal Code + +*Attribution 2.5* + +CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE +LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN +ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION +ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE +INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM +ITS USE. + +/License/ + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE +COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY +COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS +AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE +TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE +RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS +AND CONDITIONS. + +*1. Definitions* + + 1. *"Collective Work"* means a work, such as a periodical issue, + anthology or encyclopedia, in which the Work in its entirety in + unmodified form, along with a number of other contributions, + constituting separate and independent works in themselves, are + assembled into a collective whole. A work that constitutes a + Collective Work will not be considered a Derivative Work (as + defined below) for the purposes of this License. + 2. *"Derivative Work"* means a work based upon the Work or upon the + Work and other pre-existing works, such as a translation, musical + arrangement, dramatization, fictionalization, motion picture + version, sound recording, art reproduction, abridgment, + condensation, or any other form in which the Work may be recast, + transformed, or adapted, except that a work that constitutes a + Collective Work will not be considered a Derivative Work for the + purpose of this License. For the avoidance of doubt, where the + Work is a musical composition or sound recording, the + synchronization of the Work in timed-relation with a moving image + ("synching") will be considered a Derivative Work for the purpose + of this License. + 3. *"Licensor"* means the individual or entity that offers the Work + under the terms of this License. + 4. *"Original Author"* means the individual or entity who created the + Work. + 5. *"Work"* means the copyrightable work of authorship offered under + the terms of this License. + 6. *"You"* means an individual or entity exercising rights under this + License who has not previously violated the terms of this License + with respect to the Work, or who has received express permission + from the Licensor to exercise rights under this License despite a + previous violation. + +*2. Fair Use Rights.* Nothing in this license is intended to reduce, +limit, or restrict any rights arising from fair use, first sale or other +limitations on the exclusive rights of the copyright owner under +copyright law or other applicable laws. + +*3. License Grant.* Subject to the terms and conditions of this License, +Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +perpetual (for the duration of the applicable copyright) license to +exercise the rights in the Work as stated below: + + 1. to reproduce the Work, to incorporate the Work into one or more + Collective Works, and to reproduce the Work as incorporated in the + Collective Works; + 2. to create and reproduce Derivative Works; + 3. to distribute copies or phonorecords of, display publicly, perform + publicly, and perform publicly by means of a digital audio + transmission the Work including as incorporated in Collective Works; + 4. to distribute copies or phonorecords of, display publicly, perform + publicly, and perform publicly by means of a digital audio + transmission Derivative Works. + 5. + + For the avoidance of doubt, where the work is a musical composition: + + 1. *Performance Royalties Under Blanket Licenses*. Licensor + waives the exclusive right to collect, whether individually + or via a performance rights society (e.g. ASCAP, BMI, + SESAC), royalties for the public performance or public + digital performance (e.g. webcast) of the Work. + 2. *Mechanical Rights and Statutory Royalties*. Licensor waives + the exclusive right to collect, whether individually or via + a music rights agency or designated agent (e.g. Harry Fox + Agency), royalties for any phonorecord You create from the + Work ("cover version") and distribute, subject to the + compulsory license created by 17 USC Section 115 of the US + Copyright Act (or the equivalent in other jurisdictions). + 6. *Webcasting Rights and Statutory Royalties*. For the avoidance of + doubt, where the Work is a sound recording, Licensor waives the + exclusive right to collect, whether individually or via a + performance-rights society (e.g. SoundExchange), royalties for the + public digital performance (e.g. webcast) of the Work, subject to + the compulsory license created by 17 USC Section 114 of the US + Copyright Act (or the equivalent in other jurisdictions). + +The above rights may be exercised in all media and formats whether now +known or hereafter devised. The above rights include the right to make +such modifications as are technically necessary to exercise the rights +in other media and formats. All rights not expressly granted by Licensor +are hereby reserved. + +*4. Restrictions.*The license granted in Section 3 above is expressly +made subject to and limited by the following restrictions: + + 1. You may distribute, publicly display, publicly perform, or + publicly digitally perform the Work only under the terms of this + License, and You must include a copy of, or the Uniform Resource + Identifier for, this License with every copy or phonorecord of the + Work You distribute, publicly display, publicly perform, or + publicly digitally perform. You may not offer or impose any terms + on the Work that alter or restrict the terms of this License or + the recipients' exercise of the rights granted hereunder. You may + not sublicense the Work. You must keep intact all notices that + refer to this License and to the disclaimer of warranties. You may + not distribute, publicly display, publicly perform, or publicly + digitally perform the Work with any technological measures that + control access or use of the Work in a manner inconsistent with + the terms of this License Agreement. The above applies to the Work + as incorporated in a Collective Work, but this does not require + the Collective Work apart from the Work itself to be made subject + to the terms of this License. If You create a Collective Work, + upon notice from any Licensor You must, to the extent practicable, + remove from the Collective Work any credit as required by clause + 4(b), as requested. If You create a Derivative Work, upon notice + from any Licensor You must, to the extent practicable, remove from + the Derivative Work any credit as required by clause 4(b), as + requested. + 2. If you distribute, publicly display, publicly perform, or publicly + digitally perform the Work or any Derivative Works or Collective + Works, You must keep intact all copyright notices for the Work and + provide, reasonable to the medium or means You are utilizing: (i) + the name of the Original Author (or pseudonym, if applicable) if + supplied, and/or (ii) if the Original Author and/or Licensor + designate another party or parties (e.g. a sponsor institute, + publishing entity, journal) for attribution in Licensor's + copyright notice, terms of service or by other reasonable means, + the name of such party or parties; the title of the Work if + supplied; to the extent reasonably practicable, the Uniform + Resource Identifier, if any, that Licensor specifies to be + associated with the Work, unless such URI does not refer to the + copyright notice or licensing information for the Work; and in the + case of a Derivative Work, a credit identifying the use of the + Work in the Derivative Work (e.g., "French translation of the Work + by Original Author," or "Screenplay based on original Work by + Original Author"). Such credit may be implemented in any + reasonable manner; provided, however, that in the case of a + Derivative Work or Collective Work, at a minimum such credit will + appear where any other comparable authorship credit appears and in + a manner at least as prominent as such other comparable authorship + credit. + +*5. Representations, Warranties and Disclaimer* + +UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR +OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY +KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, +INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, +FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF +LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, +WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE +EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. + +*6. Limitation on Liability.* EXCEPT TO THE EXTENT REQUIRED BY +APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL +THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY +DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF +LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +*7. Termination* + + 1. This License and the rights granted hereunder will terminate + automatically upon any breach by You of the terms of this License. + Individuals or entities who have received Derivative Works or + Collective Works from You under this License, however, will not + have their licenses terminated provided such individuals or + entities remain in full compliance with those licenses. Sections + 1, 2, 5, 6, 7, and 8 will survive any termination of this License. + 2. Subject to the above terms and conditions, the license granted + here is perpetual (for the duration of the applicable copyright in + the Work). Notwithstanding the above, Licensor reserves the right + to release the Work under different license terms or to stop + distributing the Work at any time; provided, however that any such + election will not serve to withdraw this License (or any other + license that has been, or is required to be, granted under the + terms of this License), and this License will continue in full + force and effect unless terminated as stated above. + +*8. Miscellaneous* + + 1. Each time You distribute or publicly digitally perform the Work or + a Collective Work, the Licensor offers to the recipient a license + to the Work on the same terms and conditions as the license + granted to You under this License. + 2. Each time You distribute or publicly digitally perform a + Derivative Work, Licensor offers to the recipient a license to the + original Work on the same terms and conditions as the license + granted to You under this License. + 3. If any provision of this License is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability + of the remainder of the terms of this License, and without further + action by the parties to this agreement, such provision shall be + reformed to the minimum extent necessary to make such provision + valid and enforceable. + 4. No term or provision of this License shall be deemed waived and no + breach consented to unless such waiver or consent shall be in + writing and signed by the party to be charged with such waiver or + consent. + 5. This License constitutes the entire agreement between the parties + with respect to the Work licensed here. There are no + understandings, agreements or representations with respect to the + Work not specified here. Licensor shall not be bound by any + additional provisions that may appear in any communication from + You. This License may not be modified without the mutual written + agreement of the Licensor and You. + +Creative Commons is not a party to this License, and makes no warranty +whatsoever in connection with the Work. Creative Commons will not be +liable to You or any party on any legal theory for any damages +whatsoever, including without limitation any general, special, +incidental or consequential damages arising in connection to this +license. Notwithstanding the foregoing two (2) sentences, if Creative +Commons has expressly identified itself as the Licensor hereunder, it +shall have all rights and obligations of Licensor. + +Except for the limited purpose of indicating to the public that the Work +is licensed under the CCPL, neither party will use the trademark +"Creative Commons" or any related trademark or logo of Creative Commons +without the prior written consent of Creative Commons. Any permitted use +will be in compliance with Creative Commons' then-current trademark +usage guidelines, as may be published on its website or otherwise made +available upon request from time to time. + +Creative Commons may be contacted at http://creativecommons.org/ +<http://creativecommons.org>. + +« Back to Commons Deed <./> diff --git a/pyramid/paster_templates/pylons_basic/+package+/templates/mytemplate.mak b/pyramid/paster_templates/pylons_basic/+package+/templates/mytemplate.mak new file mode 100644 index 000000000..035cc2f78 --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/+package+/templates/mytemplate.mak @@ -0,0 +1,49 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" + xmlns:tal="http://xml.zope.org/namespaces/tal"> +<head> +<meta http-equiv="content-type" content="text/html; charset=utf-8" /> +<title>${project} Application</title> +<meta name="keywords" content="python web application" /> +<meta name="description" content="Pylons web application" /> +<link href="${request.application_url}/static/default.css" rel="stylesheet" type="text/css" /> +</head> +<body> +<!-- start header --> +<div id="logo"> + <h2><code>${project}</code>, a <code>Pylons</code> application</h2> +</div> +<div id="header"> + <div id="menu"> + </div> +</div> +<!-- end header --> +<div id="wrapper"> + <!-- start page --> + <div id="page"> + <!-- start content --> + <div id="content"> + <div class="post"> + <h1 class="title">Welcome to <code>${project}</code>, an + application generated by the <a + href="http://pylonshq.com">Pylons</a> web + application framework.</h1> + </div> + </div> + <!-- end content --> + <!-- start sidebar --> + <div id="sidebar"></div> + <!-- end sidebar --> + <div style="clear: both;"> </div> + </div> +</div> +<!-- end page --> +<!-- start footer --> +<div id="footer"> + <p id="legal">( c ) 2008. All Rights Reserved. Template design + by <a href="http://www.freecsstemplates.org/">Free CSS + Templates</a>.</p> +</div> +<!-- end footer --> +</body> +</html> diff --git a/pyramid/paster_templates/pylons_basic/+package+/tests.py_tmpl b/pyramid/paster_templates/pylons_basic/+package+/tests.py_tmpl new file mode 100644 index 000000000..d98bee355 --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/+package+/tests.py_tmpl @@ -0,0 +1,24 @@ +import unittest + +from pyramid.configuration import Configurator + +class MyControllerTests(unittest.TestCase): + def setUp(self): + self.config = Configurator() + self.config.begin() + + def tearDown(self): + self.config.end() + + def _makeOne(self, request): + from {{package}}.handlers import MyHandler + return MyHandler(request) + + def test_index(self): + request = DummyRequest() + controller = self._makeOne(request) + info = controller.index() + self.assertEqual(info['project'], '{{project}}') + +class DummyRequest(object): + pass diff --git a/pyramid/paster_templates/pylons_basic/CHANGES.txt_tmpl b/pyramid/paster_templates/pylons_basic/CHANGES.txt_tmpl new file mode 100644 index 000000000..35a34f332 --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/CHANGES.txt_tmpl @@ -0,0 +1,4 @@ +0.0 +--- + +- Initial version diff --git a/pyramid/paster_templates/pylons_basic/README.txt_tmpl b/pyramid/paster_templates/pylons_basic/README.txt_tmpl new file mode 100644 index 000000000..0ddebfc3e --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/README.txt_tmpl @@ -0,0 +1,4 @@ +{{project}} README + + + diff --git a/pyramid/paster_templates/pylons_basic/development.ini_tmpl b/pyramid/paster_templates/pylons_basic/development.ini_tmpl new file mode 100644 index 000000000..d3c8b57c9 --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/development.ini_tmpl @@ -0,0 +1,28 @@ +[app:{{project}}] +use = egg:{{project}} +reload_templates = true +mako.directories = {{package}}:templates +debug_authorization = false +debug_notfound = false +debug_templates = true +default_locale_name = en +session.type = file +session.data_dir = %(here)s/data/sessions/data +session.lock_dir = %(here)s/data/sessions/lock +session.key = {{project}} +session.secret = your_app_secret_string +cache.regions = default_term, second, short_term, long_term +cache.type = memory +cache.second.expire = 1 +cache.short_term.expire = 60 +cache.default_term.expire = 300 +cache.long_term.expire = 3600 + +[pipeline:main] +pipeline = egg:WebError#evalerror + {{project}} + +[server:main] +use = egg:Paste#http +host = 0.0.0.0 +port = 5000 diff --git a/pyramid/paster_templates/pylons_basic/setup.cfg_tmpl b/pyramid/paster_templates/pylons_basic/setup.cfg_tmpl new file mode 100644 index 000000000..5bec29823 --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/setup.cfg_tmpl @@ -0,0 +1,27 @@ +[nosetests] +match=^test +nocapture=1 +cover-package={{package}} +with-coverage=1 +cover-erase=1 + +[compile_catalog] +directory = {{package}}/locale +domain = {{project}} +statistics = true + +[extract_messages] +add_comments = TRANSLATORS: +output_file = {{package}}/locale/{{project}}.pot +width = 80 + +[init_catalog] +domain = {{project}} +input_file = {{package}}/locale/{{project}}.pot +output_dir = {{package}}/locale + +[update_catalog] +domain = {{project}} +input_file = {{package}}/locale/{{project}}.pot +output_dir = {{package}}/locale +previous = true diff --git a/pyramid/paster_templates/pylons_basic/setup.py_tmpl b/pyramid/paster_templates/pylons_basic/setup.py_tmpl new file mode 100644 index 000000000..baa57aa4e --- /dev/null +++ b/pyramid/paster_templates/pylons_basic/setup.py_tmpl @@ -0,0 +1,36 @@ +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_beaker', 'WebError'] + +setup(name='{{project}}', + version='0.0', + description='{{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 pylons', + packages=find_packages(), + include_package_data=True, + zip_safe=False, + install_requires=requires, + tests_require=requires, + test_suite="{{package}}", + entry_points = """\ + [paste.app_factory] + main = {{package}}:main + """ + ) + diff --git a/pyramid/paster_templates/pylons_minimal/+package+/__init__.py_tmpl b/pyramid/paster_templates/pylons_minimal/+package+/__init__.py_tmpl new file mode 100644 index 000000000..f47060997 --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/+package+/__init__.py_tmpl @@ -0,0 +1,21 @@ +from pyramid_beaker import session_factory_from_settings +from pyramid.personality.pylons import renderer_globals_factory_config + +def main(global_config, **settings): + """ This function returns a Pyramid WSGI application. + """ + from pyramid.configuration import Configurator + config = Configurator(settings=settings) + config.begin() + session_factory = session_factory_from_settings(settings) + config.set_session_factory(session_factory) + # XXX add caching setup + globals_factory = renderer_globals_factory_config(None) + config.set_renderer_globals_factory(globals_factory) + config.add_static_view('static', '{{package}}:static/') + config.add_handler('action', '/{action}', '{{package}}.handlers:MyHandler') + config.add_handler('home', '/', '{{package}}.handlers:MyHandler', + action='index') + config.end() + return config.make_wsgi_app() + diff --git a/pyramid/paster_templates/pylons_minimal/+package+/handlers.py_tmpl b/pyramid/paster_templates/pylons_minimal/+package+/handlers.py_tmpl new file mode 100644 index 000000000..be1202551 --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/+package+/handlers.py_tmpl @@ -0,0 +1,9 @@ +from pyramid.view import action + +class MyHandler(object): + def __init__(self, request): + self.request = request + + @action(renderer='mytemplate.mak') + def index(self): + return {'project':'{{project}}'} diff --git a/pyramid/paster_templates/pylons_minimal/+package+/static/default.css b/pyramid/paster_templates/pylons_minimal/+package+/static/default.css new file mode 100644 index 000000000..41b3debde --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/+package+/static/default.css @@ -0,0 +1,380 @@ +/* +Design by Free CSS Templates +http://www.freecsstemplates.org +Released for free under a Creative Commons Attribution 2.5 License +*/ + +body { + margin: 0; + padding: 0; + background: url(images/img01.gif) repeat-x left top; + font-size: 13px; + font-family: "Trebuchet MS", Georgia, "Times New Roman", Times, serif; + text-align: justify; + color: #FFFFFF; +} + +h1, h2, h3 { + margin: 0; + text-transform: lowercase; + font-weight: normal; + color: #FFFFFF; +} + +h1 { + letter-spacing: -1px; + font-size: 32px; +} + +h2 { + font-size: 23px; +} + +p, ul, ol { + margin: 0 0 2em 0; + text-align: justify; + line-height: 26px; +} + +a:link { + color: #8BD80E; +} + +a:hover, a:active { + text-decoration: none; + color: #8BD80E; +} + +a:visited { + color: #8BD80E; +} + +img { + border: none; +} + +img.left { + float: left; + margin-right: 15px; +} + +img.right { + float: right; + margin-left: 15px; +} + +/* Form */ + +form { + margin: 0; + padding: 0; +} + +fieldset { + margin: 0; + padding: 0; + border: none; +} + +legend { + display: none; +} + +input, textarea, select { + font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; + font-size: 13px; + color: #333333; +} + +#wrapper { + margin: 0; + padding: 0; + background: #000000; +} + +/* Header */ + +#header { + width: 713px; + margin: 0 auto; + height: 42px; +} + +/* Menu */ + +#menu { + float: left; + width: 713px; + height: 50px; + background: url(images/img02.gif) no-repeat left top; +} + +#menu ul { + margin: 0; + padding: 0px 0 0 10px; + list-style: none; + line-height: normal; +} + +#menu li { + display: block; + float: left; +} + +#menu a { + display: block; + float: left; + background: url(images/img04.gif) no-repeat right 55%; + margin-top: 5px; + margin-right: 3px; + padding: 8px 17px; + text-decoration: none; + font-size: 13px; + color: #000000; +} + +#menu a:hover { + color: #000000; +} + +#menu .current_page_item a { + color: #000000; +} + +/** LOGO */ + +#logo { + width: 713px; + height: 80px; + margin: 0 auto; +} + +#logo h1, #logo h2 { + float: left; + margin: 0; + padding: 30px 0 0 0px; + line-height: normal; +} + +#logo h1 { + font-family: Georgia, "Times New Roman", Times, serif; + font-size:40px; +} + +#logo h1 a { + text-decoration: none; + color: #4C4C4C; +} + +#logo h1 a:hover { text-decoration: underline; } + +#logo h2 { + float: left; + padding: 45px 0 0 18px; + font: 18px Georgia, "Times New Roman", Times, serif; + color: #8BD80E; +} + +#logo p a { + text-decoration: none; + color: #8BD80E; +} + +#logo p a:hover { text-decoration: underline; } + + + +/* Page */ + +#page { + width: 663px; + margin: 0 auto; + background: #4C4C4C url(images/img03.gif) no-repeat left bottom; + padding: 0 25px; +} + +/* Content */ + +#content { + float: left; + width: 410px; + +} + +/* Post */ + +.post { + padding: 15px 0px; + margin-bottom: 20px; +} + +.post .title { + margin-bottom: 20px; + padding-bottom: 5px; +} + +.post h1 { + padding: 0px 0 0 0px; + background: url(images/img08.jpg) no-repeat left top; + font-size: 24px; + color: #FFFFFF; +} + +.post h2 { + padding: 0px 0 0 0px; + font-size: 22px; + color: #FFFFFF; +} + +.post .entry { +} + +.post .meta { + padding: 15px 15px 30px 0px; + font-family: Arial, Helvetica, sans-serif; + font-size: 11px; +} + +.post .meta p { + margin: 0; + padding-top: 15px; + line-height: normal; + color: #FFFFFF; +} + +.post .meta .byline { + float: left; +} + +.post .meta .links { + float: right; +} + +.post .meta .more { + padding: 0 10px 0 18px; +} + +.post .meta .comments { +} + +.post .meta b { + display: none; +} + + +/* Sidebar */ + +#sidebar { + width: 210px; + float: right; + margin: 0; + padding: 0; +} + +#sidebar ul { + margin: 0; + padding: 0; + list-style: none; +} + +#sidebar li { + margin-bottom: 40px; +} + +#sidebar li ul { +} + +#sidebar li li { + margin: 0; +} + +#sidebar h2 { + width: 250px; + padding: 8px 0 0 0px; + margin-bottom: 10px; + background: url(images/img07.jpg) no-repeat left top; + font-size: 20px; + color: #FFFFFF; +} + +/* Search */ + +#search { + +} + +#search h2 { + margin-bottom: 20px; +} + +#s { + width: 140px; + margin-right: 5px; + padding: 3px; + border: 1px solid #BED99C; +} + +#x { + padding: 3px; + border: none; + background: #8BD80E; + text-transform: lowercase; + font-size: 11px; + color: #FFFFFF; +} + +/* Boxes */ + +.box1 { + padding: 20px; +} + +.box2 { + color: #BABABA; +} + +.box2 h2 { + margin-bottom: 15px; + font-size: 16px; + color: #FFFFFF; +} + +.box2 ul { + margin: 0; + padding: 0; + list-style: none; +} + +.box2 a:link, .box2 a:hover, .box2 a:active, .box2 a:visited { + color: #EDEDED; +} + +/* Footer */ +#footer-wrap { +} + +#footer { + margin: 0 auto; + padding: 20px 0 10px 0; + background: #000000; +} + +html>body #footer { + height: auto; +} + +#footer p { + font-size: 11px; +} + +#legal { + clear: both; + padding-top: 17px; + text-align: center; + color: #FFFFFF; +} + +#legal a { + font-weight: normal; + color: #FFFFFF; +} diff --git a/pyramid/paster_templates/pylons_minimal/+package+/static/images/img01.gif b/pyramid/paster_templates/pylons_minimal/+package+/static/images/img01.gif Binary files differnew file mode 100644 index 000000000..5f082bd99 --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/+package+/static/images/img01.gif diff --git a/pyramid/paster_templates/pylons_minimal/+package+/static/images/img02.gif b/pyramid/paster_templates/pylons_minimal/+package+/static/images/img02.gif Binary files differnew file mode 100644 index 000000000..45a3ae976 --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/+package+/static/images/img02.gif diff --git a/pyramid/paster_templates/pylons_minimal/+package+/static/images/img03.gif b/pyramid/paster_templates/pylons_minimal/+package+/static/images/img03.gif Binary files differnew file mode 100644 index 000000000..d92ea38f9 --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/+package+/static/images/img03.gif diff --git a/pyramid/paster_templates/pylons_minimal/+package+/static/images/img04.gif b/pyramid/paster_templates/pylons_minimal/+package+/static/images/img04.gif Binary files differnew file mode 100644 index 000000000..950c4af9d --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/+package+/static/images/img04.gif diff --git a/pyramid/paster_templates/pylons_minimal/+package+/static/images/spacer.gif b/pyramid/paster_templates/pylons_minimal/+package+/static/images/spacer.gif Binary files differnew file mode 100644 index 000000000..5bfd67a2d --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/+package+/static/images/spacer.gif diff --git a/pyramid/paster_templates/pylons_minimal/+package+/static/templatelicense.txt b/pyramid/paster_templates/pylons_minimal/+package+/static/templatelicense.txt new file mode 100644 index 000000000..ccb6b06ab --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/+package+/static/templatelicense.txt @@ -0,0 +1,243 @@ +Creative Commons </> + +Creative Commons Legal Code + +*Attribution 2.5* + +CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE +LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN +ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION +ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE +INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM +ITS USE. + +/License/ + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE +COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY +COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS +AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE +TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE +RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS +AND CONDITIONS. + +*1. Definitions* + + 1. *"Collective Work"* means a work, such as a periodical issue, + anthology or encyclopedia, in which the Work in its entirety in + unmodified form, along with a number of other contributions, + constituting separate and independent works in themselves, are + assembled into a collective whole. A work that constitutes a + Collective Work will not be considered a Derivative Work (as + defined below) for the purposes of this License. + 2. *"Derivative Work"* means a work based upon the Work or upon the + Work and other pre-existing works, such as a translation, musical + arrangement, dramatization, fictionalization, motion picture + version, sound recording, art reproduction, abridgment, + condensation, or any other form in which the Work may be recast, + transformed, or adapted, except that a work that constitutes a + Collective Work will not be considered a Derivative Work for the + purpose of this License. For the avoidance of doubt, where the + Work is a musical composition or sound recording, the + synchronization of the Work in timed-relation with a moving image + ("synching") will be considered a Derivative Work for the purpose + of this License. + 3. *"Licensor"* means the individual or entity that offers the Work + under the terms of this License. + 4. *"Original Author"* means the individual or entity who created the + Work. + 5. *"Work"* means the copyrightable work of authorship offered under + the terms of this License. + 6. *"You"* means an individual or entity exercising rights under this + License who has not previously violated the terms of this License + with respect to the Work, or who has received express permission + from the Licensor to exercise rights under this License despite a + previous violation. + +*2. Fair Use Rights.* Nothing in this license is intended to reduce, +limit, or restrict any rights arising from fair use, first sale or other +limitations on the exclusive rights of the copyright owner under +copyright law or other applicable laws. + +*3. License Grant.* Subject to the terms and conditions of this License, +Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +perpetual (for the duration of the applicable copyright) license to +exercise the rights in the Work as stated below: + + 1. to reproduce the Work, to incorporate the Work into one or more + Collective Works, and to reproduce the Work as incorporated in the + Collective Works; + 2. to create and reproduce Derivative Works; + 3. to distribute copies or phonorecords of, display publicly, perform + publicly, and perform publicly by means of a digital audio + transmission the Work including as incorporated in Collective Works; + 4. to distribute copies or phonorecords of, display publicly, perform + publicly, and perform publicly by means of a digital audio + transmission Derivative Works. + 5. + + For the avoidance of doubt, where the work is a musical composition: + + 1. *Performance Royalties Under Blanket Licenses*. Licensor + waives the exclusive right to collect, whether individually + or via a performance rights society (e.g. ASCAP, BMI, + SESAC), royalties for the public performance or public + digital performance (e.g. webcast) of the Work. + 2. *Mechanical Rights and Statutory Royalties*. Licensor waives + the exclusive right to collect, whether individually or via + a music rights agency or designated agent (e.g. Harry Fox + Agency), royalties for any phonorecord You create from the + Work ("cover version") and distribute, subject to the + compulsory license created by 17 USC Section 115 of the US + Copyright Act (or the equivalent in other jurisdictions). + 6. *Webcasting Rights and Statutory Royalties*. For the avoidance of + doubt, where the Work is a sound recording, Licensor waives the + exclusive right to collect, whether individually or via a + performance-rights society (e.g. SoundExchange), royalties for the + public digital performance (e.g. webcast) of the Work, subject to + the compulsory license created by 17 USC Section 114 of the US + Copyright Act (or the equivalent in other jurisdictions). + +The above rights may be exercised in all media and formats whether now +known or hereafter devised. The above rights include the right to make +such modifications as are technically necessary to exercise the rights +in other media and formats. All rights not expressly granted by Licensor +are hereby reserved. + +*4. Restrictions.*The license granted in Section 3 above is expressly +made subject to and limited by the following restrictions: + + 1. You may distribute, publicly display, publicly perform, or + publicly digitally perform the Work only under the terms of this + License, and You must include a copy of, or the Uniform Resource + Identifier for, this License with every copy or phonorecord of the + Work You distribute, publicly display, publicly perform, or + publicly digitally perform. You may not offer or impose any terms + on the Work that alter or restrict the terms of this License or + the recipients' exercise of the rights granted hereunder. You may + not sublicense the Work. You must keep intact all notices that + refer to this License and to the disclaimer of warranties. You may + not distribute, publicly display, publicly perform, or publicly + digitally perform the Work with any technological measures that + control access or use of the Work in a manner inconsistent with + the terms of this License Agreement. The above applies to the Work + as incorporated in a Collective Work, but this does not require + the Collective Work apart from the Work itself to be made subject + to the terms of this License. If You create a Collective Work, + upon notice from any Licensor You must, to the extent practicable, + remove from the Collective Work any credit as required by clause + 4(b), as requested. If You create a Derivative Work, upon notice + from any Licensor You must, to the extent practicable, remove from + the Derivative Work any credit as required by clause 4(b), as + requested. + 2. If you distribute, publicly display, publicly perform, or publicly + digitally perform the Work or any Derivative Works or Collective + Works, You must keep intact all copyright notices for the Work and + provide, reasonable to the medium or means You are utilizing: (i) + the name of the Original Author (or pseudonym, if applicable) if + supplied, and/or (ii) if the Original Author and/or Licensor + designate another party or parties (e.g. a sponsor institute, + publishing entity, journal) for attribution in Licensor's + copyright notice, terms of service or by other reasonable means, + the name of such party or parties; the title of the Work if + supplied; to the extent reasonably practicable, the Uniform + Resource Identifier, if any, that Licensor specifies to be + associated with the Work, unless such URI does not refer to the + copyright notice or licensing information for the Work; and in the + case of a Derivative Work, a credit identifying the use of the + Work in the Derivative Work (e.g., "French translation of the Work + by Original Author," or "Screenplay based on original Work by + Original Author"). Such credit may be implemented in any + reasonable manner; provided, however, that in the case of a + Derivative Work or Collective Work, at a minimum such credit will + appear where any other comparable authorship credit appears and in + a manner at least as prominent as such other comparable authorship + credit. + +*5. Representations, Warranties and Disclaimer* + +UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR +OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY +KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, +INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, +FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF +LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, +WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE +EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. + +*6. Limitation on Liability.* EXCEPT TO THE EXTENT REQUIRED BY +APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL +THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY +DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF +LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +*7. Termination* + + 1. This License and the rights granted hereunder will terminate + automatically upon any breach by You of the terms of this License. + Individuals or entities who have received Derivative Works or + Collective Works from You under this License, however, will not + have their licenses terminated provided such individuals or + entities remain in full compliance with those licenses. Sections + 1, 2, 5, 6, 7, and 8 will survive any termination of this License. + 2. Subject to the above terms and conditions, the license granted + here is perpetual (for the duration of the applicable copyright in + the Work). Notwithstanding the above, Licensor reserves the right + to release the Work under different license terms or to stop + distributing the Work at any time; provided, however that any such + election will not serve to withdraw this License (or any other + license that has been, or is required to be, granted under the + terms of this License), and this License will continue in full + force and effect unless terminated as stated above. + +*8. Miscellaneous* + + 1. Each time You distribute or publicly digitally perform the Work or + a Collective Work, the Licensor offers to the recipient a license + to the Work on the same terms and conditions as the license + granted to You under this License. + 2. Each time You distribute or publicly digitally perform a + Derivative Work, Licensor offers to the recipient a license to the + original Work on the same terms and conditions as the license + granted to You under this License. + 3. If any provision of this License is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability + of the remainder of the terms of this License, and without further + action by the parties to this agreement, such provision shall be + reformed to the minimum extent necessary to make such provision + valid and enforceable. + 4. No term or provision of this License shall be deemed waived and no + breach consented to unless such waiver or consent shall be in + writing and signed by the party to be charged with such waiver or + consent. + 5. This License constitutes the entire agreement between the parties + with respect to the Work licensed here. There are no + understandings, agreements or representations with respect to the + Work not specified here. Licensor shall not be bound by any + additional provisions that may appear in any communication from + You. This License may not be modified without the mutual written + agreement of the Licensor and You. + +Creative Commons is not a party to this License, and makes no warranty +whatsoever in connection with the Work. Creative Commons will not be +liable to You or any party on any legal theory for any damages +whatsoever, including without limitation any general, special, +incidental or consequential damages arising in connection to this +license. Notwithstanding the foregoing two (2) sentences, if Creative +Commons has expressly identified itself as the Licensor hereunder, it +shall have all rights and obligations of Licensor. + +Except for the limited purpose of indicating to the public that the Work +is licensed under the CCPL, neither party will use the trademark +"Creative Commons" or any related trademark or logo of Creative Commons +without the prior written consent of Creative Commons. Any permitted use +will be in compliance with Creative Commons' then-current trademark +usage guidelines, as may be published on its website or otherwise made +available upon request from time to time. + +Creative Commons may be contacted at http://creativecommons.org/ +<http://creativecommons.org>. + +« Back to Commons Deed <./> diff --git a/pyramid/paster_templates/pylons_minimal/+package+/templates/mytemplate.mak b/pyramid/paster_templates/pylons_minimal/+package+/templates/mytemplate.mak new file mode 100644 index 000000000..035cc2f78 --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/+package+/templates/mytemplate.mak @@ -0,0 +1,49 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" + xmlns:tal="http://xml.zope.org/namespaces/tal"> +<head> +<meta http-equiv="content-type" content="text/html; charset=utf-8" /> +<title>${project} Application</title> +<meta name="keywords" content="python web application" /> +<meta name="description" content="Pylons web application" /> +<link href="${request.application_url}/static/default.css" rel="stylesheet" type="text/css" /> +</head> +<body> +<!-- start header --> +<div id="logo"> + <h2><code>${project}</code>, a <code>Pylons</code> application</h2> +</div> +<div id="header"> + <div id="menu"> + </div> +</div> +<!-- end header --> +<div id="wrapper"> + <!-- start page --> + <div id="page"> + <!-- start content --> + <div id="content"> + <div class="post"> + <h1 class="title">Welcome to <code>${project}</code>, an + application generated by the <a + href="http://pylonshq.com">Pylons</a> web + application framework.</h1> + </div> + </div> + <!-- end content --> + <!-- start sidebar --> + <div id="sidebar"></div> + <!-- end sidebar --> + <div style="clear: both;"> </div> + </div> +</div> +<!-- end page --> +<!-- start footer --> +<div id="footer"> + <p id="legal">( c ) 2008. All Rights Reserved. Template design + by <a href="http://www.freecsstemplates.org/">Free CSS + Templates</a>.</p> +</div> +<!-- end footer --> +</body> +</html> diff --git a/pyramid/paster_templates/pylons_minimal/+package+/tests.py_tmpl b/pyramid/paster_templates/pylons_minimal/+package+/tests.py_tmpl new file mode 100644 index 000000000..d98bee355 --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/+package+/tests.py_tmpl @@ -0,0 +1,24 @@ +import unittest + +from pyramid.configuration import Configurator + +class MyControllerTests(unittest.TestCase): + def setUp(self): + self.config = Configurator() + self.config.begin() + + def tearDown(self): + self.config.end() + + def _makeOne(self, request): + from {{package}}.handlers import MyHandler + return MyHandler(request) + + def test_index(self): + request = DummyRequest() + controller = self._makeOne(request) + info = controller.index() + self.assertEqual(info['project'], '{{project}}') + +class DummyRequest(object): + pass diff --git a/pyramid/paster_templates/pylons_minimal/CHANGES.txt_tmpl b/pyramid/paster_templates/pylons_minimal/CHANGES.txt_tmpl new file mode 100644 index 000000000..35a34f332 --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/CHANGES.txt_tmpl @@ -0,0 +1,4 @@ +0.0 +--- + +- Initial version diff --git a/pyramid/paster_templates/pylons_minimal/README.txt_tmpl b/pyramid/paster_templates/pylons_minimal/README.txt_tmpl new file mode 100644 index 000000000..0ddebfc3e --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/README.txt_tmpl @@ -0,0 +1,4 @@ +{{project}} README + + + diff --git a/pyramid/paster_templates/pylons_minimal/development.ini_tmpl b/pyramid/paster_templates/pylons_minimal/development.ini_tmpl new file mode 100644 index 000000000..d3c8b57c9 --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/development.ini_tmpl @@ -0,0 +1,28 @@ +[app:{{project}}] +use = egg:{{project}} +reload_templates = true +mako.directories = {{package}}:templates +debug_authorization = false +debug_notfound = false +debug_templates = true +default_locale_name = en +session.type = file +session.data_dir = %(here)s/data/sessions/data +session.lock_dir = %(here)s/data/sessions/lock +session.key = {{project}} +session.secret = your_app_secret_string +cache.regions = default_term, second, short_term, long_term +cache.type = memory +cache.second.expire = 1 +cache.short_term.expire = 60 +cache.default_term.expire = 300 +cache.long_term.expire = 3600 + +[pipeline:main] +pipeline = egg:WebError#evalerror + {{project}} + +[server:main] +use = egg:Paste#http +host = 0.0.0.0 +port = 5000 diff --git a/pyramid/paster_templates/pylons_minimal/setup.cfg_tmpl b/pyramid/paster_templates/pylons_minimal/setup.cfg_tmpl new file mode 100644 index 000000000..5bec29823 --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/setup.cfg_tmpl @@ -0,0 +1,27 @@ +[nosetests] +match=^test +nocapture=1 +cover-package={{package}} +with-coverage=1 +cover-erase=1 + +[compile_catalog] +directory = {{package}}/locale +domain = {{project}} +statistics = true + +[extract_messages] +add_comments = TRANSLATORS: +output_file = {{package}}/locale/{{project}}.pot +width = 80 + +[init_catalog] +domain = {{project}} +input_file = {{package}}/locale/{{project}}.pot +output_dir = {{package}}/locale + +[update_catalog] +domain = {{project}} +input_file = {{package}}/locale/{{project}}.pot +output_dir = {{package}}/locale +previous = true diff --git a/pyramid/paster_templates/pylons_minimal/setup.py_tmpl b/pyramid/paster_templates/pylons_minimal/setup.py_tmpl new file mode 100644 index 000000000..baa57aa4e --- /dev/null +++ b/pyramid/paster_templates/pylons_minimal/setup.py_tmpl @@ -0,0 +1,36 @@ +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_beaker', 'WebError'] + +setup(name='{{project}}', + version='0.0', + description='{{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 pylons', + packages=find_packages(), + include_package_data=True, + zip_safe=False, + install_requires=requires, + tests_require=requires, + test_suite="{{package}}", + entry_points = """\ + [paste.app_factory] + main = {{package}}:main + """ + ) + diff --git a/pyramid/paster_templates/pylons_sqla/+package+/__init__.py_tmpl b/pyramid/paster_templates/pylons_sqla/+package+/__init__.py_tmpl new file mode 100644 index 000000000..cf26cd0ea --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/+package+/__init__.py_tmpl @@ -0,0 +1,38 @@ +from pyramid_beaker import session_factory_from_settings +from pyramid.personality.pylons import renderer_globals_factory_config + +def main(global_config, **settings): + """ This function returns a Pylons WSGI application. + """ + from paste.deploy.converters import asbool + from pyramid.configuration import Configurator + from {{package}}.models import initialize_sql + db_string = settings.get('db_string') + if db_string is None: + raise ValueError("No 'db_string' value in application " + "configuration.") + initialize_sql(db_string, asbool(settings.get('db_echo'))) + config = Configurator(settings=settings) + config.begin() + session_factory = session_factory_from_settings(settings) + config.set_session_factory(session_factory) + # XXX add caching setup + globals_factory = renderer_globals_factory_config(None) + config.set_renderer_globals_factory(globals_factory) + config.add_static_view( + 'static', + '{{package}}:static/' + ) + config.add_handler( + 'main', + '/{action}', + '{{package}}.handlers:MyHandler', + ) + config.add_handler( + 'home', + '/', + '{{package}}.handlers:MyHandler', + action='index' + ) + config.end() + return config.make_wsgi_app() diff --git a/pyramid/paster_templates/pylons_sqla/+package+/handlers.py_tmpl b/pyramid/paster_templates/pylons_sqla/+package+/handlers.py_tmpl new file mode 100644 index 000000000..ce30a635e --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/+package+/handlers.py_tmpl @@ -0,0 +1,12 @@ +from pyramid.view import action + +from {{package}}.models import MyModel + +class MyHandler(object): + def __init__(self, request): + self.request = request + + @action(renderer='mytemplate.mak') + def index(self): + root = MyModel.by_name('root') + return {'root':root, 'project':'{{package}}'} diff --git a/pyramid/paster_templates/pylons_sqla/+package+/models.py b/pyramid/paster_templates/pylons_sqla/+package+/models.py new file mode 100644 index 000000000..092166902 --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/+package+/models.py @@ -0,0 +1,47 @@ +import transaction + +from sqlalchemy import create_engine +from sqlalchemy import Column +from sqlalchemy import Integer +from sqlalchemy import Unicode + +from sqlalchemy.exc import IntegrityError +from sqlalchemy.ext.declarative import declarative_base + +from sqlalchemy.orm import scoped_session +from sqlalchemy.orm import sessionmaker + +from zope.sqlalchemy import ZopeTransactionExtension + +DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension())) +Base = declarative_base() + +class MyModel(Base): + __tablename__ = 'models' + id = Column(Integer, primary_key=True) + name = Column(Unicode(255), unique=True) + value = Column(Integer) + + def __init__(self, name, value): + self.name = name + self.value = value + + @classmethod + def by_name(cls, name=None): + return DBSession.query(cls).filter(cls.name == name).first() + +def populate(): + model = MyModel(name=u'root', value=55) + DBSession.add(model) + DBSession.flush() + transaction.commit() + +def initialize_sql(db_string, db_echo=False): + engine = create_engine(db_string, echo=db_echo) + DBSession.configure(bind=engine) + Base.metadata.bind = engine + Base.metadata.create_all(engine) + try: + populate() + except IntegrityError: + pass diff --git a/pyramid/paster_templates/pylons_sqla/+package+/static/default.css b/pyramid/paster_templates/pylons_sqla/+package+/static/default.css new file mode 100644 index 000000000..41b3debde --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/+package+/static/default.css @@ -0,0 +1,380 @@ +/* +Design by Free CSS Templates +http://www.freecsstemplates.org +Released for free under a Creative Commons Attribution 2.5 License +*/ + +body { + margin: 0; + padding: 0; + background: url(images/img01.gif) repeat-x left top; + font-size: 13px; + font-family: "Trebuchet MS", Georgia, "Times New Roman", Times, serif; + text-align: justify; + color: #FFFFFF; +} + +h1, h2, h3 { + margin: 0; + text-transform: lowercase; + font-weight: normal; + color: #FFFFFF; +} + +h1 { + letter-spacing: -1px; + font-size: 32px; +} + +h2 { + font-size: 23px; +} + +p, ul, ol { + margin: 0 0 2em 0; + text-align: justify; + line-height: 26px; +} + +a:link { + color: #8BD80E; +} + +a:hover, a:active { + text-decoration: none; + color: #8BD80E; +} + +a:visited { + color: #8BD80E; +} + +img { + border: none; +} + +img.left { + float: left; + margin-right: 15px; +} + +img.right { + float: right; + margin-left: 15px; +} + +/* Form */ + +form { + margin: 0; + padding: 0; +} + +fieldset { + margin: 0; + padding: 0; + border: none; +} + +legend { + display: none; +} + +input, textarea, select { + font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; + font-size: 13px; + color: #333333; +} + +#wrapper { + margin: 0; + padding: 0; + background: #000000; +} + +/* Header */ + +#header { + width: 713px; + margin: 0 auto; + height: 42px; +} + +/* Menu */ + +#menu { + float: left; + width: 713px; + height: 50px; + background: url(images/img02.gif) no-repeat left top; +} + +#menu ul { + margin: 0; + padding: 0px 0 0 10px; + list-style: none; + line-height: normal; +} + +#menu li { + display: block; + float: left; +} + +#menu a { + display: block; + float: left; + background: url(images/img04.gif) no-repeat right 55%; + margin-top: 5px; + margin-right: 3px; + padding: 8px 17px; + text-decoration: none; + font-size: 13px; + color: #000000; +} + +#menu a:hover { + color: #000000; +} + +#menu .current_page_item a { + color: #000000; +} + +/** LOGO */ + +#logo { + width: 713px; + height: 80px; + margin: 0 auto; +} + +#logo h1, #logo h2 { + float: left; + margin: 0; + padding: 30px 0 0 0px; + line-height: normal; +} + +#logo h1 { + font-family: Georgia, "Times New Roman", Times, serif; + font-size:40px; +} + +#logo h1 a { + text-decoration: none; + color: #4C4C4C; +} + +#logo h1 a:hover { text-decoration: underline; } + +#logo h2 { + float: left; + padding: 45px 0 0 18px; + font: 18px Georgia, "Times New Roman", Times, serif; + color: #8BD80E; +} + +#logo p a { + text-decoration: none; + color: #8BD80E; +} + +#logo p a:hover { text-decoration: underline; } + + + +/* Page */ + +#page { + width: 663px; + margin: 0 auto; + background: #4C4C4C url(images/img03.gif) no-repeat left bottom; + padding: 0 25px; +} + +/* Content */ + +#content { + float: left; + width: 410px; + +} + +/* Post */ + +.post { + padding: 15px 0px; + margin-bottom: 20px; +} + +.post .title { + margin-bottom: 20px; + padding-bottom: 5px; +} + +.post h1 { + padding: 0px 0 0 0px; + background: url(images/img08.jpg) no-repeat left top; + font-size: 24px; + color: #FFFFFF; +} + +.post h2 { + padding: 0px 0 0 0px; + font-size: 22px; + color: #FFFFFF; +} + +.post .entry { +} + +.post .meta { + padding: 15px 15px 30px 0px; + font-family: Arial, Helvetica, sans-serif; + font-size: 11px; +} + +.post .meta p { + margin: 0; + padding-top: 15px; + line-height: normal; + color: #FFFFFF; +} + +.post .meta .byline { + float: left; +} + +.post .meta .links { + float: right; +} + +.post .meta .more { + padding: 0 10px 0 18px; +} + +.post .meta .comments { +} + +.post .meta b { + display: none; +} + + +/* Sidebar */ + +#sidebar { + width: 210px; + float: right; + margin: 0; + padding: 0; +} + +#sidebar ul { + margin: 0; + padding: 0; + list-style: none; +} + +#sidebar li { + margin-bottom: 40px; +} + +#sidebar li ul { +} + +#sidebar li li { + margin: 0; +} + +#sidebar h2 { + width: 250px; + padding: 8px 0 0 0px; + margin-bottom: 10px; + background: url(images/img07.jpg) no-repeat left top; + font-size: 20px; + color: #FFFFFF; +} + +/* Search */ + +#search { + +} + +#search h2 { + margin-bottom: 20px; +} + +#s { + width: 140px; + margin-right: 5px; + padding: 3px; + border: 1px solid #BED99C; +} + +#x { + padding: 3px; + border: none; + background: #8BD80E; + text-transform: lowercase; + font-size: 11px; + color: #FFFFFF; +} + +/* Boxes */ + +.box1 { + padding: 20px; +} + +.box2 { + color: #BABABA; +} + +.box2 h2 { + margin-bottom: 15px; + font-size: 16px; + color: #FFFFFF; +} + +.box2 ul { + margin: 0; + padding: 0; + list-style: none; +} + +.box2 a:link, .box2 a:hover, .box2 a:active, .box2 a:visited { + color: #EDEDED; +} + +/* Footer */ +#footer-wrap { +} + +#footer { + margin: 0 auto; + padding: 20px 0 10px 0; + background: #000000; +} + +html>body #footer { + height: auto; +} + +#footer p { + font-size: 11px; +} + +#legal { + clear: both; + padding-top: 17px; + text-align: center; + color: #FFFFFF; +} + +#legal a { + font-weight: normal; + color: #FFFFFF; +} diff --git a/pyramid/paster_templates/pylons_sqla/+package+/static/images/img01.gif b/pyramid/paster_templates/pylons_sqla/+package+/static/images/img01.gif Binary files differnew file mode 100644 index 000000000..5f082bd99 --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/+package+/static/images/img01.gif diff --git a/pyramid/paster_templates/pylons_sqla/+package+/static/images/img02.gif b/pyramid/paster_templates/pylons_sqla/+package+/static/images/img02.gif Binary files differnew file mode 100644 index 000000000..45a3ae976 --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/+package+/static/images/img02.gif diff --git a/pyramid/paster_templates/pylons_sqla/+package+/static/images/img03.gif b/pyramid/paster_templates/pylons_sqla/+package+/static/images/img03.gif Binary files differnew file mode 100644 index 000000000..d92ea38f9 --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/+package+/static/images/img03.gif diff --git a/pyramid/paster_templates/pylons_sqla/+package+/static/images/img04.gif b/pyramid/paster_templates/pylons_sqla/+package+/static/images/img04.gif Binary files differnew file mode 100644 index 000000000..950c4af9d --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/+package+/static/images/img04.gif diff --git a/pyramid/paster_templates/pylons_sqla/+package+/static/images/spacer.gif b/pyramid/paster_templates/pylons_sqla/+package+/static/images/spacer.gif Binary files differnew file mode 100644 index 000000000..5bfd67a2d --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/+package+/static/images/spacer.gif diff --git a/pyramid/paster_templates/pylons_sqla/+package+/static/templatelicense.txt b/pyramid/paster_templates/pylons_sqla/+package+/static/templatelicense.txt new file mode 100644 index 000000000..ccb6b06ab --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/+package+/static/templatelicense.txt @@ -0,0 +1,243 @@ +Creative Commons </> + +Creative Commons Legal Code + +*Attribution 2.5* + +CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE +LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN +ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION +ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE +INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM +ITS USE. + +/License/ + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE +COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY +COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS +AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE +TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE +RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS +AND CONDITIONS. + +*1. Definitions* + + 1. *"Collective Work"* means a work, such as a periodical issue, + anthology or encyclopedia, in which the Work in its entirety in + unmodified form, along with a number of other contributions, + constituting separate and independent works in themselves, are + assembled into a collective whole. A work that constitutes a + Collective Work will not be considered a Derivative Work (as + defined below) for the purposes of this License. + 2. *"Derivative Work"* means a work based upon the Work or upon the + Work and other pre-existing works, such as a translation, musical + arrangement, dramatization, fictionalization, motion picture + version, sound recording, art reproduction, abridgment, + condensation, or any other form in which the Work may be recast, + transformed, or adapted, except that a work that constitutes a + Collective Work will not be considered a Derivative Work for the + purpose of this License. For the avoidance of doubt, where the + Work is a musical composition or sound recording, the + synchronization of the Work in timed-relation with a moving image + ("synching") will be considered a Derivative Work for the purpose + of this License. + 3. *"Licensor"* means the individual or entity that offers the Work + under the terms of this License. + 4. *"Original Author"* means the individual or entity who created the + Work. + 5. *"Work"* means the copyrightable work of authorship offered under + the terms of this License. + 6. *"You"* means an individual or entity exercising rights under this + License who has not previously violated the terms of this License + with respect to the Work, or who has received express permission + from the Licensor to exercise rights under this License despite a + previous violation. + +*2. Fair Use Rights.* Nothing in this license is intended to reduce, +limit, or restrict any rights arising from fair use, first sale or other +limitations on the exclusive rights of the copyright owner under +copyright law or other applicable laws. + +*3. License Grant.* Subject to the terms and conditions of this License, +Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +perpetual (for the duration of the applicable copyright) license to +exercise the rights in the Work as stated below: + + 1. to reproduce the Work, to incorporate the Work into one or more + Collective Works, and to reproduce the Work as incorporated in the + Collective Works; + 2. to create and reproduce Derivative Works; + 3. to distribute copies or phonorecords of, display publicly, perform + publicly, and perform publicly by means of a digital audio + transmission the Work including as incorporated in Collective Works; + 4. to distribute copies or phonorecords of, display publicly, perform + publicly, and perform publicly by means of a digital audio + transmission Derivative Works. + 5. + + For the avoidance of doubt, where the work is a musical composition: + + 1. *Performance Royalties Under Blanket Licenses*. Licensor + waives the exclusive right to collect, whether individually + or via a performance rights society (e.g. ASCAP, BMI, + SESAC), royalties for the public performance or public + digital performance (e.g. webcast) of the Work. + 2. *Mechanical Rights and Statutory Royalties*. Licensor waives + the exclusive right to collect, whether individually or via + a music rights agency or designated agent (e.g. Harry Fox + Agency), royalties for any phonorecord You create from the + Work ("cover version") and distribute, subject to the + compulsory license created by 17 USC Section 115 of the US + Copyright Act (or the equivalent in other jurisdictions). + 6. *Webcasting Rights and Statutory Royalties*. For the avoidance of + doubt, where the Work is a sound recording, Licensor waives the + exclusive right to collect, whether individually or via a + performance-rights society (e.g. SoundExchange), royalties for the + public digital performance (e.g. webcast) of the Work, subject to + the compulsory license created by 17 USC Section 114 of the US + Copyright Act (or the equivalent in other jurisdictions). + +The above rights may be exercised in all media and formats whether now +known or hereafter devised. The above rights include the right to make +such modifications as are technically necessary to exercise the rights +in other media and formats. All rights not expressly granted by Licensor +are hereby reserved. + +*4. Restrictions.*The license granted in Section 3 above is expressly +made subject to and limited by the following restrictions: + + 1. You may distribute, publicly display, publicly perform, or + publicly digitally perform the Work only under the terms of this + License, and You must include a copy of, or the Uniform Resource + Identifier for, this License with every copy or phonorecord of the + Work You distribute, publicly display, publicly perform, or + publicly digitally perform. You may not offer or impose any terms + on the Work that alter or restrict the terms of this License or + the recipients' exercise of the rights granted hereunder. You may + not sublicense the Work. You must keep intact all notices that + refer to this License and to the disclaimer of warranties. You may + not distribute, publicly display, publicly perform, or publicly + digitally perform the Work with any technological measures that + control access or use of the Work in a manner inconsistent with + the terms of this License Agreement. The above applies to the Work + as incorporated in a Collective Work, but this does not require + the Collective Work apart from the Work itself to be made subject + to the terms of this License. If You create a Collective Work, + upon notice from any Licensor You must, to the extent practicable, + remove from the Collective Work any credit as required by clause + 4(b), as requested. If You create a Derivative Work, upon notice + from any Licensor You must, to the extent practicable, remove from + the Derivative Work any credit as required by clause 4(b), as + requested. + 2. If you distribute, publicly display, publicly perform, or publicly + digitally perform the Work or any Derivative Works or Collective + Works, You must keep intact all copyright notices for the Work and + provide, reasonable to the medium or means You are utilizing: (i) + the name of the Original Author (or pseudonym, if applicable) if + supplied, and/or (ii) if the Original Author and/or Licensor + designate another party or parties (e.g. a sponsor institute, + publishing entity, journal) for attribution in Licensor's + copyright notice, terms of service or by other reasonable means, + the name of such party or parties; the title of the Work if + supplied; to the extent reasonably practicable, the Uniform + Resource Identifier, if any, that Licensor specifies to be + associated with the Work, unless such URI does not refer to the + copyright notice or licensing information for the Work; and in the + case of a Derivative Work, a credit identifying the use of the + Work in the Derivative Work (e.g., "French translation of the Work + by Original Author," or "Screenplay based on original Work by + Original Author"). Such credit may be implemented in any + reasonable manner; provided, however, that in the case of a + Derivative Work or Collective Work, at a minimum such credit will + appear where any other comparable authorship credit appears and in + a manner at least as prominent as such other comparable authorship + credit. + +*5. Representations, Warranties and Disclaimer* + +UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR +OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY +KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, +INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, +FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF +LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, +WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE +EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. + +*6. Limitation on Liability.* EXCEPT TO THE EXTENT REQUIRED BY +APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL +THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY +DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF +LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +*7. Termination* + + 1. This License and the rights granted hereunder will terminate + automatically upon any breach by You of the terms of this License. + Individuals or entities who have received Derivative Works or + Collective Works from You under this License, however, will not + have their licenses terminated provided such individuals or + entities remain in full compliance with those licenses. Sections + 1, 2, 5, 6, 7, and 8 will survive any termination of this License. + 2. Subject to the above terms and conditions, the license granted + here is perpetual (for the duration of the applicable copyright in + the Work). Notwithstanding the above, Licensor reserves the right + to release the Work under different license terms or to stop + distributing the Work at any time; provided, however that any such + election will not serve to withdraw this License (or any other + license that has been, or is required to be, granted under the + terms of this License), and this License will continue in full + force and effect unless terminated as stated above. + +*8. Miscellaneous* + + 1. Each time You distribute or publicly digitally perform the Work or + a Collective Work, the Licensor offers to the recipient a license + to the Work on the same terms and conditions as the license + granted to You under this License. + 2. Each time You distribute or publicly digitally perform a + Derivative Work, Licensor offers to the recipient a license to the + original Work on the same terms and conditions as the license + granted to You under this License. + 3. If any provision of this License is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability + of the remainder of the terms of this License, and without further + action by the parties to this agreement, such provision shall be + reformed to the minimum extent necessary to make such provision + valid and enforceable. + 4. No term or provision of this License shall be deemed waived and no + breach consented to unless such waiver or consent shall be in + writing and signed by the party to be charged with such waiver or + consent. + 5. This License constitutes the entire agreement between the parties + with respect to the Work licensed here. There are no + understandings, agreements or representations with respect to the + Work not specified here. Licensor shall not be bound by any + additional provisions that may appear in any communication from + You. This License may not be modified without the mutual written + agreement of the Licensor and You. + +Creative Commons is not a party to this License, and makes no warranty +whatsoever in connection with the Work. Creative Commons will not be +liable to You or any party on any legal theory for any damages +whatsoever, including without limitation any general, special, +incidental or consequential damages arising in connection to this +license. Notwithstanding the foregoing two (2) sentences, if Creative +Commons has expressly identified itself as the Licensor hereunder, it +shall have all rights and obligations of Licensor. + +Except for the limited purpose of indicating to the public that the Work +is licensed under the CCPL, neither party will use the trademark +"Creative Commons" or any related trademark or logo of Creative Commons +without the prior written consent of Creative Commons. Any permitted use +will be in compliance with Creative Commons' then-current trademark +usage guidelines, as may be published on its website or otherwise made +available upon request from time to time. + +Creative Commons may be contacted at http://creativecommons.org/ +<http://creativecommons.org>. + +« Back to Commons Deed <./> diff --git a/pyramid/paster_templates/pylons_sqla/+package+/templates/mytemplate.mak b/pyramid/paster_templates/pylons_sqla/+package+/templates/mytemplate.mak new file mode 100644 index 000000000..42c61bc4d --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/+package+/templates/mytemplate.mak @@ -0,0 +1,50 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" + xmlns:tal="http://xml.zope.org/namespaces/tal"> +<head> +<meta http-equiv="content-type" content="text/html; charset=utf-8" /> +<title>${project} Application</title> +<meta name="keywords" content="python web application" /> +<meta name="description" content="Pylons web application" /> +<link href="${request.application_url}/static/default.css" rel="stylesheet" type="text/css" /> +</head> +<body> +<!-- start header --> +<div id="logo"> + <h2><code>${project}</code>, a <code>Pylons</code> application</h2> +</div> +<div id="header"> + <div id="menu"> + </div> +</div> +<!-- end header --> +<div id="wrapper"> + <!-- start page --> + <div id="page"> + <!-- start content --> + <div id="content"> + <div class="post"> + <h1 class="title">Welcome to <code>${project}</code>, an + application generated by the <a + href="http://pylonshq.com">Pylons</a> web + application framework.</h1> + </div> + <div>The root object's name is "${root.name}"</div> + </div> + <!-- end content --> + <!-- start sidebar --> + <div id="sidebar"></div> + <!-- end sidebar --> + <div style="clear: both;"> </div> + </div> +</div> +<!-- end page --> +<!-- start footer --> +<div id="footer"> + <p id="legal">( c ) 2008. All Rights Reserved. Template design + by <a href="http://www.freecsstemplates.org/">Free CSS + Templates</a>.</p> +</div> +<!-- end footer --> +</body> +</html> diff --git a/pyramid/paster_templates/pylons_sqla/+package+/tests.py_tmpl b/pyramid/paster_templates/pylons_sqla/+package+/tests.py_tmpl new file mode 100644 index 000000000..099df47bd --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/+package+/tests.py_tmpl @@ -0,0 +1,26 @@ +import unittest + +class MyHandlerTests(unittest.TestCase): + def setUp(self): + from pyramid.configuration import Configurator + from {{package}}.models import initialize_sql + self.session = initialize_sql('sqlite://') + self.config = Configurator() + self.config.begin() + + def tearDown(self): + self.config.end() + + def _makeOne(self, request): + from {{package}}.handlers import MyHandler + return MyHandler(request) + + def test_index(self): + request = DummyRequest() + handler = self._makeOne(request) + info = handler.index() + self.assertEqual(info['project'], '{{package}}') + self.assertEqual(info['root'].name, 'root') + +class DummyRequest(object): + pass diff --git a/pyramid/paster_templates/pylons_sqla/CHANGES.txt_tmpl b/pyramid/paster_templates/pylons_sqla/CHANGES.txt_tmpl new file mode 100644 index 000000000..35a34f332 --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/CHANGES.txt_tmpl @@ -0,0 +1,4 @@ +0.0 +--- + +- Initial version diff --git a/pyramid/paster_templates/pylons_sqla/README.txt_tmpl b/pyramid/paster_templates/pylons_sqla/README.txt_tmpl new file mode 100644 index 000000000..0ddebfc3e --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/README.txt_tmpl @@ -0,0 +1,4 @@ +{{project}} README + + + diff --git a/pyramid/paster_templates/pylons_sqla/development.ini_tmpl b/pyramid/paster_templates/pylons_sqla/development.ini_tmpl new file mode 100644 index 000000000..f1f1e28f2 --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/development.ini_tmpl @@ -0,0 +1,32 @@ +[app:{{project}}] +use = egg:{{project}} +reload_templates = true +mako.directories = {{package}}:templates +debug_authorization = false +debug_notfound = false +debug_templates = true +default_locale_name = en +db_string = sqlite:///%(here)s/tutorial.db +db_echo = true +session.type = file +session.data_dir = %(here)s/data/sessions/data +session.lock_dir = %(here)s/data/sessions/lock +session.key = {{project}} +session.secret = your_app_secret_string +cache.regions = default_term, second, short_term, long_term +cache.type = memory +cache.second.expire = 1 +cache.short_term.expire = 60 +cache.default_term.expire = 300 +cache.long_term.expire = 3600 + +[pipeline:main] +pipeline = + egg:WebError#evalerror + egg:repoze.tm2#tm + {{project}} + +[server:main] +use = egg:Paste#http +host = 0.0.0.0 +port = 5000 diff --git a/pyramid/paster_templates/pylons_sqla/setup.cfg_tmpl b/pyramid/paster_templates/pylons_sqla/setup.cfg_tmpl new file mode 100644 index 000000000..5bec29823 --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/setup.cfg_tmpl @@ -0,0 +1,27 @@ +[nosetests] +match=^test +nocapture=1 +cover-package={{package}} +with-coverage=1 +cover-erase=1 + +[compile_catalog] +directory = {{package}}/locale +domain = {{project}} +statistics = true + +[extract_messages] +add_comments = TRANSLATORS: +output_file = {{package}}/locale/{{project}}.pot +width = 80 + +[init_catalog] +domain = {{project}} +input_file = {{package}}/locale/{{project}}.pot +output_dir = {{package}}/locale + +[update_catalog] +domain = {{project}} +input_file = {{package}}/locale/{{project}}.pot +output_dir = {{package}}/locale +previous = true diff --git a/pyramid/paster_templates/pylons_sqla/setup.py_tmpl b/pyramid/paster_templates/pylons_sqla/setup.py_tmpl new file mode 100644 index 000000000..38881367a --- /dev/null +++ b/pyramid/paster_templates/pylons_sqla/setup.py_tmpl @@ -0,0 +1,48 @@ +import os +import sys + +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_beaker', + 'SQLAlchemy', + 'transaction', + 'repoze.tm2', + 'zope.sqlalchemy', + 'WebError', +] + +if sys.version_info[:3] < (2,5,0): + requires.append('pysqlite') + +setup(name='{{project}}', + version='0.0', + description='{{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 pylons', + packages=find_packages(), + include_package_data=True, + zip_safe=False, + install_requires=requires, + tests_require=requires, + test_suite="{{package}}", + entry_points = """\ + [paste.app_factory] + main = {{package}}:main + """ + ) + diff --git a/pyramid/personality/__init__.py b/pyramid/personality/__init__.py new file mode 100644 index 000000000..5bb534f79 --- /dev/null +++ b/pyramid/personality/__init__.py @@ -0,0 +1 @@ +# package diff --git a/pyramid/personality/pylons.py b/pyramid/personality/pylons.py new file mode 100644 index 000000000..2e7984fd9 --- /dev/null +++ b/pyramid/personality/pylons.py @@ -0,0 +1,24 @@ +from pyramid.threadlocal import get_current_request +from pyramid.url import route_url + +def renderer_globals_factory_config(helpers): + """ Return a Pylons renderer globals factory using ``helpers`` as + a helpers key.""" + def renderer_globals_factory(system): + req = system['request'] + if req is None: + req = get_current_request() + renderer_globals = { + 'url': route_url, + 'h': helpers, + 'request':req, + } + if req is not None: + tmpl_context = req.tmpl_context + renderer_globals['c'] = tmpl_context + renderer_globals['tmpl_context'] = tmpl_context + if 'session' in req.__dict__: + renderer_globals['session'] = req.session + return renderer_globals + return renderer_globals_factory + diff --git a/pyramid/request.py b/pyramid/request.py index 7ffdb7495..76fff37a8 100644 --- a/pyramid/request.py +++ b/pyramid/request.py @@ -9,6 +9,9 @@ from pyramid.interfaces import ISessionFactory from pyramid.exceptions import ConfigurationError from pyramid.decorator import reify +class TemplateContext(object): + pass + class Request(WebobRequest): """ A subclass of the :term:`WebOb` Request class. An instance of @@ -36,6 +39,11 @@ class Request(WebobRequest): finished_callbacks = () exception = None + @reify + def tmpl_context(self): + """ Template context (for Pylons apps) """ + return TemplateContext() + def add_response_callback(self, callback): """ Add a callback to the set of callbacks to be called by the diff --git a/pyramid/session.py b/pyramid/session.py index 50f071398..158468152 100644 --- a/pyramid/session.py +++ b/pyramid/session.py @@ -30,14 +30,6 @@ def manage_accessed(wrapped): accessed.__doc__ = wrapped.__doc__ return accessed -def manage_modified(wrapped): - accessed = manage_accessed(wrapped) - def modified(session, *arg, **kw): - session.modified = int(time.time()) - return accessed(session, *arg, **kw) - modified.__doc__ = accessed.__doc__ - return modified - def InsecureCookieSessionFactoryConfig( secret, timeout=1200, @@ -116,20 +108,19 @@ def InsecureCookieSessionFactoryConfig( def __init__(self, request): self.request = request now = time.time() - created = accessed = modified = now + created = accessed = now new = True cookieval = request.cookies.get(self._cookie_name) value = deserialize(cookieval, self._secret) state = {} if value is not None: - accessed, created, modified, state = value + accessed, created, state = value new = False if now - accessed > self._timeout: state = {} self.created = created self.accessed = accessed - self.modified = modified self.new = new dict.__init__(self, state) @@ -157,13 +148,13 @@ def InsecureCookieSessionFactoryConfig( __iter__ = manage_accessed(dict.__iter__) # modifying dictionary methods - clear = manage_modified(dict.clear) - update = manage_modified(dict.update) - setdefault = manage_modified(dict.setdefault) - pop = manage_modified(dict.pop) - popitem = manage_modified(dict.popitem) - __setitem__ = manage_modified(dict.__setitem__) - __delitem__ = manage_modified(dict.__delitem__) + clear = manage_accessed(dict.clear) + update = manage_accessed(dict.update) + setdefault = manage_accessed(dict.setdefault) + pop = manage_accessed(dict.pop) + popitem = manage_accessed(dict.popitem) + __setitem__ = manage_accessed(dict.__setitem__) + __delitem__ = manage_accessed(dict.__delitem__) # non-API methods def _set_cookie(self, response): @@ -172,8 +163,7 @@ def InsecureCookieSessionFactoryConfig( if exception is not None: # dont set a cookie during exceptions return False cookieval = serialize( - (self.accessed, self.created, self.modified, dict(self)), - self._secret + (self.accessed, self.created, dict(self)), self._secret ) if len(cookieval) > 4064: raise ValueError( diff --git a/pyramid/testing.py b/pyramid/testing.py index 5d54af9e9..188485635 100644 --- a/pyramid/testing.py +++ b/pyramid/testing.py @@ -55,7 +55,7 @@ def registerDummySecurityPolicy(userid=None, groupids=(), permissive=True): .. warning:: This API is deprecated as of :mod:`pyramid` 1.0. Instead use the - :meth:`repoze.bfg.configuration.Configurator.testing_securitypolicy` + :meth:`pyramid.configuration.Configurator.testing_securitypolicy` method in your unit and integration tests. """ registry = get_current_registry() diff --git a/pyramid/tests/defpermbugapp/__init__.py b/pyramid/tests/defpermbugapp/__init__.py index b56c1c71d..82a189b9e 100644 --- a/pyramid/tests/defpermbugapp/__init__.py +++ b/pyramid/tests/defpermbugapp/__init__.py @@ -1,14 +1,14 @@ from webob import Response -from pyramid.view import bfg_view +from pyramid.view import view_config -@bfg_view(name='x') +@view_config(name='x') def x_view(request): # pragma: no cover return Response('this is private!') -@bfg_view(name='y', permission='private2') +@view_config(name='y', permission='private2') def y_view(request): # pragma: no cover return Response('this is private too!') -@bfg_view(name='z', permission='__no_permission_required__') +@view_config(name='z', permission='__no_permission_required__') def z_view(request): return Response('this is public') diff --git a/pyramid/tests/grokkedapp/__init__.py b/pyramid/tests/grokkedapp/__init__.py index 547987d8b..1411e4c49 100644 --- a/pyramid/tests/grokkedapp/__init__.py +++ b/pyramid/tests/grokkedapp/__init__.py @@ -1,15 +1,15 @@ -from pyramid.view import bfg_view +from pyramid.view import view_config -@bfg_view() +@view_config() def grokked(context, request): return 'grokked' -@bfg_view(request_method='POST') +@view_config(request_method='POST') def grokked_post(context, request): return 'grokked_post' -@bfg_view(name='stacked2') -@bfg_view(name='stacked1') +@view_config(name='stacked2') +@view_config(name='stacked1') def stacked(context, request): return 'stacked' @@ -21,8 +21,8 @@ class stacked_class(object): def __call__(self): return 'stacked_class' -stacked_class = bfg_view(name='stacked_class1')(stacked_class) -stacked_class = bfg_view(name='stacked_class2')(stacked_class) +stacked_class = view_config(name='stacked_class1')(stacked_class) +stacked_class = view_config(name='stacked_class2')(stacked_class) class oldstyle_grokked_class: def __init__(self, context, request): @@ -32,7 +32,7 @@ class oldstyle_grokked_class: def __call__(self): return 'oldstyle_grokked_class' -oldstyle_grokked_class = bfg_view(name='oldstyle_grokked_class')( +oldstyle_grokked_class = view_config(name='oldstyle_grokked_class')( oldstyle_grokked_class) class grokked_class(object): @@ -43,17 +43,17 @@ class grokked_class(object): def __call__(self): return 'grokked_class' -grokked_class = bfg_view(name='grokked_class')(grokked_class) +grokked_class = view_config(name='grokked_class')(grokked_class) class Foo(object): def __call__(self, context, request): return 'grokked_instance' grokked_instance = Foo() -grokked_instance = bfg_view(name='grokked_instance')(grokked_instance) +grokked_instance = view_config(name='grokked_instance')(grokked_instance) class Base(object): - @bfg_view(name='basemethod') + @view_config(name='basemethod') def basemethod(self): """ """ @@ -62,16 +62,16 @@ class MethodViews(Base): self.context = context self.request = request - @bfg_view(name='method1') + @view_config(name='method1') def method1(self): return 'method1' - @bfg_view(name='method2') + @view_config(name='method2') def method2(self): return 'method2' - @bfg_view(name='stacked_method2') - @bfg_view(name='stacked_method1') + @view_config(name='stacked_method2') + @view_config(name='stacked_method1') def stacked(self): return 'stacked_method' diff --git a/pyramid/tests/grokkedapp/another.py b/pyramid/tests/grokkedapp/another.py index 872eaf103..48fe81798 100644 --- a/pyramid/tests/grokkedapp/another.py +++ b/pyramid/tests/grokkedapp/another.py @@ -1,15 +1,15 @@ -from pyramid.view import bfg_view +from pyramid.view import view_config -@bfg_view(name='another') +@view_config(name='another') def grokked(context, request): return 'another_grokked' -@bfg_view(request_method='POST', name='another') +@view_config(request_method='POST', name='another') def grokked_post(context, request): return 'another_grokked_post' -@bfg_view(name='another_stacked2') -@bfg_view(name='another_stacked1') +@view_config(name='another_stacked2') +@view_config(name='another_stacked1') def stacked(context, request): return 'another_stacked' @@ -21,8 +21,8 @@ class stacked_class(object): def __call__(self): return 'another_stacked_class' -stacked_class = bfg_view(name='another_stacked_class1')(stacked_class) -stacked_class = bfg_view(name='another_stacked_class2')(stacked_class) +stacked_class = view_config(name='another_stacked_class1')(stacked_class) +stacked_class = view_config(name='another_stacked_class2')(stacked_class) class oldstyle_grokked_class: def __init__(self, context, request): @@ -32,7 +32,7 @@ class oldstyle_grokked_class: def __call__(self): return 'another_oldstyle_grokked_class' -oldstyle_grokked_class = bfg_view(name='another_oldstyle_grokked_class')( +oldstyle_grokked_class = view_config(name='another_oldstyle_grokked_class')( oldstyle_grokked_class) class grokked_class(object): @@ -43,14 +43,15 @@ class grokked_class(object): def __call__(self): return 'another_grokked_class' -grokked_class = bfg_view(name='another_grokked_class')(grokked_class) +grokked_class = view_config(name='another_grokked_class')(grokked_class) class Foo(object): def __call__(self, context, request): return 'another_grokked_instance' grokked_instance = Foo() -grokked_instance = bfg_view(name='another_grokked_instance')(grokked_instance) +grokked_instance = view_config(name='another_grokked_instance')( + grokked_instance) # ungrokkable diff --git a/pyramid/tests/grokkedapp/pod/notinit.py b/pyramid/tests/grokkedapp/pod/notinit.py index 9c033eaef..3d01f92d5 100644 --- a/pyramid/tests/grokkedapp/pod/notinit.py +++ b/pyramid/tests/grokkedapp/pod/notinit.py @@ -1,5 +1,5 @@ -from pyramid.view import bfg_view +from pyramid.view import view_config -@bfg_view(name='pod_notinit') +@view_config(name='pod_notinit') def subpackage_notinit(context, request): return 'pod_notinit' diff --git a/pyramid/tests/grokkedapp/subpackage/__init__.py b/pyramid/tests/grokkedapp/subpackage/__init__.py index 7f93f0f16..3e332913a 100644 --- a/pyramid/tests/grokkedapp/subpackage/__init__.py +++ b/pyramid/tests/grokkedapp/subpackage/__init__.py @@ -1,5 +1,5 @@ -from pyramid.view import bfg_view +from pyramid.view import view_config -@bfg_view(name='subpackage_init') +@view_config(name='subpackage_init') def subpackage_init(context, request): return 'subpackage_init' diff --git a/pyramid/tests/grokkedapp/subpackage/notinit.py b/pyramid/tests/grokkedapp/subpackage/notinit.py index 3f26180b3..41f0c5ea8 100644 --- a/pyramid/tests/grokkedapp/subpackage/notinit.py +++ b/pyramid/tests/grokkedapp/subpackage/notinit.py @@ -1,5 +1,5 @@ -from pyramid.view import bfg_view +from pyramid.view import view_config -@bfg_view(name='subpackage_notinit') +@view_config(name='subpackage_notinit') def subpackage_notinit(context, request): return 'subpackage_notinit' diff --git a/pyramid/tests/grokkedapp/subpackage/subsubpackage/__init__.py b/pyramid/tests/grokkedapp/subpackage/subsubpackage/__init__.py index d380226ab..ade9644ec 100644 --- a/pyramid/tests/grokkedapp/subpackage/subsubpackage/__init__.py +++ b/pyramid/tests/grokkedapp/subpackage/subsubpackage/__init__.py @@ -1,5 +1,5 @@ -from pyramid.view import bfg_view +from pyramid.view import view_config -@bfg_view(name='subsubpackage_init') +@view_config(name='subsubpackage_init') def subpackage_init(context, request): return 'subsubpackage_init' diff --git a/pyramid/tests/test_docs.py b/pyramid/tests/test_docs.py index a00171842..bf06c7ca6 100644 --- a/pyramid/tests/test_docs.py +++ b/pyramid/tests/test_docs.py @@ -20,7 +20,7 @@ if 0: m += manuel.capture.Manuel() docs = [] - egg_path = pkg_resources.get_distribution('repoze.bfg').location + egg_path = pkg_resources.get_distribution('pyramid').location path = os.path.join(egg_path, 'docs') for root, dirs, files in os.walk(path): for ignore in ('.svn', '.build', '.hg', '.git', 'CVS'): diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py index fffd8c03e..872f50cd4 100644 --- a/pyramid/tests/test_integration.py +++ b/pyramid/tests/test_integration.py @@ -2,7 +2,7 @@ import os import unittest from pyramid.wsgi import wsgiapp -from pyramid.view import bfg_view +from pyramid.view import view_config from pyramid.view import static from zope.interface import Interface @@ -12,7 +12,7 @@ from pyramid import testing class INothing(Interface): pass -@bfg_view(for_=INothing) +@view_config(for_=INothing) @wsgiapp def wsgiapptest(environ, start_response): """ """ diff --git a/pyramid/tests/test_pylons_personality.py b/pyramid/tests/test_pylons_personality.py new file mode 100644 index 000000000..570fcba5b --- /dev/null +++ b/pyramid/tests/test_pylons_personality.py @@ -0,0 +1,54 @@ +import unittest + + +class Test_pylons_renderer_globals_factory_config(unittest.TestCase): + def setUp(self): + from pyramid.configuration import Configurator + self.config = Configurator() + request = DummyRequest() + self.config.begin(request) + + def tearDown(self): + self.config.end() + + def _makeOne(self, helpers): + from pyramid.personality import pylons + return pylons.renderer_globals_factory_config(helpers) + + def test_with_request(self): + request = DummyRequest() + from pyramid.url import route_url + system = {'request':request} + factory = self._makeOne('helpers') + result = factory(system) + self.assertEqual(result['url'], route_url) + self.assertEqual(result['h'], 'helpers') + self.assertEqual(result['c'], request.tmpl_context) + self.assertEqual(result['tmpl_context'], request.tmpl_context) + + def test_without_request(self): + from pyramid.url import route_url + from pyramid.threadlocal import get_current_request + system = {'request':None} + factory = self._makeOne('helpers') + result = factory(system) + self.assertEqual(result['url'], route_url) + self.assertEqual(result['h'], 'helpers') + request = get_current_request() + self.assertEqual(result['c'], request.tmpl_context) + self.assertEqual(result['tmpl_context'], request.tmpl_context) + self.assertEqual(result['request'], request) + + def test_with_session(self): + request = DummyRequest() + request.session = 'session' + system = {'request':request} + factory = self._makeOne('helpers') + result = factory(system) + self.assertEqual(result['session'], 'session') + +class DummyRequest(object): + def __init__(self): + self.tmpl_context = object() + + diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py index 93cbb9691..775c41731 100644 --- a/pyramid/tests/test_request.py +++ b/pyramid/tests/test_request.py @@ -43,6 +43,12 @@ class TestRequest(unittest.TestCase): inst = self._makeOne({}) self.assertTrue(IRequest.providedBy(inst)) + def test_tmpl_context(self): + from pyramid.request import TemplateContext + inst = self._makeOne({}) + result = inst.tmpl_context + self.assertEqual(result.__class__, TemplateContext) + def test_session_configured(self): from pyramid.interfaces import ISessionFactory inst = self._makeOne({}) diff --git a/pyramid/tests/test_session.py b/pyramid/tests/test_session.py index d8c1b2c00..12f70bab9 100644 --- a/pyramid/tests/test_session.py +++ b/pyramid/tests/test_session.py @@ -13,7 +13,7 @@ class TestInsecureCookieSession(unittest.TestCase): def _serialize(self, accessed, state, secret='secret'): from pyramid.session import serialize - return serialize((accessed, accessed, accessed, state), secret) + return serialize((accessed, accessed, state), secret) def test_ctor_with_cookie_still_valid(self): import time @@ -155,21 +155,6 @@ class Test_manage_accessed(unittest.TestCase): self.assertEqual(result, None) self.assertEqual(session.response, response) -class Test_manage_modified(Test_manage_accessed): - def _makeOne(self, wrapped): - from pyramid.session import manage_modified - return manage_modified(wrapped) - - def test_modified_set(self): - request = testing.DummyRequest() - session = DummySessionFactory(request) - session.modified = None - session.accessed = None - wrapper = self._makeOne(session.__class__.__setitem__) - wrapper(session, 'a', 1) - self.assertNotEqual(session.accessed, None) - self.assertNotEqual(session.modified, None) - def serialize(data, secret): try: from hashlib import sha1 diff --git a/pyramid/tests/test_view.py b/pyramid/tests/test_view.py index 62d09358b..fc725379e 100644 --- a/pyramid/tests/test_view.py +++ b/pyramid/tests/test_view.py @@ -206,7 +206,7 @@ class TestIsResponse(unittest.TestCase): response.status = None self.assertEqual(self._callFUT(response), False) -class TestBFGViewDecorator(unittest.TestCase): +class TestViewConfigDecorator(unittest.TestCase): def setUp(self): cleanUp() @@ -214,8 +214,8 @@ class TestBFGViewDecorator(unittest.TestCase): cleanUp() def _getTargetClass(self): - from pyramid.view import bfg_view - return bfg_view + from pyramid.view import view_config + return view_config def _makeOne(self, *arg, **kw): return self._getTargetClass()(*arg, **kw) diff --git a/pyramid/tests/viewdecoratorapp/views/views.py b/pyramid/tests/viewdecoratorapp/views/views.py index 15b3e63c3..c59bc87ed 100644 --- a/pyramid/tests/viewdecoratorapp/views/views.py +++ b/pyramid/tests/viewdecoratorapp/views/views.py @@ -1,17 +1,17 @@ import os -from pyramid.view import bfg_view +from pyramid.view import view_config -@bfg_view(renderer='templates/foo.pt', name='first') +@view_config(renderer='templates/foo.pt', name='first') def first(request): return {'result':'OK1'} -@bfg_view(renderer='pyramid.tests.viewdecoratorapp.views:templates/foo.pt', - name='second') +@view_config(renderer='pyramid.tests.viewdecoratorapp.views:templates/foo.pt', + name='second') def second(request): return {'result':'OK2'} here = os.path.normpath(os.path.dirname(os.path.abspath(__file__))) foo = os.path.join(here, 'templates', 'foo.pt') -@bfg_view(renderer=foo, name='third') +@view_config(renderer=foo, name='third') def third(request): return {'result':'OK3'} diff --git a/pyramid/view.py b/pyramid/view.py index bcd4cd0b7..bd9d52a24 100644 --- a/pyramid/view.py +++ b/pyramid/view.py @@ -143,7 +143,7 @@ def is_response(ob): return True return False -class bfg_view(object): +class view_config(object): """ A function, class or method :term:`decorator` which allows a developer to create view registrations nearer to a :term:`view callable` definition than use of :term:`ZCML` or :term:`imperative @@ -153,8 +153,8 @@ class bfg_view(object): from models import MyModel - @bfg_view(name='my_view', context=MyModel, permission='read', - route_name='site1') + @view_config(name='my_view', context=MyModel, permission='read', + route_name='site1') def my_view(context, request): return 'OK' @@ -176,9 +176,13 @@ class bfg_view(object): route_name='site1' /> + .. note: :class:`pyramid.view.view_config` is also importable, for + backwards compatibility purposes, as the name + :class:`pyramid.view.bfg_view`. + The following arguments are supported as arguments to - ``bfg_view``: ``context``, ``permission``, ``name``, - ``request_type``, ``route_name``, ``request_method``, + :class:`pyramid.view.view_config``: ``context``, ``permission``, + ``name``, ``request_type``, ``route_name``, ``request_method``, ``request_param``, ``containment``, ``xhr``, ``accept``, ``header`` and ``path_info``. @@ -274,9 +278,9 @@ class bfg_view(object): predicates return ``True``. Any individual or all parameters can be omitted. The simplest - ``bfg_view`` declaration is:: + :class:`pyramid.view.view_config` declaration is:: - @bfg_view() + @view_config() def my_view(...): ... @@ -286,14 +290,14 @@ class bfg_view(object): requests, with any ``REQUEST_METHOD``, any set of request.params values, without respect to any object in the :term:`lineage`. - The ``bfg_view`` decorator can also be used as a class decorator + The ``view_config`` decorator can also be used as a class decorator in Python 2.6 and better (Python 2.5 and below do not support class decorators):: from webob import Response - from pyramid.view import bfg_view + from pyramid.view import view_config - @bfg_view() + @view_config() class MyView(object): def __init__(self, context, request): self.context = context @@ -301,11 +305,11 @@ class bfg_view(object): def __call__(self): return Response('hello from %s!' % self.context) - In Python 2.5 and below, the ``bfg_view`` decorator can still be + In Python 2.5 and below, the ``view_config`` decorator can still be used against a class, although not in decorator form:: from webob import Response - from pyramid.view import bfg_view + from pyramid.view import view_config class MyView(object): def __init__(self, context, request): @@ -314,7 +318,7 @@ class bfg_view(object): def __call__(self): return Response('hello from %s!' % self.context) - MyView = bfg_view()(MyView) + MyView = view_config()(MyView) .. note:: When a view is a class, the calling semantics are different than when it is a function or another @@ -323,22 +327,23 @@ class bfg_view(object): .. warning:: Using a class as a view is a new feature in 0.8.1+. - The bfg_view decorator can also be used against a class method:: + The ``view_config`` decorator can also be used against a class + method:: from webob import Response - from pyramid.view import bfg_view + from pyramid.view import view_config class MyView(object): def __init__(self, context, request): self.context = context self.request = request - @bfg_view(name='hello') + @view_config(name='hello') def amethod(self): return Response('hello from %s!' % self.context) - When the ``bfg_view`` decorator is used against a class method, a - view is registered for the *class* (as described above), so the + When the ``view_config`` decorator is used against a class method, + a view is registered for the *class* (as described above), so the class constructor must accept either ``request`` or ``context, request``. The method which is decorated must return a response (or rely on a :term:`renderer` to generate one). Using the @@ -349,9 +354,9 @@ class bfg_view(object): spelled equivalently as:: from webob import Response - from pyramid.view import bfg_view + from pyramid.view import view_config - @bfg_view(attr='amethod', name='hello') + @view_config(attr='amethod', name='hello') class MyView(object): def __init__(self, context, request): self.context = context @@ -360,11 +365,7 @@ class bfg_view(object): def amethod(self): return Response('hello from %s!' % self.context) - .. warning:: The ability to use the ``bfg_view`` decorator as a - method decorator is new in :mod:`pyramid` version - 1.1. - - To make use of any ``bfg_view`` declaration, you must perform a + To make use of any ``view_config`` declaration, you must perform a :term:`scan`. To do so, either insert the following boilerplate into your application registry's ZCML:: @@ -431,6 +432,8 @@ class bfg_view(object): return wrapped +bfg_view = view_config # permanent b/c + def default_exceptionresponse_view(context, request): if not isinstance(context, Exception): # backwards compat for an exception response view registered via @@ -82,6 +82,9 @@ setup(name='pyramid', pyramid_zodb=pyramid.paster:ZODBProjectTemplate pyramid_routesalchemy=pyramid.paster:RoutesAlchemyProjectTemplate pyramid_alchemy=pyramid.paster:AlchemyProjectTemplate + pylons_basic=pyramid.paster:PylonsBasicProjectTemplate + pylons_minimal=pyramid.paster:PylonsMinimalProjectTemplate + pylons_sqla=pyramid.paster:PylonsSQLAlchemyProjectTemplate [paste.paster_command] pyramid_shell=pyramid.paster:BFGShellCommand [console_scripts] |
