Myghty Documentation
Version: 1.1 Last Updated: 12/05/08 09:48:47
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