ModjyLocateCallables » History » Version 2
Alan Kennedy, 2009-03-15 11:00 PM
h1. Writing applications with modjy.
h2(#locating_callables). How modjy locates application callable objects.
According to the "WSGI specification":http://www.python.org/dev/peps/pep-0333/, all WSGI applications must be python callable objects, taking a defined parameter list. Application callables can be python "functions":http://docs.python.org/ref/function.html, class instances with a "__call__()":http://docs.python.org/ref/callable-types.html method, or indeed "any callable object":http://docs.python.org/ref/calls.html.
There are two different mechanisms by which you can specify application callable objects to modjy. They are
# By specifying a single importable name. This requires specifying the name fully-package-qualified name of an importable WSGI handler, e.g. *some_framework.web.handlers.WSGIHandler*. This is the preferred mechanism, and takes precedence over the other mechanism, if configuration values are provided for both import mechanisms.
# By specifying a combination of three names, a *directory name*, a *file name*, and a *callable name*.
Each of these mechanisms is described below
h2(#import_mechanism). The importable name mechanism.
This mechanism uses a single string which specifies an importable name, which when imported should deliver a python callable object. As described above, this can be "any python callable":http://docs.python.org/ref/calls.html. The importable name is specified as a single string. However, there are some small variations on how that string is specified, depending on the nature of the callable.
# *Simple callable*: if the target application is directly callable, e.g. a simple function, then you need only specify the name of the callable/function, and it will be called directly by modjy. Example: *some_framework.web.handlers.WSGIHandlerFunction*
# *Instance*: if the target application is an instantiable object, e.g. a class, then it will need to be "instantiated":http://www.faqs.org/docs/diveintopython/fileinfo_instantiation.html before it can be called. To do this, supply parentheses/brackets after the name. Example: *some_framework.web.handlers.WSGIHandlerClass()*. In this case, modjy will locate the definition of the *WSGIHandlerClass* in *some_framework.web.handlers*, create an instance of that class, and use that as the application. Note that when the application instance is called to service a WSGI request, the method that will be invoked is the *__call__* method.
# *Instance method*: if you want to use a class instance to service WSGI requests, but need to specify a specific method, then add the handler method name onto the end of the importable name. Example: *some_framework.web.handlers.WSGIHandlerClass().handler*. With this example, modjy will locate the WSGIHandlerClass, as described above, create an instance of it, and then use the *handler* method of that instance as that application callable.
h3. The importable name mechanism and reloading
*Reloading is not supported with the importable name mechanism*. When the importable name mechanism is used, the value of the *reload_on_mod* parameter is *ignored*.
h3. The importable name mechanism and caching
Caching means that the same application callable object will be re-used repeatedly, to save object creation overhead. You have the choice of whether or not to enable caching using the *cache_callables* parameter, described in the [[ModjyConfiguration|modjy configuration reference]].
If caching is *disabled* when using the importable name mechanism, this means that a new application object will be created for every new request, when appropriate. When the application is a simple callable, as described above, then caching has no meaning, since there is no instance to be re-used. When the application is an *instantiable*, as described above, then new instances will be created for every request.
If caching is *enabled* and the application callable is a class instance, then the same instance will be reused for every single request.
h2(#dir_file_call_mechanism). The directory/filename/callable callable mechanism
An alternative mechanism for locating an application callable is to specify the full path to an application file, and the name of an application callable within that file. The full path is specified using a combination of a directory name and a filename. In order to locate WSGI application callables with this mechanism, modjy needs three pieces of information.
# The directory in which to look for the application's python source file.
# The name of the application source file in that directory.
# The name of the callable application object in that source file.
h3. The application directory
Firstly, you need to specify the name of a directory containing the python file containing the source code for the application. Notes for this parameter include
# If do not supply a value for this parameter, the default value parameter is the [[ModjyServletContextRoot|servlet context root directory]]
# You can specify a directory relative to the [[ModjyServletContextRoot|servlet context root directory]] by using a *$* at the beginning of path. For example, if your application resides in a directory named *my_apps_dir*, at the same level as the *WEB-INF* directory, then specify *$/my_apps_dir* as the directory name. If the *my_apps_dir* directory lives inside the *WEB-INF* directory, then specify *$/WEB-INF/my_apps_dir* as the directory name.
h3. The application filename
Once it has located the application directory, modjy then looks for an application source file. Modjy uses the same filename for all application source files. The default value for this filename is *application.py*. You can change this value by setting the modjy configuration variable *app_filename*.
h3. The callable object name
Lastly, having loaded and executed the application source file in response to a request, modjy needs to find a python callable object within the resulting python namespace. There are two different ways to set the name of the callable used for a request. They are
# *By configuration*. The configuration parameter *app_callable_name* can be used to set the name of the callable in the python namespace. By default, modjy always uses the value of this parameter, whose default value is *handler*. So if you don't change callable name configuration, all WSGI application objects should called "handler".
# *From the request query string*. Modjy can be configured to extract the callable name from the query string of each request. This is done by specifying the name of the query field to be used in the configuration variable *callable_query_name*. If a value is given for this parameter, it will be used to search the query string of every request for a query parameter of that name. If the named query parameter is present, its value will be used as the name of the callable object. If the named query parameter is not found, the value configured for the *app_callable_name* configuration parameter (described above) will be used instead. Searching for callable names in query parameters *is disabled by default*. Security conscious deployers will probably wish to leave it disabled, since it provides a mechanism for the client to obtain access to the application's python objects.
Now modjy knows the pathname and callable name for the application. It now needs to decide whether it needs to load and compile the application source code, to find a definition of the application object, or whether it already has a usable instance of the application object in its *cache*.
h3. The application object cache
With the directory/file/callable mechanism, you can configure modjy to cache application objects for reuse for multiple requests. Application objects are stored in a cache, keyed under (pathname, callablename). If a request arrives which maps to an application object that is in the cache, then the cached object will be reused. Thus (unless the source file has been modified and *reload_on_mod* is true) the application source file will *not* be reloaded and recompiled.
Conversely, if caching is disabled, this means that a fresh application object will be created for every new request. This will have the effect of causing the reloading and recompilation of the application source file for every request, which may be less efficient than you would like. So use this option carefully.
Lastly, note that the *cache_callables* parameter has implications for the *wsgi.run_once* environment variable. Therefore, when caching is disabled, modjy sets the value of *wsgi.run_once* to *true* (thus essentially making cache disablement almost equivalent to running as a CGI script).
h3. Reloading source on modification
With the directory/file/callable mechanism, you can configure modjy to reload application objects when their containing source file has been modified. See under *reload_on_mod* in the [[ModjyConfiguration|modjy configuration reference]] for more information.
Obviously, this parameter *only* takes effect when caching is enabled. Disabled caching means that the application source code is reloaded and recompiled for every request. If reload_on_mod is enabled, then cached objects will only be discarded when their containing source file has been modified. This is obviously a useful facility during a testing/debugging cycle. Also obviously, checking the access time on application source files comes at a small but finite resource cost for every single request, so you may want to disable it in production scenarios.
You can configure modjy to run your application objects in either multi-threaded or single-threaded mode. See under *multithread* in the [[ModjyConfiguration|modjy configuration reference]] for more information.