Commits

Andriy Kornatskyy committed d46b406

Working on documentation

Comments (0)

Files changed (8)

demos/hello/hello.py

+
+""" Minimal helloworld application.
+"""
+
+from wheezy.http import HTTPResponse
+from wheezy.http import WSGIApplication
+from wheezy.routing import url
+from wheezy.web.handlers import BaseHandler
+from wheezy.web.middleware import bootstrap_defaults
+from wheezy.web.middleware import path_routing_middleware_factory
+
+
+class WelcomeHandler(BaseHandler):
+
+    def get(self):
+        response = HTTPResponse(options=self.request.config)
+        response.write('Hello World!')
+        return response
+
+
+def welcome(request):
+    response = HTTPResponse(options=request.config)
+    response.write('Hello World!')
+    return response
+
+
+all_urls = [
+        url('', WelcomeHandler, name='default'),
+        url('welcome', welcome, name='welcome')
+]
+
+
+main = WSGIApplication(
+        middleware=[
+            bootstrap_defaults(url_mapping=all_urls),
+            path_routing_middleware_factory
+        ]
+)
+
+
+if __name__ == '__main__':
+    from wsgiref.simple_server import make_server
+    try:
+        print('Visit http://localhost:8080/')
+        make_server('', 8080, main).serve_forever()
+    except KeyboardInterrupt:
+        pass
+    print('\nThanks!')
     $ virtualenv env
     $ env/bin/easy_install wheezy.web
 
+.. _helloworld:
+
+Hello World
+-----------
+
+`hello.py`_ shows you how to use :ref:`wheezy.web` in a pretty simple `WSGI`_
+application. It no way pretend to be shortest possible and absolutely not 
+magical:
+
+.. literalinclude:: ../demos/hello/hello.py
+   :lines: 1-
+
+Handler Contract
+~~~~~~~~~~~~~~~~
+
+Let have a look through each line in this application. First of all let take
+a look what is a handler:
+
+.. literalinclude:: ../demos/hello/hello.py
+   :lines: 21-24
+   
+This one is not changed from what you had in `wheezy.http`_ so you are good
+to keep it minimal. However there is added another one (that actually 
+implements the same handler contract internally):
+
+.. literalinclude:: ../demos/hello/hello.py
+   :lines: 13-18
+
+What is ``get`` method here? It is your response to HTTP GET request. You have
+post for HTTP POST, etc.
+
+Routing
+~~~~~~~
+
+Routing is inherited from `wheezy.routing`_. Note that both handlers are 
+working well together:
+
+.. literalinclude:: ../demos/hello/hello.py
+   :lines: 27-30
+   
+Application
+~~~~~~~~~~~
+
+``WSGIApplication`` is coming from `wheezy.http`_. Integration with 
+`wheezy.routing`_ is provided as middleware factory
+(:py:meth:`~wheezy.web.middleware.path_routing_middleware_factory`):
+
+.. literalinclude:: ../demos/hello/hello.py
+   :lines: 33-38
+
+.. _public_demo:
+
+Public
+------
+
+`Public`_ application serves template purpose for you. If you are about to start a
+new project it is a good starting point.
+
 .. _`virtualenv`: http://pypi.python.org/pypi/virtualenv
-
-
+.. _`hello.py`: https://bitbucket.org/akorn/wheezy.web/src/tip/demos/hello/hello.py
+.. _`public`: https://bitbucket.org/akorn/wheezy.web/src/tip/demos/public
+.. _`WSGI`: http://www.python.org/dev/peps/pep-3333
+.. _`wheezy.http`: http://packages.python.org/wheezy.http
+.. _`wheezy.routing`: http://packages.python.org/wheezy.routing

doc/userguide.rst

 User Guide
 ==========
 
-:ref:`wheezy.web` 
+:ref:`wheezy.web` is a lightweight `WSGI`_ framework that aims take most
+benefits out of standard python library and serves a sort of glue with other
+libraries. It can be run from python 2.4 up to most cutting age python 3. 
+The framework aims to alleviate the overhead associated with common activities
+performed in Web application development.
+
+:ref:`wheezy.web` framework follows the model–view–controller (MVC)
+architectural pattern to separate the data model from the user interface. This
+is considered a good practice as it modularizes code, promotes code reuse.
+
+:ref:`wheezy.web` framework follows a push-based architecture. Handlers do
+some processing, and then "push" the data to the template layer to render the
+results.
+
+Web Handlers
+------------
+Handler is any callable that accepts an instance of ``HTTPRequest`` and
+returns ``HTTPResponse``::
+
+    def handler(request):
+        return response
+
+:ref:`wheezy.web` comes with the following handlers:
+
+* :py:class:`~wheezy.web.handlers.method.MethodHandler` - represents the most
+  generic handler. It serves dispatcher purpose for HTTP request method (GET,
+  POST, etc). Base class for all handlers.
+* :py:class:`~wheezy.web.handlers.base.BaseHandler` - provides methods that
+  integartes such features like: routing, i18n, model binding, template
+  rendering, authentication, xsrf/resubmission protection.
+* :py:class:`~wheezy.web.handlers.base.RedirectRouteHandler` - redirects to
+  given route name.
+* :py:class:`~wheezy.web.handlers.file.FileHandler` - serves static files out
+  of some directory.
+* :py:class:`~wheezy.web.handlers.template.TemplateHandler` - serves templates
+  that doesn't require up front data processing.
+
+MethodHandler
+~~~~~~~~~~~~~
+
+:ref:`wheezy.web` routes incoming web request to handler per url mapping:
+
+.. literalinclude:: ../demos/hello/hello.py
+   :lines: 27-30
+
+You subclass from :py:class:`~wheezy.web.handlers.method.MethodHandler` or
+:py:class:`~wheezy.web.handlers.base.BaseHandler` and 
+define methods ``get()`` or ``post()`` that handle HTTP request method ``GET``
+or ``POST``.
+
+.. literalinclude:: ../demos/hello/hello.py
+   :lines: 13-18
+
+This method must return ``HTTPResponse`` object.
+
+:py:class:`~wheezy.web.handlers.method.MethodHandler` has a number of useful
+attributes:
+
+* ``options`` - a dictionary of application configuration options.
+* ``request`` - an instance of ``wheezy.http.HTTPRequest``.
+* ``route_args`` - a dictionary of arguments matched in url routing.
+* ``cookies`` - a list of cookies that extend ``HTTPResponse``.
+
+BaseHandler
+~~~~~~~~~~~
+
+:py:class:`~wheezy.web.handlers.base.BaseHandler` provides methods that
+integarte such features like: 
+
+#. routing
+#. i18n
+#. model binding
+#. template rendering
+#. authentication
+#. xsrf/resubmission protection.
+
+Routing
+^^^^^^^
+
+Routing feature is provided via integartation with `wheezy.routing`_ package.
+There the following methods:
+
+* ``path_for(name, **kwargs)`` - returns url path by route name.
+* ``absolute_url_for(name, **kwargs)`` - returns url by route name.
+* ``redirect_for(name, **kwargs)`` - returns redirect response by route name.
+
+All these methods support the following arguments:
+
+* ``name`` - a name of the route.
+* ``kwargs`` - extra arguments necessary for routing.
+
+Please refer to `wheezy.routing`_ documentation for more information.
+
+Internationalization
+^^^^^^^^^^^^^^^^^^^^
+
+Internationalization feature is provided via integartation with `wheezy.core`_
+package (module ``i18n``). There the following attributes:
+
+* ``locale`` - default implementation return a value resolved from route
+  arguments, particularly to name ``locale``.
+* ``translations`` - returns ``TranslationsManager`` (`wheezy.core`_ feature)
+  for the current locale.
+* ``translation`` - returns translations for the current handler. Default
+  implementation return ``NullTranslations`` object. You application handler
+  must override this attribute to provide valid ``gettext`` translations.
+
+Here is example from :ref:`public_demo` demo application::
+
+    class SignInHandler(BaseHandler):
+
+        @attribute
+        def translation(self):
+            return self.translations['membership']
+
+This code loads `membership` translations from `i18n`_ directory. In order
+to function properly the following configuration options must be defined::
+
+    from wheezy.core.i18n import TranslationsManager
+    
+    options = {}
+    options['translations_manager'] = TranslationsManager(
+                directories=['i18n'],
+                default_lang='en')
+
+See complete example in public demo application `config`_.
+
+Model Binding
+^^^^^^^^^^^^^
+
+Once html form submitted you need a way to bind these values to some domain
+model, validate, report errors, etc. This is where integartation with 
+`wheezy.validation`_ package happens.
+
+
+
+
+
+
+
+
+
+
+
+
+.. _`WSGI`: http://www.python.org/dev/peps/pep-3333
+.. _`wheezy.core`: http://bitbucket.org/akorn/wheezy.core
+.. _`wheezy.http`: http://packages.python.org/wheezy.http
+.. _`wheezy.routing`: http://packages.python.org/wheezy.routing
+.. _`wheezy.validation`: http://packages.python.org/wheezy.validation
+.. _`i18n`: https://bitbucket.org/akorn/wheezy.web/src/tip/demos/public/i18n
+.. _`config`: https://bitbucket.org/akorn/wheezy.web/src/tip/demos/public/src/config.py
+

src/wheezy/web/handlers/base.py

 
 
 class BaseHandler(MethodHandler, ValidationMixin):
+    """ Provides methods that integarte such features like: routing,
+        i18n, model binding, template rendering, authentication,
+        xsrf/resubmission protection.
+
+        You need inherit this class and define get() and/or post() to
+        be able respond to HTTP requests.
+    """
 
     @attribute
     def context(self):
 
 
 class RedirectRouteHandler(BaseHandler):
+    """ Redirects to given route name.
+    """
 
     def __init__(self, request, route_name, **route_args):
         self.route_name = route_name

src/wheezy/web/handlers/file.py

 
 
 class FileHandler(MethodHandler):
+    """ Serves static files out of some directory.
+    """
 
     def __init__(self, request, root, age=None):
         assert age is None or isinstance(age, timedelta)

src/wheezy/web/handlers/method.py

 
 
 class MethodHandler(object):
+    """ Represents the most generic handler. It serves dispatcher purpose
+        for HTTP request method (GET, POST, etc). Base class for all
+        handlers.
+    """
 
     def __new__(klass, *args, **kwargs):
         handler = super(MethodHandler, klass).__new__(klass)
         return response
 
     def head(self):
+        """ Responds to HTTP HEAD requests.
+        """
         return method_not_allowed(self.request.config)
 
     def get(self):
+        """ Responds to HTTP GET requests.
+        """
         return method_not_allowed(self.request.config)
 
     def post(self):
+        """ Responds to HTTP POST requests.
+        """
         return method_not_allowed(self.request.config)

src/wheezy/web/handlers/template.py

 
 
 class TemplateHandler(BaseHandler):
+    """ Serves templates that doesn't require up front data processing.
+    """
 
     def __init__(self, request, template_name, status_code=200):
         self.template_name = template_name

src/wheezy/web/middleware/__init__.py

 
 
 def bootstrap_defaults(url_mapping=None):
+    """ Defaults bootstrap.
+    """
     def load(options):
         if 'path_router' not in options:
             options['path_router'] = path_router = PathRouter()
 
 
 def http_error_middleware_factory(options):
+    """ HTTP error middleware factory.
+    """
     path_router = options['path_router']
     try:
         error_mapping = options['http_errors']
 
 
 def path_routing_middleware_factory(options):
+    """ PathRouting middleware factory.
+    """
     path_router = options['path_router']
     return PathRoutingMiddleware(
             path_router=path_router)