.. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% .. % Copyright 2001 by Object Craft P/L, Melbourne, Australia. .. % LICENCE - see LICENCE file distributed with this software for details. .. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% .. _mixin-ref: ********************* Mixin Class Reference ********************* Most of Albatross exists as a collection of plug compatible mixin classes which you select from to define the way your application should behave and how it will be deployed. Figure :ref:`fig-toolkit` shows the organisation of the component types in the toolkit. .. _fig-toolkit: .. figure:: .build/figures/toolkit.* :align: center Toolkit Components The divisions in the diagram represent conceptually different functional areas within the toolkit. Templating This layer provides the Albatross templating functionality. Template classes make use of the methods defined in the next layer down to access application functionality and data. Classes in this layer are defined in the :mod:`albatross.template` and :mod:`albatross.tags` modules. Template Execution An execution context suitable for interpreting template files is constructed by combining one mixin of each type from this layer. Application Model Execution contexts which subclass a :class:`PageMixin` class in addition to the mixins from the above layer are suitable for use in Albatross applications. The :class:`PageMixin` class controls how the application locates code and template files for each page served by the application. The :class:`PickleSignMixin` class is responsible for modifying pickles which are sent to the browser to prevent or detect modification. Your Application In this layer you will typically create your own application and execution context classes by subclassing a prepared application class. For the most part Albatross applications are independent of the method by which they are deployed. Depending upon which :class:`Request` class you choose from this layer you can either deploy your application via CGI, ``mod_python`` (``_), FastCGI (``_) or as a stand-alone python HTTP server. Wherever possible the Albatross mixin classes use member names which begin with double underscore to trigger Python name mangling. This protects your classes from having member name clashes with private members of the mixin classes. Any member names which are not mangled are intended to be accessed in your application code. .. _mixin-resource: ResourceMixin Class =================== Albatross only supplies one class for this function; the :class:`ResourceMixin` class. This mixin manages application resources which which do not change regardless of context. The resources managed are tag classes, HTML macros, and HTML lookup tables. The :class:`SimpleContext` execution context class subclasses the :class:`ResourceMixin` class. During the constructor it registers all of the standard Albatross tags. As HTML templates are executed the macros and lookup tables in those templates are registered. All standard Albatross application classes inherit from the :class:`Application` class which in turn subclasses the :class:`ResourceMixin` class. During the application class constructor all of the standard Albatross tags are registered. The :class:`AppContext` class which is subclassed by all Albatross application execution context classes proxies all HTML macro and lookup table methods and directs them to the application object. .. method:: ResourceMixin.__init__() When you inherit from the :class:`ResourceMixin` class you must call this constructor to initialise the internal variables. .. method:: ResourceMixin.get_macro(name) Returns the macro previously registered by the name in the *name* argument. If no such macro exists ``None`` is returned. .. method:: ResourceMixin.register_macro(name, macro) Registers the HTML macro in the *macro* argument under the name in the *name* argument. .. method:: ResourceMixin.get_lookup(name) Returns the lookup table previously registered by the name in the *name* argument. If no such lookup exists ``None`` is returned. .. method:: ResourceMixin.register_lookup(name, lookup) Registers the HTML lookup table in the *lookup* argument under the name in the *name* argument. .. method:: ResourceMixin.discard_file_resources(filename) Discards macros and lookups loaded from *filename*. This is called prior to reloading a template. .. method:: ResourceMixin.get_tagclass(name) Returns the tag class in which the :attr:`name` member matches the name in the *name* argument. If no such tag class exists ``None`` is returned. .. method:: ResourceMixin.register_tagclasses(...) Registers one or more tag classes indexing them by the value in the :attr:`name` member of each class. .. _mixin-execute: ExecuteMixin Class ================== Albatross only supplies one class for this function; the :class:`ExecuteMixin` class. This mixin provides a "virtual machine" which is used to execute HTML template files. All standard Albatross execution context classes inherit from this class. .. method:: ExecuteMixin.__init__() When you inherit from the :class:`ExecuteMixin` class you must call this constructor to initialise the internal variables. .. method:: ExecuteMixin.get_macro_arg(name) Retrieves a macro argument from the macro execution stack. The stack is searched from the most recently pushed dictionary for an argument keyed by *name*. If no argument is found a :exc:`MacroError` exception is raised. .. method:: ExecuteMixin.push_macro_args(dict) Pushes a dictionary of macro arguments onto the macro execution stack. .. method:: ExecuteMixin.pop_macro_args() Pops the most recently pushed dictionary of macro arguments from the macro execution stack. .. method:: ExecuteMixin.push_content_trap() Saves accumulated content on the trap stack and then resets the content list. .. method:: ExecuteMixin.pop_content_trap() Joins all parts on the content list and returns the result. Sets the content list to the value popped off the trap stack. The content trap is useful for performing out-of-order execution of template text. The ```` tag makes use of the content trap. .. method:: ExecuteMixin.write_content(data) Appends the content in *data* to the content list. .. method:: ExecuteMixin.flush_content() Does nothing if a content trap stack is in effect, otherwise it joins all parts in the content list and sends it to the browser via the :meth:`send_content` method. The content list is then reset via the :meth:`reset_content` method. .. method:: ExecuteMixin.flush_html() This is an alias for :meth:`flush_content`. .. method:: ExecuteMixin.send_content(data) Sends the content passed in the *data* argument to standard output. This is overridden in the :class:`AppContext` class to redirect *data* to the :meth:`write_content` method of the application referenced in the :attr:`app` member. .. method:: ExecuteMixin.reset_content() Sets the content list to an empty list and clears the content trap stack. .. _mixin-response: ResponseMixin Class =================== The :class:`ResponseMixin` class provides functionality to manage the delivery of the application response to the browser. The class maintains headers in a case insensitive ordered dictionary that ensures the headers are sent to the browser in the same sequence as they are set (via :meth:`set_header` or :meth:`add_header`). The class automatically sends the headers to the browser when the first content is sent. Any attempt to modify or send headers after they have been sent will raise an :exc:`ApplicationError` exception. All Albatross execution context classes except for :class:`SimpleContext` inherit from this class. .. method:: ResponseMixin.__init__() When you inherit from the :class:`ResponseMixin` class you must call this constructor to initialise the internal variables. .. method:: ResponseMixin.get_header(name) Returns a list of values of the *name* header from the internal store. If the header does not exist then ``None`` is returned. .. method:: ResponseMixin.set_header(name, value) Sets the value of the *name* header to *value* in the internal store, replacing any existing headers of the same name. If headers have already been sent to the browser then an :exc:`ApplicationError` exception will be raised. .. method:: ResponseMixin.add_header(name, value) Sets the value of the *name* header to *value* in the internal store, appending the new header immediately after any existing headers of the same name. If headers have already been sent to the browser then an :exc:`ApplicationError` exception will be raised. .. method:: ResponseMixin.del_header(name) Removes the *name* header from the internal store. If headers have already been sent to the browser then an :exc:`ApplicationError` exception will be raised. .. method:: ResponseMixin.write_headers() Writes all headers in ascending sequence to the browser. Each header is sent via the :class:`Request` object :meth:`write_header` method. At the end of headers the :class:`Request` object :meth:`end_headers` method is called. If headers have already been sent to the browser then an :exc:`ApplicationError` exception will be raised. .. method:: ResponseMixin.send_content(data) Sends the content in *data* to the browser via the :class:`Request` object :meth:`write_content` method. If headers have not already been delivered to the browser then the :meth:`write_headers` method is called before the *data* is written. .. method:: ResponseMixin.send_redirect(loc) If a cookie header has been set it is sent to the browser then the :meth:`redirect` method of the :attr:`request` member is called and the result is returned. .. _mixin-template: TemplateLoaderMixin Classes =========================== This mixin is responsible for loading template files. Albatross supplies two classes; :class:`TemplateLoaderMixin` and :class:`CachingTemplateLoaderMixin`. .. _mixin-templ-loader: TemplateLoaderMixin ------------------- The :class:`TemplateLoaderMixin` class is a simplistic loader which performs no caching. .. method:: TemplateLoaderMixin.__init__(base_dir) When you inherit from the :class:`TemplateLoaderMixin` class you must call the constructor to define the root directory where template files will be loaded in the *base_dir* argument. .. method:: TemplateLoaderMixin.load_template(name) Load and return the parsed template file specified in the *name* argument. The path to the template file is constructed by performing ``os.path.join()`` on the *base_dir* specified in the constructor and the *name* argument. If there is an error reading the template a :exc:`TemplateLoadError` will be raised. The class remembers the names of all loaded templates. .. method:: TemplateLoaderMixin.load_template_once(name) Returns ``None`` if the template specified in the *name* argument has been previously loaded. If not previously loaded it is loaded via the :meth:`load_template` method and returned. .. _mixin-templ-cache: CachingTemplateLoaderMixin -------------------------- The :class:`CachingTemplateLoaderMixin` class caches loaded templates to and only reloads them if they have been modified since they were last loaded. .. method:: CachingTemplateLoaderMixin.__init__(base_dir) When you inherit from the :class:`CachingTemplateLoaderMixin` class you must call the constructor to define the root directory where template files will be loaded in the *base_dir* argument. .. method:: CachingTemplateLoaderMixin.load_template(name) Return the parsed template file specified in the *name* argument. The path to the template file is constructed by performing ``os.path.join()`` on the *base_dir* specified in the constructor and the *name* argument. If there is an error reading the template a :exc:`TemplateLoadError` will be raised. If the template has been previously loaded it will only be reloaded if it has been modified since last load. .. method:: CachingTemplateLoaderMixin.load_template_once(name) Call the :meth:`load_template` method and return the template if it is either loaded for the first time or reloaded, else return ``None``. .. _mixin-recorder: RecorderMixin Classes ===================== This mixin is passed form and input field recording messages as ````, ````, ````, and ```` tags are executed. Albatross supplies two classes; :class:`StubRecorderMixin` and :class:`NameRecorderMixin`. .. _mixin-rec-stub: StubRecorderMixin ----------------- The :class:`StubRecorderMixin` class ignores all form events. .. method:: StubRecorderMixin.form_open() Does nothing. .. method:: StubRecorderMixin.form_close() Does nothing. .. method:: StubRecorderMixin.input_add(itype, name [, value ``= None``]) Does nothing. .. method:: StubRecorderMixin.merge_request() Merges request fields into ``ctx.locals``. .. _mixin-rec-name: NameRecorderMixin ----------------- The :class:`NameRecorderMixin` class records details of all input fields used by a form. When the form element is closed, a hidden field named ``__albform__`` containing these details is added to the form. When processing a request, the :meth:`merge_request` method only merges fields with ``ctx.locals`` when they match the details found in the submitted ``__albform__`` field. .. method:: NameRecorderMixin.__init__() When you inherit from the :class:`NameRecorderMixin` class you must call the constructor. .. method:: NameRecorderMixin.form_open() Called when the ```` tag is opened. .. method:: NameRecorderMixin.form_close() Called just before the ```` tag is closed. A hidden field named ``__albform__`` is written to the output. .. method:: NameRecorderMixin.input_add(itype, name [, value ``= None``] [, return_list ``= 0``]) Called when an ```` tag is executed. The *itype* argument contains the ``type`` attribute from the input tag, *name* contains the ``name`` tag attribute, and *value* contains the value of the input field if it is known and relevant. The *return_list* argument indicates the presence of the ``list`` attribute on the input tag. As fields are added to each form the value of the *return_list* argument is checked against any previous setting of the argument for the same field name. The argument value is also checked against whether or not there are multiple instances of the field name. An detected discrepancy between the argument value and actual fields will raise a :exc:`ApplicationError` exception. .. method:: NameRecorderMixin.merge_request() Retrieves the ``__albform__`` value from the browser request decodes it and then merges the browser request into the local namespace accordingly. If an input field has been flagged to return a list (via the ``list`` tag attribute) then the method will create a list in ``ctx.locals`` for the field regardless of the number of values sent by the browser. An empty list is created when the field is missing from the browser request. Request fields not listed in ``__albform__`` are ignored. .. _mixin-namespace: NamespaceMixin Class ==================== Albatross only supplies one class for this function; the :class:`NamespaceMixin` class. This mixin provides a local and global namespace for evaluating expressions embedded in HTML template files. When the browser request is merged into the execution context the input field values are written to the local namespace. .. method:: NamespaceMixin.__init__() When you inherit from the :class:`NamespaceMixin` class you must call the constructor. The global namespace for evaluating Python expressions in HTML templates is initialised as an empty dictionary in the constructor. .. attribute:: NamespaceMixin.locals An empty object which is used for the local namespace for evaluating expressions in HTML templates. It is initialised as an instance of an empty class in the constructor to allow values to simply be assigned to attributes of this member. Loading the session merges the session values into this member. .. method:: NamespaceMixin.clear_locals() Resets the :attr:`locals` member to an empty object. .. method:: NamespaceMixin.set_globals(dict) Sets the global namespace for evaluating expressions to the *dict* argument. The :class:`SimpleContext` class constructor automatically sets this to the globals of the function which invoked the :class:`SimpleContext` constructor. The :meth:`run_template` and :meth:`run_template_once` methods of the :class:`AppContext` calls this method to set global namespace to the globals of the calling function. .. method:: NamespaceMixin.eval_expr(expr) Called by the template file interpreter to evaluate the embedded Python expression in the *expr* argument. .. method:: NamespaceMixin.set_value(name, value) Sets the local namespace attribute named in the *name* argument to the value in the *value* argument. If the *name* argument begins with an underscore the method will raise a :exc:`SecurityError` exception. This is used by the application :meth:`merge_request` method to merge individual browser request fields into the local namespace. There is a special "backdoor" identifier format which which directs browser request fields to the :meth:`set_backdoor` method of :class:`ListIterator` and :class:`TreeIterator` objects. The backdoor identifiers are generated by the ```` and ```` tags to implement sequence and tree browsing requests. The method implements a parser which can handle names of the form: .. productionlist:: name: identifier \| list-backdoor \| tree-backdoor identifier: identifier (("." identifier) \| ("[" number "]"))\* list-backdoor: operation "," iter tree-backdoor: operation "," iter "," alias .. method:: NamespaceMixin.merge_vars(...) This method merges request fields matching a prefix given in the argument list to the local namespace (via the :meth:`set_value` method described above). Normally, merging of request fields is automatic: either all request fields are copied when :class:`StubRecorderMixin` is used, or fields listed in ``__albform__`` are copied when :class:`NameRecorderMixin` is used. However in cases where :class:`NameRecorderMixin` is used and no ``__albform__`` field is present, request merging does not occur, and this method is needed to allow the application to explicitly request fields be merged. .. method:: NamespaceMixin.make_alias(name) Called to generate an alternate name for an object referenced in the ``alias`` attribute of an Albatross tag. The method resolves the *name* argument up to the last "." and then calls the :meth:`albatross_alias` method of the resolved object. The resolved object is then entered into the local namespace and the session using the name returned by :meth:`albatross_alias`. The return value is a new name by combining the name returned by :meth:`albatross_alias` with the part of the original name following and including the last ".". Refer to the ```` documentation in the :ref:`tag-input` section for an explanation of why this method exists. .. method:: NamespaceMixin.get_value(name) Retrieves the value identified by the *name* argument from the local namespace. If the named value does not exist then ``None`` is returned. .. method:: NamespaceMixin.has_value(name) Returns whether or not the value named in the *name* attribute exists in the local namespace. .. method:: NamespaceMixin.has_values(...) Returns TRUE only if values named in the argument list exist in the local namespace. .. _mixin-ctxsession: SessionContextMixin Classes =========================== This mixin is used to manage the encoding and decoding of session data. Albatross supplies a number of classes for use in the execution context; :class:`StubSessionMixin`, :class:`SessionBase`, :class:`HiddenFieldSessionMixin`, :class:`SessionServerContextMixin`, and :class:`SessionFileContextMixin`. The :class:`SessionBase` class provides base functionality for non-stub session classes. Loading and storing of session data is usually performed by an application mixin. The :class:`SessionServerAppMixin` is designed to be used in the application object. .. _mixin-ses-stub: StubSessionMixin ---------------- The :class:`StubSessionMixin` class ignores all session operations. .. method:: StubSessionMixin.add_session_vars(...) Does nothing. .. method:: StubSessionMixin.del_session_vars(...) Does nothing. .. method:: StubSessionMixin.encode_session() Does nothing. .. method:: StubSessionMixin.load_session() Does nothing. .. method:: StubSessionMixin.save_session() Does nothing. .. method:: StubSessionMixin.remove_session() Does nothing. .. method:: StubSessionMixin.set_save_session(flag) Does nothing. .. method:: StubSessionMixin.should_save_session() Returns ``0``. .. _mixin-ses-base: SessionBase ----------- The :class:`SessionBase` class provides base session handling functionality which is used by all standard Albatross execution context session mixin classes. .. method:: SessionBase.__init__() When you inherit from the :class:`SessionBase` class you must call this constructor. The class maintains a dictionary of all names from the execution context local namespace which belong in the session. This dictionary is restored along with the session when the session is decoded. .. method:: SessionBase.add_session_vars(...) Adds all listed names to the session dictionary. The named variables must exist in the :attr:`locals` member or a :exc:`SessionError` will be raised. The names can optionally be supplied as a list or tuple of names. .. method:: SessionBase.default_session_var(name, value) Adds a name to the session directory. Sets a value in the local namespace if the name is not already in the local namespace. .. method:: SessionBase.del_session_vars(...) Deletes all listed names from the session dictionary. The names can optionally be supplied as a list or tuple of names. .. method:: SessionBase.session_vars() Returns a list of the names that are currently in the session. .. method:: SessionBase.remove_session() Deletes all names from the session dictionary and clears all values from the local namespace via the :meth:`clear_locals` method. .. method:: SessionBase.decode_session(text) Performs ``cPickle.loads()`` to retrieve a dictionary of session values. The dictionary is merged into the session local namespace. Adds the keys of the dictionary to the session dictionary. Note that an import hook is used around the ``cPickle.loads()`` to redirect requests to load page modules to the :meth:`app.load_page_module` method. This allows the pickler to find classes which are defined in application page modules. Whether a module is a page module is determined by calling the :meth:`app.is_page_module` method, passing the module name. .. method:: SessionBase.encode_session() Builds a dictionary by extracting all local namespace values which are listed in the session dictionary. A test pickle is performed on each value and any unpickleable value is discarded and an error message is written to ``sys.stderr``. The dictionary is then passed to ``cPickle.dumps()`` and the result is returned. .. method:: SessionBase.set_save_session(flag) Sets the flag which controls whether the session will be saved at the end of request processing. By default the internal flag is ``TRUE`` which means the session will be saved. .. method:: SessionBase.should_save_session() Returns the flag which controls whether the session will be saved at the end of request processing. .. _mixin-ses-field: HiddenFieldSessionMixin ----------------------- Saves session state to a hidden field named ``__albstate__`` at the end of every form produced by ```` tags. Inherits from the :class:`SessionBase` class so you must call the constructor if you subclass this class. .. method:: HiddenFieldSessionMixin.encode_session() Extends the base class :meth:`encode_session` method to ``zlib.compress()`` and ``base64.encodestring()`` the result. This makes the session data suitable for placing in a hidden field in the HTML. .. method:: HiddenFieldSessionMixin.load_session() This is called from the :class:`Application` class :meth:`load_session` method. The session state is retrieved from the browser request, decoded and decompressed then passed to the :meth:`decode_session` method. .. method:: HiddenFieldSessionMixin.save_session() This is called from the :class:`Application` class :meth:`save_session` method at the end of the request processing sequence. The method does nothing because the session state is saved in hidden fields in the HTML. .. method:: HiddenFieldSessionMixin.form_close() Called just before the ```` tag is closed. If the session is flagged to be saved a hidden field named ``__albstate__`` is written to the output. Note that this method is also present in the :class:`RecorderMixin`, so if you inherit from the :class:`HiddenFieldSessionMixin` class you must define a :meth:`form_close` method in the derived class which calls this method in both of the super classes. .. _mixin-ctx-sess: SessionServerContextMixin ------------------------- This class works in concert with the :class:`SessionServerAppMixin` application mixin class to store session data in the Albatross session server. All management of session data storage is performed by the application class. Inherits from the :class:`SessionBase` class so you must call the constructor if you subclass this class. .. method:: SessionServerContextMixin.__init__() When you inherit from the :class:`SessionServerContextMixin` class you must call this constructor. .. method:: SessionServerContextMixin.sesid() Returns the session id. .. method:: SessionServerContextMixin.load_session() This is usually called from the :class:`Application` class :meth:`load_session` method. Retrieves the session id and then either retrieves an existing session or creates a new session via the application object. If an existing session is retrieved it is passed to ``base64.decodestring()`` and ``zlib.decompress()`` then passed to the :meth:`decode_session` method (inherited from the superclass). If an exception is raised during :meth:`decode_session` then the session will be deleted from the server and a new session will be created via the application object :meth:`new_session` method. .. method:: SessionServerContextMixin.save_session() This is called from the :class:`Application` class :meth:`save_session` method at the end of the request processing sequence. If the session save flag has been cleared via the :meth:`set_save_session` method then the session is not saved. Before saving a session the method calls the superclass :meth:`encode_session` then calls ``zlib.compress()`` and ``base64.encodestring()`` to convert the session to plain text which is passed to the :meth:`put_session` application method to save the session. .. method:: SessionServerContextMixin.remove_session() This is called from the :class:`Application` class :meth:`remove_session` method. The method calls the superclass :meth:`remove_session` then calls the :meth:`del_session` application method to remove the session at the server. .. _mixin-ctx-file-sess: SessionFileContextMixin ----------------------- This class works in concert with the :class:`SessionFileAppMixin` application mixin class to store session data in the local file-system. All management of session data storage is performed by the application class. Inherits from the :class:`SessionBase` class so you must call the constructor if you subclass this class. .. method:: SessionFileContextMixin.__init__() When you inherit from the :class:`SessionFileContextMixin` class you must call this constructor. .. method:: SessionFileContextMixin.sesid() Returns the session id. .. method:: SessionFileContextMixin.load_session() This is usually called from the :class:`Application` class :meth:`load_session` method. Retrieves the session id and then either retrieves an existing session or creates a new session via the application object. If an existing session is retrieved it is passed to the :meth:`decode_session` method (inherited from the superclass). If an exception is raised during :meth:`decode_session` then the session will be deleted from the server and a new session will be created via the application object :meth:`new_session` method. .. method:: SessionFileContextMixin.save_session() This is called from the :class:`Application` class :meth:`save_session` method at the end of the request processing sequence. If the session save flag has been cleared via the :meth:`set_save_session` method then the session is not saved. Before saving a session the method calls the superclass :meth:`encode_session` then calls the :meth:`put_session` application method to save the session. .. method:: SessionFileContextMixin.remove_session() This is called from the :class:`Application` class :meth:`remove_session` method. The method calls the superclass :meth:`remove_session` then calls the :meth:`del_session` application method to remove the session at the server. .. _mixin-ctx-branching-sess: BranchingSessionMixin --------------------- A persistent problem with server-side sessions is the browser state getting out of synchronisation with the application state. This occurs when the browser "back" button is used, or when a form is reloaded (this is logically equivilent to a "back" then a resubmission of the old form state). One solution to this problem is to maintain a server-side session for each interaction with the browser, rather than a single session per client that is recycled for each interaction. A unique session identifier is stored in a hidden form field, which allows us to retrieve the appropriate version of the session on form submission (the hidden field value is rolled back with the browser state when the "back" button is used, unlike a cookie). This class provides a drop-in replacement for the :class:`SessionServerContextMixin` and implements this session-per-interaction behaviour. .. method:: BranchingSessionMixin.__init__() When you inherit from the :class:`BranchingSessionMixin` class you must call this constructor. .. method:: BranchingSessionMixin.sesid() Returns the session id. .. method:: BranchingSessionMixin.load_session() This is usually called from the :class:`Application` class :meth:`load_session` method. Retrieves the session id and then either retrieves an existing session or creates a new session via the application object. If an existing session is retrieved it is passed to the :meth:`decode_session` method (inherited from the superclass). If an exception is raised during :meth:`decode_session` then the session will be deleted from the server and a new session will be created via the application object :meth:`new_session` method. .. method:: BranchingSessionMixin.save_session() This is called from the :class:`Application` class :meth:`save_session` method at the end of the request processing sequence. If the session save flag has been cleared via the :meth:`set_save_session` method then the session is not saved. Before saving a session the method calls the superclass :meth:`encode_session` then calls the :meth:`put_session` application method to save the session. .. method:: BranchingSessionMixin.remove_session() This is called from the :class:`Application` class :meth:`remove_session` method. The method calls the superclass :meth:`remove_session` then calls the :meth:`del_session` application method to remove the session at the server. .. method:: BranchingSessionMixin.form_close() Called just before the ```` tag is closed. If the session is flagged to be saved a hidden field named ``__albsessid__`` containing the session identifier is written to the output. Note that this method is also present in the :class:`RecorderMixin`, so if you inherit from the :class:`BranchingSessionMixin` class you must define a :meth:`form_close` method in the derived class which calls this method in both of the super classes. .. _mixin-appsession: SessionAppMixin Classes ======================= .. _mixin-app-sess: SessionServerAppMixin --------------------- The application mixin works in concert with the :class:`SessionServerContextMixin` execution context method to store sessions in the Albatross session server. Whenever there are problems communicating with the session server the class raises a :exc:`SessionServerError` exception, which is a subclass of :exc:`SessionError`. Unless you have a reason to do otherwise, catch :exc:`SessionError` rather than :exc:`SessionServerError`, as this allows other Session classes to be substituted with minimal change. .. method:: SessionServerAppMixin.__init__(appid [, server ``= 'localhost'``] [, port ``= 34343``] [, age ``= 1800``]) When you inherit from the :class:`SessionServerAppMixin` class you must call this constructor. The *appid* argument specifies the name of the cookie attribute which is used to store the session id. This uniquely identifies the application at the web server. Multiple applications can share sessions by defining the same value in this argument. The *server* and *port* arguments specify the location of the Albatross session server. By using a session server you can have a number of web serving machines which transparently share session data. The *age* argument specifies how long (in seconds) an idle session will be stored at the server before it is discarded. A connection to the session server is established. The connection will be kept open for the lifetime of the application object. .. method:: SessionServerAppMixin.ses_appid() Returns the *appid* argument which was passed to the constructor. .. method:: SessionServerAppMixin.get_session(sesid) Returns the session identified by *sesid* argument and the *appid* passed to the constructor. If no such session exists ``None`` is returned. .. method:: SessionServerAppMixin.new_session() Returns a new session id for the *appid* passed to the constructor. .. method:: SessionServerAppMixin.put_session(sesid, text) Saves the *text* argument as session data for the session identified by *sesid* argument and the *appid* passed to the constructor. .. method:: SessionServerAppMixin.del_session(sesid) Removes the session identified by *sesid* argument and the *appid* passed to the constructor. .. _mixin-app-file-sess: SessionFileAppMixin ------------------- The application mixin works in concert with the :class:`SessionFileContextMixin` execution context method to store sessions in the local file-system. Whenever there are problems reading or writing sessions from or to disk, the class raises a :exc:`SessionFileError` exception, which is a subclass of :exc:`SessionError`. Unless you have a reason to do otherwise, catch :exc:`SessionError` rather than :exc:`SessionFileError`, as this allows other Session classes to be substituted with minimal change. .. method:: SessionFileAppMixin.__init__(appid , session_dir) When you inherit from the :class:`SessionFileAppMixin` class you must call this constructor. The *appid* argument specifies the name of the cookie attribute which is used to store the session id. This uniquely identifies the application at the web server. Multiple applications can share sessions by defining the same value in this argument. The *session_dir* argument specifies the location on the local file-system in which this application's sessions will be stored. The directory should not be publicly readable, as the session file names are the session id's (knowing a session id allows an attacker to steal that session). Sessions recorded via this class are not automatically aged. An external process will be required to clean orphaned sessions from the session directory (for example, by removing any file that has not been accessed in the last two hours). .. method:: SessionFileAppMixin.ses_appid() Returns the *appid* argument which was passed to the constructor. .. method:: SessionFileAppMixin.get_session(sesid) Returns the session identified by *sesid* argument and the *appid* passed to the constructor. If no such session exists ``None`` is returned. .. method:: SessionFileAppMixin.new_session() Returns a new session id for the *appid* passed to the constructor. Note that if the *session_dir* passed to the constructor does not already exist, this method will attempt to create it. .. method:: SessionFileAppMixin.put_session(sesid, text) Saves the *text* argument as session data for the session identified by *sesid* argument and the *appid* passed to the constructor. .. method:: SessionFileAppMixin.del_session(sesid) Removes the session identified by *sesid* argument and the *appid* passed to the constructor. .. _mixin-sign: PickleSignMixin Classes ======================= This is mixed with the application class to sign or modify pickles before sending them to the browser and to undo and check that modification on the return trip. When processing modified pickles returned from the browser the class discards pickles which do not pass the security check. There is only one mixin supplied for this function; the :class:`PickleSignMixin` class. Pickle strings are combined with the secret string which was passed to the application constructor as the *secret* argument using the HMAC-SHA1 algorithm. The resulting signature is then prepended to the pickle. On the return trip the HMAC-SHA1 sign is compared with the result of the signing process on the pickle returned from the browser. If the two signs are not the same, the pickle is discarded. The process does not prevent users from seeing the contents of a pickle, rather it provides an assurance of its authenticity. The mixin has the following interface. .. method:: PickleSignMixin.__init__(secret) When you inherit from the :class:`PickleSignMixin` class you must call this constructor. The *secret* argument is the secret key which is combined with the pickle to produces the HMAC-SHA1 signature. .. method:: PickleSignMixin.pickle_sign(text) Generates an HMAC-SHA1 signed copy of the *text* argument, using the *secret* constructor argument as key. .. method:: PickleSignMixin.pickle_unsign(text) Compares the HMAC-SHA1 signature on the given *text*, and if valid, returns the unsigned text. If the signature does not match, a :exc:`SecurityError` exception is raised. .. _mixin-page: PageMixin Classes ================= The choice of mixin for this functionality determines how Albatross will locate the code to process the browser request and display the response for each page. Albatross supplies three classes; :class:`PageModuleMixin`, :class:`RandomPageModuleMixin`, and :class:`PageObjectMixin`. .. _mixin-page-module: PageModuleMixin --------------- This class uses a separate Python module for each page in the application. This scales very well at runtime because at most two modules will be loaded for each request; one to process the browser request, and possibly another to display the response. Page modules are cached for further efficiency. The class is designed to be used where the application controls the sequence of pages seen in a browser session so the start page is also specified in the constructor. Application page modules are loaded from a base directory which is specified by the constructor *base_dir* argument. The current application page is identified by the path to the page module relative to the module base directory. Page identifiers consist of an optional path component followed by a module name without extension. For example ``"login"``, ``"user/list"``, ``"home-page/default"``. Page modules are loaded into a dummy ``__alpage__`` namespace to avoid conflicts with python modules, so loading ``"user/list"`` actually imports the module as :mod:`__alpage__.user.list`. To support pickling of instances defined in a page module, a dummy hierarchy of modules needs to be created. In the :mod:`__alpage__.user.list` case mentioned above, a temporary dummy module called :mod:`__alpage__.user` is registered. This will be replaced by the real ``user`` module later if it is loaded. Note also that the :class:`SessionBase` mixin uses an import hook while decoding the session to redirects attempts to load page modules (those that being with ``__alpage__``) to the :meth:`load_page_module` method. Page modules handled by this mixin have the following interface: .. function:: page_enter(ctx [, ...]) :noindex: If this function is present in the new page module it will be called whenever your application code calls the execution context :meth:`set_page` method. For application types which define a start page this method is called in the start page when a new session is created. The *ctx* argument contains the execution context. Any extra arguments which are passed to the :func:`set_page` method are passed as optional extra arguments to this function. .. function:: page_leave(ctx) :noindex: If this function is present in the current page module it will be called whenever your application code changes to another page by calling the execution context :meth:`set_page` method. The *ctx* argument contains the execution context. .. function:: page_process(ctx) :noindex: If this function is present in the page module it will be called when the application object executes the :meth:`process_request` method. This occurs if the browser request was successfully validated. Refer to the :ref:`app-model` section for an overview of the application processing sequence. .. function:: page_display(ctx) :noindex: This is the only mandatory page module function. The application object calls this function when it executes the :meth:`display_response` method as the final step before saving the browser session. Refer to the :ref:`app-model` section for an overview of the application processing sequence. The :class:`PageModuleMixin` class has the following interface. .. method:: PageModuleMixin.__init__(base_dir, start_page) When you inherit from the :class:`PageModuleMixin` class you must call this constructor. The *base_dir* argument specifies the path of the root directory where page modules are loaded from. When deploying your application as a CGI program you can specify a relative path from the location of the application mainline. Apache sets the current directory to root so when using ``mod_python`` deployment you will need to specify a path relative to the root. The *start_page* argument is a page identifier which specifies the first page that new browser session will see. .. method:: PageModuleMixin.module_path() Returns the *base_dir* which was passed to the constructor. .. method:: PageModuleMixin.start_page() Returns the *start_page* which was passed to the constructor. .. method:: PageModuleMixin.load_page(ctx) This method implements part of the standard application processing sequence. It is called immediately after restoring the browser session. The *ctx* argument is the execution context for the current browser request. If no current page is defined in *ctx* then the method will invoke :meth:`ctx.set_page` passing the page specified as the *start_page* argument to the application constructor. The actual page module load is performed via the :meth:`load_page_module` method. Refer to the :ref:`app-model` section for an overview of the application processing sequence. .. method:: PageModuleMixin.load_page_module(ctx, name) Loads the page module identified by the *name* argument and saves a reference to the module in the :attr:`page` member. .. method:: PageModuleMixin.page_enter(ctx, args) Called when your application code calls the execution context :meth:`set_page` method. The *ctx* argument is the execution context for the current browser request. The *args* argument is a tuple which contains all optional extra arguments which were passed to the :meth:`set_page` method. The page module :func:`page_enter` function is called by this method. .. method:: PageModuleMixin.page_leave(ctx) Called before changing pages when your application code calls the execution context :meth:`set_page` method. The *ctx* argument is the execution context for the current browser request. The page module :func:`page_leave` function is called by this method. .. method:: PageModuleMixin.process_request(ctx) This method implements part of the standard application processing sequence. It is called if the browser request is successfully validated. The *ctx* argument is the execution context for the current browser request. The page module :func:`page_process` function is called by this method. Refer to the :ref:`app-model` section for an overview of the application processing sequence. .. method:: PageModuleMixin.display_response(ctx) This method implements part of the standard application processing sequence. It is called as the final stage just before the session is saved. The *ctx* argument is the execution context for the current browser request. The page module :func:`page_display` function is called by this method. Refer to section the :ref:`app-model` section for an overview of the application processing sequence. .. _mixin-randpage-module: RandomPageModuleMixin --------------------- This class inherits from the :class:`PageModuleMixin` class. It redefines the way in which page modules are selected. Instead of the application calling the :meth:`set_page` execution context method, the URL in the browser request controls which page module is loaded and processed for each request. Page module management is inherited from :class:`PageModuleMixin`. The *base_dir* argument to the constructor determines the root directory where modules are loaded from. Page modules handled by this mixin have the following interface: .. function:: page_enter(ctx) :noindex: If this function is present in the page module it will be called every time the page module is used for a browser request. The *ctx* argument contains the execution context. .. function:: page_process(ctx) :noindex: If this function is present in the page module it will be called when the application object executes the :meth:`process_request` method. This occurs if the browser request was successfully validated. Refer to the :ref:`app-model` section for an overview of the application processing sequence. .. function:: page_display(ctx) :noindex: This is the only mandatory page module function. The application object calls this function when it executes the :meth:`display_response` method as the final step before saving the browser session. Refer to the :ref:`app-model` section for an overview of the application processing sequence. The :class:`RandomPageModuleMixin` class has the following interface. .. method:: RandomPageModuleMixin.load_page(ctx) This method implements part of the standard application processing sequence. It is called immediately after restoring the browser session. The *ctx* argument is the execution context for the current browser request. The :meth:`get_page_from_uri` method is called to determine the identifier of the page module that will be loaded. The identifier is then passed to the :meth:`load_page_module` method (which is inherited from :class:`PageModuleMixin`). Refer to the :ref:`app-model` section for an overview of the application processing sequence. .. method:: RandomPageModuleMixin.get_page_from_uri(ctx, uri) The method uses the :func:`urlparse` function from the standard Python :func:`urlparse` module to extract the path component from both the *uri* parameter and the value returned by the :meth:`base_url` method (which returns the *base_url* argument to the application constructor). The *path* component of the *base_url* is then used to split the *path* component of the *uri*. Element one (first split to the right of *base_url*) of the resulting string list is returned as the page identifier. Override this method in your application if you wish to implement a your own scheme for mapping the request onto a page identifier. .. method:: RandomPageModuleMixin.load_badurl_template(ctx) Called when your page template identified by the request URL does not exist. The *ctx* argument is the execution context for the current browser request. Override this method if you want to supply a different error page template. .. method:: RandomPageModuleMixin.page_enter(ctx) Called as soon as the page module has been loaded. The *ctx* argument is the execution context for the current browser request. The page module :func:`page_enter` function is called by this method if a page module was located by the :meth:`load_page` method. .. method:: RandomPageModuleMixin.process_request(ctx) This method implements part of the standard application processing sequence. It is called if the browser request is successfully validated. The *ctx* argument is the execution context for the current browser request. The page module :func:`page_process` function is called by this method if a page module was located by the :meth:`load_page` method. Refer to the :ref:`app-model` section for an overview of the application processing sequence. .. method:: RandomPageModuleMixin.display_response(ctx) This method implements part of the standard application processing sequence. It is called as the final stage just before the session is saved. The *ctx* argument is the execution context for the current browser request. The page module :func:`page_display` function is called by this method if a page module was located by the :meth:`load_page` method. Refer to the :ref:`app-model` section for an overview of the application processing sequence. .. _mixin-page-object: PageObjectMixin --------------- This class is intended for applications which do not require a separate Python module for each page in the application. Page processing is performed by a set of objects which the application registers with this class. The class is designed to be used where the application controls the sequence of pages seen in a browser session so the start page is specified in the constructor. Application page objects must be registered before they can be used. Typically you will register the page objects immediately after constructing your application object. Since the current application page is identified by an internal value, any hashable pickleable value can be used as an identifier. Page objects handled by this mixin have the following interface: .. method:: PageObject.page_enter(ctx [, ...]) :noindex: If this method is present in the new page object it will be called whenever your application code changes current the page by calling the execution context :meth:`set_page` method. For application types which define a start page this method is called in the start page when a new session is created. The *ctx* argument contains the execution context. Any extra arguments which are passed to the :func:`set_page` method are passed as optional extra arguments to this method. .. method:: PageObject.page_leave(ctx [, ...]) :noindex: If this method is present in the old page object it will be called whenever your application code changes current the page by calling the execution context :meth:`set_page` method. The *ctx* argument contains the execution context. .. method:: PageObject.page_process(ctx) :noindex: If this method is present in the page object it will be called when the application object executes the :meth:`process_request` method. This occurs if the browser request was successfully validated. Refer to the :ref:`app-model` section for an overview of the application processing sequence. .. method:: PageObject.page_display(ctx) :noindex: This is the only mandatory page object function. The application object calls this method when it executes the :meth:`display_response` method as the final step before saving the browser session. Refer to the :ref:`app-model` section for an overview of the application processing sequence. The :class:`PageObjectMixin` class has the following interface. .. method:: PageObjectMixin.__init__(start_page) When you inherit from the :class:`PageObjectMixin` class you must call this constructor. The *start_page* argument is a page identifier which specifies the first page that new browser session will see. .. method:: PageObjectMixin.module_path() Returns ``None``. .. method:: PageObjectMixin.start_page() Returns the *start_page* argument which was passed to the constructor. .. method:: PageObjectMixin.register_page(name, obj) You must call this method to register every page object in your application. The *name* argument defines the page identifier which is used to select the page object specified in the *obj* argument. All pages must be registered before they can be used. .. method:: PageObjectMixin.load_page(ctx) This method implements part of the standard application processing sequence. It is called immediately after restoring the browser session. The *ctx* argument is the execution context for the current browser request. If no current page is defined in *ctx* then the method will invoke :meth:`ctx.set_page` passing the page specified as the *start_page* argument to the application constructor. Refer to the :ref:`app-model` section for an overview of the application processing sequence. .. method:: PageObjectMixin.page_enter(ctx, args) Called when your application code calls the execution context :meth:`set_page` method. The *ctx* argument is the execution context for the current browser request. The *args* argument is a tuple which contains all optional extra arguments which were passed to the :meth:`set_page` method. The page object :func:`page_enter` method is called by this method. .. method:: PageObjectMixin.page_leave(ctx) Called before changing pages when your application code calls the execution context :meth:`set_page` method. The *ctx* argument is the execution context for the current browser request. The page object :func:`page_leave` method is called by this method. .. method:: PageObjectMixin.process_request(ctx) This method implements part of the standard application processing sequence. It is called if the browser request is successfully validated. The *ctx* argument is the execution context for the current browser request. The page object :func:`page_process` method is called by this method. Refer to the :ref:`app-model` section for an overview of the application processing sequence. .. method:: PageObjectMixin.display_response(ctx) This method implements part of the standard application processing sequence. It is called as the final stage just before the session is saved. The *ctx* argument is the execution context for the current browser request. The page object :func:`page_display` method is called by this method. Refer to the :ref:`app-model` section for an overview of the application processing sequence. .. _mixin-request: Request Classes =============== The choice of :class:`Request` class determines how you wish to deploy your application. Albatross supplies a number of pre-built Request implementations suited to various deployment methods. These include: +--------------------------------+----------------------------+ | Deployment Method | Request Module | +================================+============================+ | CGI | :mod:`albatross.cgiapp` | +--------------------------------+----------------------------+ | mod_python | :mod:`albatross.apacheapp` | +--------------------------------+----------------------------+ | FastCGI_python | :mod:`albatross.fcgiapp` | +--------------------------------+----------------------------+ | Stand-alone Python HTTP server | :mod:`albatross.httpdapp` | +--------------------------------+----------------------------+ You can also develop your own :class:`Request` class to deploy an Albatross application in other ways. All :class:`Request` classes implement the same interface. Much of this interface can be supplied by the :class:`RequestBase` mixin. .. method:: Request.has_field(name) Returns ``TRUE`` if the field identified by the *name* argument is present in the request. .. method:: Request.field_value(name) Return the value of the field identified by the *name* argument. .. method:: Request.field_file(name) Returns an object that contains the value of a file input field. .. method:: Request.field_names() Return a list of all all fields names in the request. .. method:: Request.get_uri() Return the URL which the browser used to perform the request. .. method:: Request.get_servername() Return the name of the server (Apache ServerName setting). .. method:: Request.get_header(name) Return the value of the HTTP header identified in the *name* argument. .. method:: Request.write_header(name, value) Add a header named *name* with the value *value* to the response. This method should not be called once you have started sending content to the browser. .. method:: Request.end_headers() Signal to the Request object that header generation has finished and that you are ready to start sending content. .. method:: Request.redirect(loc) Send a ``"301 Moved Permanently"`` response back to the browser. .. method:: Request.write_content(data) Send *data* as part of the request response. .. method:: Request.set_status(status) Sets the HTTP status code of the response. Defaults to 200. For deployment methods based on the cgiapp module, this value is used to derive the ``Status:`` header. The apacheapp module uses it to set the :attr:`status` member of the mod_python :class:`request` object. .. method:: Request.status(num) Return the saved value for the HTTP status code. .. method:: Request.return_code() Returns a value which should be returned from the :class:`Application` class :meth:`run` method. For most deployment methods, this is ``None``, however the ``mod_python`` requires that ``mod_python.apache.OK`` be returned if application emits any content. Your ``mod_python`` application should include code such as this: .. code-block:: python from albatross.apacheapp import Request ... def handler(req): return app.run(Request(req))