home     documentation     download     Spyce logo

Documentation - Modules

Prev: - Taglib Up: 3.8 - Modules Next: 3.9 - Tags

3.8.12. Writing Modules

Writing your own Spyce modules is simple.

A Spyce modules is simply a Python class that exposes specific methods to the Spyce server. The most important are start, finish, and init. With these, a Spyce module may access the internal request and response structures or alter the behaviour of the runtime engine in some way.

Let us begin with a basic example called myModule. It is a module that implements one function named foo().

from spyceModule import spyceModule

class myModule(spyceModule):
  def foo(self):
    print 'foo called'

Saving this code in myModule.py in the same directory as the Spyce script, or somewhere on the module path, we could use it as expected:

[[.import name=myModule]]
[[ myModule.foo() ]]

A Spyce module can be any Python class that derives from spyceModule.spyceModule. When it is loaded, Spyce assigns it a __file__ attribute indicating its source location. Do not override the __init__(...) method because it is inherited from spyceModule and has an fixed signature that is expected by the Spyce engine's module loader. The inherited method accepts a Spyce API object, a Bastion of spyce.spyceWrapper, an internal engine object, and stores it in self._api. This is the building block for all the functionality that any module provides. The available API methods of the wrapper are (listed in spyceModule.spyceModuleAPI):

  • getFilename: Return filename of current Spyce
  • getCode: Return processed Spyce (i.e. Python) code
  • getCodeRefs: Return python-to-Spyce code line references
  • getModRefs: Return list of import references in Spyce code
  • getServerObject: Return unique (per engine instance) server object
  • getServerGlobals: Return server configuration globals
  • getServerID: Return unique server identifier
  • getModules: Return references to currently loaded modules
  • getModule: Get module reference. The module is dynamically loaded and initialised if it does not exist (ie. if it was not explicitly imported, but requested by another module during processing)
  • setModule: Add existing module (by reference) to Spyce namespace (used for includes)
  • getGlobals: Return the Spyce global namespace dictionary
  • registerModuleCallback: Register a callback for modules change
  • unregisterModuleCallback: Unregister a callback for modules change
  • getRequest: Return internal request object
  • getResponse: Return internal response object
  • setResponse: Set internal response object
  • registerResponseCallback: Register a callback for when internal response changes
  • unregisterResponseCallback: Unregister a callback for when internal response changes
  • spyceString: Return a spyceCode object of a string
  • spyceFile: Return a spyceCode object of a file
  • spyceModule: Return Spyce module class
  • spyceTaglib: Return Spyce taglib class
  • setStdout: Set the stdout stream (thread-safe)
  • getStdout: Get the stdout stream (thread-safe)

For convenience, one can sub-class the spyceModulePlus class instead of the regular spyceModule. The spyceModulePlus defines a self.modules field, which can be used to acquire references to other modules loaded into the Spyce environment. The response module, for instance, would be referenced as self.modules.response. Modules are loaded on demand, if necessary. The spyceModulePlus also contains a self.globals field, which is a reference to the Spyce global namespace dictionary, though this should rarely be needed.

Note: It is not expected that many module writers will need the entire API functionality. In fact, the vast majority of modules will use a small portion of the API, if at all. Many of these functions are included for just one of the standard Spyce modules that needs to perform some esoteric function.

Three Spyce module methods, start(), init([args]) and finish(error) are special in that they are automatically called by the runtime during Spyce request startup, processing and cleanup, respectively. The modules are started in the order in which module directives appear in the file, before processing begins. The implicitly loaded modules are always loaded first. The init method is called during Spyce processing at the location of the module directive in the file, with the optional args attribute is passed as the arguments of this call. Finally, after Spyce processing is complete, the modules are finalized in reverse order. If there is an unhandled exception, it will be wrapped in a spyce.spyceException object and passed as the first parameter to finish(). During successful completion of Spyce processing (i.e. without exception), the error parameter is None. The default inherited start, init and finish methods from spyceModule are noops.

Note 2: When writing a Spyce module, consider carefully why you are selecting a Spyce module over a regular Python module. If it is just code, that does not interact with the Spyce engine, then a regular Python import instead of an Spyce [[.import]] can just as easily bring in the necessary code, and is preferred. In other words, choose a Spyce module only when there is a need for per-request initialization or for one of the engine APIs.

Module writers are encouraged to look at the existing standard modules as examples and the definitions of the core Spyce objects in spyce.py as well. If you write or use a novel Spyce module that you think is of general use, please email your contribution, or a link to it. Also, please keep in mind that the standard modules are designed with the goal of being minimalist. Much functionality is readily available using the Python language libraries. If you think that they should be expanded, also please send a note.

Prev: - Taglib Up: 3.8 - Modules Next: 3.9 - Tags

Spyce logo
Python Server Pages
version 2.1.3
Spyce Powered SourceForge Logo