Myghty Documentation
Version: 1.2 Last Updated: 07/07/10 12:55:17
View: Paged  |  One Page
Table of Contents    (view full table)

Introduction
Setting Up
The Myghty Environment
Additional Features
Appendix
Table of Contents: Full    (view brief table)

Introduction
Setting Up
The Myghty Environment
Additional Features
Appendix

Heres a rundown of what Myghty is about, touching upon the basic features one would expect in a template system, as well as the unique features Myghty provides.

High Performance Python Server Pages (PSP)

Myghty's primary feature is it's Python Server Page (PSP) system. Individual templates are generated into pure Python modules which become the method of serving the content. Myghty creates real Python modules from templates, which are regular .py files with corresponding .pyc bytecode files. These modules can also be generated in memory only, if desired.

Myghty templates allow full Python syntax to be embedded amongst HTML or other markup, and keeps intact the full syntax and indentation scheme of Python, even within very markup-interactive sections of code. Myghty also lets you organize embedded Python code in ways that minimize its intrusion upon markup. Python embedded within markup is clearly denoted via <%python> tags or the more interactive "%" syntax:

 
 <%python>
     def somefunc():
         return True
 </%python>
 
 % if somefunc():
 <p>
     hello!
 </p>
 % # end for

Read more about Myghty syntax in Embedding Python in HTML.

Python sections can optionally have scope attributes specified, with values such as "global", "request", "init" and "cleanup", which cause the contained python code to execute at specific points in the template's execution, regardless of where they are placed in the template. This allows flexible organization of template code and a very distinct separation of Python and markup. Read more about Myghty code scope in Scoped <%python> Blocks.

back to section top
Componentized Development

Myghty allows you to organize Python code and markup into smaller sub-units of a page called Components. Consider a page like this:

                        +--------------------+
                        |    |    toolbar    |
                        |    +---------------|
                        |  header            |
                        |--------------------|
                        |        |           |
                        | left   |           |
                        | nav    | content   |
                        |        |           |
                        |        |           |
                        |--------------------|
                        |        footer      |
                        +--------------------+

Each subsection of this page is a likely candidate to be its own component. The overall template is referred to as the top-level component, and contains any number of subcomponents, which are effectively semi-autonomous units of code within a larger template file. They have their own namespaces, passed-in argument lists, buffering and caching attributes, etc. Components normally send their output to the current output stream, but can also be called as Python functions with return values, or their output content can be grabbed into a string as the return value.

All components are capable of calling any other component within the same template, and also of calling another template to be executed inline, or even the subcomponents contained within other templates, which are known as methods. With these functions, the page above can be organized into any variety of HTML/python code-snippets either within a single template file or across any combination of template and/or method library files:

           components.myt
        +-----------------+                                      
        |                 |                              page.myt
        |                 |       header.myt        +---------------+
        |  +-----------+  |    +---------------+    |   **********  |
        |  | toolbar   |--------------->*****  |------> **********  |
        |  +-----------+  |    |    header     |    |               |
        |                 |    +---------------+    | **            |
        |    +------+     |                         | **    page    |
        |    |      |     |                         | **   content  |
        |    | left | ------------------------------->**            |
        |    | nav  |     |                         | **            |
        |    |      |     |                         |               |
        |    +------+     |                         | +-----------+ |
        |                 |                         | |  footer   | |
        +-----------------+                         | +-----------+ |
                                                    +---------------+
                                       
                                    

Components are called via the <& &> tag construct, and also support "open-tag/close-tag" behavior via the <&| &></&> syntax, known as a component call with content. The content within the tags is enclosed into its own Python function that is callable by the component code, allowing custom tags with full control of execution to be created.

Read more about Myghty components in Components.

back to section top
Module Components

Myghty introduces a convenient environment-agnostic way to mix regular Python modules with template code known as Module Components. The same component model that applies to templates can be applied to regular Python objects and functions, either by explicitly subclassing the ModuleComponent class in a manner similar to a Servlet, or by configuring Myghty to implicitly resolve any regular Python function, callable object, or plain object instance into a FunctionComponent (version 0.98).

Module Components serve primarily as the "controller" stage in a request, the initial entry point for a request that handles data loading and state changes, and then passes control onto a template for display. As they are also fully capable component objects, they can also just as easily be embedded within templates, either by themselves or wrapped around further sub-content, to allow the creation of module-based tag libraries.

A big advantage to using Module Components for controller code is that the application remains completely portable to any environment, including mod_python, any WSGI environment, or non-web oriented environments.

Read more about Myghty Module Components in Module Components.

back to section top
Page Inheritance

Any top level component can also be inherited by another top level component. This means the execution of pages can be implicitly or explicitly "wrapped" by an enclosing template, which can control the execution and content embedding of its "subtemplate" at any point in its execution. In the diagram below, a content-based HTML file is enclosed by a file providing a standardized layout, which is enclosed by another file that provides session authentication code and management:

        /lib/authenticate.myt
        +------------------+
        |% authenticate()  |
        |-------------------             /autohandler
        |                  |         +-----------------+                
        |                            |      header     |    /foo/content.myt
        |                            |-----------------|      +--------+
        |    m.call_next() --->      |                        |        |
        |                            |   m.call_next() --->   |content |
        |                            |                        |        |
        |                  |         |-----------------|      +--------+
        |------------------|         |      footer     |                
        |% cleanup()       |         +-----------------+                
        +------------------+

The methods of a parent template are also inherited by the child and can also be overridden, allowing a sub-template to change the behavior of its parent. Layout and behavior of individual groups of templates, directories, or entire sites can be managed through a concise and centralized group of inheritable templates.

Read more about Inheritance in Inheritance.

back to section top
Performance

Myghty is written with fast performance and highly concurrent service in mind. A flexible cache API, supporting in-memory, file, DBM and Memcached backends allows quick re-delivery of complicated pages. Buffering can be completely disabled, for an entire site or just individual pages, to send template output to directly to the client. Expensive cache and compilation operations are process- and thread-synchronized to prevent data corruption and redundant computation. A configurable least-recently-used cache holds only the most heavily used components in memory, deferring less used ones to be loaded again from .pyc files. Filesystem checks can be disabled as well, allowing complete in-memory operation. Large chunks of plain text are distilled into large, multi-line write() statements to minimize method call overhead for large and mostly static pages.

back to section top
Other Features
  • Session object support - can write session data into memory, plain or DBM files, or Memcached.
  • Direct connectors for mod_python, CGI, WSGI, Python Paste, SimpleHTTPServer. As the Interpreter object is a lightweight object with no external dependencies whatsoever, any Python application or application server can invoke any series of Myghty components with just one line of code.
  • A super-configurable ruleset driven URI resolution architecture allowing many options for resolving URI's both externally and within templates. Allows any combination of resolution directly to templates, Module Components, or any plain Python function or object instance. Special rules exist to route non-existent URI's to specific components, to cache the results of URI resolution for higher performance, and to execute conditionally based on contextual information.
  • Cache API and implementation, can cache component output and any other data structure in memory, in plain files, DBM files, or Memcached. Includes a "busy lock" feature that allows a slow re-generation method to execute while the old data continues to be returned to other threads and processes. New cache implementations can be added fairly easily.
  • Flexible global namespaces allow components to have any number of custom "global" variables.
  • Special code blocks allow the construction of code that is local to the current request, or local to the current thread. A ThreadLocal object is supplied as well for safe management of thread-sensitive resources such as databases.
  • Fine grained control of buffering - the buffering of textual output as it is delivered to the client can controlled at the application, page, or component level.
  • Custom filtering functions can be defined for the output any component, within the source of the component via the <%filter> tag.
  • Full featured error handling and reporting. errors can be logged to the Apache logs or standard error, caught by application code, and/or reported to the browser screen. stack traces are delivered showing original template line numbers.
back to section top

Requirements
  • Python 2.3.3 or greater. There is an issue with weakrefs (Python bug id 839548) prior to that version which impacts stability.
  • For production webserver usage, a server environment that supports one of: CGI, WSGI, or mod_python.
  • For mod_python usage, Apache 1.3/mod_python 2.7 (or greater) or Apache 2.0/mod_python 3.1 (or greater).
  • Tested platforms: Linux (RedHat 6.2, RedHat 9), Mac OSX, Solaris, Windows 2000. Prefork and worker MPMs tested on Apache 2.0.
  • Familiarity with the webserver being used and whatever plug-in architecture being used.
back to section top
Quick Start - Running the Demo Server

Myghty includes an out-of-the-box instant-gratification examples/documentation server you can run directly from the distribution files, which listens on port 8000 by default. Extract the distribution from its .tar.gz file. Then run the server as follows:

cd /path/to/Myghty-X.XX/
python ./tools/run_docs.py

Then point a webbrowser to the location http://localhost:8000/. An alternative port can be specified on the command line, e.g. python ./tools/run_docs.py 8100.

The demo server is a handy tool to browse through a release without having to perform an install. The underlying HTTP server implementation can also be handy for development and prototyping.

back to section top
Installing the Library

Myghty now installs with setuptools, which is the next generation of the standard Python distutils module. Its basic usage is the same as that of distutils. Switch to the user account under which Python is installed, and run:

cd /path/to/Myghty-X.XX/
python setup.py install
As some systems may have multiple Python interpreters installed, be sure to use the Python executeable that corresponds to the Python being used by the webserver, such as the mod_python configuration, to insure the files go into the correct library path. setup.py will precompile the Myghty .py files and install them in the library path for the Python executeable you just ran.

This installer also installs Myghty in a version-specific location, such as "site-packages/Myghty-0.99-py2.3.egg/". If you have installed a version of Myghty prior to 0.99, the distutils-based installation, which lives in "site-packages/myghty", will produce a conflict message when running setup.py. After installation, you should delete the old install, either manually or via the command python ez_setup.py -D myghty.

back to section top
Generating the Documentation

This documentation can also be generated into flat html files that are browseable directly from the filesystem. Myghty can create these files by running the genhtml.py utility:

cd /path/to/Myghty-X.XX/doc
python genhtml.py
back to section top
Running Paste Templates

Myghty now includes a few Python Paste templates, which are pre-built Myghty applications that can install themselves into a runnable application. Python 2.4 is required to run Python Paste.

Myghty's standard install procedure will automatically download and install all Python Paste components, which are also available at http://pythonpaste.org/download. Also required is WSGIUtils, which must be installed from a particular .egg file format, via:

python ez_setup.py http://pylons.groovie.org/files/WSGIUtils-0.6-py2.4.egg

When Python Paste is installed, it will install the script "paster" into the standard Python scripts location. Insure that this location is in your path. Then to set up a Paste Template, just do:

cd /target/directory
paster create --template=myghty_simple myproject
cd myproject
        paster serve server.conf

The myghty_simple template is a very small four-template configuration, which will by default listen on port 8080. Also included is myghty_modulecomponent, which shows off a more controller-oriented configuration, and myghty_routes, which builds a new Rails-like "Routes" configuration.

When a new Paste Template project is created, the file <projectname>/server.conf illustrates the general Paste options, such as the server listening port. Myghty-specific configuration information is in <projectname>/<projectname>/webconfig.py.

back to section top
Running Filesystem Components

There is also a generic tool for running any Myghty template either to standard output or to a file. The command is as follows:

python tools/gen.py --help

usage: gen.py [options] files...

options:
  -h, --help            show this help message and exit
  --croot=COMPONENT_ROOT
                        set component root (default: ./)
  --dest=DESTINATION    set destination directory (default: ./)
  --stdout              send output to stdout
  --datadir=DATADIR     set data directory (default: dont use data directory)
  --ext=EXTENSION       file extension for output files (default: .html)
  --source              generate the source component to stdout
back to section top

Below are configuration instructions for the three most basic types of configuration: the standalone handler, a CGI handler, and running under mod_python. For further information on configuration, see:

Standalone Handler

The standalone handler is a web server built off of Python's BaseHTTPServer class, and is great for local workstation development and testing. Here is a quick example to simply serve pages from the current directory - place the following code into a file run_server.py:

#!/usr/local/bin/python

import myghty.http.HTTPServerHandler as HTTPServerHandler

# create the server.
httpd = HTTPServerHandler.HTTPServer(
    # port number to listen on.
    port = 8080,
    
    # HSHandler list.  indicates paths where the file should be interpreted
    # as a Myghty component request.
    # Format is a list of dictionaries, each maps a regular expression  matching a URI
    # to an instance of HTTPServerHandler.HSHandler, containing the arguments for
    # a Myghty interprter.  for HTTP requests of type "text/*", this list is matched
    # first against the incoming request URI.  
    handlers = [
        {'.*\.myt' : HTTPServerHandler.HSHandler(data_dir = './cache', component_root = './')},
    ],

    # document root list.  indicates paths where the file should be served
    # like a normal file, with the appropriate MIME type set as the content-type.
    # These are served for all non "text/*" HTTP requests, and all
    # incoming URIs that do not match the list of handlers above.
    docroot = [{'.*' : './'}],
    
)       
        
# run the server
httpd.serve_forever()

Then, in that same directory, place another file, called index.myt:

<html>
<head><title>Test Page</title></head>
<body>
    Welcome to Myghty !
</body>
</html>

To run the server, type:

python ./run_server.py

and point a web browser to http://localhost:8080/index.myt. The data directory ./cache will be automatically created to store data files.

Other examples of the Standalone handler are available in examples/shoppingcart/run_cart.py for a straightforward example, or tools/run_docs.py for an advanced example that also makes use of custom resolution strategies.

back to section top
CGI

Serving Myghty template files directly via CGI can be achieved with the myghty.cgi utility located in the /tools directory. This program is a simple interface to the CGIHandler, which converts the "path-info" of the requested URI into a Myghty component call. The script's configuration information is present within the top half of the script itself, to allow the most straightforward configuration, although it could certainly be modified to load configuration information from any other source such as other Python modules or configuration files.

It requires configuration of the component root, data directory, and optionally additional Python libraries to run. Other configuration parameters can be added to the handle() call as well. The cgi handler will handle requests of the form:

http://<domain>/<cgi-bin directory>/myghty.cgi/<uri of template>.

The script is below. Modify the appropriate lines and copy the myghty.cgi program into your webserver's cgi-bin directory for a basic cgi-based template handler. For usage within custom CGI scripts, see the next section detailing programmatic methods of calling Myghty.

#!/usr/local/bin/python

# myghty cgi runner.  place in cgi-bin directory and address Myghty templates
# with URLs in the form:

# http://mysite.com/cgi-bin/myghty.cgi/path/to/template.myt

# component root.  this is where the Myghty templates are.
component_root = '/path/to/croot'

# data directory.  this is where Myghty puts its object files.
data_dir = '/path/to/datadir'

# libraries.  Put paths to additional custom Python libraries here.
lib = ['/path/to/custom/libraries']

import sys
[sys.path.append(path) for path in lib]

import myghty.http.CGIHandler as handler

handler.handle(component_root=component_root, data_dir=data_dir)
back to section top
mod_python

This section assumes familiarity with basic Apache configuration. Myghty includes a handler known as myghty.http.ApacheHandler which can interpret requests from the mod_python request object. This handler can be configured directly within the httpd.conf file of Apache, using regular Apache configuration file directives to configure its options. Alternatively, the ApacheHandler can be used within an external Python module that defines its own mod_python handler, which allows most of the configuration of the handler to be stated within a Python file instead of the httpd.conf file. The first method, described in this section, is expedient for a straightforward Myghty template service, or a simple view-controller setup. While the full range of configurational options can be present directly in http.conf stated as Apache configuration directives, including Python imports, functions, and datastructures, the syntax of embedding Python into conf directives can quickly become burdensome when configuring an application with a complex resolution stream. Therefore it is recommended that Apache users also become familiar with programmatic configuration, described in the section ApacheHandler.

Myghty configuration parameters are written in the Apache httpd.conf file as "Myghty" plus the parameter name in InitialCaps. The full range of configuration parameters in None may be used. The values (right-hand side of the configuration directive) are Python evaluable expressions. In the simplest case, this is just a string, which is mostly easily identified as r"<string>" so that Apache does not strip the quotes out. Any Python structure can be used as the value, such as a list, dictionary, lambda, etc., as long as the proper Apache conf escaping is used.

Below is a straightforward example that routes all Apache requests for files with the extension ".myt" to the Myghty ApacheHandler:

# associate .myt files with mod_python
# mod_python 3.1 uses 'mod_python'
AddHandler mod_python .myt

# or for mod_python 2.7 use 'python-program'
# AddHandler python-program .myt

# set the handler called by mod_python to be the Myghty ApacheHandler
PythonHandler myghty.ApacheHandler::handle

# set python library paths - this line is used to indicate
# additional user-defined library paths.  this path is not required for the 
# Myghty templates themselves.
PythonPath "sys.path+[r'/path/to/my/libraries']"

# set component root.
# for this example, an incoming URL of http://mysite.com/files/myfile.myt 
# will be resolved as: /path/to/htdocs/files/myfile.myt
PythonOption MyghtyComponentRoot r"/path/to/htdocs"

# data directory where myghty will write its object files,
# as well as session, cache, and lock files
PythonOption MyghtyDataDir r"/path/to/writeable/data/directory/"

# other options - simply write as 'Myghty' with the param name in
# InitialCaps format, values should be legal python expressions
# watch out for using quotes "" as apache.conf removes them - 
# use r"value" or '"value"' instead
PythonOption Myghty<paramname> <paramvalue>

When this is done, requests to Apache which refer to pages with the extension .myt will be routed to the ApacheHandler, which will resolve the filename into a component which is then executed.

An additional format for the "MyghtyComponentRoot" parameter, a list of multiple paths, can be specified as a list of dictionaries. An example:

# Multiple Roots, each has a key to identify it,
# and their ordering determines their precedence
PythonOption MyghtyComponentRoot \
    "[  \
         {'components':'/optional/path/to/components'}, \
         {'main':'/path/to/htdocs/htdocs'} \
    ]"

Keep in mind that the MyghtyComponentRoot parameter (normally called component_root) defines filesystem paths that have no relationship to Apache DocumentRoots. From the perspective of Apache, there is only a single mod_python handler being invoked, and it has no awareness of the component_root. This means that any incoming URL which matches the Myghty handler will be matched to a root in the component_root and served as a Myghty template, effectively allowing "access" to files that are not directly access-controlled by Apache. To restrict direct access to Myghty component files which are meant for internal use, an alternate file extension, such as ".myc" can be used, so that while a Myghty component can internally find those files within the component_root, the Apache server has no knowledge of the .myc extension and they are not served. This also requires that the .myc files are kept in a directory or directories separate from any configured Apache DocuementRoots.

Myghty also has the ability to handle directory requests and requests for nonexistent files via various mechanisms, including dhandler and Module Components. However, the example above is configured to only respond to URLs with the specific file extension of ".myt". To handle directory requests without a filename being present, or requests for many different file extensions at once, replace the usage of AddHandler with the Apache SetHandler directive combined with the <FilesMatch>, <LocationMatch>, or <DirectoryMatch> Apache directives. These directives are described in the Apache documentation. For example:

<LocationMatch '/store/.*'>
    SetHandler mod_python
    PythonHandler myghty.ApacheHandler::handle
    PythonPath "sys.path+[r'/path/to/my/libraries']"
    
    # module component directive.  matches regular expressions to Python classes and functions.
    PythonOption MyghtyModuleComponents "[ \
            {'/store/product/.*':store:ProductHandler},\
            {'/store/checkout/.*':store:CheckoutHandler},\
        ]"
    PythonOption MyghtyComponentRoot r"/path/to/htdocs"
    PythonOption MyghtyDataDir r"/path/to/writeable/data/directory/"
</LocationMatch>

The above MyghtyModuleComponents, the apache version of module_components, is just one way to serve module components; there is also module_root, as well as the Routes resolver.

When serving all files within a directory, one should take care that Myghty is not be used to handle binary files, such as images. Also, it might be inappropriate to serve other kinds of text files such as stylesheets (.css files) and javascript files (.js files), even though one could use Myghty templating to serve these. To get around these issues, when straight file-extension matching is not enough, the Myghty and non-Myghty files can be placed in different directories and Apache correspondingly configured to enable Python handling in the Myghty directory only.

Advanced mod_python Configuration - Multiple ApacheHandlers

Several Interpreters can be configured with their own set of configuration parameters and executed all within the same Python interpreter instance, through the use of the interpreter_name configuration parameter. In the example below, a site configures three main dynamic areas: a documentation section, a catalog section, and the default section for all requests that do not correspond to the previous two. It uses three ApacheHandlers each with different component_root configuration parameters, but they share a common data_dir. The handlers are each configured inside a <LocationMatch> directive where they are given a unique name that identifies them upon each request.

# Apache resolves the LocationMatch directives in the order they 
# appear so the most general directive is last.

# note that every path within each "component root" parameter has a unique name, since 
# all the Myghty interpreters happen to be using the same data directory.

# also, the PythonPath is set for each SetHandler.  while this should work as a single
# configuration for all three sections, in testing it seems to work sporadically, so its 
# set explicitly for each one.

# set Myghty data dir, will be used by all sub-directives
PythonOption MyghtyDataDir r"/web/myapp/cache/"

# '/docs/', serves product documentation
<LocationMatch "/docs/.*\.myt">
    # set myghty handler
    SetHandler mod_python
    PythonHandler myghty.ApacheHandler::handle
    PythonPath "['/foo/bar/lib', '/usr/local/myapp/lib'] + sys.path"

    # set interpreter name
    PythonOption MyghtyInterpreterName r"document_interp"
    
    # set component root
    PythonOption MyghtyComponentRoot "[\
        {'docs_components' : r'/web/myapp/components'},\
        {'docs_htdocs' : r'/web/myapp/documents'},\
        ]"

    # add a translation rule to trim off the /docs/
    # when resolving the component
    PythonOption MyghtyPathTranslate "[\
            (r'/docs/(.*)' : r'\1'),\
        ]"
</LocationMatch>

# '/catalog/', serves a browseable catalog via a module component
# users can also log in to this area
<LocationMatch "/catalog/.*">
    # set myghty handler
    SetHandler mod_python
    PythonHandler myghty.ApacheHandler::handle
    PythonPath "['/foo/bar/lib', '/usr/local/myapp/lib'] + sys.path"

    # set interpreter name
    PythonOption MyghtyInterpreterName r"catalog_interp"

    # set component root
    PythonOption MyghtyComponentRoot "[\
            {'catalog_components' : r'/web/myapp/catalog/comp'},\
        ]"

    # configure some module components
    PythonOption MyghtyModuleComponents "[\
            {r'/catalog/login' : 'myapp.components:Login'},\
            {r'/catalog/.*' : 'myapp.components:Catalog'},\
        ]"
</LocationMatch>

# default: all other site docs
<LocationMatch ".*\.myt">
    # set myghty handler
    SetHandler mod_python
    PythonHandler myghty.ApacheHandler::handle
    PythonPath "['/foo/bar/lib', '/usr/local/myapp/lib'] + sys.path"
        
    PythonOption MyghtyInterpreterName r"default_interp"
        
    # set component root
    PythonOption MyghtyComponentRoot "[\
            {'default' : r'/web/myapp/htdocs'},\
        ]"
</LocationMatch>

Configuring component roots and path translation based on the incoming URI can also be accomplished within the scope of a single Interpreter by defining a custom set of resolver rules. This technique is described in Advanced Resolver Configuration.

back to section top

This section illustrates how to link the Myghty interpreter to a Python application. If you already have a basic configuration running and want to jump into programming templates, skip ahead to Embedding Python in HTML.

The central request-handling unit within Myghty is called the Interpreter. When an application is set up to handle a request and pass control onto the Interpreter, it is referred to as an external controller. In the model-view-controller paradigm, the application is the controller, the template called by the Interpreter is the view, and whatever data is passed from the controller to the template is the model.

Currently, all Myghty installations, except for mod_python, require at least a rudimentary external controller, which serves as the place for configuration directives to be set up and specified to the Myghty environment. Since a lot of configuration directives reference datastructures or functions themselves, a Python module is the most natural place for this to happen.

A more elaborate external controller may be the point at which an application passes control from its application code and business logic onto a view layer, served by a Myghty Interpreter and corresponding template files. This may be appropriate for an application that is already handling the details of its HTTP environment, if any, or any application that just needs basic template support.

In contrast to the "external controller" concept is the internal controller, which is Python code that executes after the Interpreter begins handling the request, forwarding data onto template-driven components at the end of its request cycle. Myghty provides a construct for this kind of controller described in Module Components. It is recommended that an application that aims to be designed in a full MVC (model-view-controller) style, particularly one that runs in an HTTP environment, place its controller code into Module Components, and only application configuration code and externally-dependent code into a single external controller module. That way the majority of an application's controller code is written in an environment-neutral fashion, and also has the full benefits of the Myghty resolution and request environment available to it.

The two general categories of external controller are:

Chaining to HTTPHandler

For applications running in an HTTP environment, chaining to HTTPHandler is the usual method. An HTTPHandler object has awareness of HTTP requests for any of four different environments, which are WSGI, CGI, mod_python, and the standalone handler. It can construct the appropriate HTTP-aware environment to be delivered to the Interpreter and ultimately onto templates, which then receive an implementation-neutral interface to that environment via the r global object.

All HTTP-based Myghty configurations utilize a subclass of myghty.http.HTTPHandler.HTTPHandler to serve requests. Each HTTP environment has its own module: myghty.http.ApacheHandler, myghty.http.CGIHandler, myghty.http.HTTPServerHandler and myghty.http.WSGIHandler, containing the classes ApacheHandler, CGIHandler, HSHandler, and WSGIHandler, respectively.

As of version 0.98, the recommended way to chain to an HTTPHandler is to first get an instance to a handler via the function get_handler(), and then execute a request on that handler via the method handle(). In previous versions, a single function handle() is used which combines the argument sets of both functions; this function is still available.

The get_handler function retrieves a handler from a registry based on the given interpreter_name, which defaults to 'main' or in the case of Apache uses the http.conf variable "MyghtyInterpreterName". Application-scoped configuration variables are sent to this method which are used to create the initial HTTPHandler object. Once created, subsequent calls with the same interpreter_name will return the same HTTPHandler instance.

HTTPHandler then supplies the method handle() to handle requests, which accepts configurational parameters on a per request basis. Common per-request parameters include the component path or object to serve, the request arguments, and out_buffer to capture component output.

Each handler module has a slightly different calling signature, illustrated below.

ApacheHandler

The ApacheHandler handles mod_python requests. It retrieves configuration via directives found in the host's httpd.conf file in the manner detailed in mod_python, and by default serves the component referenced by the request.uri data member. Configuration parameters sent programmatically override those found in the Apache configuration.

In the example below, a file "myghty_handler.py" is created, which contains a very simple mod_python handler that "chains" to the myghty ApacheHandler.

myghty_handler.py
import myghty.http.ApacheHandler as ApacheHandler
from mod_python import apache

def handle(request):
    handler = ApacheHandler.get_handler(request)
    return handler.handle(request)

A configuration for the above file is similar to a straight Apache configuration. Since the ApacheHandler created in the myghty_handler.py file contains no configuration at all, all of its options will come from the httpd.conf directives:

AddHandler mod_python .myt
PythonHandler myghty_handler::handle
PythonPath "sys.path+[r'/path/to/my/libraries']"
PythonOption MyghtyComponentRoot r"/path/to/htdocs"
PythonOption MyghtyDataDir r"/path/to/writeable/data/directory/"

When we take the above handler file and add configuration directives programmatically, they will override those named in the httpd.conf file:

myghty_handler.py
import myghty.http.ApacheHandler as ApacheHandler
from mod_python import apache

def handle(request):
    handler = ApacheHandler.get_handler(request,
            data_dir='/usr/local/web/data',
            component_root=[
                {'components':'/usr/local/web/components'},
                {'templates':'/usr/local/web/templates'}
            ])
    return handler.handle(request)

Another example, overriding the application's data directory, and also the request's component path and request arguments:

import myghty.http.ApacheHandler as ApacheHandler
from mod_python import apache

def handle(request):
    handler = ApacheHandler.get_handler(
        request, interpreter_name = 'mainhandler', data_dir = '/data'
    )
    return handler.handle(request, 
        component = 'mypage.myt', request_args = {'foo' : 'bar'}
    )

The above example also specifies the interpreter_name configuration parameter which identifies which ApacheHandler is returned by get_handler. If this parameter is not specified, it defaults to "main".

back to section top
CGIHandler

The CGI handler retreives its environment information via the cgi.FieldStorage() method as well as os.environ. Configuration parameters sent programmatically override those found in the CGI environment. By default, CGIHandler serves the component indicated by the environment variable PATH_INFO.

CGI application chaining to CGIHandler.handle() function
#!/usr/local/bin/python

import myghty.http.CGIHandler as CGIHandler

# serve the component based on PATH_INFO
CGIHandler.get_handler(
        component_root='/path/to/htdocs',
        data_dir='/path/to/datadirectory'
).handle()
back to section top
WSGIHandler

WSGIHandler works similarly to CGIHandler. Its r object maintains a reference to both the environ and start_response members. These members are used to extract the core data members of the r object, such as headers_in, method, etc.

When running under WSGI, the environ and start_response variables are available via:

# WSGI environment variables

r.environ
r.start_response

WSGI application chaining to WSGIHandler.handle() method
import myghty.http.WSGIHandler as WSGIHandler

def application(environ, start_response):
    return WSGIHandler.get_handler(
        component_root='/path/to/htdocs', 
        data_dir='/path/to/datadirectory').handle(environ, start_response)

Also supported with WSGI is the standard application(environ, start_response) function, which takes in all application and request-scoped configuration parameters via the environ argument:

WSGI application via application()
import myghty.http.WSGIHandler as WSGIHandler

params = dict(
    interpreter_name='main_wsgi',
    component_root='/path/to/htdocs', 
    data_dir='/path/to/datadirectory'
)

def application(environ, start_response):
    environ['myghty.application'] = params
    environ['myghty.request'] = {'component' : 'mycomponent.myt'}
    return WSGIHandler.application(environ, start_response)
back to section top
Chaining to Interpreter

The Myghty Interpreter object is the underlying engine that creates Myghty requests and executes them, supplying the necessary services each request needs. The Interpreter can be programmatically instantiated with a full set of configuration parameters and used directly.

While the advantage of using an HTTPHandler in an application is that Myghty components are aware of HTTP-specific information, such as the mod_python request object, HTTP headers, the httpd.conf configuration, etc., an application can also bypass all this by chaining directly to the Interpreter, if templates do not need HTTP awareness and the configuration can be programatically specified.

mod_python handler chaining to Interpreter
import myghty.interp as interp
from mod_python import apache

# set up a singleton instance of Interpreter
interpreter = interp.Interpreter(
        data_dir = './cache',
        component_root = './doc/components',
    )

def handle(request):
    # set up some data to send to the template
    data = {
        'foo': 'bar',
        'info' : get_info()
    }

    # call a template
    interpreter.execute('mytemplate.myt', request_args = data, out_buffer = request)

In the above approach, Myghty components are unaware of the HTTP environment, meaning there is no r global variable, and also can't make HTTP return calls or location redirects. A greater amount of responsibility is placed within the controller.

Configuring a Standalone Application

Chaining to the Interpreter directly also allows Myghty to run outside of a web context completely, within any Python application. It doesnt really need much configuration to run in "barebones" mode; the two most common features are the component root, which specifies one or more roots to search for input files, and the optional data directory, where it will store compiled python modules. Without the data directory, the compiled python modules are created in memory only.

A standlone application to run Myghty templates looks like this:

#!/usr/local/bin/python

import myghty.interp as interp
import sys

interpreter = interp.Interpreter(
        data_dir = './cache',
        component_root = './doc/components',
        out_buffer = sys.stdout
    )

# component name is relative to component_root
interpreter.execute('/index.myt')

The execute method of Intepreter takes optional parameters and sends them off to a newly created Request object. You can specify any of the constructor arguments used by Request or its embedded helper object RequestImpl in the execute call of Interpreter, which will override the values given in the constructor to Interpreter. The below example sends a buffer to each request with which to capture output, via the out_buffer parameter:

file = open('index.html', 'w')
interpreter.execute('/index.myt', out_buffer = file)
file.close()
back to section top

A Myghty file usually is laid out as an HTML file, or other text file, containing specialized tags that are recognized by the Myghty page compiler. When compiled, the file is converted into a python module which is then executed as regular python code. A Myghty template in its compiled form is typically referred to as a component. A component can also contain one or more subcomponents and/or methods, which are described further in the section Components. Basically when we say "component" we are talking about a self contained unit of Myghty templating code. The term "top level component" refers to the outermost component within a request, which is the page itself being executed. The term "file based component" refers to a component corresponding to the file that it appears in.

Control Lines

Control lines look like this:

 
 % for x in range(0, 10):
     hello!<br/>
 % # end for

The percent sign must be the very first character on the line, and the rest of the text is interpreted directly as Python code. The whitespace of the line, as well as the presence of a colon at the end of the line, is significant in determining the indentation of subsequent, non-control lines. As in the example above, the "for" statement followed by a colon, sets the indentation to be one level deeper, which causes the html text "hello!" to be iterated within the block created by the Python statement. The block is then closed by placing another control line, containing only whitespace plus an optional comment.

A more involved example:

% for mood in ['happy', 'happy', 'sad', 'sad', 'happy']:
%   if mood == 'happy':

  <img src="happyface.gif"/> Hey There !

%   else:

  <img src="sadface.gif"/> Buzz Off !

% #if statement
% #for loop

Note that the whitespace is not significant in plain HTML or text lines. When this template is converted to Python code, the plain text will be embedded in write statements that are indented properly within the block. Block-closing statements like "else:" and "except:" are also properly interpreted.

back to section top
Comment Lines

Note that a blank control line, i.e. starting with '%', is significant in affecting the whitespace indentation level, whether or not it contains a comment character '#' followed by a comment. To do line-based comments without affecting whitespace, use '#' as the very first character on a line:

% for x in (1,2,3):
    <b>hi <% x %></b>

# a comment

% # a block-closing control line

Comments can also be done with the <%doc> tag described in <%doc>.

back to section top
Substitutions

A substitution is an embedded python expression, whos evaluated value will be sent to the output stream of the component via a m.write() statement:

Three plus five is: <% 3 + 5 %>

produces:

Three plus five is: 8

Substitutions can also span multiple lines which is handy in conjunction with triple-quoted blocks.

The text of substitutions can also be HTML or URL escaped via the use of flags. For a description of escape flags, see the section Escaping Content.

back to section top
Python Blocks

A python block is a block of pure python code:

<%python>
    user = usermanager.get_user()
    m.write("username is %s" % user.get_name())
</%python>

Code within a %python block is inserted directly into the component's generated Python code, with its whitespace normalized to that of the most recent control line. The %python tags, as well as the code within the tags, can be at any indentation level in relation to the rest of the document, including other %python blocks; it is only necessary that the indentation of the code within the block is internally consistent with itself. See the next section for an example.

There are also variations upon the %python block, where the contained Python code is executed within a specific context of a component's execution, such as initialization, cleanup, or global. These special variations are explained in Scoped <%python> Blocks.

back to section top
Controlling Whitespace with the Backslash

To allow for finer control of the whitespace inherently generated by multiline HTML or Python control structures, the backslash character "\" can be used at the end of any line to suppress newline generation:

<span class="light">\
% for x in (1,2,3):
    [<% x %>]\
%
</span>
Which will produce:
<span class="light">[1][2][3]</span>
back to section top
Indentation Behavior

The interaction of control lines, plain text, and python blocks is regulated by the Myghty engine to create an overall indentation scheme that is functional but also allows HTML and python blocks to be laid out with a high degree of freedom. The following example illustrates the indentation behavior:

<%python>
    forecasts = {
        'monday':'stormy',
        'tuesday':'sunny',
        'wednesday':'sunny', 
        'thursday':'humid',
        'friday':'tornado'
    }

</%python>

% for day in ['monday', 'tuesday', 'wednesday', 'thursday', 'friday']:

    <%python>

    weather = forecasts[day]
    if weather == 'tornado':
        advice = "run for the hills !"
    elif weather == 'stormy':
        advice = "bring an umbrella"
    else:
        advice = "enjoy the day...."
    </%python>

Weather for <% day %>:  <% forecasts[day] %>
Advice: <% advice %>

% # end for

The above block, when compiled, translates into the following Python code, that is then executed to produce the final output:

# BEGIN BLOCK body
m.write('''
''')
# test.myt Line 1

forecasts = {
        'monday':'stormy',
        'tuesday':'sunny',
        'wednesday':'sunny', 
        'thursday':'humid',
        'friday':'tornado'
}


# test.myt Line 11
m.write('''
''')
for day in ['monday', 'tuesday', 'wednesday', 'thursday', 'friday']:
       # test.myt Line 13
       m.write('''
    ''')
       # test.myt Line 14


       weather = forecasts[day]
       if weather == 'tornado':
               advice = "run for the hills !"
       elif weather == 'stormy':
               advice = "bring an umbrella"
       else:
               advice = "enjoy the day...."
       
       # test.myt Line 24
       m.write('''
Weather for ''')
       m.write( day )
       m.write(''':  ''')
       m.write( forecasts[day] )
       m.write('''
Advice: ''')
       # test.myt Line 26
       m.write( advice )
       m.write('''

''')
       # test.myt Line 28
# end for
# END BLOCK body
back to section top

The <%python> tag is also capable of specifying Python code that occurs within a specific scope of a template's execution, using the scope attribute. Scopes are provided that specify Python code as always the first thing executed within a component, always the last thing executed, or executes once per request, once per application thread, or once per application process.

Originally, these scopes had their own specific tag names, which are still available. These names include all those that are familiar to HTML::Mason users, as well as some new names. All synonyms are noted in each section.

Component Scope

Usage: <%python scope="component">

Also called: <%python>

A component-scoped block is a regular block of Python that executes within the body of a template, as illustrated in the previous section Python Blocks . Many component-scoped blocks may exist in a template and they will all be executed in the place that they occur. Component scope has two variants, init and cleanup scope, which while still being component scope, execute at specific times in a component's execution regardless of their position in a template. They are described later in this section.

back to section top
Global Scope

Usage: <%python scope="global">

Also called: <%global>, <%once>

A global-scoped block refers to a section of Python code that is executed exactly once for a component, within the scope of its process. In reality, this usually means code that is executed each time the module is newly loaded or reloaded in the current Python process, as it is called as part of the module import process. Variables that are declared in a global-scoped block are compiled as global variables at the top of the generated module, and thus can be seen from within the bodies of all components defined within the module. Assignment to these variables follows the Python scoping rules, meaning that they will magically be copied into local variables once assigned to unless they are pre-declared in the local block with the Python keyword global.

Global-scoped Python executes only once when a component module is first loaded, as part of its import. As such, it is called slightly outside of the normal request call-chain and does not have the usual access to the the built-in request-scoped variables m, r, ARGS, etc. However, you can access the Request that is corresponding to this very first execution via the static call request.instance(), which will give you the current request instance that is servicing the global-scoped block.

 
 <%python scope="global">
     # declare global variables, accessible
     # across this component's generated module
     
     message1 = "this is message one."
     message2 = "this is message two."
     message3 = "doh, im message three."
 </%python>
 
 <%python>
     # reference the global variables
     m.write("message one: " + message1)
     m.write("message two: " + message2)
     
     # we want to assign to message3,
     # so declare "global" first
     global message3
     
     message3 = "this is message three."
     
     m.write("message three: " + message3)
     
 </%python>

Use a global-scoped Python block to declare constants and resources which are shareable amongst all components within a template file. Note that for a threaded environment, global-scoped section applies to all threads within a process. This may not be appropriate for certain kinds of non-threadsafe resources, such as database handles, certain dbm modules, etc. For thread-local global variable declaration, see the section Thread Scope, or use the Myghty ThreadLocal() object described in Alternative to Thread Scope: ThreadLocal(). Similarly, request-scoped operation is provided as well, described in the section Request Scope.

A global-scoped block can only be placed in a top-level component, i.e. cannot be used within %def or %method.

back to section top
Init Scope

Usage: <%python scope="init">

Also called: <%init>

Init-scoped Python is python code that is executed once per component execution, before any other local python code or text is processed. It really is just a variant of component scope, since it is still technically within component scope, just executed before any other component-scoped code executes. One handy thing about init scope is that you can stick it at the bottom of a big HTML file, or in any other weird place, and it will still execute before all the other local code. Its recommended as the place for setting up HTTP headers which can only be set before any content and/or whitespace is written (although if autoflush is disabled, this is less of an issue; see The Autoflush Option for more details).

In this example, a login function is queried to detect if the current browser is a logged in user. If not, the component wants to redirect to a login page. Since a redirect should occur before any output is generated, the login function and redirect occurs within an init-scoped Python block:

<%python scope="init">
    # check that the user is logged in, else
    # redirect them to a login page
    if not user_logged_in():
        m.send_redirect("/login.myt", hard = True)
</%python>  

<%doc>rest of page follows....</%doc>   
<html>
    <head>
    ....
back to section top
Cleanup Scope

Usage: <%python scope="cleanup">

Also called: <%cleanup>

Cleanup-scoped Python is Python code executed at the end of everything else within a component's execution. It is executed within the scope of a try..finally construct so its guaranteed to execute even in the case of an error condition.

In this example, a hypothetical LDAP database is accessed to get user information. Since the database connection is opened within the scope of the component inside its init-scoped block, it is closed within the cleanup-scoped block:

<%args>
    userid
</%args>
<%python scope="init">
    # open a connection to an expensive resource
    ldap = Ldap.connect()
    userrec = ldap.lookup(userid)
</%python>
    
    name: <% userrec['name'] %><br/>
    address: <% userrec['address'] %><br/>
    email: <% userrec['email'] %><br/>
    
<%python scope="cleanup">
    # insure the expensive resource is closed
    if ldap is not None:
        ldap.close()
</%python>
back to section top
Request Scope

Usage: <%python scope="request">

Also called: <%requestlocal>, <%requestonce> or <%shared>

A request-scoped Python block has similarities to a global-scoped block, except instead of executing at the top of the generated component's module, it is executed within the context of a function definition that is executed once per request. Within this function definition, all the rest of the component's functions and variable namespaces are declared, so that when variables, functions and objects declared within this function are referenced, they are effectively unique to the individual request.

<%python scope="request">
    context = {}
</%python>

% context['start'] = True
<& dosomething &>

<%def dosomething>
% if context.has_key('start'):
    hi
% else:
    bye
</%def>

The good news is, the regular Myghty variables m, ARGS, r etc. are all available within a request-scoped block. Although since a request-scoped block executes within a unique place in the call-chain, the full functionality of m, such as component calling, is not currently supported within such a block.

Request-scoped sections can only be used in top-level components, i.e. cannot be used within %def or %method.

Using Pass-By-Value

While the net result of a request-scoped Python block looks similar to a global-scoped block, there are differences with how declared variables are referenced. Since they are not module-level variables, they can't be used with the Python global keyword. There actually is no way to directly change what a request-scoped variable points to; however this can be easily worked around through the use of pass-by-value variables. A pass-by-value effect can be achieved with an array, a dictionary, a user-defined object whose value can change, or the automatically imported Myghty datatype Value(), which represents an object whose contents you can change:

<%python scope="request">
    status = Value("initial status")
</%python>

<%python>
    if some_status_changed():
        status.assign("new status")
</%python>

the status is <% status() %>
back to section top
Alternative - Request Attributes

An alternative to using request-scoped blocks is to assign attributes to the request object, which can then be accessed by any other component within that request. This is achieved via the member attributes:

<%python>
m.attributes['whatmawsaw'] = 'i just saw a flyin turkey!'
</%python>

# .... somewhere in some other part of the template


JIMMY: Hey maw, what'd ya see ?  
MAW: <% m.attributes['whatmawsaw'] %>

Produces:

JIMMY: Hey maw, what'd ya see ?
MAW: i just saw a flyin turkey!

Also see The Request which lists all request methods, including those used for attributes.

back to section top
Thread Scope

Usage: <%python scope="thread">

Also called: <%threadlocal>, <%threadonce>

A thread-scoped Python block is nearly the same as a Request Scope block, except its defining function is executed once per thread of execution, rather than once per request. In a non-threaded environment, this amounts to once per process. The standard global variables m, r etc. are still available, but their usefulness is limited, as they only represent the one particular request that happens to be the first request to execute within the current thread. Also, like request-scope, variables declared in a thread-scoped block cannot be changed except with pass-by-value techniques, described in Using Pass-By-Value

In this example, a gdbm file-based database is accessed to retreive weather information keyed off of a zipcode. Since gdbm uses the flock() system call, it's a good idea to keep the reference to a gdbm handle local to a particular thread (at least, the thread that opens the database must be the one that closes it). The reference to gdbm is created and initialized within a thread-scoped block to insure this behavior:

<%python scope="thread">
    # use GNU dbm, which definitely doesnt work in 
    # multiple threads (unless you specify 'u')
    import gdbm
    db = gdbm.open("weather.dbm", 'r')
</%python>

<%args>
    zipcode
</%args>

temperature in your zip for today is: <% db[zipcode] %>

Use a thread-scoped block to declare global resources which are not thread-safe. A big candidate for this is a database connection, or an object that contains a database-connection reference, for applications that are not trying too hard to separate their presentation code from their business logic (which, of course, they should be).

Thread-scoped sections can only be used in top-level components, i.e. cannot be used within %def or %method.

Alternative to Thread Scope: ThreadLocal()

A possibly higher-performing alternative to a thread-scoped section is to declare thread-local variables via the automatically imported class ThreadLocal(). The ThreadLocal() class works similarly to a Value() object, except that assigning and retrieving its value attaches the data internally to a dictionary, keyed off of an identifier for the current thread. In this way each value can only be accessed by the thread which assigned the value, and other threads are left to assign their own value:

<%python scope="global">
    x = ThreadLocal()
</%python>

<%python>
    import time
    x.assign("the current time is " + repr(time.time()))
</%python>

value of x: <% x() %>

ThreadLocal() also supports automatic creation of its value per thread, by supplying a pointer to a function to the parameter creator. Here is the above gdbm example with ThreadLocal(), using an anonymous (lambda) creation function to automatically allocate a new gdbm handle per thread:

<%python scope="global">
    import gdbm
    db = ThreadLocal(creator = lambda: gdbm.open("weather.dbm", 'r'))
</%python>

<%args>
    zipcode
</%args>

temperature in your zip for today is: <% db()[zipcode] %>
back to section top

Myghty templates and components always have access to a set of global variables that are initialized on a per-request basis. The Myghty request object m is always available, as are the component arguments ARGS. When running with any HTTPHandler-based environment, the HTTP request object r is also available, which in mod_python is the actual mod_python request object, else it is a compatible emulating object. The Myghty session object, or mod_python's own session object, may be configured to be available as the variable s. Finally, any set of user-configured global variables can be defined as well; the value of these globals can be specified on a per-interpreter or per-request basis.

Your Best Friend: m

m is known as the "request", which represents the runtime context of the template being executed. Its not the same as the HTTP-specific request object r and is mostly agnostic of HTTP. m includes methods for handling output and writing content, calling other components, as well as other services that a template will usually need. The full list of request methods is described in The Request.

back to section top
Your Other Best Friend: ARGS

ARGS represents a dictionary of all arguments sent to the current component. While a component can specify arguments to be available in the component's namespace via the <%args> tag, the ARGS dictionary contains all arguments supplied to a component regardless of them being named in the <%args> section or not.

In the case of a top-level component called in an HTTP context, ARGS contains the full set of client request parameters. Each field is one of: a string, a list of strings, or for handling file upload objects, a Field object (from the FieldStorage API) or a list of Field objects.

For components called by other components, ARGS contains all the arguments sent by the calling component.

In all cases, the HTTP request arguments, or whatever arguments were originally sent to the request, are available via the request member request_args.

Component arguments are described in Component Arguments - the <%args> tag.

back to section top
Your Pal: r

When running Myghty with any of the HTTPHandlers, i.e. ApacheHandler, CGIHandler, WSGIHandler, or HTTPServerHandler, variable r is a reference to either the mod python request object or a compatible emulation object. In the case of ApacheHandler, it is the actual mod_python request. In other cases, it attempts to provide a reasonably compatible interface, including the member variables headers_in, headers_out, err_headers_out, args, content_type, method, path_info, and filename (more can be added...just ask/submit patches). The request object is useful applications that need awareness of HTTP-specific concepts, such as headers and cookies, beyond what the more generic m object provides which attempts to be largely agnostic with regards to HTTP.

Under WSGIHandler, r also contains the member variables environ and start_response, so that an application may also have direct access to WSGI-specific constructs if needed.

back to section top
Your Fair Weather Friend: s

s references the Myghty session object. It can also be configured to reference the mod_python session object when running with mod_python 3.1 To use s, you need to turn it on via use_session.

The Myghty session is still available even if s is not configured. See the section Session for full information on the session object.

back to section top
Make your Own Friends

Myghty supports the addition of any number of global variables that will be compiled into the namespace of all templates. The value of these variables can be specified on a per-application basis or a per-request basis. As of version 0.98, both scopes can be used simultaneously. Per-application globals can be specified via the initial interpreter configurational parameters, or within the httpd.conf file in a mod_python environment. Per-request globals require that the variables be initialized before the Myghty request begins, which requires programmatic "chaining" to the Interpreter via the methods described in Programmatic Configuration.

The two configuration parameters to add global arguments are allow_globals, which specifies a list of global variable names to compile into templates, and global_args, which is a dictionary containing the names of the variables mapped to their desired values. A basic example of programmatic global variables looks like:

import myghty.http.WSGIHandler

def application(environ, start_response):

    handler = myghty.http.WSGIHandler.get_handler(
        allow_globals = ['myglobal'],
        component_root='/path/to/htdocs', 
        data_dir='/path/to/datadirectory'
    )
    
    return handler.handle(
            environ, 
            start_response,
            global_args = {'myglobal' : 'hi'}
    )

Above, all Myghty components will have access to the global variable "myglobal" which has a per-request value of "hi". Note that the allow_globals parameter is only used on the first request, when constructing a new Interpreter object, whereas global_args may be specified for each request.

Another example, using Interpreter:

interpreter = interp.Interpreter(
    allow_globals = ['myglobal'],
    data_dir = '/path/to/datadir',
    component_root = '/foo/components',
)

interpreter.execute("file.myt", 
    global_args = {'myglobal':MyGlobalThingy()}
)

Here is an ApacheHandler example which specifies globals within both scopes:

import myghty.http.ApacheHandler as ApacheHandler

# create per-application global object
appglobal = 'myappglobal'

def handle(req):
    # create per-request global object
    myglob = MyGlobal(req)
    
    handler = ApacheHandler.get_handler(
            req, 
            allow_globals = ['appglobal', 'myglobal'],
            global_args = {'appglobal' : appglobal}
    )
            
    return handler.handle(req, global_args = {'myglobal':myglob})

Here is an application-scoped global added in a mod_python environment via the httpd.conf file:

# specify list of global variable names
PythonOption MyghtyAllowGlobals ['myglobal']

# specify the value of the global variable
PythonOption MyghtyGlobalArgs "{'myglobal':  \
    __import__('mystuff.util').util.MyGlobalThingy()}"
Assignment to Request-Scoped Globals

When the allow_globals configuration parameter specifies global variables to be compiled into all templates, if the variable is not present at request time, it is assigned the value of None (as of 0.98a). This is handy for global variables whos value is not determined until within a request.

To assign to a global variable, use m.global_args:

# assume the configuration parameter global_args = ['x','y','z'] is set
<& hi &>
% m.global_args['x'] = 'im x!'
% m.global_args['y'] = 'im y!'
<& hi &>

<%def hi>
    x is '<% x %>'
    y is '<% y %>'
    z is '<% z %>'
</%def>

this will produce:

x is: ''
y is: ''
z is: ''
x is: 'im x!'
y is: 'im y!'
z is: ''
back to section top

All templates in Myghty are referred to as "Components". Components, while they may look like plain HTML pages with a few lines of Python in them, are actually callable units of code which have their own properties, attributes, input arguments, and return values. One can think of a Component anywhere within the spectrum between "HTML page" and "callable Python object", and use it in either way or a combination of both.

A single template, while it is a component itself, also can contain other components within it, which are referred to as "subcomponents", and a subcategory of subcomponents called "methods". The template's component itself is called a "file-based component", and when it is the main component referenced by a request it is also known as the "top level component".

When a component is instantiated within the runtime environment, it is a Python object with the usual reference to "self" as well as its own attributes and methods, and the body of the component occurs within a function call on that object. All components extend from the base class myghty.component.Component. File-based components extend from myghty.component.FileComponent and subcomponents extend from myghty.component.SubComponent.

Additionally, unique to Myghty is a non-template form of component called a "module component", which is written instead as a regular Python class. These components are described in the next section, Module Components, extending from the class myghty.component.ModuleComponent.

Component Calling Example

The most basic component operation is to have one template call another. In the simplest sense, this is just an HTML include, like a server side include. To have a template "page.myt" call upon another template "header.myt":

page.myt
<html>
    <& header.myt &>
    <body>
    ... rest of page
    </body>
</html>
header.myt
<head>
    <title>header</title>
</head>

Produces:

<html>
<head>
    <title>header</title>
</head>
    <body>
    ... rest of page
    </body>
</html>
back to section top
Component Path Scheme

When calling components, the path to the component is given as an environment-specific URI, and not an actual filesystem path. While the path can be specified as absolute, it is still determined as relative to one or more of the configured Myghty component roots. Myghty uses the component_root parameter as a list of filesystem paths with which to search for the requested component. If a relative path is used, the path is converted to an absolute path based on its relation to the location of the calling component, and then matched up against the list of component roots.

back to section top
Component Arguments - the <%args> tag

Components, since they are really Python functions, support argument lists. These arguments are supplied to the top-level component from the client request arguments, such as via a POST'ed form. When a component is called from another component, the calling component specifies its own local argument list to be sent to the called component.

A component can access all arguments that were sent to it by locating them in the ARGS dictionary. More commonly, it can specify a list of arguments it would like to receive as local variables via the <%args> tag:

<%args>
    username
    password
    
    # sessionid defaults to None
    sessionid = None
</%args>
<%python scope="init">
    if sessionid is None:
        sessionid = create_sid()
        
    if password != get_password(username):
        m.send_redirect("loginfailed.myt", hard=True)
</%python>

In the above example, the 'username' and 'password' arguments are required; if they are not present in the argument list sent to this component, an error will be raised. The 'sessionid' argument is given a default value, so it is not required in the argument list.

A component like the one above may be called with a URL such as:

http://foo.bar.com/login.myt?username=john&password=foo&sessionid=57347438

The values sent in an <%args> section are analgous to a Python function being called with named parameters. The above set of arguments, expressed as a Python function, looks like this:

def do_run_component(self, username, password, sessionid = None):

What this implies is that the default value sent for "sessionid" only takes effect within the body of the component. It does not set a default value for "sessionid" anywhere else. Different components could easily set different default values for "sessionid" and they would all take effect if "sessionid" is not present in the argument list.

Components can pass argument lists to other components when called. Below, a component 'showuser.myt' is called by another component 'page.myt':

showuser.myt
<%args>
    username
    email
</%args>

Username: <% username %><br/>
Email: <a href="mailto:<% email %>"><% email %></a><br/>
page.myt
Login information:
<& showuser.myt, username='john', email='jsmith@foo.com' &>

The component call tags "<& &>" take a named-parameter list just like a Python function, and can also have as the very last argument dictionary with ** notation just like in regular Python:

<& comp.myt, arg1=3.7, **ARGS &>

Above, the dictionary ARGS always has a list of all arguments sent to the component, regardless of whether or not they were specified in the <%args> section. This is a way of passing through "anonymous" arguments from a component's caller to its components being called.

Argument Scope: component/request/subrequest/dynamic

So far we have talked about "component-scoped" arguments, that is, the list of arguments that are sent directly to a component by its caller. While the very first component called in a request (i.e. the top-level component) will receive the client request arguments as its component-scoped arguments, any further component calls will only receive the arguments sent by its direct caller.

To make it easier for all components to see the original request arguments, the attribute scope="request" may be specified in any <%args> section to indicate that arguments should be taken from the original request, and not the immediate caller. Normally, the default value of scope is component, indicating that only the immediate component arguments should be used.

<%args scope="request">
    sessionid
</%args>

<%args scope="component">
    username
</%args>

hello <% username %>, to edit your preferences click
<a href="prefs.myt?sessionid=<% sessionid %>">here</a>.

Above, the argument "sessionid" must be sent by client request, but the argument "username" must be sent by the calling component. If this component is called as the top-level component, both arguments must be present in the client request.

Request arguments are also always available via the request_args and root_request_args members of the request object.

Note that there is special behavior associated with request-scoped arguments when using subrequests (described later in this section). Since a subrequest is a "request within a request", it is not clear whether the "request" arguments should come from the originating request, or the immediate, "child" request. The attribute scope="subrequest" indicates that arguments should be located in the immediate request, whether or not it is a subrequest, in contrast to scope="request" which always refers to the arguments of the ultimate root request. Subrequests are described in the section Subrequests below.

The component that wants to be flexible about its arguments may also specify its arguments with "dynamic" scope. In dynamic scope, the argument is located within the most local arguments first, and then upwards towards the request until found. The following component will retrieve its arguments locally if present, or if not, from the request, no matter where it is called:

<%args scope="dynamic">
    username
    email
</%args>

hello <% username %>, your email address is <% email %>.
back to section top
How to Define a Subcomponent

A subcomponent is a component defined within a larger template, and acts as a callable "subsection" of that page. Subcomponents support almost all the functionality of a file-based component, allowing Python blocks of init, cleanup and component scope, but not global, request or thread scope.

A subcomponent, albeit a nonsensical one, looks like this:

<%def mycomponent>
    <%args>
        arg1 = 'foo'
        arg2 = 'bar'
    </%args>
    <%python scope="init">
        string = arg1 + " " + arg2
    </%python>
    
    i am mycomponent !
    
    <% string %>
</%def>

A regular subcomponent like this one is always called by another component, i.e. it can never be called directly from the request as a top-level component. Furthermore, subcomponents defined with the <%def> tag are private to the template file they appear in.

The subcomponent has access to all global variables, such as m and r, but it does not have access to the local variables of its containing component. This would include variables specified in the body of the main component, i.e. in init-, cleanup- and component-scoped <%python> blocks. Variables declared in global-, request- and thread-scoped <%python> blocks are available within subcomponents, subject to the restrictions on variables declared in those blocks. Variables declared within the body of a subcomponent remain local to that subcomponent.

Calling a Subcomponent

Subcomponents are called in a similar manner as a file-based component:

welcome to <& title, username='john' &>

<%def title>
    <%args>
        username
    </%args>
    
    <b>bling bling bling <% username %> bling bling bling</b
</%def>

Note that a subcomponent can be defined at any point in a template and is still available throughout the entire template.

back to section top
How to Define a Method

A method is similar to a subcomponent, except its functionality is available outside of the file it appears in, and it can take advantage of inheritance from other template files.

<%method imamethod>
    <%args>
        radius
        coeffiecient = .5424
    </%args>
    <%python scope="init">
        foob = call_my_func(radius, coefficient)
    </%python>

    fractional fizzywhatsle: <% foob %>
</%method>
Calling a Method

A method can be called from within the file it appears in the same fashion as a subcomponent, i.e. simply by its name, in which case it is located in the same way as a subcomponent. The other format of method calling is <location>:<methodname>, where location specifies what component to initially search for the method in. The location may be specified as the URI of the desired component file, or one of the special keywords SELF, REQUEST, or PARENT.

# call the method print_date in 
# component file /lib/functions.myt
<& /lib/functions.myt:print_date, date="3/12/2004" &>

# call a method in the local template
<& tablerow, content="cell content" &>

# call a method in the base component, taking 
# advantage of inheritance
<& SELF:printtitle &>

With the compound method calling format, if the method is not located in the specified component, the component's inherited parent will be searched, and in turn that component's inherited parent, etc., until no more parents exist. The parent-child relationship of components, as well as the keywords SELF, REQUEST, and PARENT are described in the section Inheritance.

back to section top
How to Define a Closure
Version 0.98 introduces a lightweight alternative to %def and %method called <%closure>. This tag defines a local function definition using Python keyword def, which is callable via the same mechanism as that of subcomponents. A closure is in fact not a component at all and can only be used within the block that it is defined, and also must be defined before it is called. It offers the advantage that it is created within the scope of the current code body, and therefore has access to the same variable namespace:
<%closure format_x>
    <%args>
        format = '%d'
    </%args>
    <% format % x %>
</%closure>

%   for x in (1,2,3):
        <& format_x, format='X:%d' &>
%

Closures support the <%args> tag, as well as Init Scope and Cleanup Scope. Closures can also be nested. They currently do not support the "component call with content" calling style but this may be added in the future.

back to section top
Subcomponent Flags

Subcomponents and methods also may specify flags as described in the section <%flags>. The most useful flags for a subcomponent are the trim and autoflush flags, described in Filtering and Flushing (and Escaping).

There are two formats for specifing flags in a subcomponent:

 
 # traditional way
 
 <%def buffered>
     <%flags>
         autoflush=False
     </%flags>
     this is a buffered component
 </%def>
 
 
 # inline-attribute way
 
 <%method hyperlink trim="both">
     <%args>
         link
         name
     </%args>
     
     <a href="<% link %>">name</a>
 </%method>
back to section top
Component Calls with Content

Subcomponents and methods can also be called with a slightly different syntax, in a way that allows the calling component to specify a contained section of content to be made available to the called component as a Python function. Any subcomponent can query the global m object for a function that executes this content, if it is present. When the function is called, the code sent within the body of the component call with content is executed; this contained code executes within the context and namespace of the calling component.

<&| printme &>
    i am content that will be grabbed by PRINTME.
</&>

The called component can then reference the contained content like this:

<%def printme>
    I am PRINTME, what do you have to say ?<br/>
    <% m.content() %>
</%def>

The method m.content() executes the code contained within the <&| &>/</&> tags in its call to "printme", and returns it as a string. A component may query the request object m for the presense of this function via the method m.has_content().

A component call with content is one of the most powerful features of Myghty, allowing the creation of custom tags that can produce conditional sections, iterated sections, content-grabbing, and many other features. It is similar but not quite the same as the template inheritance methodology, in that it allows the body of a component to be distilled into a callable function passed to an enclosing component, but it involves a client explicitly opting to wrap part of itself in the body of another component call, rather than a client implicitly opting to wrap its entire self in the body of another component call.

back to section top
Calling Components Programmatically

The special component calling tags described above are just one way to call components. They can also be called directly off of the request object m, which is handy both for calling components within %python blocks as well as for capturing either the return value or the resulting content of a subcomponent. Component objects can also be directly referenced and executed via these methods.

The full index of request methods and members can be found in The Request.

m.comp(component, **params)

This method allows you to call a component just like in the regular way except via Python code. The arguments are specified in the same way to the function's argument list. The output will be streamed to the component's output stream just like any other content. If the component specifies a return value, it will be returned. A component, since it is really just a python function, can have a return value simply by using the python statement return. The value of component can be an actual component object obtained via fetch_component(), or a string specifying a filesystem path or local subcomponent or method location.

<%python>
m.comp('/foo/bar.myt', arg1='hi')
</%python>
back to section top
m.scomp(component, **params)

This method is the same as "comp" except the output of the component is captured in a separate buffer and returned as the return value of scomp().

<%python>
component = m.fetch_component('mycomponent')
content = m.scomp(component)

m.write("<pre>" + content + "</pre>")
</%python>
back to section top
Subrequests

A subrequest is an additional twist on calling a component, it calls the component with its own request object that is created from the current request. A subrequest is similar to an internal redirect which returns control back to the calling page. The subrequest has its own local argument list as well, separate from the original request arguments.

<%python>
    ret = m.subexec('/my/new/component.myt', arg1='hi')
</%python>

The subexec method takes either a string URI or a component object as its first argument, and the rest of the named parameters are sent as arguments to the component.

Use subrequests to call a component when you want its full inheritance chain, i.e. its autohandlers, to be called as well.

The subexec method is comprised of several more fine-grained methods as illustrated in this example:

<%python>
    # get a component to call
    component = m.fetch_component('mysubreq.myt')
    
    # make_subrequest - 
    # first argument is the component or component URI,
    # following arguments are component arguments
    subreq = m.make_subrequest(component, arg1 = 'foo')
    
    # execute the request.  return value is sent
    ret = subreq.execute()
</%python>

The make_subrequest method can also be called as create_subrequest, which in addition to supporting component arguments, lets you specify all other request object arguments as well:

<%python>
    import StringIO
    
    # get a component to call
    component = m.fetch_component('mysubreq.myt')

    # make a subrequest with our own 
    # output buffer specified               
    buf = StringIO.StringIO()
    subreq = m.create_subrequest(component, 
        out_buffer = buf,
        request_args = {'arg1':'foo'},
        )
    
    # execute the request.  
    # return value is sent, our own buffer
    # is populated with the component's 
    # content output
    ret = subreq.execute()
    
    
    </%python>
back to section top
call_self(buffer, retval)

The "call_self" method is provided so that a component may call itself and receive its own content in a buffer as well as its return value. "call_self" is an exotic way of having a component filter its own results, and is also the underlying method by which component caching operates. Note that for normal filtering of a component's results, Myghty provides a full set of methods described in the section Filtering, so call_self should not generally be needed.

call_self uses a "reentrant" methodology, like this:

<%python scope="init">
    import StringIO
    
    # value object to store the return value
    ret = Value()
    
    # buffer to store the component output
    buffer = StringIO.StringIO()
    
    if m.call_self(buffer, ret):
        m.write("woop! call self !" + 
            buffer.getvalue() + " and we're done")
        return ret()
        
    # ... rest of component
</%python>

The initial call to call_self will return True, indicating that the component has been called and its output and return value captured, at which point the component should return. Within the call_self call, the component is executed again; call_self returns False to indicate that the thread of execution is "inside" of the initial call_self and that content is being captured.

It is recommended that call_self be called only in an init-scoped Python block before any other content has been written, else that content will be printed to the output as well as captured.

back to section top
Component Methods

Instances of Component objects can be accessed many ways from the request object, including the fetch_component method, and the current_component, request_component, and base_component members. The fetch_next method returns the next component in an inheritance chain. Finally, self refers to the current component.

The methods available directly from Component are listed below, followed by the members.

call_method(methodname, **params)

Calls a method on the current component, and returns its return value. This method is shorthand for locating the current request via request.instance(), locating the method via locate_inherited_method() and calling m.comp().

get_flag(key, inherit=False)

Returns the value of a flag for this component. If "inherit" is True, the value of the flag will be searched for in the chain of parent components, if it is not found locally.

get_sub_component(name)

Returns the subcomponent denoted by name. For a subcomponent or method, returns the subcomponent of the owning (file-based) component. Note this is not for methods; for those, use locate_inherited_method.

has_filter()

Returns true if this component has a filter section, and or a "trim" flag.

locate_inherited_method(name)

Returns the method component associated with name. The method is searched for in the current component and up the inheritance chain. For a subcomponent or method, returns the method of the owning (file-based) component. Note this is not for non-method subcomponents; for those, use get_sub_component().

scall_method(methodname, **params)

Calls a method on the current component, captures its content and returns its content as a string. This method is shorthand for locating the current request via request.instance(), locating the method via locate_inherited_method() and calling m.scomp().

use_auto_flush()

Returns True or False if this component requires autoflush be turned on or off for its execution, or returns None if no requirement is set. This method searches within the current components flags, or within parent component flags if not present.

back to section top
Component Members
args
A list of argument names, corresponding to variable names in the component-scoped <%args> section, which have a default value specified.
attr
A dictionary of component attributes, corresponding to those set by the <%attr> tag. The attributes can be set at once by assigning a dictionary to this member. However, to set and retrieve individual attributes, it is best to use the special attributes member which takes advantage of inheritance.
attributes
A dictionary accessor for the attr dictionary member that locates its members first in the local component attributes, then searches up the inheritance chain for the attribute.
dir_name

The web-specific directory name where the current component resides, i.e. for this component its "/". For a subcomponent or method, it is the directory name of the owning (file-based) component.

file

The actual filesystem location of a component, for a component that was loaded directly from a Myghty template file, else it is None.

filter

Reference to the function that will perform filtering on the component. This filter is directly stated in the <%filter> section described in The <%filter> Tag.

flags
Dictionary of flags for this component. Also can be accessed via the get_flag method.
id

A unique identifier for the current component, which is comprised of the key name for its component root joined with its web-specific path, i.e. for this component its "content|components.myt".

is_file_component

True if this component is a file based component.

is_method_component

True if this component is a method component.

is_module_component

True if this component is a module component.

is_sub_component

True if this component is a subcomponent or method component.

name

The filename or name of the current component, i.e. for this component its "components.myt".

owner

For a subcomponent or method subcomponent, the owning file-based component, otherwise it is self.

parent_component

For a component in an inheritance chain (i.e. via %flags or via autohandlers), the inheriting component. For a subcomponent or method, returns the parent of the owning (file-based) component. Inheritance is described in Inheritance.

path

The URI corresponding to the component. For this component its "/components.myt". For a subcomponent or method, it is the URI of the owning (file-based) component.

request_args
A list of argument names, corresponding to variable names in the request-scoped <%args scope="request"> section, which do have a default value specified.
required_args
A list of argument names, corresponding to variable names in the component-scoped <%args> section, which do not have a default value specified., i.e. they are required component arguments.
required_request_args
A list of argument names, corresponding to variable names in the request-scoped <%args scope="request"> section, which do not have a default value specified, i.e. are required request arguments.
required_subrequest_args
A list of argument names, corresponding to variable names in the subrequest-scoped <%args scope="subrequest"> section, which do not have a default value specified, i.e. are required subrequest arguments.
subrequest_args
A list of argument names, corresponding to variable names in the subrequest-scoped <%args scope="subrequest"> section, which do have a default value specified.
back to section top

Module components build upon the component concept as introduced and explained in the previous section, Components. They represent a way of writing Myghty components using regular Python code within importable .py modules. A module component can be used to handle requests, controlling the flow of an application across one or more templates; this role is known as a "controller". Module components can also be embedded as component calls within templates just like any other component. In both cases, Module Components are the appropriate place to place code-intensive control or view logic.

Module Components, or MC's, are not a new idea, and have analogies in other environments, such as the Java Servlet class, the mod_python handler() function, or the WSGI application() callable. To suit the preferences of the both the class-oriented and the function-oriented developer, MC's can be written either as classes that subclass a specific Myghty class (similar to subclassing the Java Servlet class) or just as a regular Python function or callable object (i.e., an object instance that has a __call__ method). Additionally, individual methods upon a class instance can also be called as MC's.

When a plain Python function, callable object, or arbitrary instance method (herein will be generically referred to as a "callable") is to be called as a Module Component, the resulting component is referred to as an implicit module component. In this case, the Myghty Interpreter is given the location of the callable either via a string pattern or via passing the callable itself, and is told to execute it as a component. The Interpreter then creates a "real" component behind the scenes which proxies the Myghty argument set to the callable. The developer need not be aware of this proxying component (though it is available).

The flipside to the implicit module component is the explicit module component. Here, the developer creates a class that is a subclass of myghty.component.ModuleComponent, and implements the method do_run_component(), which satisfies the execution of the component. Like the implicit module component, the Interpreter is given its location either via a string pattern or via the Class object itself, and is told to execute it. The Interpreter, upon receiving a Class object, instantiates the class which becomes directly the component to be executed; no "proxy" component is created.

The differences between implicit and explicit module components are mostly differences in style. The explicit form allows the developer more direct access to the flags, attributes, and argument lists of the component to be called, whereas the implicit form is more sparse, lightweight and flexible. Both styles can be mixed; essentially, the Intepreter receives the object and determines the calling style based on the type of object passed to it. In all cases, the rest of a Myghty application sees just more myghty.component.Component objects, which have the same properties as any other component.

An added layer of complexity to module components involves the configuration of URI resolution, which allows the mapping of arbitrary URI's to specific module component callables or classes based on different schemes. This is required for MC's that are to be called as the top-level, request-handling component. Myghty currently includes two methods of achieving this, which are described later in this section, as well as an API to allow any user-defined mapping algorithm (part of Advanced Resolver Configuration).

Example Module Component

Lets start with hello world. All we need to do is create a new .py file, called hello.py, and place the following function inside it:

def helloworld(m):
    m.write("hello world !")

That is the extent of the module component itself. Since it is a plain function, this is an "implicit" module component.

To call the component, the request object is given a string starting with the prefix "MODULE:", followed by the module name and name of the callable or class, separated by a colon. In a template it is one of the following:

# inline
<& MODULE:hello:helloworld &>

# code
<%python>
    m.comp("MODULE:hello:helloworld")
</%python>

Alternatively (release 0.99b), the "MODULE:" prefix can also be an "at" sign as follows:

<& @hello:helloworld &>

<%python>
    m.comp("@hello:helloworld")
</%python>

Both the module name and the callable/class name can contain any number of periods to represent sub-modules or sub-properties of the module. Suppose helloworld was a property on an object:

hello = object()

def doit(m):
    m.write("hello world !")
    
hello.helloworld = doit

This component can be called as:

<& MODULE:hello:hello.helloworld &>

or just:

<& @hello:hello.helloworld &>

The callable can have any argument list, and even the m variable is optional (though highly recommended). Myghty uses the inspect library to determine the desired arguments based on the callable's signature. (for the performance minded, this is done only once when the component is first loaded). Using the names present in the argument list, Myghty will determine which of the available global variables will be specified, as well as what required and optional component arguments this MC will require. The component arguments are configured in exactly the same way as a template-based component configures its <%ARGS> section.

So to our "hello world" lets add the current and optionally tomorrow's weather:

def helloworld(m, today, tomorrow = None):
    m.write("hello world !  its a %s day today." % today)
    if tomorrow is None:
        m.write("Don't know what it is tomorrow, though.")
    else:
        m.write("But tomorrow, it'll be %s" % tomorrow)

This component can be called like these examples:

# inline shorthand
<& @hello:helloworld, today='sunny' &>

# inline longhand
<& MODULE:hello:helloworld, today='sunny' &>

# code
<%python>
    m.comp("MODULE:hello:helloworld", today='cloudy', tomorrow='rainy')
</%python>

The argument list of a module component may specify any of the standard and/or user-configured global arguments (globals were introduced in Standard Global Variables). All arguments are passed by name, so the ordering is not important:

def handle_request(m, ARGS, r, s, **params):
    # ...

The above component specifies that it will receive the global variables m, ARGS, r, and s. It also defines **params, so all remaining component arguments will be in this dictionary. A callable that defines simply **params will receive all globals and component arguments within the dictionary.

back to section top
Flavors of Module Component

A summary of the various styles of MC are as follows. For each of the below examples, assume the callable exists within a module named mylib.hello:

Function
This is the most basic type of implicit module component.
def helloworld(m, **params):
    m.write("hello world!")
Called as:
<& MODULE:mylib.hello:helloworld &>
back to section top
Callable Object

A callable object must be instantiated, but to the outside world looks almost the same as a function:

class HelloWorld:
    def __call__(self, m, **params):
        m.write("hello world!")

# instantiate the class
helloworld = HelloWorld()
Called as:
<& MODULE:mylib.hello:helloworld &>
Note that this is identical to the previous function example.
back to section top
Object Method
The object method is set up similarly to a callable object, the only difference being that a specific named method is called, instead of the generic __call__ method. The difference lies in how it is specified when called.
class HelloWorld:
    def doit(self, m, **params):
        m.write("hello world!")

# instantiate the class
helloworld = HelloWorld()
Called as:
<& MODULE:mylib.hello:helloworld.doit &>
One particular quirk about the object method style is that if an object instance contains multiple methods that are called as MC's, the interpreter creates a separate "proxy" component for each method.

With both callable object styles, the same object instance handles many requests, including multiple simultaneous requests among different threads, if the application is running in a threaded environment. A developer should take care to store request-scoped information as attributes upon the request object and not as instance variables of the object, as well as to appropriately synchronize access to instance variables and module attributes.

back to section top
Class / Explicit Module Component

This style works differently from the previously mentioned styles, in that the developer is writing a class directly against the Myghty API. In this style, the developer directly defines the class of the component that is ultimately being accessed by the outside world. No "proxying" component is created; instead, the Interpreter instantiates the specified class the first time it is referenced. This also removes the need to explicitly instantiate the class:

import myghty.component

class HelloWorld(myghty.component.ModuleComponent):
    
    def do_run_component(self, m, **params):
        m.write("hello world!")
Called as:
<& MODULE:mylib.hello:HelloWorld &>

Note that the scoping rules for this style of component are the same, i.e. the same component instance is called for many requests and must be aware of variable scope as well as concurrency issues.

The do_run_component method works similarly to the callable of an implicit component. Its argument list is dynamically inspected to determine the desired globals and component arguments, in the same way as that of implicit MC's. However, there also is the option to bypass this inspection process and name the arguments explicitly, as well as their desired scope. In previous versions of Myghty, this was the only way to define the arguments of an MC, but now its only optional. This method is described in the next section, as well as the configuration of flags and attributes for MC's.

back to section top
Module Component Initialization

Explicit MCs as well as implicit MCs based on an object instance have an optional initialization step that is called the first time the object instance is referenced. The method is called on an explicit ModuleComponent subclass as:

def do_component_init(self)

And is called on an implicit callable object as:

def do_component_init(self, component)

In the second version, the argument component is an instance of myghty.component.FunctionComponent that is hosting the implicit module component's __call__ method or other method. It is important to note that an object instance with many callable methods will actually have many FunctionComponents created, each one hosting an individual methods...however, the do_component_init() method is only called once with whatever FunctionComponent was first associated with the object.

In previous versions of Myghty, the initialization phase was required for components with arguments, which had to be explicitly declared within this stage. As of version 0.98, explicit declaration of component arguments is optional, and the argument lists are by default determined from the signature of the explicit do_run_component method or the implicit callable.

Explicit specification of an MCs arguments in the init section are as follows:

import myghty.component as component

class MyComponent(component.ModuleComponent):

    def do_component_init(self, **params):
        # component arguments
        self.args = ['arg1', 'arg2']
        
        # required component arguments
        self.required_args = ['arg3', 'arg4']
        
        # request-only arguments
        self.request_args = ['docid']
        
        # required request-only arguments
        self.required_request_args = ['userid']
        
        # subrequest or request arguments
        self.subrequest_args = ['foo']
        
        # required subrequest or request arguments
        self.required_subrequest_args = ['bar']

A component as above would have the do_run_component signature as follows:

def do_run_component(
    self, m, userid, arg3, arg4, bar, 
    docid = None, arg1 = None, arg2 = None, foo = None, **params
    ):

Note that if a module component defines any arguments explicitly in the do_component_init method, all arguments for the do_run_component method must be specified; no automatic introspection of function arguments will occur.

Similarly, <%flags> and <%attr> sections can be achieved like this:

def do_component_init(self, **params):
    # flags
    self.flags = {
        'autoflush':True,
        'trim': 'both'
    }
    
    # attributes
    self.attr = {
        'style':'green',
        'docid':5843
    }
back to section top
Using MCs as Controllers

The two most prominent features of an MC used as a controller includes that URI resolution is configured so that one or more URIs result in the component being called directly from a request, and that the component typically uses subrequests to forward execution onto a template, which serves as the view.

Here are two versions of a controller component that is used to pull documents from a database based on the request arguments, and displays them via a template called "documents.myt".

Figure 1: Implicit Style, using a Callable Object

 
 class DocumentManager:

     def do_component_init(self, component):
         # load some application-wide constants via Interpreter attributes.
         # the Interpreter is located via the hosting component.
         self.document_base = component.interpreter.attributes['document_base']
         self.db_string = component.interpreter.attributes['db_connect_string']

     def __call__(self, m, docid = None):

         # if no document id, return '404 - not found'       
         if docid is None:
             m.abort(404)

         # access a hypothetical document database
         docdb = get_doc_db(self.document_base, self.db_string)

         # load document
         document = docdb.find_document(docid)

         # couldnt find document - return '404 - not found'
         if document is None:
             m.abort(404)

         # run template
         m.subexec('documents.myt', document = document, **params)

 documentmanager = DocumentManager()

Figure 2: Explicit Style, with Pre-Declared Arguments

import myghty.component as component

class DocumentManager(component.ModuleComponent):

    def do_component_init(self, **params):
        # load some application-wide constants
        self.document_base = self.interpreter.attributes['document_base']
        self.db_string = self.interpreter.attributes['db_connect_string']

        # establish the argument names we want (optional as of 0.98)
        self.args = ['docid']

    def do_run_component(self, m, ARGS, docid = None, **params):

        # if no document id, return '404 - not found'       
        if docid is None:
            m.abort(404)

        # access a hypothetical document database
        docdb = get_doc_db(self.document_base, self.db_string)
        
        # load document
        document = docdb.find_document(docid)
        
        # couldnt find document - return '404 - not found'
        if document is None:
            m.abort(404)

        # run template
        m.subexec('documents.myt', document = document, **params)

The next section describes the two methods of configuring request URIs to execute "controller" components like this one.

back to section top
Configuring Module Component Resolution

Module components can be used anywhere within the request, either right at the beginning (i.e. a controller) or within the scope of other components already executing. A module component can be fetched and/or called based on its importable module name followed by a path to a callable object, or the name of a class that subclasses myghty.components.ModuleComponent. However, this doesn't work as a URL sent to a webserver. For request-level operation, MCs must be mapped to URIs. This resolution is achieved through two different configuration directives, module_components and module_root. A third option also exists which is to use the new routesresolver resolver object.

module_components
The module_components configuration parameter looks like this:
module_components = [
    {r'myapplication/home/.*' : 'myapp.home:HomeHandler'}, 
    {r'myapplication/login/.*' : 'myapp.login:LoginHandler'}, 
    {r'.*/cart' : 'myapp.cart:process_cart'}, 
    {r'.*' : 'myapp.home:HomeHandler'} 
]
Which in an apache configuration looks like:
PythonOption MyghtyModuleComponents "[ \
    {r'myapplication/home/.*' : 'myapp.home:HomeHandler'}, \
    {r'myapplication/login/.*' : 'myapp.login:LoginHandler'}, \
    {r'.*/cart' : 'myapp.cart:ShoppingCart'}, \
    {r'.*' : 'myapp.home:HomeHandler'} \
]"

Each entry in the module_components array is a single-member hash containing a regular expression to be matched against the incoming URI, and an expression that can be resolved into a Module Component. This expression can be any of the following forms:

module_components = [
    # a string in the form '<modulename>:<classname>'           
    {r'myapplication/home/.*' : 'myapp.home:HomeHandler'}, 
    
    # a string in the form '<modulename>:<functionname>'
    {r'myapplication/login/.*' : 'myapp.login:do_login'}, 
    
    # a string in the form '<modulename>:<some>.<callable>.<thing>'
    {r'myapplication/status/.*' : 'myapp.status:handler.mcomp.get_status'},
    
    # a Class
    {r'.*/cart' : MyClass}, 
    
    # a function reference, or reference to a callable() object
    {r'.*/dostuff' : do_stuff},
    
    # reference to a class instance method
    {r'.*' : mymodule.processor.main_process}
]

Generally, its better to use the string forms since they encompass all the information needed to load the class or callable object, which allows the Myghty interpreter to dynamically reload the object when the underlying module has changed.

For module components that resolve to a Class, the Class will be instantiated by the Interpreter, and is expected to be a subclass of myghty.component.ModuleComponent. This is also known as an explicit module component. For components that resolve to a function, object instance method, or callable object (i.e. any object that has a __call__ method), a "wrapper" module component will be created automatically which adapts to the callable's argument list. This is also known as an implicit module component.

The corresponding Resolver class for module_components is ResolveModule.

Passing Resolution Arguments

The module_components configuration parameter also includes some methods of returning information about the actual resolution of the component at request time.

Since module_components uses regular expressions to match URIs to components, the re.Match object produced when a match occurs can be accessed via the m global variable. This example places capturing parenthesis in the regular expression to capture the additional path information:

module_components = [
    # place capturing parenthesis in the regexp
    {r'/catalog/(.*)' : 'store:Catalog'}
]
The contents of the capturing parenthesis are available as:
m.resolution.match.group(1)

User-defined arguments can also be configured which will be passed to the request object at resolution time. To use this form, a dictionary is used instead of a single string to specify the module and callable/class name of the component, and the address of the component itself is placed under the key 'component':

module_components = [
    # supply the component with some arguments
    {r'/login/' : 
        {
        'component' : 'myapp:loginmanager',
        'ldap_server' : 'ldap://localhost:5678'
        }
    }
]
The contents of the ldap_server argument are available as:
m.resolution.args['ldap_server']
back to section top
module_root

This parameter locates module components based on paths. It is similar to the component_root configuration parameter in that it defines one or more roots which will all be matched against the incoming URI. However, it not only traverses through directories, it also will traverse into a Python module where it attempts to locate a function or callable object instance. Currently, only the "implicit" style of module components can be used with module_root (but module_components, from the previous section, can be used with implicit or explicit MCs).

The entries in module_root take the following forms:

module_root = [
    # a regular file path
    '/web/lib/modules/',
    
    # the full file path of a Python module
    '/web/extra/modules/mycontroller.py',
    
    # the name of an importable Python module
    'mylib.loginhandlers',
]

Using the first path '/web/lib/modules', heres an example. Start with the following file:

/web/lib/modules/admin/login.py

This file contains the following code:

def hello(m):
    m.write("hello world!")
    
class _do_login:
    def __call__(self, m):
        m.write("please login")
        # ....

    def foo(self, m):
        m.write("this is foo")
        
index = _do_login()

_my_var = 12

Finally, lets have a module_root of:

module_root = ['/web/lib/modules']

With this configuration, URLs will be resolved as follows:

http://mysite.com/admin/login/hello/     --->  "hello world!"    (login.py:hello())
http://mysite.com/admin/login/           --->  "please login"    (login.py:index.__call__())
http://mysite.com/admin/login/foo/       --->  "this is foo"     (login.py:index.foo())
http://mysite.com/admin/login/lala/      --->  "please login"    (login.py:index.__call__())
http://mysite.com/admin/login/_my_var/   --->  "please login"    (_my_var is private and is skipped)
http://mysite.com/admin/lala/            --->  404 not found     (no file named lala.py)

The spirit of this resolver is that of the mod_python Publisher handler. Path tokens are converted into the names of .py files on the filesystem. When a file is located and it is a valid Python module, the module is loaded and further path tokens are resolved as attributes within the module itself. Attributes that start with an underscore are skipped, which is the default way to flag "private" attributes. There is also a "public" attribute marker which can be used to mark public functions instead of marking private functions, explained in the options section below. If no matching attribute exists for a path token, it looks for the attribute name "index", else returns a ComponentNotFound exception.

module_root can also be combined with dhandler resolution (described in dhandler), so that a file named dhandler.py in the current or parent directory serves as the "default" Python module for a path token that does not correspond to any other file. In the case of ResolvePathModule locating a dhandler.py file, the additional path tokens that normally reside within dhandler_path are also searched as attributes within the dhandler.py module.

The corresponding Resolver class for module_root is ResolvePathModule.

Module Root Options

The underlying Resolver object for the module_root parameter is called ResolvePathModule (resolver objects are described in Advanced Resolver Configuration). This object also has configuration options of its own. These options may be specified to the ResolvePathModule constructor directly. They can be specified as regular Myghty configuration parameters as well as of version 0.99b:

  • module_root_adjust=None (release 0.99b) - a reference to a function which receives the incoming URI and returns a modified version of that URI with which to resolve. The modified URI is not propigated onto other rules in the resolution chain, so therefore it represents a "local" alternative to path_translate.

    This parameter is also called 'adjust' in all releases, but that name conflicts with the same name in the ResolveFile resolver, so should only be used when constructing individual ResolvePathModule objects and not as a global configuration parameter.

  • require_publish=False - when set to True, the callable object must have an attribute publish set to True in order to mark it as publically accessible; else it will not be resolved. This effectively reverses the "negative publishing" model established via the underscore "_" syntax into a "positive publishing" model. Given this configuration:

    module_root = ['/web/lib/modules']
    require_publish = True

    Marking functions and methods public looks like this:

    class MyController(object):
        def __call__(self, m, **kwargs):
            # ...
            m.subexec('mytemplate.myt')
        __call__.public = True
            
        def do_stuff(self, m, **kwargs):
            # ...
            m.subexec('dostuff.myt')
        do_stuff.public = True
        
    def call_index(m,r, s, ARGS):
        # ...
        m.subexec('index.myt')
    call_index.public = True
    
    mycallable = MyController()

    The public attribute can also be set in Python 2.4 via decorator:

    def mark_public(func):
        func.public = True
        return func
        
    @mark_public
    def mycontroller(m, **kwargs):
        # ...
  • path_moduletokens=['index'] - this is a list of special "default" token names when searching for module attributes. For example: If a given path "/foo/bar/bat" resolves to the module "bar.py" inside of directory "foo/", it will first look for an attribute named "bat" inside the module. If "bat" is not present, it will then look for all the names inside the moduletokens list, which defaults to the single entry "index". Therefore /foo/bar/bat not only looks for "bat", it also looks for "index". The tokens inside moduletokens are checked as defaults for every module token, so that a path such as "/foo/bar/bat" can also correspond to a module attribute "foo.index.bat", "index.bar.bat", etc.
  • path_stringtokens=[] - this is the path equivalent to the moduletokens parameter. It is a list of "default" path tokens when searching for files. In some ways, this parameter's functionality overlaps that of dhandler_name, except it allows multiple names and applies only to the module_root configuration. For example, if stringtokens is configured to ["default", "index"], and a given path "/foo/bar" resolves to the directory "foo/" but there is no file named "bar.py" inside the directory, it will then look for the files "default.py" and "index.py", respectively. Like moduletokens, stringtokens also checks these defaults for every path token, so a URL of "/foo/bar/bat" can also match "/default/bar/index", for example.
back to section top
Routes Resolver

The Routes Resolver provides Rails-like functionality, building upon the resolution architecture described in Advanced Resolver Configuration. Since it is not part of the default set of resolver objects, it must be included in the resolution chain via the resolver_strategy configuration parameter.

A rudimentary example of the Routes resolver can be viewed by installing the myghty_routes Paste template. Instructions for installing Paste templates are in Running Paste Templates. The routes resolver also serves as the core resolver for the Pylons web framework which is based on Myghty, and includes more comprehensive and up-to-date examples.

back to section top
Module Component Pre and Post processing

Request-handling module components can also be used to perform pre- and post-processing on a request. This means that the information about a request is modified before and/or after the main response is determined. The following two examples both wrap the main body of the request inside of a subrequest.

A module component that performs translations on incoming URI's, and then passes control onto the requested template, looks like this:

def translate_path(self, m, **params):
    path = m.get_request_path()
    path = re.sub('/sitedocs/john/', '/', path)
    m.subexec(path, **params)

A URI configuration for this component might look like:

module_components = [{r'/sitedocs/john/.*\.myt', 'mymodule:translate_path'}]

Path translation is also accomplished in Myghty via the path_translate parameter, and can be controlled in finer detail through the use of custom resolution rules, described in Advanced Resolver Configuration.

An example post processing component, which filters the output of the subrequest before returning data:

import StringIO, re

def filter(self, m, **params):
    # make a buffer
    buf = StringIO.StringIO()

    # create a subrequest using that buffer
    # our templates are located relative to the 
    # request URI underneath '/components'
    subreq = m.create_subrequest('/components' + m.get_request_uri(), out_buffer = buf)

    # execute the subrequest
    ret = subreq.execute()

    # perform a meaningless filter operation on the content
    content = re.sub(r'foo', r'bar', buf.getvalue())            

    # write the content                 
    m.write(content)

This component might be configured as:

module_components = [{r'/sitedocs/john/.*\.myt', 'mymodule:filter'}]

Filtering is also built in to Myghty via the use of <%filter> section, described in Filtering and Flushing (and Escaping).

back to section top
Using Module Components within Templates

MCs can also be called from within templates. If an MC is configured to be callable against a URI using module_components or module_root, that URI can also be used within a regular <& &>-style component call. Or, the MODULE: prefix style described previously can be used.

Example: Form Visitor

Here is an example of a module component that is used to generate HTML forms from a data object, using the visitor pattern. Such an architecture can be used to have form information stored in a database or XML file which can then be used to automatically construct a corresponding form. This example is included in working form with the Myghty distribution.

Step 1: Data Model - The data model consists of a hierarchy of FormElement objects. Some FormElement objects can contain collections of other FormElements (the "composite" pattern):

form.py
class FormElement(object):
    """ abstract FormElement superclass."""
    
    def __init__(self):
        pass
    
    def accept_visitor(self, visitor): 
        """subclasses override accept_visitor to provide
        the appropriate type-based visitor method."""
        pass
    
class Form(FormElement):
    """represents a <FORM> tag."""

    def __init__(self, name, action, elements):
        self.name = name
        self.action = action
        self.elements = elements

    def accept_visitor(self, visitor):
        visitor.visit_form(self)
    
class Field(FormElement):
    """abstract base class for individual user-entry fields, each 
    having a name, a description, and an optional value."""

    def __init__(self, name, description, value = None):
        self.name = name
        self.description = description
        self.value = value
    
class TextField(Field):
    """an <INPUT TYPE="text"> field."""

    def __init__(self, name, description, size, value = None):
        Field.__init__(self, name, description, value)
        self.size = size

    def accept_visitor(self, visitor):
        visitor.visit_textfield(self)
        
class SelectField(Field):
    """a <SELECT></SELECT> tag."""

    def __init__(self, name, description, options, value = None):
        Field.__init__(self, name, description, value)
        self.options = options
        for o in self.options:
            o.parent = self
            if o.id == self.value:
                o.selected = True
                
    def accept_visitor(self, visitor):
        visitor.visit_selectfield(self)

class OptionField(FormElement):
    """an <OPTION></OPTION> tag.
    contains a parent attribute that points to a <SELECT> field."""

    def __init__(self, id, description):
        self.id = id
        self.description = description
        self.parent = None
        self.selected = False
        
    def accept_visitor(self, visitor):
        visitor.visit_option(self)

class SubmitField(FormElement):
    """an <INPUT TYPE="submit"> field."""

    def __init__(self, value):
        self.value = value

    def accept_visitor(self, visitor):
        visitor.visit_submit(self)

Step 2: Visitor Interface - This class provides the layout of a visitor object:

form.py
class FormVisitor:
    def visit_form(self, form):pass
    def visit_textfield(self, textfield):pass
    def visit_selectfield(self, selectfield):pass
    def visit_option(self, option):pass
    def visit_submit(self, submit):pass

Step 3: HTML Rendering Components - a set of Myghty methods that will render the HTML of each form element:

formfields.myc
<%doc>
    each method renders one particular HTML form element, 
    as well as <table> tags to provide basic layout for each.  
    the "form" and "select" methods are component calls with content, 
    to render the form elements within them.
</%doc>

<%method form>
    <%args>form</%args>
    
    <FORM name="<% form.name %>" method="POST" action="<% form.action %>">
    <table>
    <% m.content() %>
    </table>
    </FORM>
</%method>

<%method textfield>
    <%args>textfield</%args>

    <tr>
        <td><% textfield.description %>:</td>
    
        <td>
        <input type="text" name="<% textfield.name %>" value="<% textfield.value %>" size="<% textfield.size %>" >
        </td>
    </tr>
</%method>

<%method submit>
    <%args>submit</%args>
    
    <tr><td colspan="2">
        <input type="submit" value="<% submit.value %>">
    </td></tr>
</%method>

<%method select>
    <%args>select</%args>
    
    <tr>
        <td><% select.description %></td>
        <td>
            <select name="<% select.name %>">
            <% m.content() %>
            </select>
        </td>
    </tr>
</%method>

<%method option>
    <%args>option</%args>
    <option value="<% option.id %>" <% option.selected and "SELECTED" or "" %>><% option.description %></option>
</%method>

Step 4: Module Component - ties it all together. The FormGenerator serves as the traversal unit for the Form object, as well as the visitor implementation itself. The visit_form and visit_selectfield methods both involve contained formelements, and the corresponding myghty components are component calls with content; so for those, a content function is created to handle the embedded content.

form.py
def renderform(self, m, form, **params):
    form.accept_visitor(FormGenerator.RenderForm(m))
    
class RenderForm(FormVisitor):
    def __init__(self, m):
        self.m = m

    def visit_form(self, form):
        def formcontent():
            for element in form.elements:
                element.accept_visitor(self)

        self.m.execute_component("formfields.myc:form", args = dict(form = form), content=formcontent)

    def visit_textfield(self, textfield):
        self.m.comp("formfields.myc:textfield", textfield = textfield)

    def visit_selectfield(self, selectfield):
        def selectcontent():
            for element in selectfield.options:
                element.accept_visitor(self)

        self.m.execute_component("formfields.myc:select", args = dict(select = selectfield), content=selectcontent)

    def visit_option(self, option):
        self.m.comp("formfields.myc:option", option = option)

    def visit_submit(self, submit):
        self.m.comp("formfields.myc:submit", submit = submit)

Step 5: Fire it Up - this myghty template actually calls the renderform Module Component.

registration.myt
<%doc>
    an example firstname/lastname/occupation registration form.
</%doc>

<%python>
    import form
    registerform = form.Form('myform', 'register.myt', elements = [
            form.TextField('firstname', 'First Name', size=50),
            form.TextField('lastname', 'Last Name', size=50),
            form.SelectField('occupation', 'Occupation', 
                options = [
                    form.OptionField('skydiver', 'Sky Diver'),
                    form.OptionField('programmer', 'Computer Programmer'),
                    form.OptionField('', 'No Answer'),
                ]
            ),
            form.SubmitField('register')
        ]
    )
</%python>

Welcome to the Skydivers or Computer Programmers Club !

<& MODULE:form:renderform, form = registerform &>
back to section top

View: Paged  |  One Page

The Request, available in all Myghty templates as the global variable m, is the central processor of a component and all the calls it makes to other components. Following are all the useful methods and members of a request.

Note: many request methods have been converted to straight data members as of version 0.96, such as get_base_component(), get_request_args(), get_dhandler_arg(), etc. These methods are still present for existing applications but their use is deprecated. Their functionality can be located in the Request Members section.

Request Methods
abort(status_code = None)

Halts the currently executing component, and optionally sends the specified HTTP status code. Any content that is still in the output buffer is discarded. If the status code is None, the request simply ends with no further output, and the HTTP code 200:OK is returned as a normal request.

Abort can be used to send any HTTP status code desired to the client. However, to send a soft redirect via a subrequest, or a hard redirect via the "Location:" header along with 302:Moved, its easier to use m.send_redirect(), described below.

apply_escapes(text, flags)
programmatically applies escape flags to the given text, the same as they would be used inside of a substitution. text is a string to be processed, and flags is an array of single-character escape flags. The two built in flags are "u" for url escaping and "h" for HTML escaping, and user-defined flags are supported as well. See Escaping Content for more information on escape flags.
cache(component=None, cache_type=None, cache_container_class=None, **params)

Returns the cache for the current component, or if called with an optional component argument, returns the cache for the specified component. If the cache does not yet exist within the scope of the current request, it will be created using the given list of arguments, else the arguments are disregarded and the previous request-scoped cache interface is returned (note that multiple instances of a cache interface may all reference the same underlying data store, if they are of the same type). The arguments here override those set in the global configuration for the interpreter, but will usually not override the arguments specified in the %flags section of the component.

The cache type defaults to 'dbm' if a data_dir is in use, else uses 'memory'. Additional arguments can be added that are specific to MemoryContainer, DBMContainer, or other custom types of containers. See the section Data Caching.

Also called as: get_cache

cache_self(component=None, key=None, retval=None, cache_type=None, cache_container_class=None, **params)

Caches the current component (or the specified component's) output and return value. All arguments are optional. The component argument is a component argument specifying a component other than the currently executing component. The key argument is the key to store the information under, which defaults to the string "_self". The key can be modified if you want to cache the comopnent's output based on some kind of conditional information such as component arguments. The retval argument is a value object which can be used to receive the return value of the component. The rest of the parameters are the same as those for the cache/get_cache method.

The function returns True indicating that the retval has been populated and the component's output has been flushed to the output, or False indicating that the value is not yet cached (or needs refreshing) and execution should continue on into the rest of the component. See Data Caching for an example.

callers(index = None)

Returns a single component from the call stack object indicated by the given index, or if None returns the full list of components stored within the current call stack.

caller_args(index = None)

Returns a single dictionary of component arguments from the call stack object indicated by the given index, or if None returns the full list of argument dictionaries sent to each component stored within the current call stack.

call_content()

Similar to the content() method used within a component call with content, except does not push a new buffer onto the buffer stack. When combined with programmatic pushing and popping buffers onto the request via push_buffer() and pop_buffer(), it can be used for complicated content-grabbing schemes. For advanced usage.

call_next(**params)
Within a chain of inheriting pages, calls the next component in the inheritance chain, i.e. the "wrapped" component. See Inheritance for more information on the inheritance chain. Optional **params specify arguments that will override the subclass-component's default argument list on a parameter-by-parameter basis.
call_stack(index = None)

Provides access to the current call stack. The call stack is a list of StackFrame objects, which are internal representations of components calling each other. Each StackFrame object contains the fields "component", "args", "base_component", "content", "is_call_self", and "filter". The given index refers to what index within the stack to return; if it is None, the entire call stack is returned.

comp(component, **params)
calls a component, subcomponent, or method. See m.comp(component, **params).
component_exists(path)
returns True if the specified file-based component, identified by its URI, can be located. Performs the full filesystem check even if the requested component is already loaded, therefore repeated calls to this method can get expensive.
content()
returns the content of an embedded component call in the context of a component call with content. See Component Calls with Content.
create_subrequest(component, resolver_context='subrequest', **params)
Creates a subrequest, which is a child request to this one. The request can then serve a new component call, which will be serviced within the same output stream as this one. By default, the subrequest is configured in much the same way as the originating request. The **params dictionary can be used to override individual configuration parameters; any per-request parameter listed in Index of Configuration Parameters is relevant.

Users will usually prefer to use the methods make_subrequest() or subexec() since they are more compact for typical component-call scenarios. See Subrequests.

Also see Resolver Contexts for information on the resolver_context parameter.

decline()
Used by a dhandler to forego processing a directory request, and to bump the interpreter up to the enclosing directory, where it will search again for a dhandler. See dhandler.
execute()
Executes this request. Chances are you are already inside the execute call, which can only be called once on any given request object. However, if you make yourself a subrequest, then you can call execute on that object. See Subrequests.
execute_component(component, args = {}, base_component = None, content = None, store = None, is_call_self = False)
The base component-calling method, at the root of all the other component calling methods (i.e. execute(), comp(), subexec(), etc.). The richer argument set of this method is useful for calling components with an embedded content call, and also for supplying a custom output buffer to capture the component output directly. The parameters are:
  • component - the string name/URI of the component, or an actual component argument
  • args - dictionary of arguments sent to the component. this is supplied to the component via ARGS as well as via the component-scoped <%args> tag.
  • base_component - the base component for the component call. This is best left as None, where it will be determined dynamically.
  • content - reference to a function that will be attached to the m.content() method inside the component call. this is used to programmatically call a "component call with content". The function takes no arguments and is normally a "closure" within the span of the code calling the enclosing component.
  • store - reference to a buffer, such as a file, StringIO, or myghty.buffer object, where the component's output will be sent.
  • is_call_self - used internally by the m.call_self() method to mark a stack frame as the original "self caller". Just leave it as False.

Example: component call with content:

<%def testcall>
    this is testcall.  embedded content:
    [ <% m.content() %> ]
</%def>

<%python>
    def mycontent():
        m.write("this is the embedded content.")
        
    m.execute_component('testcall', args = {}, content = mycontent)
</%python>

This will produce:

this is testcall.  embedded content:
[ this is the embedded content. ]
fetch_all()
Returns a list of the full "wrapper chain" of components inheriting each other, beginning with the current inheriting component and going down to the innermost component. Each element is popped of the request's internal wrapper stack. See Inheritance for details on component inheritance.
fetch_component(path, resolver_context='component', raise_error=True)

Returns a component object corresponding to the specified component path. This path may be:

  • a URI path relative to one of the application's configured component roots, with an optional clause ":methodname" indicating a method to be called from the resulting file-based component.
  • one of the special names SELF, PARENT, REQUEST, with an optional clause ":methodname" indicating a method to be called from the resulting file-based component, or the current subcomponent's owner in the case of a subcomponent that calls SELF.
  • the name of a method component stated in the form "METHOD:modulename:classname".
When the component is located, it will be compiled and/or loaded into the current Python environment if it has not been already. In this way it is the Myghty equivalent of "import".

If the component cannot be located, it raises a myghty.exceptions.ComponentNotFound error, unless raise_error is False, in which case the method returns None.

More details on how to identify components can be found in Components.

Also see Resolver Contexts for information on the resolver_context parameter.

fetch_lead_component(path)

Fetches a component similarly to fetch_component(), but also resolves directory requests and requests for nonexistent components to dhandlers.

If the component cannot be located, or a useable dhandler cannot be located because either no dhandler was found or all valid dhandlers have already sent decline() within the span of this request, a myghty.exceptions.ComponentNotFound error is raised.

fetch_module_component(moduleorpath, classname, raise_error=True)

Fetches a module component. The value of "moduleorpath" is either a string in the form "modulename:classname", or it is a reference to a Python module containing the desired component. In the latter case, the argument "classname" must also be sent indicating the name of the desired class to load.

Using this method with a string is the same as using the fetch_component() method using the syntax "METHOD:modulename:classname".

If the module component cannot be located, a myghty.exceptions.ComponentNotFound error is raised, unless raise_error is False, in which case the method returns None.

fetch_next()
Within a chain of inheriting pages, this method returns the next component in the inheritance chain (also called the "wrapper" chain), popping it off the stack. The component can then be executed via the m.comp() or similar method. See the section Inheritance.
get_session(**params)

Creates or returns the current Myghty session object (or optionally the mod_python Session object). If the session has not been created, the given **params are used to override defaults and interpreter-wide configuration settings during initialization.

Details on the Session are described in Session.

has_content()
Inside of a subcomponent or method call, returns whether or not the component was a component call with content. See the section Component Calls with Content.
has_current_component()
Returns True if this request has a currently executing component. This becomes true once a request's execute() method has been called.
instance()
This static method returns the request corresponding to the current process and thread. You can access the current request in a globally scoped block via this method. See Global Scope.
<%python scope="global">
    req = request.instance()
</%python>
is_subrequest()
Returns True if the currently executing request is a subrequest. See the section Subrequests.
log(message)
Logs a message. The actual method of logging is specific to the underlying request implementation; for standalone and CGI it is the standard error stream, for mod_python it is a [notice] in the Apache error log.
make_subrequest(component, **params)
Creates a new subrequest with the given component object or string path component and the request arguments **params. The returned request object can then be executed via the execute() method. See Subrequests.
scomp(component, **params)
Executes a component and returns its content as a string. See m.scomp(component, **params).
send_redirect(path, hard=True)
Sends a hard or soft redirect to the specified path. A hard redirect is when the http server returns the "Location:" header and instructs the browser to go to a new URL via the 302 - MOVED_TEMPORARILY return code. A soft redirect means the new page will be executed within the same execution context as the current component. In both cases, the current component is aborted, and any buffered output is cleared. For this reason, if auto_flush is enabled (which it is not by default), you would want to call this method, particular the soft redirect, only before any content has been output, most ideally in an %init section. If auto_flush is disabled, you can call either version of this method anywhere in a component and it will work fine.
set_output_encoding(encoding, errors="strict")

Change the output_encoding, and, optionally, the encoding error handling strategy.

Generally, you will not want to change the output encdoing after you have written any output (as then your output will be in two different encodings --- probably not what you wanted unless, for example, you are generating Mime multipart output.)

See the section on Unicode Support for further details.

subexec(component, **params)
All-in-one version of make_subrequest and m.execute(). See Subrequests.
write()
Writes text to the current output buffer. If auto_flush is enabled, will flush the text to the final output stream as well.

Also called as: out
back to section top
Request Members
attributes

A dictionary where request-local information can be stored. Also can be referenced by the member notes. If the request is a subrequest, this dictionary inherits information from its parent request.

base_component
Represents the "effective" file-based component being serviced, from which methods and attributes may be accessed. When autohandlers or other inherited components are executing, this member always points to the file-based component at the bottom of the inheritance chain. This allows an inherited component to access methods or attributes that may be "dynamically overridden" further down the inheritance chain. It is equivalent to the special path SELF. When a method or def component is called via the path of another file-based component, base_component will change to reflect that file-based component for the life of the subcomponent call.
current_component
The component currently being executed. Within the body of a component, this is equivalent to self.
dhandler_path
In the case of a dhandler call, the request path adjusted to the current dhandler.

For information on dhandlers see dhandler.

encoding_errors

The current output encoding error handling strategy. This is a read-only attribute, though you may change it using the set_output_encoding method.

See the section on Unicode Support for further details.

global_args

A dictionary of custom-configured global variables to be used throughout the request. Global variables can be initialized or re-assigned here, and the new value will become available to all further component calls. Each key in this dictionary must already correspond to a value in the allow_globals configuration parameter. See Make your Own Friends for full examples.

interpreter

The Interpreter object that created this Request object.

notes
A synonym for attributes.
output_encoding

The current output encoding. This is a read-only attribute, though you may change it using the set_output_encoding method.

See the section on Unicode Support for further details.

parent_request
In a subrequest call, refers to the immediate parent request of this request, else defaults to None.
request_args

A dictionary containing the initial request arguments sent when this request was created. In an HTTP context, this usually refers to the request arguments sent by the client browser.

In the case of a subrequest (described in Subrequests), this member refers to the request arguments sent to the local subrequest. To get the original request arguments, use the root_request_args parameter.

For detailed description of component and request arguments, see Component Arguments - the <%args> tag.

request_component
Returns the top-level component corresponding to the current request.
request_path

The original path sent to this request for resolution. In the case of a subrequest, the path sent to the subrequest.

In the case of a new request that is called with a pre-existing component object, such as in a custom application interfacing to the Myghty interpreter, the request_path defaults to None, but can also be set programmatically via the request_path configuration argument.

root_request
Refers to the ultimate originating request in a string of subrequests. If this request is not a subrequest, this member references the current request.
root_request_args

Used in subrequests, returns the request arguments sent to the ultimate root request in a chain of subrequests. For a regular request with no parent, this dictionary is synonymous with request_args.

For detailed description of component and request arguments, see Component Arguments - the <%args> tag.

root_request_path

The request path for the original root request, in a chain of subrequests.

back to section top

View: Paged  |  One Page

Myghty has some miscellaneous <%xxxx> blocks, whose contents are less than pure Python. The most important is the <%flags> section, since it controls several important behaviors of a component.

<%flags>

%flags is used to specify special properties of the component, which are significant to the execution of the component in the Myghty environment. Some flags can be inherited from a parent supercomponent, and overridden as well. Current flags are:

  • inherit = "/path/to/template" - used in a file-based component only, this flag indicates that this component should inherit from the given template file. This argument can also be None to indicate that this component should not inherit from anything, even the standard autohandler. This flag only applies to the component file that it appears in, and does not affect any super- or subclass components. See the section Inheritance for details.

  • autoflush = [True|False] - will override the configuration parameter auto_flush for this individual component. This is mostly useful for a particularly large top-level component, or a filter component that requires the full output text in one chunk. When a comopnent has autoflush disabled, it essentially means that a buffer is placed between the component's output and the ultimate output stream. As a result, the delivery of any component within a buffered component is also going to be buffered - this includes when a superclass component calls m.call_next() or for any subcomponent or method call.

    This flag is also inherited from a superclass component, such as the autohandler. See the section The Autoflush Option for information on auto_flush.

  • trim = ["left"|"right"|"both"] - provides automatic left and/or right whitespace trimming for the output of a component. This is the equivalent of a <%filter> section utilizing string.strip() combined with autoflush=False. This allows component source code to be laid out on multiple lines without the whitespace surrounding the component output being presented in the final output. For information on trim, see the section Filtering Whitespace - the Trim Flag.

  • use_cache - Enables caching for the component. See Data Caching for further cache options.

  • encoding = ["utf-8" | "latin-1" | etc ] - Specifies the character encoding of the component's text file (such as utf-8, etc.). This encoding goes directly to the Python "magic comment" at the top of the generated Python component, so any character set is supported by Myghty templates.

  • persistent = [True|False] - overrides the per-interpreter setting of delete_modules to specify that this file-based component should or should not specifically have it's module removed from sys.modules when it has fallen from scope. A file-based component that contains class definitions which may remain active after the component itself has fallen out of use may want to do this.

Flags may be specified via the <%flags> tag, or for subcomponents and methods may be specified as inline attributes within the <%def> or <%method> tags. The <%flags> tag may appear anywhere in a component, or even across multiple %flags sections, and will still take effect before a component is actually executed.

Example: the <%flags> tag:

<%flags>
    inherit = None
    autoflush = True
</%flags>

<%python scope="init">
    ...
</%python>

Example: subcomponent flags as attributes:

<%method getlink trim="both">
    <%init>
    </%init>
    
    <A href="foo.bar">lala</a>
</%method>
back to section top
<%attr>

%attr simply sets some attributes on the component. These attributes are accessed via the attributes member of the component. Below, two attributes are accessed from a component to provide style information. One uses current_component, and the other uses base_component. The difference is the former always returns the very same component that is currently executing, whereas the latter corresponds to the component at the bottom of the inheritance chain:

<%attr>
    bgcolor = "#FF0000"
    fgcolor = "#FA456A"
</%attr>

<style>
    body {
    background-color: <% m.current_component.attributes['bgcolor'] %>;
    text-color: <% m.base_component.attributes['fgcolor'] %>;
    }       
</style>

# ...

In both cases, if the attribute does not exist in the current component or within futher inheriting child components, it will then traverse upwards via parent components to locate the attribute. For more information on parent/child relationships between components, see the section Inheritance.

back to section top
<%text>

%text surrounds a block where Myghty will not parse for control lines, line comments, substitutions, or any other Myghty tag. This allows the placement of free text which is intended to print as is, even if it may contain characters that are normally significant to the Myghty lexer. The %text tag is also essential for writing documentation that illustrates examples of Myghty (or similar) code.

back to section top
<%doc>

%doc is simply a comment string - the content inside of a <%doc> section is discarded upon compilation. Comments can also be stated on a per-line basis using a '#' character as the very first character on a line, as described in Comment Lines.

back to section top

Inheritance allows a file-based component to be "wrapped" by another file-based component. This means the requested page executes as a method call inside of the inheriting page, which executes first. The basic idea of this is to allow a whole set of pages to have standardized behavior applied to them by an "inheriting" component, the application of which can be as simple as a standard header and footer, or something more complicated such as an authentication scheme, a content caching scheme, or a filtering scheme.

Inheritance also establishes a relationship between pages with regards to method calling as well as component attributes.

The Wrapper Chain

A set of pages that all inherit each other is sometimes called the "wrapper chain". The wrapper chain is an actual property of the request, and is determined dynamically for each new request based on what files are present in the filesystem and what inheritance pattern they specify. When a template X inherits from a template Y, and that template in turn inherits from template Z, the wrapper chain is created:

Z -> Y -> X

The request above was called specifying component X as the requested component. X inherits from Y, either via an explicit flag or an autohandler configuration (more on that later), and Y inherits from Z. Therefore a wrapper chain with Z at the beginning and X at the end is created. When the request executes, control is passed to Z first. Z performs its component operations, then programmatically instructs the request to call the next component in the wrapper chain, which is Y. Y does the same thing and calls X, the originally requested component. When X is complete, control passes back to Y, and when Y is complete, control passes back to Z.

The flag used to specify that a component should inherit from another is called "inherit", and is specified in the <%flags> section of the component. The component to inherit from is specified by its component-root-relative URI. When an inherited parent component wants to call its inheriting child, it usually uses the call_next method of the request object. The child is only executed if its inherited parent explicitly does so.

If no "inherit" flag is specified for a page, the page will attempt to inherit from a template in the nearest enclosing directory named "autohandler". Whereas the inherit flag allows a component to explicitly specify its inherited parent, the autohandler mechanism allows the configuration of implicitly inheriting parents. Autohandlers are described in the next section Autohandlers.

back to section top
Example - Basic Wrapping

In this example, the requested page is called "index.myt", and its inherited parent is called "base.myt". base.myt supplies a standard HTML header and footer, and index.myt supplies the content in the middle of the <body> tags.

index.myt, inherits from base.myt
<%flags>inherit='/base.myt'</%flags>


I am index.myt
base.myt, the parent template
<html>
<body>

<h3>example of content wrapping</h3>

# fetch the next component in the wrapper chain
# and call it
% m.call_next()

</body>
</html>
The resulting document would be:
<html>
<body>

<h3>example of content wrapping</h3>

I am index.myt

</body>
</html>

While the call_next method of request is the simplest way to call the next component in the wrapper chain, the method fetch_next exists to pop the next component off the chain but not execute it, as well as fetch_all which pops off and returns the entire list of components in the wrapper chain.

back to section top
The Base Component

In the wrapper chain "Z -> Y -> X" described at the beginning of the section, the component X is known as the request component, and is accessible throughout the life of the request via the request_component member of the request. It also is established as the initial "base component" of the request. The base component is accessible via the base_component request member, and it is defined first as the lead requested component in a wrapper chain. When methods in other template files are called, the base component changes to be the file that the method appears in, throughout the life of that method's execution, and upon method completion returns to its previous value.

The base component is also referred to by the special component keyword 'SELF'. This keyword can be used directly via the fetch_component method, but it is more commonly referenced in method component calls, as detailed in the next section.

back to section top
Method and Attribute Inheritance

Methods, first described in Component Methods, are normally called with the <location>:<methodname> syntax, where <location> is the URI or special keyword identifier of a component, and <methodname> is the name of the method to search for. This syntax enables the component to search not only its local method list for the requested method, it also will search its immediate parent for the method if not found, and that parent will continue the search up the wrapper chain.

It is for this reason that the base component and the SELF keyword is of particular value in fetch_component and method calls, since it indicates the innermost component in the current inheritance chain. An template at the end of a wrapper chain (i.e. template Z in the previous section) can specify the SELF keyword when calling a method, and the method will be located from the innermost template first (i.e. component X), and on up the wrapper chain until found.

Similarly, component attributes are located using an inheritance scheme as well. Attributes are referenced via the attributes member of the component object. The attributes dictionary, while it is a regular dictionary interface, will search for requested values in the parent of the component if not found locally.

back to section top
Method Inheritance Example

Here is an example where the parent component is an autohandler, which because of its name, automatically becomes the inherited parent of the child component, as long as the child component does not explicitly specify otherwise.

Both in the parent component as well as the child component that inherits from it specify a method "title". The autohandler can render the title of the page via the "title" method, where it is guaranteed to exist at least in the autohandler's own version of the method, but can be overridden by the inheriting page. Additionally, the autohandler has an <%attr> section indicating the path to a file location. The child page will look in its own attribute dictionary for this location, where it will ultimately come from the inheriting parent.

autohandler - specifies root title method and attributes
<%attr>
    # path to some files
    fileroot = '/docs/myfiles'
</%attr>

<html>
<head>
    <title>
#   the "title" method is called here from SELF,
#   so the method will be searched in the base component first,
#   then traverse up the inheritance chain until found
    <& SELF:title &>
    </title>
</head>
<body>

# call the next component in the wrapper chain
% m.call_next()

</body>
</html>

# default "title" method implementation
<%method title>
Welcome to My Site
</%method>
pressrelease.myt - overrides title method
<%python scope="init">
    # locate the file root via a parent attribute
    pr = get_press_releases(fileroot = self.attributes['fileroot'])
</%python>

# specify a title method to override that of the parent's
<%method title>
My Site: Press Releases
</%method>

<h2>Press Releases</h2>

% for release in pr:

#    ... print data ...

%
back to section top

autohandler

an autohandler is an optional file, by default named autohandler, that will serve as the base inheriting template for all requests within a directory and its subdirectories. Inheritance is discussed in more detail in the section Inheritance. The basic idea is that the autohandler template executes first; it runs some code and/or outputs some HTML, and then calls a special method to deliver the content of the requested template. When the embedded template has completed its execution, the autohandler can then output some more HTML at the bottom and/or execute cleanup code:

<html>
<head>autohandler demo</head>
<body>
% m.call_next()
</body>
</html>

Autohandlers are searched for first in the current directory, then upwards in the enclosing directories, until the component root is reached. If more than one autohandler is found, they will all be executed within each other, with the most directory-specific autohandler executed at the innermost level. Any page or autohandler can deny the execution of an enclosing autohandler by setting the "inherit" flag to be None.

Autohandlers are ideal for standardized HTML enclosing schemes as above. There are also many more creative uses. An autohandler that automatically protects a whole directory based on a custom login scheme would look something like this:

# autohandler

<%python scope="init">
    # look in the apache request for some kind of 
    # login token
    user = login_manager.check_login(r)
    if not user:
        # redirect out of here, the rest of the content
        # in this page will not be sent
        m.send_redirect("/login.myt", hard=True)

    else:               
        # otherwise, they are ok, deliver content
        m.call_next()
</%python>
back to section top
dhandler

A dhandler, otherwise known as a directory handler, is a file, by default named dhandler, that serves requests for which the requested Myghty template can not be located, or for a request that names a directory by itself without a file. dhandlers are searched for similarly to autohandlers, i.e. in the innermost enclosing directory first, then upwards towards the component root. However, only one dhandler is executed at a time. The code within the dhandler has access to the request member dhandler_path which refers to the path information for the requested (but unlocated) component, relative to the path of the current dhandler. It also can call decline which will abort the current dhandler and search up the directory tree for the next enclosing dhandler.

Dhandlers are good for special path-based requests used in places such as news sites who want to have clean URLs that have no query strings, for writing components that process the contents of a directory dynamically, such as image or filesystem browsers, or custom per-directory "file not found" handlers.

Example: content management system. A lot of news sites have fancy URLs with dates and article keywords (sometimes called slugs) specified within them. These URLs sometimes are resolved into database parameters, and the actual content is retrieved from some source that is not the same as a local file with that path scheme. This example extracts tokens from a URI and uses them as parameters to retrieve content.

# Hypothetical URL:
# http://foonews.com/news/2004/10/23/aapl.myt

# dhandler, inside of the web directory /news/

<%python scope="init">
    import re
    
    # get path
    path = m.dhandler_path
    
    # get arguments from the path
    match = re.match(r"(\d+)\/(\d+)\/(\d+)\/(\w+)\.myt", path)
    
    if match:
        (year, month, day, slug) = match.groups()
        
        # look up a news article in a 
        # hypothetical content-management database 
        # based on this parameters from the path
        article = db.lookup(year, month, day, slug)
    else:
        article = None
        
    if article is None:
        # improper URL, or no article found
        m.send_redirect("article_not_found.myt", hard=False)
</%python>

<!-- display the article -->

<h3><% article.get_headline() %></h3>

<% article.get_text() %>

The tricky part about a dhandler in conjunction with Apache is that the URL used to access the dhandler has to be identified by apache as a Myghty request. For a basic setup that associates *.myt with Myghty files, the URL used to access the dhandler would have to end with the string ".myt". To call dhandlers more flexibly, you would have to insure that Apache is configured to send all requests for a particular directory to Myghty for processing, using a directive like DirectoryMatch or FilesMatch.

back to section top
Using Module Components for autohandler/dhandler

First described in Module Components, these components can also be used as autohandlers or dhandlers. Simply configure the Myghty environment to recognize paths with "autohandler" and/or "dhandler" as module component paths:

module_components = [
    # configure the root autohandler to resolve to Autohandler class
    {r'/autohandler$' : 'modcomp:Autohandler'},
    
    # configure all dhandlers to resolve to Dhandler class
    {r'.*/dhandler$' : 'modcomp:Dhandler'},
]

In particular, code-intensive autohandlers and dhandlers such as content delivery mechanisms, translation components, or authentication controllers would be suitable as module components. Also see the section Advanced Resolver Configuration for more information on the resolution of autohandlers and dhandlers.

back to section top

This section describes some options that can be applied to Myghty components which affect how the request object deals with their output. The request object supports the capturing of component output in a buffer which is flushed upon completion to provide simple and flexible component output behavior, or sending the output directly to the underlying output stream to provide faster perceived response time. This option is known as autoflush. Post-processing functions can be attached to the final output of a component at the top-level or callable component level, allowing user-defined text operations on the output, known as filtering. Autoflushing and filtering have some dependencies on each other, so they are described together.

As a convenient alternative to filtering, common text-escaping functions applicable to a web application environment, plus support for user-defined escape functions, are provided under the functionality of escapes, described at the end of the section.

The Autoflush Option

The autoflush option controls whether the output of a component is sent to the underlying output stream as it is produced, or if it is first captured in a buffer which is then sent in one chunk at the end of the request's lifecycle. This is significant in a web context, as it affects "perceived performance", which means the response time of an unbuffered page is nearly immediate, even though the time it takes to finish might be the same as that of a buffered page.

While the autoflush option can improve perceived performance, there are also increased complexities with an autoflushed, i.e. unbuffered page. HTTP headers, including hard redirects, must be sent before any content is written, else the response will have already begun and any new headers will simply be displayed with the page's content. A soft redirect, not being dependent on HTTP headers, will still function, but it's output also may be corrupted via any preceding output. Error messages also will appear inline with already existing content rather than on a page of their own.

The option can be set for an entire application, for a set of files or directories via autohandlers/inherited superpages, for an individual page, or even an individual method or subcomponent within a page. Within all of those scopes, the flag can be set at a more specific level and will override the more general level.

With no configuration, the parameter defaults to False, meaning that component output is captured in a buffer, which is flushed at the end of the request or subcomponent's execution. This produces the simplest behavior and is fine for most applications.

But, here you are and you want to turn autoflush on. To set it across an entire application, specify autoflush=True to the Interpreter or HTTPHandler being used. Or to configure via http.conf with mod_python:

PythonOption MyghtyAutoflush True

When autoflush is true for an entire application, no buffer is placed between the output of a component and the underlying request output stream. The flag can be overridden back to False within directories and pages via the use of the autoflush flag within the %flags section of the page. To set the value of autoflush for a particular directory, place an autohandler file at the base of the directory as such:

<%flags>autoflush=False</%flags>
% m.call_next()

The Myghty request will run the autohandler which then calls the inherited page via the m.call_next() call. The autoflush flag indicates that buffering should be enabled for the execution of this page, overriding the per-application setting of True.

The ultimate autoflush flag that is used for a page is the innermost occuring flag within the templates that comprise the wrapper chain. If no autoflush flag is present, the next enclosing template is used, and if no template contains an autoflush flag, the application setting is used. Even though an autohandler executes before the page that it encloses, the Myghty request figures out what the autoflush behavior should be before executing any components so that it takes the proper effect.

So any page can control its own autoflush behavior as follows:

<%flags>autoflush=False</%flags>
<html>
    <head>
    ...
</html>
Setting Autoflush in Subcomponents

Subcomponent or methods can determine their autoflush behavior as follows:

<%def mycomp>
<%flags>autoflush=False</%flags>
    ... stuff ...
</%def>

There is one limitation to the autoflush flag when used in a subcomponent. If autoflush is set to True on a subcomponent, within a request that has autoflush set to False, the component will send its unfiltered data directly to the output stream of its parent; however since the overall request is not autoflushing and is instead capturing its content in a buffer of its own, the content is still stored in a buffer, which does not get sent to the client until the request is complete. Note that this limitation does not exist the other way around; if an overall request is autoflushing, and a subcomponent sets autoflush to False, that subcomponent's output will be buffered, until the subcomponent completes its execution. This is significant for a subcomponent whos output is being processed by a <%filter> section. More on this later.

back to section top
Non-Buffered with Autohandlers

What happens when a page in an autoflush=True environment interacts with one or more autohandlers or inherited superpages? The superpage will execute first, output whatever content it has before it calls the subpage, and then will call m.call_next() to pass control to the subpage. If the subpage then wants to play with HTTP headers and/or perform redirects, it's out of luck:

autohandler - autoflush enabled
<%flags>autoflush=True</%flags>
<html>
    <head></head>
    <body>
% m.call_next()
    </body>
</html>
page.myt - wants to send a redirect
<%python scope="init">
    m.send_redirect("page2.myt", hard=True)
</%python>

The above example will fail! Since the autohandler executes and prints the top HTML tags to the underlying output stream, by the time page.myt tries to send its redirect, the HTTP headers have already been written and you'll basically get a broken HTML page. What to do? Either page.myt needs to specify that it is not an autoflushing page, or it can detach itself from its inherited parent.

Solution One - Turn Autoflush On:

page.myt
<%flags>autoflush=False</%flags>
<%python scope="init">
    m.send_redirect("page2.myt", hard=True)
</%python>

This is the most general-purpose method, which just disables autoflush for just that one page.

Solution Two - Inherit from None

page.myt
<%flags>inherit=None</%flags>
<%python scope="init">
    m.send_redirect("page2.myt", hard=True)
</%python>

This method is appropriate for a page that never needs to output any content, i.e. it always will be performing a redirect. The autohandler here is not inherited, so never even gets called. This saves you the processing time of the autohandler setting up buffers and producing content. Of course, if there are autohandlers that are performing operations that this subpage depends upon, then you must be sure to inherit from those pages, possibly through the use of "alternate" autohandlers that inherit only from the desired pages.

back to section top
Filtering

Filtering means that the output stream of a component is sent through a text processing function which modifies the content before it is passed on to the ultimate output stream. Typical usages of text filtering are modifying entity references, trimming whitespace, converting plain-text to HTML, and lots of other things. For the general purpose per-component filter, Myghty supplies the <%filter> tag.

The <%filter> Tag

%filter describes a filtering function that is applied to the final output of a component. This is more common on subcomponents or methods but works within the scope of any top-level component as well. The Python code within the %filter section provides the body of the to be used; the heading of the function is generated within the compiled component and not normally seen. The filter function is provided with one argument f which contains the content to be filtered; the function processes content and returns the new value.

Example:

<%filter>
import re
return re.sub(r"turkey", "penguin", f)
</%filter>

dang those flyin turkeys !

will produce:

dang those flyin penguins !
back to section top
Escaping Content in a Filter Section

Myghty has some built in escaping functions, described in the next section Escaping Content. While these functions are easy enough to use within substitutions or any other Python code, you can of course use them within a filter section as well.

This is a component that HTML escapes its output, i.e. replaces the special characters &, <, and > with entity reference encoding:

<%def bodytext>
    <%filter>
        return m.apply_escapes(f, 'h')
    </%filter>

    # ... component output
</%def>
back to section top
Filtering Behavior with Autoflush Enabled

The usual case when a %filter section is used is that all m.write() statements, both explicit and implicit, send their content to a buffer. Upon completion of the component's execution, the buffer's content is passed through the function defined in the %filter section. However when autoflush is enabled, the extra buffer is not used and the filtering function is attached directly to each call to m.write(). For regular blocks of HTML, the entire block is sent inside of one big write() statement, but each python substitution or other code call splits it up, resulting in another call to write().

Since a non-autoflushing component is more predictable for filtering purposes than an autoflushing component, it is often useful to have autoflush disabled for a component that uses a %filter section. As stated in the autoflush section, autoflushing behavior can be changed per component, per page or for the whole application, and is the default value as well. There is also another configuration option can be overridden for all filter components by the setting "dont_auto_flush_filters" - see the section Index of Configuration Parameters for more information.

back to section top
Filtering Whitespace - the Trim Flag

A common need for components is to trim off the whitespace at the beginning and/or the end of a component output. It is convenient to define subcomponents and methods on multiple lines, but this inherently includes newlines in the output of that component, since Myghty sees the blank lines in the source. But lots of times the ultimate output of a component needs to not have any surrounding whitespace, such as a component that outputs a hyperlink. While a regular %filter section can be used for this, Myghty provides the trim flag, as so:

for more information, click <&makelink, a="here", p=4.3, xg="foo" &>.

<%def makelink trim="both">
<%args>
    p
    xg
    a
</%args>

<%doc>note this component has a lot of whitespace in it</%doc>
<A href="http://foo.myt?xg=<% xg %>&p=<% p | u %>"><% a %></a>

</%def>

Output:

for more information, click <A href="http://foo.myt?xg=foo&p=4.3">here</a>.

trim supports the three options left, right, or both, trimming whitespace on the left, right and both sides of component output, respectively.

back to section top
Escaping Content

Escaping usually refers to a kind of filtering that converts the characters in a string into encoded values that can be safely passed through other character-parsing systems without them interfering.

Myghty provides built in support for HTML and URL escaping (also called URL encoding), and has plans for entity-reference escaping. User-defined escape functions can be added to an application as well.

Escaping Substitutions

Substitutions, first introduced in Substitutions, can include escape flags, specified by the following notation:

 
    <% "i am an argument" | u %>

The above example will URL encode the embedded string. The two escape flags included with Myghty are "u" for url encoding, and "h" for HTML encoding. Entity reference encoding is in the works.

Multiple escape flags are separated by a comma:

 
    <% "multiple escapes" | h, u %>

Which will HTML and URL escape the given string.

back to section top
Programmatic Escaping

The HTML and URL-encoded escaping functions described above are easy enough to use programmatically as well. The request object provides the escaping functions via the apply_escapes() method for this purpose. This method uses the same flags as an escaped substitution, the defaults being "h" for HTML escaping and "u" for URL encoding.

In this example, a component receives the argument "text" and displays it in a textarea, where HTML escaping is required:

<%args>
    text
</%args>
<%python>
    # HTML escape the given text
    text = m.apply_escapes(text, 'h')
</%python>

<textarea><% text %></textarea>

The first argument to apply_escapes() is the text to be escaped, and the second is a list of escape flags. Since strings are lists in Python, multiple flags can be specified either in a single string as in "hu" or as a regular list such as ['h', 'u'].

back to section top
Custom Escape Flags

You can add your own escape flags to your application via the escapes configuration parameter. escapes is in the form of a dictionary, with the key names being the single-character escaping token and the values being function pointers to escaping functions.

In this example, an escape flag 'p' is added which provides the ability to convert the word "turkey" into "penguin":

escapes = {
    'p':re.sub('turkey', 'penguin', f)
}
back to section top
Default Escape Flags

Default escaping can be configured via the configuration parameter default_escape_flags (PythonOption MyghtyDefaultEscapeFlags). The format of this parameter is a list of escape flag characters. This applies the given flags to all substitutions in an application.

When default escaping is used, the special flag "n" can be specified in the substitution to disable the default escape flags for that substitution.

back to section top

Myghty now has its own session storage class. This class offers some advantages over the mod python session, including:

  • It is independent of mod_python, so it works with either version of Apache, other web connectors, and in CGI mode
  • The file-based version keeps each user's session in separate DBM files, so no synchronization issues are present between disparate sessions, session files are small, and old sessions can be cleaned up via an external file-deletion process.
  • The session object loads its data in immediately from the persistent store and unlocks, so that a page containing multiple session-enabled requests (i.e., such as a page with IFRAMEs or image delivery servlets) can allow access to all of its sub-elements with a minimum of waiting between the concurrent requests.
  • The package can also run directly with the mod_python request, independently of Myghty.
Basic Usage

The session is retrieved from the request object via the get_session() method, operated upon like a dictionary, and then can have its save() method called to write its data to persistent storage:

<%python scope="init">
    # get the session
    session = m.get_session()
    
    # add data
    session['key1'] = 'foo'
    
    # get data
    if session.has_key('user'):
        user = session['user']
    else:
        user = User()
        session['user'] = user
        
    # save new information
    session.save()
</%python>

The session handles generation of session IDs automatically as well as storing and retrieving them from cookies. Options exist to pass in custom session IDs, to not use cookies, to use "signed" session IDs, and to change the cookie-based session key (defaulting to myghty_session_id). It loads its data in fully when instantiated and then unlocks, so no programmatic locking or unlocking is necessary (but lock methods are available if you want the session to stay locked throughout a request).

back to section top
Session Options

Session options are specified as Myghty configuration parameters in the form session_XXXX, to identify them as options being sent to the Session object. When calling the m.get_session() method, parameters may be specified with or without the "session_" prefix; they are stripped off.

The get_session method can take any of the configuration parameters that are identified below as used directly by the Session object or by the underlying Namespace objects.

session_cookie_expires (boolean, datetime, timedelta)
default: True
used by: Session

The expiration time to use on the session cookie. Defaults to "True" which means, dont specify any expiration time (the cookie will expire when the browser is closed). A value of "False" means, never expire (specifies the maximum date that can be stored in a datetime object and uses that). The value can also be a datetime.timedelta() object which will be added to the current date and time, or a datetime.datetime() object.

session_data_dir (string)
default: None
used by: Session

The data directory where sessions will be stored. If this argument is not present, the regular data_dir parameter is used, with the path "./sessions" appended to it.

session_dbmmodule (dbm module)
default: anydbm
used by: DBMNamespace

When dbm is used as the session type, this parameter points to a module to use for DBM support, such as gdbm, dbhash, etc.

session_id (String)
default: None
used by: Session

Session id for this session. When using sessions with cookies, this parameter is not needed as the session automatically creates, writes and retrieves the value from the request. When using a URL-based method for the session, the id should be retreived from the id data member when the session is first created, and then used in writing new URLs.

session_invalidate_corrupt (boolean)
default: False
used by: Session

If there are any exceptions upon loading the session, the entire session will be invalidated and started clean. When object interfaces change in an application, old versions of those objects might still be present in existing session files, and exceptions will be raised when the session object tries to deserialize them into memory. Setting this to True allows those sessions to be cleaned out and started from scratch again.

This parameter should be used carefully since it can conceal real application errors in certain situations.

session_key (string)
default: myghty_session_id
used by: Session

The key that will be used as a cookie key to identify sessions. Changing this could allow several different applications to have different sessions underneath the same hostname.

session_log_file (file)
default: None
used by: Session

A file or buffer object where debugging information will be sent.

session_namespace_class (class)
default: None
used by: Session

A class that will be used to create the underlying NamespaceManager used by this Session, when a custom NamespaceManager implementation is being used. By default, the implementation is determined among the built-in NamespaceManagers by the session_type parameter.

session_type (string)
default: dbm
used by: Session

Type of storage used for the session, current types are "dbm" (also called "file"), and "memory". The storage uses the Container API that is also used by the cache system.

When using dbm files, each user's session is stored in its own dbm file, via the class myghty.container.DBMNamespaceManager class. To get the dbm filename used by a session, use session.namespace.file.path, or to retrieve a list of the actual files created by the particular dbm instance, use session.namespace.file.get_filenames().

session_secret (string)
default: None
used by: Session

Secret key to enable encrypted session ids. When non-None, the session ids are generated with an MD5-signature created against this value.

session_timeout (integer)
default: None
used by: Session

Time in seconds before the session times out. A timeout occurs when the session has not been loaded for more than timeout seconds.

session_use_cookies (boolean)
default: True
used by: Session

Whether or not to store and retrieve the session ID from the cookies present in the request. If False, the session ID must be present in the argument list to retrieve an existing session.

use_modpython_session (boolean)
default: None
used by: ApacheHandler

Instructs the get_session() method, or the global variable s if configured, to return an instance of the mod_python session object instead of the Myghty session object. If this is configured, only the session_timeout parameter is supported.

use_session (boolean)
default: None
used by: ApacheHandler,CGIHandler

Establishes the global variable s as a reference to the Session object. This means all requests will automatically have the session initialized and loaded. If an application has a lot of templates that dont have use for the session, this could add unnecessary overhead.

back to section top
Session Methods
delete()
deletes the persistent storage for this session, but the session remains valid. When save() is called, the new data will be written.
invalidate()
invalidates this session, creates a new session id, returns to the is_new state
load()
Loads the data from this session from persistent storage and updates the last modified time of the session. This method is called automatically upon session object construction and does not need to be called explicitly. If the session's persistant storage does not exist, it will be created. If the session has not been accessed since the timeout period, the invalidate() method will be called, and the session will return to the is_new state, as well as was_invalidated.
lock()
Locks this session against other accesses. This method is called automatically by the load() and save() methods. However, this method can be called to keep the session locked persistently until explicitly unlocked by the unlock() method.
unlock()
Unlocks this session against other accesses. This method is called automatically by the load() and save() methods. However, this method can be called to unlock a persistent lock set up by the lock() method.
save()
Saves the data for this session to persistent storage. This should be called whenever you know the session has been modified.
back to section top
Session Members
accessed
The last time this session was accessed.
created
The time this session was created.
id

The id for this session. When using cookies, this is retrieved and set within the cookie referenced by the key string. The id is automatically created when a new session is instantiated.

When regular cookies are used (the default), this value is the same value sent in the session cookie to the client. When signed cookies are enabled via the session_secret parameter, this id is MD5 signed against the secret to form the client cookie value.

is_new
True if this session was newly created. This can be because no previous session existed, or the session existed but was invalidated, usually due to a timeout.
key
The key used in cookies to set this session's id.
secret
timeout
The timeout span of this session.
was_invalidated
True if this session was invalidated upon opening, usually due to a timeout. is_new will always be True as well.
back to section top
Using the Session Object Standalone

The session object is actually functionally independent of the rest of Myghty, and is compatible with the mod python request object directly, as well as the request emulator used by CGIHandler. To instantiate it, simply use its constructor as follows:

from mod_python import apache
from myghty.session import Session

def handle(req):
    session = Session(req, data_dir='/path/to/session_dir', key='user_session_id')

The full constructor signature for the Session object is as follows:

Session(request, id = None, use_cookies = True, 
    invalidate_corrupt = False,
    type = None, data_dir = None, 
    key = 'myghty_session_id', timeout = None, 
    secret = None, log_file = None, **params)

Note that the parameters are the same as the configuration arguments with the prefix "session_" removed.

back to section top

Myghty provides the ability to cache any kind of data, including component output, component return values, and user-defined data structures, for fast re-retrieval. All components, whether file-based or subcomponent, are provided with their own cache namespace, which in turn stores any number of key/value pairs. Included with Myghty are implementations using files, dbm files, direct in-memory dictionaries, and memcached. User-defined implementations are also supported and can be specified at runtime. The particular implementation used can optionally be specified on a per-key basis, so that any single namespace can store individual values across any number of implementations at the same time.

Caching is generally used when there are process-intensive and/or slow operations that must be performed to produce output, and those operations also have little or no dependencies on external arguments, i.e. their value is not likely to change in response to request variables. Examples of things that are good for caching include weather information, stock data, sports scores, news headlines, or anything other kind of data that can be expensive to retrieve and does not need to be updated with real-time frequency.

The front-end to the mechanism is provided by the myghty.cache package, and can be configured and used through global configuration parameters, per-component flags, and a programmatic interface.

Caching a Component's Output

The simplest form of caching is the caching of a component's return value and output content via flags. An example using a subcomponent (subcomponents are explained in How to Define a Subcomponent):

<%def heavytext>
    <%flags>
        use_cache = True
        cache_type = 'dbm'
        cache_expiretime = 30
    </%flags>
    <%init>
        data = big_long_query()
    </%init>
    Your big query returned: <% data.get_info() %>
</%def>

In this example, the component's output text and its return value (if any) will be stored the first time it is called. Any calls to this component within the next 30 seconds will automatically return the cached value, and the %init section and body will not be executed. At the moment 30 seconds have elapsed, the first call to occur within this new period will result in the component executing in full again and recreating its output text and return value. Subsequent calls that occur during this second execution will continue to return the prior value until the new value is complete. Once the new value is complete, it is stored in the cache and the expiration counter begins again, for the next 30 seconds.

Note that the parameter cache_type is set to 'dbm', which indicates that dbm-based caching is used. This is the default setting when a data_dir parameter is configured with the Myghty application.

For components that contain a %filter section, the result of filtering is stored in the cache as well. This allows the cache to be useful in limiting the execution of a process-intensive or time-consuming filtering function.

When a component is recompiled, its cache contents are automatically expired, so that the cache can be refreshed with the value returned by the newly modified component. This means it is safe to set a cache setting with no expire time at all for a component whose output never changes, and in fact such a component only executes once per compilation and never at all again, for the life of the cache.

back to section top
Programmatic Interface

The traditional caching interface looks like this:

<%init>
    def create_data():
        return get_some_data()

    cache = m.get_cache()
    data = cache.get_value('mydata', type='memory', 
        createfunc=create_data, expiretime=60)
</%init>
Where "mydata" is a key that the data will be keyed upon, the type of cache is in memory only, the create_data() function is used to create the initial value of 'mydata' as well as regenerating it when it is expired, and the expire time is 60 seconds.

The creation function argument is optional, and the cache can be populated externally as well:

<%init>

    cache = m.get_cache()
    if not cache.has_key('mydata'):
        cache.set_value('mydata', get_some_data(), expiretime=60)

    data = cache.get_value('mydata')

</%init>
This is a more familiar way to check a dictionary for a value and set it. However, the previous "creation function" methodology has a significant advantage, in that it allows the cache mechanism to execute the function in the context of a global "busy" lock, which prevents other processes and threads from executing the same function at the same time, and instead forces them to retrieve the previous expired value until the new value is completed. If no previous value exists, they all wait for the single process/thread to create the new value. For a creation function that is slow or uses a lot of resources, this limits those resources to only one concurrent usage at a time, and once a cache value exists, only one request will experience any slowness upon recreation.

To programmatically cache the output text of a component, use the m.cache_self() method on request, which is a reentrant component-calling method:

<%init>
    if m.cache_self(key="mykey"):
        return
</%init>

# rest of component
For an uncached component, the cache_self method will execute the current component a second time. Upon the second execution, when the cache_self line is encountered the second time, it returns false and allows the component to complete its execution. The return value and output is cached, after being sent through any output filters present. Then returning up to the initial cache_self call, it returns true and delivers the components output and optionally its return value. Filtering is also disabled in the component as it should have already occurred within the original caching step. The process for an already cached component is that it simply returns true and delivers the component output.

To get the component's return value via this method:

<%init>
    ret = Value()
    if m.cache_self(key="mykey", retval = ret):
        return ret()

    # rest of component
    return 3 + 5
</%init>
A value object is used here to pass a return value via a method parameter. The return value is simply the cached return value of the component.

Generally, the %flags method of caching a component's output and return value is a lot easier than the programmatic interface. The main advantage of the programmatic interface is if the actual key is to be programmatically decided based on component arguments it can be figured out at runtime and sent as the "key" argument. This also applies if any of the other properties of the cache are to be determined at run-time rather than compile time.

back to section top
More on Caching

The cached information may be shared within the scope of one process or across multiple processes. Synchronization mechanisms are used to insure that the regeneration is only called by one thread of one process at a time, returning the expired value to other processes and threads while the regeneration is occuring. This maximizes performance even for a very slow data-regeneration mechanism. In the case of a non-memory-based cache, an external process can also access the same cache.

Note that Myghty only includes thread-scoped synchronization for the Windows platform (contributors feel free to contribute a Win32 file locking scheme). The "file" and "dbm" cache methodologies therefore may not be entirely synchronized across multiple processes on Windows. This only occurs if multiple servers are running against the same cache since Windows doesnt have any forking capability and therefore an Apache server or similar is only using threads.

Caching has an assortment of container methodolgies, such as MemoryContainer and DBMContainer, and provides a base Container class that can be subclassed to add new methodologies. A single component's cache can have containers of any number of different types and configurations.

Caching of the URI resolution step can also be done to improve performance. See use_static_source for more information on using the URICache.

back to section top
Cache Options

Caching options are all specified as Myghty configuration parameters in the form cache_XXXX, to identify them as options being sent to the Cache object. When calling the m.get_cache() method, parameters may be specified with or without the cache_ prefix; they are stripped off. While some cache options apply to the Cache object itself, others apply to specific forms of the Container class, the two current classes being MemoryContainer and DBMContainer.

The full list of current options is as follows:

cache_container_class (class object)
default: None
used by: Cache

This is a class object which is expected to be a subclass of myghty.container.Container, which will be used to provide containment services. This option need only be used in the case of a user-defined container class that is not built into the static list of options in the Cache class. To use one of the built in container classes, use cache_type instead.

cache_data_dir (string)
default: same as Interpreter data_dir
used by: DBMContainer

This is the data directory to be used by the DBMContainer (file-based cache) to store its DBM files as well as its lockfiles. It is set by default to be the same as the data_dir parameter for the Myghty application. As it creates its own subdirectories for its files (as does Interpreter), the files are kept separate from Myghty compiled pages.

cache_dbm_dir (string)
default: cache_data_dir + '/container_dbm'
used by: DBMContainer

This value indicates the directory in which to create the dbm files used by DBMContainer; if not present, defaults to a subdirectory beneath cache_data_dir.

cache_dbmmodule (module)
default: anydbm
used by: DBMContainer

DBMContainer uses dbm files via the Python built-in anydbm module, which searches for a platform specific dbm module to use. Any Python dbm module can be specified here in place of it. To specify this option under mod_python as an Apache configuration directive, use this format:

PythonOption MyghtyCacheDbmmodule "__import__('gdbm')"

cache_debug_file (file object)
default: None
used by: Cache

If pointing to a Python file object, container operations performed by the caching system will be logged, allowing the viewing of how often data is being refreshed as well as how many concurrent threads and processes are hitting various containers. When running with ApacheHandler or CGIHandler, this parameter can be set to the standard Apache log via the parameter log_cache_operations.

cache_lock_dir (string)
default: cache_data_dir + '/container_dbm_lock'
used by: DBMContainer

This value indicates the directory in which to create the lock files used by DBMContainer; if not present, defaults to a subdirectory beneath cache_data_dir.

cache_url (string)
default: None
used by: MemcachedNamespaceManager

The memcached URL to connect to for memcached usage, e.g. "localhost:11211".

cache_type (module)
default: file or memory
used by: Cache

This is the type of container being used. Current options are file, dbm, memory, and ext:memcached.

This option defaults to dbm if a data_dir option is present in the current application, else uses memory.

log_cache_operations (boolean)
default: False
used by: ApacheHandler or CGIHandler

Sets the Cache cache_debug_file argument to point to the Apache error log or standard error output. See cache_debug_file.

back to section top
Cache Types
  • 'dbm' - uses the anydbm module combined with cPickle to store data.
  • 'file' - uses the cPickle module combined with regular file access to store data. This method may be faster than 'dbm' if the entire contents of the file are retrieved often, whereas dbm is faster for pulling a single key out of a larger set of data.
  • 'memory' - uses a regular Python dictionary. Speed is the fastest, but the cache is not useable across processes nor is it persistent across server restarts. It also has the highest utilization of RAM.
  • 'ext:memcached' - uses memcached for caching and requires the Python memcached module to be installed.
back to section top

Introduction

With version 0.97 comes a new and highly configurable URI resolution engine. This engine is responsible for converting the URI address of a component into a ComponentSource object, from which an actual Component is created. Originally, components were only retrieved from one or more file-based component roots, configured by component_root. Special logic existed for locating dhandler and autohandler components as well, and the resolution of URIs could be cached (i.e. use_static_source). Myghty added the ability to load module-based components based on regular expressions (module_components), and also to translate incoming URIs via path_translate.

With the new resolution engine, it is now possible to:

  • Change the order of all resolution steps, or remove unneeded resolution steps. The steps that can be controlled are component root lookup, module component lookup, path translation, dhandler resolution, autohandler resolution (also called 'upwards resolution'), and URI caching (static source).
  • Create conditional resolution rules or rule chains. Built-in conditional rules allow matching the URI with a regular expression, or matching the "resolution context" of the incoming request. Built-in resolution contexts include request, subrequest, component, and inherit. User-defined resolution contexts can be created as well and specified in component lookup calls and also as the default context to be used in a subrequest.
  • Control the point at which the caching of URIs occurs, by placing a special rule above only those rules whose results should be reused, or to enable caching of just a single rule.
  • Inspect the full series of steps involved in a URI resolution via logging, regardless of whether or not it succeeded. This is crucial for developing custom rule-chains.
  • Add special behavior to file-based resolution, so that the conversion from a URI to a filesystem path can be more than just a straight path concatenation of the component root and URI.
  • Retrieve an re.Match object that is created when a URI matches the regular expression used by a module component. Capturing parenthesis can also be added to the regular expressions, whose results will also be available in the resulting Match object.
  • Create custom resolution rules using small and simple classes that can easily coexist with the built-in rules.
back to section top
Basic Example
Lets start with some component code that wants to locate another component:
comp = m.fetch_component("/training/index.myt")

In the above line, the code is using the request to fetch the component referenced by the uri "/training/index.myt". The process of looking up a component corresponding to a uri is called resolution.

When the resolver attempts to locate the uri, it executes a series of resolver rules specified within the configuration option resolver_strategy, which is represented as a list. This list contains instances of one or more myghty.resolver.ResolverRule subclasses, each of which represents a single rule along with configurational arguments for that rule. A list of ResolverRule objects to be executed in order is also referred to as a chain. A resolver strategy for the above search might look like:

from myghty.resolver import *

resolver_strategy = [
    ResolveFile(
        {'htdocs' : '/web/htdocs'}
    )
]

Above, the resolver strategy has only one rule, an instance of ResolveFile. This rule searches through one or more component roots given as constructor arguments and concatenates the incoming URI to each root, until one of them matches an actual file located on the filesystem. When a match is found, the rule cancels any further rule processing, and returns a result object from which the component can be loaded. If no match is found, the rule passes control onto the next rule, or if no further rules exist, the resolver determines that the component cannot be located. Since in the above example we have only one rule, if the file /web/htdocs/training/index.myt doesn't exist, the fetch_component call will raise a ComponentNotFound exception.

If no arguments are given to the constructor, ResolveFile instead uses the value of component_root as its list of roots. From this one can see that when a Myghty installation specifies the component_root configuration parameter, this rule is implicitly activated behind the scenes.

The rule classes themselves require the symbols from the resolver package to be imported, as in from myghty.resolver import *. These symbols are also available in mod_python configuration within PythonOption directives, as of version 0.97a or the current CVS version.

A few more rules can be added above, which allow more options for how this uri can be resolved:

from myghty.resolver import *

resolver_strategy = [
    ResolveModule(
        {r'/user/.*' : 'myapp.UserManager'},
        {r'/admin/.*' : 'myapp.Administration'},
    ),
    
    PathTranslate(
        (r'/training/' , r'/newmembers/'),
        (r'/$', '/index.myt'),
    ),
    
    
    ResolveFile(
        {'htdocs' : '/web/htdocs'}
    )
]

Two more rules have been added. ResolveModule will be the first to attempt resolving the uri, and it will attempt to match the uri against a series of regular expressions that each refer to a module component. Module components are described in the section Module Components. As our uri does not match either regular expression, the ResolveModule rule will give up, and pass control onto the next rule in the chain. The ResolveModule rule, if instantiated with no arguments, will instead use the value of module_components as its list. As with ResolveFile, when a Myghty installation specifies the module_components configuration parameter, this rule is also implicitly activated.

Next is the PathTranslate rule. This rule is a uri processing rule which itself will never return a result, but rather changes the incoming uri and then passes the modified uri onto the remaining rules in the chain. PathTranslate executes a series of regular expression search-and-replace operations on the uri before passing it on, which are specified as a list of two-element tuples. PathTranslate, when given no arguments, will use the value of path_translate as its list.

We have specified a path translation rule that all uris starting with "/training/" should be changed to reference the same file within "/newmembers/" instead. Secondly, we specify that any uri which is a directory request, i.e. uris that end with a slash, should have the default file "index.myt" appended to it. Our uri does match the first regular expression, so upon matching it will be converted into /newmembers/index.myt. We then arrive back at our ResolveFile rule, where either the existing file /web/htdocs/newmembers/index.myt will be used as the source of the resolved component, or if no such file exists a ComponentNotFound exception will be raised.

Behind the scenes, the myghty.resolver.Resolver object is invoked to resolve the incoming uri, and when located it returns an instance of myghty.resolver.Resolution, which in turn contains an instance of myghty.csource.ComponentSource. Whereas the Resolution instance describes just one of potentially many resolution paths the same component, the ComponentSource instance is the only object that describes location information for the component exactly.

back to section top
The Real Set of Rules

The previous section illustrated the three basic ResolverRules that are behind the configuration parameters component_root, module_components, and path_translate. In fact, these three rules also have an ordering that is used by default, and there are also several more rules installed by default which accomplish some other important tasks. The default strategy is:

from myghty.resolver import *

resolver_strategy = [
    PathTranslate(),
    ResolveDhandler(),
    URICache(),
    ResolveUpwards(),
    ResolveModule(),
    ResolvePathModule(),
    ResolveFile()
]

Our familiar rules PathTranslate, ResolveModule and ResolveFile are all present, and as they are specified with no constructor arguments they will use the values of their correspoinding configuration parameters. Also one can see that path translation happens at the very front of everything before other resolution starts. ResolvePathModule is also a new rule which corresponds to the configuration parameter module_root.

Three new rules are introduced in this chain, ResolveDhandler, URICache, and ResolveUpwards. All have two things in common which are different from the first three rules: they all are conditional rules that do not necessarily get activated, and also they are rollup rules which cannot resolve a component on their own, but rather rely upon the full list of rules that occur directly below them in order to retrieve results.

The ResolveDhandler rule is activated when the request looks for a top level component, with the option to serve a not-found component or directory request as a dhandler. After not matching any resolution rules or file lookups for the given URI, it looks instead for /path/dhandler, and searches "upwards" through successive parent paths to resolve a dhandler. The rules below are executed repeatedly with each new URI until a match is made, or no more path tokens exist. Additionally, any resolved dhandlers that have been declined by the current request are also bypassed.

The ResolveUpwards rule is similar to the dhandler rule, except it is activated when a component searches for its inherited autohandler. This rule also searches upwards through successive parent paths to locate the module or file. In fact this rule can be used for any kind of upwards search but normally is used for autohandler only.

The URICache rule caches the results of all rules below it, keyed against the incoming URI. If the component is located, the resulting ComponentSource object is cached. If it is not located, the resulting ComponentNotFound condition is cached. Whether or not this rule is enabled is based on the value of use_static_source. URI caching has the effect of disabling repeated resolution/filesystem lookups for components that have already been located, as well as components that were not found when searched. URICache also takes an optional constructor parameter source_cache_size, which indicates that this URICache should use its own cache of the given size, separately from the per-interpreter source cache. Through custom configuration of URICache rules, parts of a site can be configured as static source and other parts can be configured as being more dynamically alterable.

Since URICache caches data based only on the URI, it will complain if you try to put a dhandler rule below it. This is because the dhandler rule does not necessarily return the same result for the same URI each time, as its upwards logic is conditionally enabled. In theory, ResolveUpwards should have this effect as well, but since normal usage will use ResolveUpwards for all autohandlers and nothing else, it by default will not complain about a ResolveUpwards rule. If you construct ResolveUpwards using ResolveUpwards(enable_caching = False), then the URICache rule will complain about it.

URICache also has an additional parameter which allows it to cache the results of just a single rule, instead of all rules below it:

from myghty.resolver import *

resolver_strategy = [
    URICache(rule = ResolveModule()),
    ResolveFile()
]

Above, only the results of ResolveModule will be cached. ResolveFile will be executed every time it is called.

back to section top
Conditionals, Groups and ConditionalGroups

Here is an example of conditional and group-based rules:

from myghty.resolver import *

resolver_strategy = [
    ConditionalGroup(context = 'subrequest', rules = [
        ResolveDhandler(),
        ResolveUpwards(),
        ResolveFile(),  
        NotFound()
    ]),
    
    Conditional(regexp = '/login/.*', rule = ResolveModule({'.*' : 'myapp:LoginHandler'})),
    
    AdjustedResolveFile(
            adjust = [('/docs/', '/')], 
            ('main' : '/web/htdocs'), 
            ('comp' : '/web/comp') 
    )
]

The above example routes all subrequests into a rule subchain, which resolves files only, including optional dhandler and autohandler resolution. The subchain is terminated by the rule NotFound, which always results in a ComponentNotFound error. If NotFound is not included, the resolution would fall through back into the main rule chain. Continuing on, all non-subrequest component requests will first check for the URI '/login/' which matches to a specific module component, and then onto the bottom where it does a special file resolution rule.

That last rule above is AdjustedResolveFile(), which is a subclass of ResolveFile() that performs path translation on the incoming URI before concatenating it to each of its file paths. In contrast to using PathTranslate(), the result of this translation is not propigated forward onto new requests nor is it used in the resulting component source; it is only used in the actual path concatenation.

back to section top
Resolver Contexts

The Resolver is used for all resolution of URIs into components, which is not just the URI used by a client browser, but also URIs used for all components called by a template, the inheriting component of a template, and subrequests. Custom resolver strategies allow different rules to execute based on this context, using the Conditional and ConditionalGroup rules.

A common use for a conditional rule based on resolver context is to have module components be invoked only for request-based URIs, and all internal subreqests, component calls, and templates use file-based components:

from myghty.resolver import *

resolver_strategy = [
    ConditionalGroup(context = 'request', rules = [
        ResolveModule(),
        
        # optional - dont allow requests to "fall through"
        # into file-based resolution
        NotFound()
    ]),
    
    ResolveDhandler(),
    URICache(),
    ResolveUpwards(),
    ResolveFile()
    
]

Above, all requests from the outside world must be resolved by module components, as the conditional is terminated by a NotFound() rule. If the NotFound() rule is omitted, incoming uris that do not match a module component path will "fall through" into the file-based rules.

The resolver context is also customizable programmatically. The request methods create_subrequest and fetch_component take the optional parameter resolver_context which can be any user-defined string, or one of the standard names request, subrequest, component or inherit. Any Conditional or ConditionalGroup rule which specifies the name as the value of context will be activated by this name.

back to section top
Resolution Logging
Details about a component resolution are attached to ComponentNotFound exceptions, when a page or component is not found. Additionally, if you add the configuration parameter debug_elements = ['resolution'] to your Interpreter config, the resolution of all components will be logged. This log details each step within a resolution with an identifying keyword, such as "resolvemodule:", "resolvefile:", or "dhandler". See debug_elements for information on debug_elements.
back to section top
Custom Rules

The basic idea of a custom rule is to subclass the ResolverRule class, overriding at least the do method, which is tasked with returning a Resolution object, which in turn contains a ComponentSource object.

Example 1 - File-based Custom Rule

from myghty.resolver import *
from myghty.csource import *
import os

class MyFileResolver(ResolverRule):
    """a user-defined resolver rule that looks up file-based components"""
    def __init__(self, file_root):
        """builds a new MyFileResolver."""
        self.file_root = file_root
    
    def do_init_resolver(self, resolver, remaining_rules, **kwargs):
        """called when the MyFileResolver is established in the rule chain.
        'resolver' is the instance of Resolver being used to run the rules.
        'remaining_rules' is a list of all ResolverRules that occur below this rule.
        **kwargs receives the full dictionary of Myghty configuration parameters."""
        pass
    
    def do(self, uri, remaining, resolution_detail, **kwargs):
        """attempts to resolve the given uri into a Resolution object.
        'resolution_detail' is a list of log messages that will be appended to the debug log when 
        resolution is being logged, or to ComponentNotFound exceptions.
        **kwargs contains extra resolution arguments, such as "resolver_context" and "enable_dhandler". """
    
        if resolution_detail is not None: 
            resolution_detail.append("MyFileResolver:" + uri)

        # a simple resolution.
        file = self.file_root + uri
        if os.access(file, os.F_OK):
            # file exists, so return a Resolution/FileComponentSource
            return Resolution(
                    FileComponentSource(
                        file_path = file,
                        # file modification time - this is not required as of 0.99b
                        last_modified = os.stat(srcfile)[stat.ST_MTIME],
                        path = uri,
                        # key to identify the 'compilation root' for the component
                        path_id = 'myfileresolve',
                        # unique key to identify the component
                        id = "%s|%s" % (key, path), 
                    ), 
                    resolution_detail
                )
        else:
            # file doesnt exist, so call the next resolver in the chain
            return remaining.next().do(uri, remaining, resolution_detail, **params)

Example 2 - Module Component Custom Rule

from myghty.resolver import *
from myghty.csource import *
import sys, re

class MyModuleResolver(ResolverRule):
    """a user-defined resolver rule that looks up module-based components"""
    def __init__(self, path):
        """constructs a new MyModuleResover with the given module path."""
        self.path = path

    def do_init_resolver(self, resolver, remaining_rules, **kwargs):
        """initializes the MyModuleResolver."""
        pass
        
    def do(self, uri, remaining, resolution_detail, context = None, **params):
        """resolves the given URI to a specific callable."""
        
        if resolution_detail is not None: 
            resolution_detail.append("MyModuleResolver: " + uri)

        # here we illustrate a variety of constructor arguments
        # for Resolution and ModuleComponentSource.
        if uri eq '/shopping/':
            # return a ModuleComponentSource with a callable inside of it
            # the "cache_arg" flag, new in version 0.99b, indicates that the 
            # given argument is not changing its type (i.e. function, object, class) and can be 
            # cached with regards to inspecting its type, parent module, etc.
            return Resolution(
                ModuleComponentSource(shopping, cache_arg=True),
                resolution_detail
                )
        elif uri eq '/checkout/':
            # or with the standard "package.module:callable" string
            return Resolution(
                ModuleComponentSource("mypackage.mymodule:checkout", cache_arg=True),
                resolution_detail
                )
        elif uri eq '/inspector/':
            # the Resolution object will also attach any additional **kwargs as attributes
            # which other components can then retreive via m.resolution
            return Resolution(
                ModuleComponentSource(inspector, cache_arg=True),
                resolution_detail
                param1 = 'inspect',
                param2 = 3
                )
        else:
            # no component matches, return next resolver in the chain
            return remaining.next().do(uri, remaining, resolution_detail, **params)
Installing the Rule

The new rule is then installed by specifying it within resolver_strategy, as in this example which first resolves via MyModuleResolver, and then resolves file components via MyFileResolver, plugged into the standard URICache/dhandler/autohandler chain:

from myghty.resolver import *

resolver_strategy = [
    MyModuleResolver('/usr/local/mymodules'),
    ResolveDHandler(),
    URICache(),
    ResolveUpwards(),
    MyFileResolver('/web/htdocs')
]
back to section top

Since version 1.1, Myghty provides support for writing unicode strings, and for including non-ASCII characters within component source files.

What You Can Give to m.write() (and m.apply_escapes())

When unicode support is enabled, you may pass either unicode or plain strs to m.write(). Strs will be interpreted according the Python's system default encoding (as returned by sys.getdefaultencoding(). You may also write any other object, in which case the object will be coerced to unicode by calling unicode() before it is output. There is one exception to this rule: writing a None generates no output.

back to section top
The Magic Encoding Comment

If a myghty component source file contains contains characters other than those in the python system default encoding (as reported by sys.getdefaultencoding() --- usually ASCII), you may so indicate this by placing a magic encoding comment at the top of the file. The exact syntax of the magic comment is essentially the same as that used by python, with the added restriction that the '#' which introduces the magic comment must start at the beginning of a line (without leading whitespace.)

The magic encoding comment affects the interpretation of any plain text in the component source file, and the contents of any python unicode string literals. It does not have any effect on the interpretation of bytes within python plain str literals. In particular, the following is likely to generate a UnicodeDecodeError:

# encoding: latin1

# This is fine:
Français

% m.write(u"Français")  # This is fine, too

% m.write("Français")   # BAD! => UnicodeDecodeError
back to section top
Controlling the Output Encoding

The output encoding, and output encoding error handling strategy can be specified using the output_encoding and encoding_errors configuration parameters. It can also be changed for a specific request (or portion thereof) by calling the set_output_encoding method.

Choices for the value of encoding_errors include:

strict
Raise an exception in case of an encoding error.
replace
Replace malformed data with a suitable replacement marker, such as "?".
xmlcharrefreplace
Replace with the appropriate XML character reference.
htmlentityreplace
Replace with the appropriate HTML character entity reference, if there is one; otherwise replace with a numeric character reference. (This is not a standard python encoding error handler. It is provided by the mighty.escapes module.)
backslashreplace
Replace with backslashed escape sequence.
ignore
Ignore malformed data and continue without further notice.

See the Python codecs documentation for more information on how encoding error handlers work, and on how you can define your own.

Generally, for components generating HTML output, it sufficient to set output_encoding to 'latin1' (or even 'ascii'), and encoding_errors to 'htmlentityreplace'. (Latin1 is the default encoding for HTML, as specified in RFC 2616.) The 'htmlentityreplace' error handler replaces any characters which can't be encoded by an HTML named character reference (or a numeric character reference, if that is not possible) so this setting can correctly handle the output of any unicode character to HTML.

back to section top
Other Details

With unicode support enabled the return value from m.scomp() will be either a unicode or a str in the system default encoding.

Similarly, the input passed to any component output filters will also be either a unicode or a str. The filter may return any object which is coercable to a unicode.

Output passed to the .write() method of component capture buffers (specified using the store argument of execute_component) will be either a unicode or a plain str. (Using a StringIO.StringIO buffer should just work. Using a cStringIO.StringIO buffer will probably not work, as they don't accept unicode input.)

Output passed to the .write() method of subrequest capture buffers (specified using the out_buffer argument of create_subrequest) will be encoded strs. The encoding and error strategy, by default, will be the system default encoding and 'strict' respectively, irrespective of the output_encoding of the parent request. These can be changed using the output_encoding and encoding_errors arguments of create_subrequest (or by calling set_output_encoding on the subrequest.)

back to section top
Disabling Unicode Support

Myghty's unicode support may be disabled by setting the disable_unicode configuration parameter.

back to section top

View: Paged  |  One Page
Index of Configuration Parameters

Configuration parameters in Myghty are basically a big dictionary of data that is initially passed to the constructor for myghty.interp.Interpreter, which represents the entry point for running a Myghty template. Upon construction, the Interpreter instantiates all the other objects it needs, such as the Compiler, the Resolver, and a prototype Request object (a prototype is an object that is used as a template to make copies of itself), passing in the same hash of configuration parameters. Each object takes what it needs out of the dictionary.

If you are writing your own interface to Interpreter, such as a standalone or simple CGI client, you can pass one or more of these values programmatically to the constructor of the Interpreter. If running from mod python, values can be specified in the http.conf file using the format Myghty<Name>, where Name is the parameter name in InitialCaps format (i.e., data_dir becomes DataDir).

Note also that there are configuration parameters specific to the caching mechanism, listed in Cache Options, as well as session specific parameters listed in Session Options.

allow_globals (list of strings)
for users: developers
default: None
used by: Compiler

A list of global variable names that will be compiled into Myghty templates, and will be expected to be provided upon template execution. The variable "r", representing the Apache Request, is delivered to templates via this parameter. To add your own variables, specify their names in this list, and also specify it as a key in the RequestImpl argument global_args to provide the values. See the section Make your Own Friends for details.

attributes (dictionary)
for users: all
default: None
used by: Interpreter

A dictionary of data that will be stored by the Interpreter used throughout a particular Myghty application. This is a way to set per-application global variables. The values are accessible via the interpreter.attributes dictionary.

i = interp.Interpreter(attributes = {'param': 'value'})
Accessing attributes:
# call interpreter off request,
# and get an attribute
p = m.interpreter.attributes['param']

# call interpreter off component,
# and set an attribute
self.interpreter.attributes['param'] = 'value'

Interpreter attributes can be compared to component attributes, as well as request attributes.

auto_flush (boolean)
for users: developers
default: False
used by: Request

Whether or not m.write calls will be automatically flushed to the final output stream as they are called, or will be buffered until the end of the request. Autoflush being on makes things a little more tricky, as you can't do any kind of page redirects (neither external nor internal) once the content starts coming out. Error messages become messy as well since they are similar to an internal redirect.

Autoflush can be set in a variety of ways and is described fully in the section The Autoflush Option.

auto_handler_name (string)
for users: administrators
default: autohandler
used by: Interpreter

The name of the file used as a global page wrapper, defaults to 'autohandler'. See the section autohandlers for information on autohandlers.

cache_debug_file (file object)
for users: optimizers
default: None
used by: Cache
since version: 0.94

If pointing to a Python file object, container operations performed by the caching system will be logged, allowing the viewing of how often data is being refreshed as well as how many concurrent threads and processes are hitting various containers. When running with ApacheHandler or CGIHandler, this parameter can be set to the standard Apache log via the parameter log_cache_operations.

code_cache_size (integer)
for users: optimizers
default: 16777216
used by: Interpreter

Size of the cache used by Interpreter to cache loaded component objects, measured in bytes. The cache works on a "least recently used" scheme. This value has a great impact on performance, as too large a value can use up lots of memory for a very large site, and too small results in excessive "swapping" of components in and out of memory. Cache operations can be logged via debug_file.

compiler (object)
for users: hackers
default: myghty.compiler.Compiler
used by: Interpreter

An instance of myghty.compiler.Compiler used to generate object files. Not much reason to play with this unless you are seriously hacking your own engine. The default Compiler object will receive its optional parameters from the argument list sent to the constructor for Interpreter.

component_root (string or list)
for users: all
default: None
used by: Resolver

This parameter is almost always required; it is the filesystem location, or list of locations, with which to locate Myghty component files.

The two formats of component_root are as follows:

Single string

component_root = "/web/sites/mysite/htdocs"

List of hashes

component_root = [
        {'main':"/web/sites/mysite/htdocs"},
        {'components':"/web/sites/mysite/components"},
        {'alt':"/usr/local/lib/special-comp"}
    ]

The single string specifies one root for all component calls, which will be assigned the identifying key "main". The list of hashes specifies the keys and paths for a collection of locations which will be searched in order for a component. This allows you to have one file tree that is web-server accessible files, and another file tree that contains files which can only be used as embedded components, and can't be accessed by themselves. The key names are used to uniquely identify a component by both its location and its name, such as "main:/docs/index.myt".

For examples of component_root configuration, see the section Configuration. For advanced options on file-based resolution, see Advanced Resolver Configuration.

data_dir (string)
for users: all
default: None
used by: Interpreter

Directory to be used to store compiled object files (.py files and .pyc files), lock files used for synchronization, as well as container files which store data for the component caching system and the session object. A non-None value implies True for the "use_object_files" setting. Compiled object files are stored in the obj directory, and cache/session files are stored underneath container_XXX directories.

debug_elements (list)
for users: optimizers
default: []
used by: Interpreter
since version: 0.97alpha3

A list of string names that refer to various elements that can send debug information to the Interpreter's debug output. An example with all allowed names:

debug_elements = [
    # all resolution of components
    'resolution', 

    # inspection of component objects and modules loaded into memory and later garbage-collected
    'codecache', 
    
    # inspection of the generation and compilation of components
    'classloading',
    
    # cache operations, reloading of cached data
    'cache', 
]

debug_file (file object)
for users: optimizers
default: stderr
used by: Interpreter
since version: 0.93b

References a Python file object; if non-None, the Interpreter will send debugging information to this file. Note that line breaks are not sent by default; use code such as myghty.buffer.LinePrinter(sys.stderr) to wrap the file in a line-based formatter.

When running the Interpreter in an HTTP context, various implementations of HTTPHandler supply their own stream for debugging information, such as the ApacheHandler which supplies the Apache error log as a filehandle.

As of version 0.97alpha3, to actually enable debug logging requires the debug_elements parameter to be set up.

default_escape_flags (list)
for users: developers
default: None
used by: Compiler

This is a list of escape flags that will be automatically applied to all substitution calls, i.e. <% string %>. See Escaping Content for more information on content escaping.

dhandler_name (string)
for users: administrators
default: dhandler
used by: Request

The name of the file used as a directory handler, defaults to 'dhandler'. See the section dhandlers for information on directory handlers.

disable_unicode (boolean)
for users: developers
default: False
used by: Request, Compiler
since version: 1.1

Disable the new unicode support features. If set, all strings are assumed to be strs in the system default encoding (usually ASCII). See the section on Unicode Support for further details.

dont_auto_flush_filters (boolean)
for users: developers
default: False
used by: Request

If auto_flush is turned on, this option will keep auto_flush turned off for components that use <%filter> sections. This is useful if you have filters that rely upon receiving the entire block of text at once. See the section <%filter> for more information on filters.

encoding_errors (string)
for users: developers
default: strict
used by: Request
since version: 1.1

Sets the initial value for the encoding_errors of requests, which, in turn, determines how character set encoding errors are handled.

Some choices are:

strict
Raise an exception in case of an encoding error.
replace
Replace malformed data with a suitable replacement marker, such as "?".
xmlcharrefreplace
Replace with the appropriate XML character reference.
htmlentityreplace
Replace with the appropriate HTML character entity reference, if there is one; otherwise replace with a numeric character reference. (This is not a standard python encoding error handler. It is provided by the mighty.escapes module.)
backslashreplace
Replace with backslashed escape sequence.
ignore
Ignore malformed data and continue without further notice.

See also the section on Unicode Support, and the Python codecs documentation.

error_handler (function)
for users: developers
default: None
used by: RequestImpl

A function object that will be passed all exceptions and given the chance to handle them before regular processing occurs. The format of the function is:

def handle_error(e, m, **params):
    # custom error handling goes here
    # ...

    # return False to continue handling error, True to disregard
    return False

Where 'e' is a myghty.exception.Error object and m is the request object. The global variable 'r' will also be passed if running in an HTTP context. The function should return True to stop all further error handling, or False to continue error handling as normal.

The request object, while it is the same instance used to handle the request initially, no longer will have any buffered content and will also not have a current component instance. It is safe to call subrequests from it, allowing the construction of custom error pages.

See also raise_error to simply raise an error outside the Request and bypass all internal and custom error handling.

escapes (dict)
for users: developers
default: {'h':html_escape, 'u':url_escape}
used by: Interpreter

Use this parameter to define your own custom escaping functions that are available within substitutions, as well as m.apply_escapes(). Within a dictionary key/value pair, the key is the identifying character, and the value is a reference to a single-argument function that will be called with the string with which to apply the text escape. The function should return the filtered text.

Escaping is described fully at Escaping Content.

generator (object)
for users: hackers
default: myghty.objgen.PythonGenerator
used by: Compiler

An instance of myghty.objgen.ObjectGenerator that is used to generate object files. Again, for the brave hacker, you can write your own generator and output object files in whatever language you like.

global_args (dictionary)
for users: developers
default: None
used by: RequestImpl

A list of global argument names and values that will be available in all template calls. See the section Make your Own Friends for details.

interpreter_name (string)
for users: administrators
default: None
used by: HTTPHandler

Specifies the name of the Myghty interpreter that should be used. All HTTP handlers modules maintain a dictionary of HTTPHandler instances, each of which references a Myghty interpreter, keyed off of a name. When this name is explicitly specified, that particular handler will be created if it doesnt exist and then used.

This option is currently most useful for use within multiple Apache directives, so that different sets of configuration parameters can be used for different directives, without requiring the use mod_python's multiple Python interpreters feature. See the example in Advanced mod_python Configuration - Multiple ApacheHandlers.

lexer (object)
for users: hackers
default: myghty.lexer.Lexer
used by: Compiler

An instance of myghty.request.Lexer, used to parse the text of template files.

log_cache_operations (boolean)
for users: optimizers
default: False
used by: ApacheHandler or CGIHandler
since version: 0.93b

Deprecated; use debug_elements instead.

log_component_loading (boolean)
for users: optimizers
default: False
used by: ApacheHandler or CGIHandler
since version: 0.93b

Deprecated; use debug_elements instead.

log_errors (boolean)
for users: administrators
default: False
used by: HTTPHandler

Specifies whether or not component errors should receive a full stack trace in the Apache error log, standard error output of CGIHandler, or other HTTP-specific logging system. If false, component errors still produce a single-line description of the error in the log. See also output_errors. If raise_error is set to true, no logging of errors occurs.

max_recursion (integer)
for users: optimizers
default: 32
used by: Request

The highest level of component recursion that can occur, i.e. as in recursive calls to a subcomponent.

module_components (array of hashes)
for users: all
default: None
used by: ResolveModule

This parameter is used for resolving Module Components using regular expressions which are mapped to function, class or class instance objects. See module_components for examples.

module_root (array of hashes)
for users: all
default: None
used by: ResolvePathModule

This parameter is used for resolving Module Components using file paths which map to the locations of python files and the attributes within. See module_root for examples.

module_root_adjust (callable)
for users: all
default: None
used by: ResolvePathModule
since version: 0.99b

This parameter is used in combination with module_root to specify a callable that will translate an incoming URI before being resolved to a path-based module. See module_root for more detail.

out_buffer (object)
for users: developers
default: None
used by: DefaultRequestImpl

A Python file object, or similar, with which to send component output. See the Configuration section for examples.

output_encoding (string)
for users: developers
default: sys.getdefaultencoding()
used by: Request
since version: 1.1

Sets the initial value for the output_encoding of requests. The default value is python's system default encoding (usually ASCII.) See the section on Unicode Support for further details.

output_errors (boolean)
for users: administrators
default: True
used by: ApacheHandler or CGIHandler
since version: 0.93b

Specifies whether or not component errors with full stack trace should be reported to the client application. If false, component errors will produce a 500 Server Error. See also log_errors. If raise_error is set to True, this parameter is overridden and client will receive a 500 server error (unless the error is caught by an external handler).

parent_request (object)
for users: hackers
default: None
used by: Request

This parameter specifies the parent request when making subrequests, and is automatically provided. For more information see Programmatic Interface.

path_moduletokens (list of strings)
for users: all
default: ['index']
used by: ResolvePathModule
since version: 0.99b

Used by module_root to specify default path tokens that should be searched in module attribute paths. See Module Root Options for details.

path_stringtokens (list of strings)
for users: all
default: []
used by: ResolvePathModule
since version: 0.99b

Used by module_root to specify default path tokens that should be searched in file paths. See Module Root Options for details.

path_translate (list of tuples, or a callable)
for users: administrators
default: None
used by: Resolver

A list of regular-expression translations that will be performed on paths before they are used to locate a component and/or module component. This can be useful for complicated web server configurations where aliases point to component roots, or specifying a default document for path requests. It looks as follows:

path_translate = [
        # convert /store/* to /shop/*
        (r'^/store/(.*)', r'/shop/\1'),
        
        # convert /documents/* to /docs/*
        (r'^/documents/', '/docs/'),
        
        # convert /foo/bar/ to /foo/bar/index.myt
        (r'/$', '/index.myt'),
    ]

As of revision 0.99b, the argument to path_translate can alternatively be specified as a callable, which converts its given URI to the translated value:

def my_translate(uri):
    return "/doc/" + uri
path_translate = my_translate

Note that the request_path member of the request object will reference the original path before translation, whereas the path of the component served will contain the translated path (for file-based components).

More detail about path translation can be found in Advanced Resolver Configuration.

python_post_processor (function)
for users: hackers
default: None
used by: Compiler

References a function that will be invoked with the full text of each individual unit of Python code created during component generation (i.e., creation of .py files). The returned string will be used as the Python code that is actually placed within the generated .py file. Also see text_post_processor.

python_pre_processor (function)
for users: hackers
default: None
used by: Compiler

References a function that will be invoked with the full text of a template's source file before it is parsed. The returned string will then be used as the source to be parsed.

raise_error (boolean)
for users: developers
default: False
used by: Request
since version: 0.97a

Indicates if errors should be raised when they occur, or be handled by error handling functionality. If set to True, no error logging, friendly client response, or custom internal error handler function will happen. Instead, an external error handler can be used. This parameter overrides invalidates the functionality of log_errors, output_errors and error_handler.

This parameter allows the entire interpreter.execute() or handler.handle() call to be wrapped in a try: / except: block, where the error can be handled externally to all Myghty functionality.

request (object)
for users: hackers
default: myghty.request.Request
used by: Interpreter

An instance of myghty.request.Request used as a prototype to generate new requests. Its context-specific behavior is supplied by a separate instance of myghty.request.RequestImpl, so there is not much reason to change this either.

request_impl (object)
for users: hackers
default: myghty.request.DefaultRequestImpl
used by: Request

An instance of myghty.request.RequestImpl that will be used either as a prototype to create new RequestImpls per request, or can be passed per individual interpreter execution. RequestImpl tells Request how it should interact with its environment. Take a look at ApacheHandler.ApacheRequestImpl, CGIHandler.CGIRequestImpl, and myghty.request.DefaultRequestImpl for examples.

request_path (string)
for users: developers
default: myghty.request.Request
used by: Request

Sets the initial request path for this request. In most cases, this is set automatically by simply calling a request with a string-based component name, or with a file-based component which can return its originating path. However, in the case of a request being called with a memory or module-based component, the path defaults to None and must be set by the calling function if it is to be referenced by components.

require_publish (boolean)
for users: all
default: False
used by: ResolvePathModule
since version: 0.99b

Indicates that callables located via module_root resolution require an attribute named 'public' set to True attached to them, in order to allow access. See Module Root Options for details.

resolver (object)
for users: hackers
default: myghty.resolver.FileResolver
used by: Interpreter

An instance of myghty.resolver.Resolver that is used to locate component files. Both ApacheHandler and CGIHandler have their own instances of Resolver but don't yet do anything special. If you wanted some kind of special file resolution behavior, you can swap in your own subclass of Resolver.

resolver_strategy (list)
for users: developers
default: None
used by: Resolver

Allows configuration of the rules used in component resolution. See the section Advanced Resolver Configuration for details.

source_cache_size (integer)
for users: optimizers
default: 1000
used by: Interpreter

Size of the cache used by Interpreter to cache the source of components. See use_static_source for a description of source caching, and see code_cache_size for a description of the LRU caching scheme.

text_post_processor (function)
for users: hackers
default: None
used by: Compiler

References a function that will be invoked with the full text of each individual unit of output text created during component generation (i.e., creation of .py files). The returned string will be used as the output text that is actually placed within the generated .py file. Also see python_post_processor.

use_auto_handlers (boolean)
for users: developers
default: True
used by: Interpreter

Whether or not to use autohandlers. See the section autohandlers for more information.

use_dhandlers (boolean)
for users: developers
default: True
used by: Request

Whether or not to use directory handlers. See the section dhandlers for more information.

use_object_files (boolean)
for users: optimizers
default: True if data_dir is not null
used by: Interpreter

Indicates whether or not components should be compiled into module files on the filesystem, or into strings held in memory. A value of None for the data_dir parameter will have the same effect. There is no advantage whatsoever to having components compiled in memory, and startup performance will be degraded for repeated calls to the same component. It might be useful if you are running the interpreter in a "one shot" fashion where there is no need to have compiled object files lying around.

use_session (boolean)
for users: developers
default: None
used by: ApacheHandler

The additional global variable s to reference the Myghty session, or alternatively the mod_python 3.1 session, is turned on when this option is set to True. See the section Session for details.

use_source_line_numbers (boolean)
for users: hackers
default: None
used by: Compiler

Whether or not to put source line numbers in compiled object files. This is used to generate friendly stack traces upon errors (when that feature is complete).

use_static_source (boolean)
for users: optimizers
default: False
used by: Interpreter, Resolver

This parameter, when set to True:

  • Enables URI caching within the resolver, and/or turns on all configured URICache() resolution rules, so that visiting a URI a second time does not produce any filesystem checks, within the currently cached set of URIs.
  • Disables repeated last-modification time checks on all template files and module-component files
  • Disables last-modification time checks on compiled template object files against the template they were generated from, which in effect disables re-compilation of templates even across server restarts, unless the object file is removed from the obj directory underneath the configured data_dir directory
Use use_static_source on production servers where the site's structure is not being changed, to prevent auto-recompilation of modified templates, and to prevent reloads of modified module component modules. There is both a performance increase due to fewer filesystem checks, and also a stability increase, as no Python modules are dynamically reloaded within a running server. Dynamic reloads in Python are somewhat error-prone, particularly if a module with a base class changes, and a corresponding subclass in a different, non-reloaded module attempts to instantiate itself.

back to section top

This section refers to the inner workings of Myghty and how it relates to HTML::Mason.

Design Goals

The main goal in developing Myghty is, port HTML::Mason to Python ! Beyond that, it is important that it retain all the central features of HTML::Mason, to make it easy for people already familiar with Mason to use Myghty as well.

But even though the language should be similar to Mason's, it also should be altered as needed to appropriately fit the Python language style, which while having some notable similarities to Perl, is still a different beast. The design of the engine should model itself after that of Mason's at a high level, but also should take advantage of the opportunities the "clean start" porting to Python gives, including code streamlining, introduction of new design patterns, and putting to use the unique programming capabilities Python affords (since after all, I wouldnt be porting to Python if I didn't think Python had some unique things to offer).

Going forward, the design and featureset of Myghty is expected to diverge from that of HTML::Mason, which is seen as more of a "starting point" rather than a continuous benchmark to follow. Since it is intended for a different audience than that of Mason, i.e. the Python developmental community, I am hoping that its development can be steered into being a useful and "first choice" enterprise web development tool specifically for Python enthusiasts.

back to section top
Approaches to Templating

Myghty is a compiled page system, as opposed to a directly interpreted system. A compiled page system means that templates are used to generate source code files consisting a programming language that is different from that of the actual template, typically the same language as that of the language compiler itself. Whereas a directly interpreted language provides its own language interpreter for templates. Compiled page systems include Java Server Pages, Embperl, HTML::Mason, Python Server Pages. Directly interpreted systems include PHP, Webmacro, and FreeMarker (whose early development history bears the name of Myghty's author).

Each approach has its own advantages and disadvantages. A directly interpreted system has the burden of providing a full programming language written from scratch, which can result in a language that is somewhat rigid and single-purposed, but can potentially deliver extremely fast performance. A compiled page system is much simpler to write, and typically allows full blocks of the host language to be dropped into templates. This allows great flexibility, but is also known to result in templates that are more complicated than is appropriate, depending on the developer's code practices. For developers of Python code, Python is probably an elegant and powerful enough language that it deserves to live within templates unadulterated, as it does within Myghty.

back to section top
Generating Python Modules

A Myghty template file, which might have an extension such as ".myt", is parsed by the engine and converted into a python module, which contains a subclass of the class Component. This new python module, which also gets compiled by python into a .pyc file, then forms the basis for generating the template's final output, and is only changed whenever the original template changes.

The majority of the template is encoded as Python statements inside of a class method called do_run_component(). Straight text from the template file gets distilled into write statements, lines and blocks of Python code get inserted inline as they are (with their whitespace adjusted to the appropriate context), and calls to other parts of the template or other templates get translated into calls that look like m.execute_component(). A pre-determined namespace of one or more helper variables is provided to statements within the template so that your template can attend to its daily chores, such as looking at the apache request, sending headers, ordering takeout, what have you. Other details to be dealt with by Component include handling argument lists being passed around as well as properly specifying the scoping of variables and custom methods.

back to section top
Handling a Request

A request starts first with the module that is handling the host environment. This may be the ApacheHandler, the CGIHandler, a standalone handler, or any developer-custom handler (they're pretty easy to write).

The handler then is responsible for creating an instance of myghty.interp.Interpreter with the proper arguments corresponding to the execution environment, and then calling the execute() method on that interpreter with request-specific arguments, which will begin the process of compiling, loading, and running a Myghty template.

The Interpreter then creates an instance of myghty.request.Request which represents the template and arguments we are actually going to serve, and optionally a myghty.request.RequestImpl object which provides additional environment-specific behavior to the Request object, including the request arguments and the output buffer where content will be written.

Request is responsible for looking up the requested component and also other referenced components, which may be inherit components, methods in other component files, etc. The individual lookup operations are sent back to the hosting Interpreter object, which will coordinate amongst an instance of myghty.resolver.Resolver to locate files, a cache of myghty.resolver.ComponentSource instances representing located template files, and a thread-local instance of myghty.compiler.Compiler which is responsible for parsing in new template files and producing compiled component files from them, from which Interpreter can receive new myghty.component.Component objects. myghty.compiler.Compiler makes use of the Lexer and ObjectGenerator objects to compile templates.

The Request object executes the components it locates, passing itself as the primary namespace variable m to components, manages a call-stack of components, and manages a stack of myghty.buffer.AbstractBuffer objects which capture component output. Exceptions are also handled here and processed so that they contain clean stack traces.

Request then cleans up and finishes, Interpreter finishes, and its back up to the handler to send return codes and exit its handle method.

back to section top
Modules

To gain a deeper understanding of Myghty, heres a quick rundown of the modules and what their purpose is.

request

The request package is home to the Request object. Request is an object that is instantiated by Interpreter to service a top-level component exactly once. It is available within a component's namespace by the special variable m. It is responsible for locating all components and inherited components referenced by its top-level component, including autohandlers and dhandlers, calling them in the appropriate order, buffering their output, and handling exceptions. It interacts with the outside world via an embedded RequestImpl object, such as DefaultRequestImpl (also included in the request package) for dealing with a command-line environment, ApacheRequestImpl for dealing with mod_python, and CGIRequestImpl which handles a CGI environment.

back to section top
interp

interp is home to the Interpreter object. Interpreter represents a Myghty application environment and its configuration parameters, and is the primary API used for executing requests within that environment. Interpreter contains logic for loading and compiling component objects at a high level, and dispatching those compiled component objects to new requests. It also deals with the filesystem structure where component files, lock files, and cache files are stored.

back to section top
lexer

The lexer package contains the Lexer object, which is responsible for parsing component files or in-memory strings and sending the resulting tokens to an instance of Compiler. Lexer relies heavily on the regular expression package to produce its results.

back to section top
compiler

Compiler represents a location for Lexer to send its parsing events, and aggregates a compiled parse tree structure for a particular compilation. Once complete it calls an instance of ObjectGenerator with the new parse tree to produce the source code of a Myghty component. The parse tree itself is an instance of Compiler.Compiled, which stores the various code blocks and supports visitor-based traversal.

back to section top
objgen

The home to ObjectGenerator, PythonGenerator, and PythonPrinter. ObjectGenerator is a generic interface for receiving visitor events from a compiled structure. The PythonGenerator extends ObjectGenerator to produce source code strings/files from that compiled structure. PythonPrinter handles printing of python code lines while keeping track of the indentation level, to allow all kinds of Myghty blocks to aggregate into one coherent Python source file.

back to section top
component

component contains the hierarchy of Component, FileComponent and SubComponent, which serve as the base classes for user-defined Myghty components. FileComponent contains initialization logic for handling requestlocal and threadlocal sections, as well as the initial determination of inheritance.

back to section top
resolver

contains the Resolver object and the various built in ResolverRule objects. The Resolver is called by the Interpreter.

back to section top
escapes

Contains code for handling substitution escaping, which includes URL, HTML and XML escaping.

back to section top
buffer

Provides interfaces for Python file objects which allow structures of buffers to be created. This is used to direct the output of components, subcomponents, filter sections, etc. to its final destination according to autoflush rules.

back to section top
HTTPHandler

HTTPHandler is the base class for the the HTTP-oriented handlers, which includes ApacheHandler, CGIHandler, WSGIHandler, and HTTPServerHandler.

back to section top
util

Util contains the data structure objects Value, ThreadLocal, OrderedDict as well as the cloning helper object ConstructorClone.

back to section top
synchronizer

synchronizer contains code for synchronizing read and write operations on data structures against thread mutexes and file-based mutexes.

back to section top
cache

The cache package provides the primary API for component output caching and data structure caching.

back to section top
container

The container package provides a system of storing namespaces of key/value pairs in memory or filesystem based storage units, with additional support for DBM and memcached. It is used as the common storage engine for the cache system as well as the session object.

back to section top
exception

The exception package defines a hierarchy of errors used across Myghty, as well as stack-trace formatting code used for logging and printing exceptions.

back to section top
Differences from HTML::Mason

Myghty is not the same as Mason. Mason, which has established itself as a fast and efficient methodology for producing high capacity websites, has provided the initial starting point, but should the direction of Myghty go in a divergent direction, that is entirely OK. When porting Mason to Myghty, opportunities arose to rework a lot of sections in new ways, and also to take advantage of the unique features of Python. Browsing the source code of both applications can reveal a lot about this process.

As far as the user experience as well as the internal architecture, beyond the obvious "its python, not perl" as well as the python indentation scheme, the differences between Myghty and Mason continue to mount, with some significant syntactical differences as well as executional differences:

  • %python tag contains the "scope" attribute, which effectively replaces %shared, %once, %init, %cleanup.
  • %args tag contains optional "scope" attribute, to specify component or request-scoped arguments
  • %shared, %once, %init, %cleanup still exist, and %shared is also synonymous with %requestlocal and %requestonce, %once is synonymous with %global
  • thread-scoped python was added, referenced by scope="thread" or alternatively %threadlocal, %threadonce
  • the %flags section can also be specified inline inside the %method and %def tags as attributes
  • filter sections and filter functions need to return a new instance of string with the filtered content since python strings are immutable. Mason filters modify content in place.
  • the %cleanup section is guaranteed to execute even in the case of components that raise an error, as the section is executed in a finally block.
  • %cleanup is also available within methods and subcomponents
  • additional component flags: autoflush for fine-grained control of buffering, trim for whitespace trimming of component output. full cache functionality is available via the use_cache flag as well as all the options as cache_XXXX.
  • the request object and component object interfaces were changed to be more pythonic, using properties as much as possible, as well as having different method names in some cases. the execution model is a little different as well.
  • module components architecture added, provides servlet-like objects to applications
  • The m and r objects are available in request-scoped (%shared) and thread-scoped blocks
  • ApacheHandler and CGIHandler were rewritten entirely. They give their behavior to the Request object via their own implementations of RequestImpl.
  • Caching API was rewritten entirely, and utilizes a genericized "container" API. It includes a mutex-based "busy lock" feature. The file storage system is DBM based. Component caching can also be configured via the %flags section of any component to avoid the more complicated programmatic interface.
  • Building off of the container API, a Session object is included in the base distribution which can also be configured as a global variable.
  • The Mason strategy of Class::Container has been removed, and some of its functionality replaced with a small helper object called myghty.util.ConstructorClone that is used to create clones of objects.
  • The buffer object was entirely rewritten as a hierarchy of classes that resemble Python's built-in file objects, and the attachment of buffers to each other is acheived through a "decorator" pattern.
  • Object generation was completely rewritten using a "visitor" paradigm and is more decoupled from the Compiler.
  • The Request object's context-specific behavior is provided by an internally-referenced RequestImpl object, which can be replaced with different implementations without the class of Request having to change.

back to section top

Module myghty.request

The request package and its primary class, Request, provide the "m" object in Myghty templates. The Request is instantiated by the Interpreter and handles component execution state as well as buffered state. It provides the interface to all actions taken by components, such as writing output, calling other components, calling subrequests, and controllling request state. Also provides the programmatic interface to key objects such as caches and sessions.

Module Functions
def instance()

returns the Request instance corresponding to the current thread

def threadlocal(value=None)

returns a thread local container, with initial value that of the given variable

back to section top
Class Request(object)

request object, calls components and directs output. also is the primary programmatic interface presented to a template's environment.

def __init__(self, interpreter, component=None, request_impl=None, max_recursion=32, auto_flush=False, use_dhandlers=True, dont_auto_flush_filters=False, resolver_context='request', parent_request=None, request_depth=0, request_path=None, raise_error=False, disable_wrapping=False, output_encoding='ascii', encoding_errors='strict', disable_unicode=False, **params)

init is called internally by the Interpreter.

def abort(self, status_code=None, reason=None)

raises an abort exception.

def apply_escapes(self, text, escapes)

applies the given escape flags to the given text. escapes is a list of escape flags, such as 'h', 'u', and 'x'.

attributes = property()

A dictionary where arbitrary attributes can be stored and retrieved. Inherits data from its parent request, if any.

def base_comp(self)

deprecated. use the base_component property.

base_component = property()

Returns the "base component" for the current stack frame, which is either the top level component or the owning component of a method component.

def cache(self, **params)

a synonym for get_cache().

def cache_self(self, key='_self', component=None, retval=None, **params)

caches this component's output. this is called in a "reentrant" fashion; if it returns False, component execution should continue. If it returns True, component execution should cease.

def call_content(self, **kwargs)

calls the "captured content" function within a component call with content

def call_next(self, **params)

used within an inheritance chain to call the next component in the chain. If **params are given, each parameter will override the arguments sent to this component when calling the next component.

def call_self(self, output_buffer, return_buffer)

calls this component and places its output and return value in the given buffers. This component is called in a "reentrant" fashion, where a return value of False means to continue component execution and a return value of True means to halt execution and return.

def call_stack(self, index=None)

returns the current execution stack, which consists of StackFrame objects. if an integer index is given, returns the StackFrame object at that position in the current call stack.

caller = property()

returns the calling component for the currently executing component.

def caller_args(self, index=None)

returns the list of component arguments in the current call stack. if an integer index is given, returns the component arguments at that position in the current call stack.

def callers(self, index=None)

returns the list of components in the current call stack. if an integer index is given, returns the component at that position in the current call stack.

def clear_buffer(self)

clears all content from the current output buffer.

def clone(self, **params)

creates a copy of this Request. Normally used to create subrequests.

def closure_with_content(self, func, content=None, args=None)

given a function, will execute it with the given arguments, after pushing the given content function onto the call stack via a new StackFrame, enabling the function to call it via the content() method.

def comp(self, component, **params)

component calling method which takes a simple parameter list. this method is meant to be the default method to call when calling components programmatically. compare to scomp().

component_args = property()

returns the argument dictionary from the current stack frame, corresponding to the arguments sent to the currently executing component.

def component_exists(self, path, **params)

returns True if the given component path exists.

def content(self, **kwargs)

when inside a component call with content, this method calls the "captured content" function and buffers the content, returning the string value.

content_args = property()

returns the component-call-with-content argument dictionary from the current stack frame, corresponding to the arguments sent in an m.content() call.

def create_subrequest(self, component, resolver_context='subrequest', **params)

base subrequest-creation method. A subrequest is a request that is a child to this one, enabling execution of a component and its full inheritance chain within this request.

def current_comp(self)

deprecated. use the current_component property.

current_component = property()

returns the component currently executing from the current stack frame.

def decline(self, returnval=None)

used by dhandlers to decline handling the current request. Control will be passed to the next enclosing dhandler, or if none is found a ComponentNotFound (and possibly 404 error) is raised.

depth = property()

Returns the current depth of the execution stack.

def dhandler_arg(self)

deprecated. use the request_path or dhandler_argument property.

dhandler_argument = property()

returns the current dhandler_argument, which corresopnds to the remaining path tokens in the request URI when executing a dhandler.

encoding_errors = property()

The encoding error handling strategy for the request

This is the error handling strategy used when encoding text writtent to the output buffer of the top-level request.

This is a read-only attribute, though you can change its value using the `set_output_encoding`_ method.

def execute(self)

executes this request after constructed. This is the first method called, and can only be called once per request.

def execute_component(self, component, args={}, base_component=None, content=None, store=None, is_call_self=False)

component calling method which takes parameter list as a dictionary, and allows special execution options. This method is used by component call tags and internally within the Request object.

def fetch_all(self)

pops off the entire remaining list of components in the inheritance chain.

def fetch_component(self, path, resolver_context='component', **params)

Given a component path (absolute or relative), returns a component. Handles SELF, PARENT, REQUEST, comp:method, relative->absolute conversion, MODULE, and local subcomponents.

def fetch_lead_component(self, path)

fetches the top level (initial) component to be executed by this request. Differs from fetch_component in that the resolver context is "request" or "subrequest" and the dhandler flag is enabled when resolving. Also does not support method calls.

def fetch_module_component(self, moduleorpath, classname=None, raise_error=True)

fetches a module-based component. Usually called by fetch_component when the 'MODULE' keyword is given as a prefix.

def fetch_next(self)

in an inheritance chain (i.e. of autohandlers), returns the next component in the chain

def flush_buffer(self)

flushes the current output buffer to its destination.

def get_attribute(self, key)

deprecated. use the attributes property.

def get_attributes(self)

deprecated. use the attributes property.

def get_base_component(self)

deprecated. use the base_component property.

def get_cache(self, component=None, **params)

returns the given component's cache. **params is a dictionary of options used as the default options for individually cached elements.

def get_component_args(self)

deprecated. use the component_args property.

def get_current_component(self)

deprecated. use the current_component property.

def get_depth(self)

deprecated. use the depth property.

def get_dhandler_argument(self)

deprecated. use the request_path or dhandler_argument property.

def get_encoding_errors(self)

def get_interpreter(self)

deprecated. use the interpreter property.

def get_log(self)

deprecated. use the logger property.

def get_output_encoding(self)

def get_request_args(self)

deprecated. use the request_args property.

def get_request_component(self)

deprecated. use the request_component property.

def get_request_path(self)

deprecated. use the request_path property.

def get_session(self, *args, **params)

returns the Session object used by this request. If the session has not been created it will be created when this method is called. Once the session is created, this method will return the same session object repeatedly. **params is a dictionary of options used when the session is first constructed; if it already exists, the parameters are ignored.

def get_start_time(self)

deprecated. use the starttime property.

def has_content(self)

returns whether or not the current component call was called with captured content specified

def has_current_component(self)

returns if this request has a currently executing component. This could return false if the request's top-level-component is in the loading stage.

def is_subrequest(self)

returns True if this request is a subrequest.

def load_component(self, path, raise_error=True, resolver_context=None, **params)

a mirror of interpreter.load() which caches its results in a request-local dictionary, thereby bypassing all the filesystem checks that interp does for a repeated file-based request.

def log(self, message)

writes a message to the request log. The log is RequestImpl-specific and can be standard error, a webserver error log, or a user-defined file object.

logger = property()

returns the logger for this Request, which is a file-like object.

def make_subrequest(self, component, **params)

creates a subrequest with the given component and request parameters. see create_subrequest().

notes = property()

A synonym for m.attributes

def out(self, string)

a synonym for write

output_encoding = property()

The ouput encoding for the request

This is the encoding of the output written to the output buffer of the top-level request. (I.e. the encoding delivered to the user.)

This is a read-only attribute, though you can change its value using the `set_output_encoding`_ method.

def request_comp(self)

deprecated. use the request_component property.

root_request_args = property()

The request argument dictionary sent to the ultimate root request of this Request.

root_request_path = property()

The URI sent to the ultimate root request of this Request.

def scomp(self, component, **params)

component calling method which returns output as a string

def send_redirect(self, path, hard=True)

sends a redirect to the given path. If hard is True, sends an HTTP 302 redirect via the underlying RequestImpl being used. If False, clears out the current output buffer and executes a subrequest with the given path. The path can also contain url encoded query string arguments with a question mark which will be converted to key/value arguments for the next request, even if hard=False.

def set_attribute(self, key, value)

deprecated. use the attributes property.

def set_output_encoding(self, encoding, errors='strict')

Change the output_encoding. Note that in most cases you do not want to change it after you have written any output (as then your output will be in two different encodings --- probably not what you wanted unless, perhaps, you are generating Mime multipart output.)

def subexec(self, component, **params)

creates a subrequest with the given component and request parameters and executes it. see create_subrequest().

def write(self, string)

writes textual content to the current output buffer.

back to section top
Module myghty.component

the component package defines the Component class and several subclasses. FileComponent serves as the base class for template style-components, and ModuleComponent the base for module-based components.

Class Component(object)

Base class for all components. the primary method is the run() method which executes the Component in the context of a particular request. A Component instance is usually cached in memory based on its component ID and can execute many requests simultaneously.

def __init__(self, interpreter, component_source, **params)

initializes a new Component. this method is called by the Interpreter.

def attribute_exists(self, key)

attributes = property()

def call_method(self, method_name, **params)

calls a method SubComponent of the given name on this component. This amounts to locating it via locate_inherited_method, retrieving the current request via request.instance(), and then calling execute_component on that request.

See also m.comp("component:methodname")

def component_init(self)

initializes the component after construction. Calls the do_component_init() method before setting up the component's arguments.

dir_name = property()

relative directory name of the component

def do_component_init(self)

overridden by subclasses to perform per-instance initialization steps.

def do_run_component(self, m, ARGS, **params)

overridden by subclasses to provide the main execution body of the component.

def do_thread_init(self)

overridden by subclasses to provide a per-thread initialization routine.

file = property()

the actual filename of the component, if one exists

def get_attribute(self, key, inherit=True)

def get_attributes(self)

def get_dir_name(self)

def get_file(self)

def get_flag(self, key, inherit=False)

returns a flag defines in this component's <%flags> section.

def get_id(self)

def get_name(self)

def get_owner(self)

def get_parent_component(self)

def get_path(self)

def get_source_id(self)

def get_sub_component(self, name)

returns a SubComponent of the given name, represented within the source of this Component.

def has_filter(self)

returns True if this component defines a <%filter> section.

id = property()

unique identifier for this component

def is_file_component(self)

def is_method_component(self)

def is_module_component(self)

def is_sub_component(self)

def locate_inherited_method(self, method_name)

returns a method SubComponent of the given name, represented either within the source of this Component or within the source of an inherited Component, i.e. the inheritance hierarchy will be searched for the approrpriate method call.

name = property()

name of this component

path = property()

relative full path of the component

def run(self, request, **params)

runs this component in the context of the given request. **params are the arguments sent to the component, which become ARGS in the context of the component's runtime environment.

def scall_method(self, method_name, **params)

same as call_method, but returns the component output as a string See also m.scomp("component:methodname")

def set_attribute(self, key, value)

source_id = property()

unique identifier for the ComponentSource of this component

def use_auto_flush(self)

returns True if this component defines the "autoflush" flag as True, or if an inherited component defines this flag.

back to section top
Class FileComponent(Component)

a component that corresponds to a Myghty template file

def __init__(self, interpreter, component_source, **params)

def get_sub_component(self, name)

def is_file_component(self)

def locate_inherited_method(self, method_name)

parent_component = property()

returns the parent component of this component, taking into account the component's inherit flag as well as the interpreter's autohandler properties

def uses_request_local(self)

def uses_thread_local(self)

back to section top
Class HTTPModuleComponent(ModuleComponent)

A ModuleComponent that contains methods specific to a generic HTTP request.

def do_get(self, m, r, **params)

def do_post(self, m, r, **params)

def do_run_component(self, m, r, **params)

back to section top
Class ModuleComponent(Component)

A component that is a regular Python class inside of a plain Python module.

def __init__(self, interp, component_source, owner=None, do_init=True)

def component_init(self)

def do_component_init(self)

def do_run_component(self, m, ARGS, **params)

def is_module_component(self)

def locate_inherited_method(self, method_name)

name = property()

owner = property()

back to section top
Class SubComponent(Component)

a component that corresponds to a <%def> or <%method> tag inside a file-based component.

def __init__(self, name, owner, is_method, **params)

def call_method(self, *args, **params)

def get_sub_component(self, name)

id = property()

def locate_inherited_method(self, method_name)

name = property()

owner = property()

parent_component = property()

def scall_method(self, *args, **params)

back to section top
Module myghty.interp

The interp package and its primary class, Interpreter, represents the runtime environment for Myghty components. It serves as a "home base" for configuration information and request construction, and also assists the Request object in locating components. The Interpreter maintains a pool of component objects and handles, at a high level, their compilation and filesystem representation.

Class Interpreter

Represents an environment in which to create requests, compile and execute components.

def __init__(self, attributes=None, data_dir=None, compiler=None, resolver=None, request=None, code_cache_size=16777216, use_auto_handlers=True, use_object_files=True, debug_file=BufferDecorator, enclosing ', mode 'w' at 0x100283270>., debug_threads=False, debug_elements=[], escapes={}, global_args=None, auto_handler_name='autohandler', **params)

constructs a new Interpreter object. All Myghty configuration parameters are sent to this method as keyword parameters. Those parameters that are used directly by this Interpreter are consumed. Remaining arguments are sent off to other constructed objects, which include a Compiler, a Resolver, and a Request prototype object.

def component_exists(self, path, **params)

returns True if the given path can be resolved to a ComponentSource instance, i.e. if a component can be loaded for this path.

def debug(self, message, type=None)

writes a debug message to the debug file. the optional type string refers to a "debug_element" type, i.e. 'resolution', 'cache', etc. which will only write a message if that debug_element was enabled with this Interpreter.

def execute(self, component, **params)

executes the given component with the given request construction arguments. The component can be a string path which will be resolved, or a Component object.

def get_attribute(self, key)

gets an attribute from this Interpreter. deprecated, use the "attributes" member directly instead.

def get_attributes(self)

returns the attributes dictionary for this Interpreter. deprecated, use the "attributes" member directly instead.

def get_compiled_component(self, csource, always_recompile=False, recompile_newer=True, use_file=True)

used by load_component to deliver a new Component object from a ComponentSource.

def get_component_object_files(self, component_source)

returns a tuple containing the full paths to the .py, .pyc, and .pyo files corresponding to the given FileComponentSource object.

def load(self, path, **params)

resolves and loads the component specified by the given path. **params is a set of keyword arguments passed to the resolution system.

def load_component(self, csource)

loads the component corresponding to the given ComponentSource object. This can be any subclass of ComponentSource. If the component was already loaded and exists within this Interpreter's code cache, returns the existing Component. If the Component has been modified at its source, it will re-load or re-compile the Component as needed. If this Component has not been loaded, it will import or compile the Component as needed. This operation is also synchronized against other threads. On systems that support file-locking it is synchronized against other processes as well.

def load_module_component(self, raise_error=True, **params)

resolves and loads a module component specified within the given keyword parameters. The keyword parameters are passed directly to myghty.csource.ModuleComponentSource. The easiest way to use this method is to pass the keyword parameter "arg", which references a string in the form "<modulename>:<callable_or_class>", where <modulename> is a regular Python module to be loaded via __import__, and <callable_or_class> is the dotted path to either a callable object inside the module or a class inside the module which subclasses myghty.component.ModuleComponent.

def make_component(self, source, id=None)

creates an in-memory template Component given its source as a string...this can be any Myghty template that would ordinarily be compiled from the filesystem. the optional "id" string parameter is used to identify this component within this Interpreter's code cache. If not given, one will be generated.

def make_request(self, component, **params)

creates a new request with the given component and request construction arguments. The request is copied from an existing request instance, overriding its parameters with those given. The returned request is executed by calling its execute() method. The component can be a string path which will be resolved when the request is executed, or a Component object.

def raise_error(self, error)

raises an Interpreter error with the given message string.

def resolve_component(self, path, **params)

resolves the component specified by the given path. a myghty.resolver.Resolution object is returned containing a myghty.csource.ComponentSource reference. Raises ComponentNotFound by default if the path cannot be resolved. **params is a set of keyword parameters sent directly to the resolve() method on myghty.resolver.Resolver.

def set_attribute(self, key, value)

sets an attribute on this Interpreter. deprecated, use the "attributes" member directly instead.

back to section top
Module myghty.resolver

Class AdjustedResolveFile(ResolveFile)

a ResolveFile rule that adds a pre-path-concatenation adjustment step, so the uri can be translated before determining the file path. unlike path_translate, this translated uri is only used to determine a filesystem path, and is not propigated anywhere else.

def __init__(self, adjust, *component_roots)

back to section top
Class Conditional(ResolverRule)

conditionally executes a rule, only executes if the uri matches a certain regexp, or a passed-in context string matches one of the contexts set up for this rule.

def __init__(self, rule, regexp=None, context=None)

def do(self, uri, remaining, resolution_detail, resolver_context=None, **params)

def do_init_resolver(self, resolver, remaining_rules, **params)

def test_condition(self, uri, resolver_context, **params)

back to section top
Class ConditionalGroup(Conditional)

combines a Conditional and a Group to make a conditionally-executing Group.

def __init__(self, regexp=None, context=None, rules=[])

back to section top
Class Group(ResolverRule)

creates a subgroup of resolver strategies.

def __init__(self, rules=[])

def do(self, uri, remaining, resolution_detail, **params)

def do_init_resolver(self, resolver, remaining_rules, **params)

back to section top
Class NotFound(ResolverRule)

returns not found. place at the bottom of Group and Match chains to have them terminate.

def __init__(self, silent=False)

silent = True indicates that a resulting TopLevelNotFound exception should be 'silent', i.e. not logged. this is used when a 404 error is being propigated to another application layer.

def do(self, uri, remaining, resolution_detail, **params)

back to section top
Class PathTranslate(ResolverRule)

performs path translation rules on the given uri and sends control off to the next rule.

def __init__(self, *translations)

def do(self, uri, remaining, resolution_detail, **params)

def do_init_resolver(self, resolver, remaining_rules, path_translate=None, **params)

def modifies_uri(self)

back to section top
Class ResolveDhandler(ResolverRule)

collects all the resolver rules below it and runs them for the requested uri, and if not found re-runs them again for the "dhandler" filename, pruning off path tokens until the root is reached.

def __init__(self, dhandler_name='dhandler')

def do(self, uri, remaining, resolution_detail, enable_dhandler=False, declined_components=None, **params)

back to section top
Class ResolveFile(ResolverRule)

performs file based resolution. looks up files within one or more component roots.

def __init__(self, *component_roots, **params)

def do(self, uri, remaining, resolution_detail, **params)

def do_init_resolver(self, resolver, remaining_rules, component_root=None, **params)

back to section top
Class ResolveModule(ResolverRule)

resolves a Module Component based on information in a given list of dictionaries, containing regular expressions for keys which are matched against the URI. The value for each key references either a class, a callable object or function, or a string in the form "<module>:<path.to.callable>".

def __init__(self, *module_components)

def do(self, uri, remaining, resolution_detail, context=None, **params)

def do_init_resolver(self, resolver, remaining_rules, module_components=None, **params)

back to section top
Class ResolvePathModule(ResolverRule)

resolves a callable object or class instance inside a module, based on a traversal of path tokens corresponding to the module's file location, and then of the object paths defined within the module.

def __init__(self, *module_roots, **params)

def do(self, uri, remaining, resolution_detail, dhandler_path=None, **params)

def do_init_resolver(self, resolver, remaining_rules, module_root=None, **params)

back to section top
Class ResolveUpwards(ResolverRule)

takes the rules below it and applies "search upwards" logic to them, where it iteratively breaks off path tokens behind the filename and searches upwards until the root path is reached. if require_context is True, then this rule only takes effect if "search_upwards" is sent within the resolution options. this indicates that the upwards resolve is context-sensitive, and therefore should not be cached based on a URI alone. however, by default it allows its results to be cached since in practice its used strictly for autohandlers, which are always searched upwards.

def __init__(self, require_context=True)

def do(self, uri, remaining, resolution_detail, search_upwards=False, **params)

back to section top
Class Resolver(object)

resolves incoming URIs against a list of rules, and returns Resolution objects and/or raises ComponentNotFound exceptions.

def __init__(self, resolver_strategy=None, request_resolver=None, use_static_source=False, source_cache_size=1000, track_resolution_detail=True, debug_file=None, **params)

def resolve(self, uri, raise_error=True, **params)

back to section top
Class ResolverRule(object)

base class for a single rule that attempts to resolve a uri into a Resolution object. acts inside a chain of ResolverRules where when a uri cannot be resolved, the next rule in the chain is called in a continuation pattern.

def do(self, uri, remaining, resolution_detail, **params)

performs resolution or translation on the given path. "remaining" is an Iterator referencing an element in the full list of ResolverRule objects. the method either returns a Resolution object, or passes control to the next ResolverRule in the iterator.

def do_init_resolver(self, resolver, remaining_rules, **params)

called when the resolver first receives the new rule. objects usually will want to do most of their initialization at this stage.

def init_resolver(self, resolver, remaining_rules, **params)

def modifies_uri(self)

returns True if the rule makes a modification to the URI. if so, the URICache rule wont allow this rule to be cached as a single rule, since it becomes ineffective. As part of a cached chain is still OK.

back to section top
Class URICache(ResolverRule)

caches the result of either a given nested rule, or the remaining rules in its chain, based on the incoming URI.

def __init__(self, source_cache_size=None, rule=None)

rule is a single ResolverRule (or Group) whos results will be cached on a per-uri basis. if rule is None, then the result of remaining rules in the current chain will be cached based on the incoming URI. This rule cannot be a PathTranslation rule or other uri-modifying rule, since the translated uri is not stored. source_cache_size is the size of the LRUCache to create. if source_cache_size is None, it will use the Resolver's source cache, sharing it with any other URICaches that also use the Resolver's source cache. When using the Resolver's source cache, if the Resolver has use_static_source disabled, then caching is disabled in this URICache.

def do(self, uri, remaining, resolution_detail, **params)

def do_init_resolver(self, resolver, remaining_rules, **params)

back to section top
Module myghty.csource

Class ComponentSource(object)

a time-sensitive descriptor object for a Myghty component.

def __init__(self, id, last_modified=None)

unique identifier of the component.

def can_compile(self)

def get_component_source(self)

def get_component_source_file(self)

def get_object_code(self, compiler, file)

compiles the source of this component using the given compiler, sending output to the given file

back to section top
Class FileComponentSource(ComponentSource)

def __init__(self, id, path_id, path, file_path, last_modified=None)

def get_component_source(self)

def get_component_source_file(self)

back to section top
Class MemoryComponentSource(ComponentSource)

def __init__(self, source, id=None, last_modified=None)

def get_component_source(self)

def get_component_source_file(self)

back to section top
Class ModuleComponentSource(ComponentSource)

represents a loadable module containing either a ModuleComponent class, a function, a class instance which is callable or a method on a class instance.

def __init__(self, arg=None, module=None, objpath=None, name=None, callable_=None, class_=None, last_modified=None)

def can_compile(self)

def copy(self, use_static_source=False)

def inspect_target(self, arg, objpath)

def reload(self, module)

back to section top
Class ModuleComponentSourceSingleton(type)

a metaclass for ModuleComponentSource which allows its constructor to cache the inspection results of the "arg" constructor parameter.

back to section top
Module myghty.session

Class MyghtySessionArgs

def __init__(self, data_dir=None, **params)

def clone(self, **params)

def get_session(self, request, **params)

back to section top
Class Session

session object that uses container package for storage

def __init__(self, request, id=None, invalidate_corrupt=False, use_cookies=True, type=None, data_dir=None, key='myghty_session_id', timeout=None, cookie_expires=True, secret=None, log_file=None, namespace_class=None, **params)

created = property()

def debug(self, message)

def delete(self)

deletes the persistent storage for this session, but remains valid.

def has_key(self, key)

def invalidate(self)

invalidates this session, creates a new session id, returns to the is_new state

def iteritems(self)

def keys(self)

def load(self)

loads the data from this session from persistent storage

def lock(self)

locks this session against other processes/threads. this is automatic when load/save is called. ***use with caution*** and always with a corresponding 'unlock' inside a "finally:" block, as a stray lock typically cannot be unlocked without shutting down the whole application.

def save(self)

saves the data for this session to persistent storage

def unlock(self)

unlocks this session against other processes/threads. this is automatic when load/save is called.

***use with caution*** and always within a "finally:" block, as a stray lock typically cannot be unlocked without shutting down the whole application.

back to section top
Class SignedCookie(BaseCookie)

extends python cookie to give digital signature support

def __init__(self, secret, input=None)

def value_decode(self, val)

def value_encode(self, val)

back to section top