This chapter describes the changes made to Albatross between releases.
This section describes the changes made to Albatross since release 1.40.
Template evaluation namespaces
Evaluation of expressions in templates normally takes place within the scope of ctx.locals. The new <al-namespace> tag allows you to switch temporarily to a subordinate namespace. Expression evaluation will take place with respect to that namespace, and input names will automatically be prefixed with the name of the namespace.
For example:
class Field: prompt = 'Enter age' data = 23 field = Field()
And
<al-namespace name="field"> <al-value expr="prompt">: <al-input name="data" whitespace> </al-namespace>
Would produce:
Enter age: <input name="field.data" value="23" />
A namespace="..." attribute has also been added to the <al-expand> and <al-for> tags allowing you to execute their contained content in the specified namespace.
Easier selection of Application and Context classes
A new get_app_classes(page_model, context_model) function has been added that makes choosing Application and Context classes easier. Previously, you had to choose between one of twelve Application classes and match this with an appropriate Context class. With the get_app_classes() function, you just need to choose a page model and a session model, and the appropriate Application and Context classes are returned. For more information, see Prepackaged Application and Execution Context Classes.
Albatross command line and quick-start application skeleton
An albatross command line utility has been added. This utility currently has four sub-commands:
This makes it very easy to get started writing Albatross applications:
$ albatross create myapp
$ cd myapp
$ ls
app.ini app.py pages session static
$ ls pages
environment.html macros.html new_session.py session_expired.html
environment.py main.html page_not_found.html uncaught_exception.html
__init__.py main.py raise_exception.py unhandled_exception.html
1$ ls static
alxform.css favicon.ico logo.png style.css
$ albatross serve
Starting web server for "myapp" on port 8000
Stop the server with Ctrl-C
http://localhost:8000/
A new alternative to the noescape attribute has been implemented that allows a data source to signal that a given string does not require escaping when it is rendered by template execution by casting it to the htmlsafe() type. This moves the responsibility for this potentially risky action from the template closer to the code that generated the string. The htmlsafe() type can also be used to selectively disable the escaping of evaluated attributes.
While the “noescape” attribute still works, it’s scope has been reduced, and it should be considered deprecated.
RandomModular applications will now attempt to render an application-supplied page_not_found.html template, before falling back to an internal “URL .. was not found on this server” message.
A simple logging mechanism has been added. Calling the Application.set_logger(logger) method with a logger compatible with the standard python logging module registers that logger with the application. Exceptions will be logged to the logger at “error” level, and a ctx.log(msg) method allows messages to be logged at “info” level.
This section describes the changes made to Albatross since release 1.36.
Conversion of documentation to reStructuredText
With the Python documentation moving from LaTeX markup to reStructuredText and the Sphinx documentation generator, we could no longer rely on the documentation utilities released with Python. The Albatross documentation has been converted to ReST, and uses Sphinx to render this to HTML and PDF formats.
Albatross Forms
A simple HTML form generation and validation framework has been added to Albatross (as an optional extension under the module name albatross.ext.form).
This section describes the changes in release 1.36 of Albatross that were made since release 1.35.
A vars attribute has been added to <al-for> - this inserts the iterator value into the local namespace. The iterator value was previously only accessible via the iterator value() method.
<al-for> now loops over sequences using the iterator protocol by default. The previous behaviour of indexing the sequence is retained where pagination or columns are requested.
New <al-setdefault> tag which allows macros to define default values for their arguments (suggested by Greg Bond).
Macro expansion can now use attributes on the <al-expand> tag to specify macro arguments (suggested by Greg Bond).
Added get_param() method to Request classes, which deployment method agnostic access to http “environment” variables.
NameRecorderMixin no longer falls back to merging all request fields if no __albform__ field is present. Applications using the NameRecorderMixin and GET-style requests will need to explicitly merge relevent fields with the ctx.merge_vars(...) method.
Pickles embedded in hidden fields are now signed using the HMAC-SHA1 algorithm (was MD5).
The experimental FastCGI driver included in version 1.35 now becomes the default FastCGI driver. The old driver has been renamed fcgiappold. The new driver implements the FastCGI protocol itself, rather than depending on an external module.
If the <al-option> tag was not immediately enclosed within an <al-select> tag, it would be silently ignored. <al-option> now works within containing flow control tags such as <al-for> or <al-if>, has improved error reporting, and supports attributes for dynamically setting value and label.
Communication with the session server has been made more robust. EINTR is handled, as are partial reads and writes, and requests are restarted if the socket closes.
Mixing radio inputs with other inputs of the same name did not raise an exception (reported by Michael Neel).
FCGI_MAX_DATA was incorrect due to an operator precedence mistake. Found by Tom Limoncelli.
This section describes the changes in release 1.35 of Albatross that were made since release 1.34. Note that release 1.34 was an internal release.
A drop-in replacement for the fcgiapp module, called fcgiappnew has been added. This version implements the FastCGI protocol itself, rather than relying on an external module to implement the protocol (we have not been able to clarify the license of the fcgi.py module). This new module addresses several minor problems with fcgi.py, and should be faster, although it should not be used in critical applications until it has received wider testing. This module will eventually be renamed to replace fcgiapp (at which point, the fcgiappnew name will dropped).
When extension tags (alx-*) are registered, their name is now checked against the template parsing regexp to ensure they can subsequently be matched.
The AnyTag functionality was given knowledge of HTML tags for which the close tag is forbidden, so it can avoid generating XHTML empty tag (which could cause the page to fail HTML validation).
When the disabledbool attribute was used on input tags, the disabled state was not being passed through to the input registry within the NameRecorderMixin.
If a client closed it’s connection to the session server while the server had data pending for the client, a subsequent del_write_file would generate an exception, killing the session server.
This section describes the changes in release 1.33 of Albatross that were made since release 1.32.
This section describes the changes in release 1.32 of Albatross that were made since release 1.31.
To obtain a reference to the current frame, _caller_globals was raising and catching an exception, then extracting the tb_frame member of sys.exc_traceback. sys.exc_traceback was deprecated in python 1.5 as it is not thread-safe. It now appears to be unreliable in 2.4, so _caller_globals has been changed to use sys._getframe().
If ctx.set_page() was called from within the start page, then the wrong page methods (page_enter, page_display, etc) would be called (those of the initial page, rather than the page requested via set_page).
This section describes the changes in release 1.31 of Albatross that were made since release 1.30.
This section describes the changes in release 1.30 of Albatross that were made since release 1.20.
Arbitrary HTML tags can now access the templating engine by prefixing the tag with “al-”. Attributes of the tag can then be selectively evaluated to derive their value. Appending “expr” to the attribute name causes the result of evaluating the expression to be substituted for the value of the attribute. Appending “bool” results in the attribute value being evaluated in a boolean context, and if true, a boolean HTML attribute is emitted. For example:
<al-td colspanexpr="i.span()">
could produce
<td colspan="3">
and:
<al-input name="abc.value" disabledbool="abc.isdisabled()">
could produce
<input name="abc.value" disabled>
Since macros and lookups are an application global resource, they can only be defined once per application, however this was not previously enforced. Redefinition of macros or lookups will now result in an ApplicationError exception.
The <al-lookup> tag can now be optionally expanded in place. If the tag has an expr= attribute, this will be evaluated and used as the value to look up, and the results of the lookup substituted for the tag.
Functionality of named lookups remains unchanged.
A new <al-require> tag has been added to allow templates to assert that specific Albatross features are available, or templating scheme version number is high enough. For instance, the addition of the “Any Tag” functionality has resulting in the templating version incrementing from 1 to 2.
Cache-Control: no-cache is now set in addition to Pragma: no-cache.
Cache-Control was introduced in HTTP/1.1, prior to this the same effect was achieved with Pragma. Some browsers change their behaviour depending on whether the page was delivered via HTTP/1.1 or HTTP/1.0.
Session cookie handling has been simplified.
FastCGI apps were not being explicitly finalised, relying instead on their object destructor, with the result that writing application output (or errors) would be indefinitely deferred if object cycles existed. We now call fcgi.Finish() from the fcgiapp Request.return_code() method.
When handling exceptions, the traceback is now explicitly deleted from the local namespace to prevent cycles (otherwise the garbage collection of other objects in the local namespace will be delayed).
Two fixes to the <al-select> tag: the albatross-specific “list” attribute was leaking into resulting markup, and the use of the “expr” attribute would result in invalid markup being emitted.
Thanks to Robert Fendt for picking this up: the Albatross-generated hidden field input element must not appear naked inside a form element for strict HTML conformance. The solution is to wrap the input elements in div.
BranchingSession sessions could not be “deleted” because each interaction is a separate session. The solution implemented is to add a dummy “session” shared by all branches, which is deleted when one branch “logs out”.
This section describes the changes in release 1.20 of Albatross that were made since release 1.11.
A persistent problem with server-side sessions is the browser state getting out of synchronisation with the application state. This occurs when the user reloads the page or uses the “back” button.
A new BranchingSessionContext application context class has been added that attempts to work around this problem by creating a new server-side session for every interaction with the browser. The unique session identifier is stored in a hidden form field, rather than a cookie.
The new Context class is intended to be used with the server-side Application classes, and provides a similar experience to storing the context in a hidden form field, without the overhead and security issues of sending the context on a round-trip through the user’s browser.
No effort is made at this time to control the resources used by these server- side sessions, other than expiring them after session_age seconds.
The Request classes provide the interface between specific application deployment models (CGI, FastCGI, mod_python, etc), and the Albatross application. These classes have been refactored to extract common functionality into a new RequestBase class. The Request classes also now have methods for passing status back to browser.
The page module loader in PageModuleMixin has been reimplemented so that it does not pollute sys.modules. Page modules are now loaded into a synthetic module’s namespace, rather than the global module namespace. This will break code that defined classes in page modules and placed instances of those classes into the session.
Some HTTP headers can appear multiple times (for example Set-Cookie) - the response handling has been modified to allow multiple instances of a header. ResponseMixin.get_header() now returns a list of strings, rather than just a string. The httpdapp module has also been updated to allow multiple instances of a header, keeping headers in a list rather than a dictionary.
ctx.req_equals(name) now checks for name.x if name is not found. This makes using image maps as buttons easier (from Michael C. Neel).
Under some circumstances, redirect_url() would redirect to incorrect or invalid URLs (for example, an https app would redirect to http) - the URI parsing has been refactored, and this bug has been fixed. Tests were also added for the refactored URI parsing.
Response header names were being matched in a case-sensitive way - this was incorrect and has been fixed.
This section describes the changes in release 1.11 of Albatross that were made since release 1.10.
<al-select> handling of name, expr, valueexpr and value attributes has been made consistent with that of <al-input>.
New method absolute_base_url() has been added to the AppContext.
Matt Goodall has continued to improve the capabilities of the al-httpd program and httpdapp.py so that it is now possible to run all of the CGI based sample applications.
You can now initialise the static_resources from the command line. For example, the tree samples can be executed to serve up their images like this:
$ cd samples/tree2
$ al-httpd tree.app 8080 /alsamp/images ../images/
The <al-input> and <al-img> tags now output XHTML compliant end tags.
Greg Bond fixed a cgiapp field handling incompatibility with mod_python 3.
The get_servername() method of the cgiapp and fcgiapp Request classes now use the HTTP_HOST environment variable rather than SERVER_NAME.
All session cookies now include a path attribute. This prevents multiple redundant cookies being set for all URI paths in an application.
This section describes the changes in release 1.10 of Albatross that were made since release 1.01.
Matt Goodall developed support for deployment of applications via FastCGI. FastCGI applications import their Request class from albatross.fcgiapp.
Matt Goodall developed support for standalone deployment of applications via the standard Python BaseHTTPServer module. The al-httpd program can be used to deploy a CGI application as a standalone BaseHTTPServer server.
All Albatross exceptions have been redefined to indicate the source of the error; user (UserError), programmer (ApplicationError), or Albatross itself (InternalError). The ServerError exception reports problems related to the session server, SecurityError reports either a programmer error, or a user attempt to access restricted values in the execution context, and TemplateLoadError reports failures to load templates.
All of the exceptions inherit from AlbatrossError.
The albatross.common module defines the exceptions.
All response header management has been moved to the ResponseMixin class. The AppContext class now inherits from ResponseMixin. The Request class no longer tracks whether or not headers have been sent.
ResponseMixin provides the ability to set, get, delete, and send headers. Headers are automatically sent when the application sends any content to the browser.
The write_headers() method has been deleted from the following classes; SimpleAppContext, SessionAppContext, SessionServerContextMixin, SessionFileContextMixin, SessionFileAppContext.
For SessionServerContextMixin and SessionFileContextMixin the Set-Cookie header is set when session is created or loaded.
The Application.run() method no longer unconditionally returns an HTTP response code of 200. The returned response code is retrieved from the Request.status() method. You can call the Request.set_status() method to override the default HTTP response code of 200.
The <al-input> tag now supports type="file" input tags. When you use file input tags the enclosing <al-form> tag automatically adds the enctype="multipart/form-data" attribute to the generated <form> tag.
The albatross.cgiapp and albatross.apacheapp modules define a FileField class which provides access to uploaded files. During request merging the Request.field_file() method returns instances of FileField for uploaded files.
The Application.run() method now saves the session before flushing the response to the browser. This allows applications to support dynamically generated images.
The SessionBase.add_session_vars() method now raises an ApplicationError exception if you attempt to add variables to the session which do not exist in the local namespace.
The SessionBase.default_session_var() method allows you to add a variable to the session and place it in the local namespace at the same time.
Session saving previously silently removed session values which could not be pickled. Now unpickleable values are reported via an ApplicationError exception.
Errors handling and reporting during session loading has been improved.
The exception formatting in Application.handle_exception() has been moved into the format_exception() method. Applications can perform their own exception formatting and/or send formatted exceptions to locations other than the browser.
The ExecuteMixin.write_content() method now converts unicode to UTF-8.
During NamespaceMixin.eval_expr() the execution context is temporary placed into the local namespace as the variable __ctx__.
NamespaceMixin.set_value() ignores attempts to set Albatross iterators that are not present in the namespace.
NamespaceMixin.set_value() produces a nice syntax error like report when an illegal field name is used.
The _caller_globals() function has been changed to use the name of a function rather a stack frame count. This is used by the methods AppContext.run_template(), AppContext.run_template_once(), RandomPageModuleMixin.display_response(), and SimpleContext.__init__() to locate the module whose globals will be used as the global namespace for evaluating template expressions.
The <al-tree> tag now has a single attribute which enables the single select mode. In single select mode, selecting a node automatically deselects any previously selected node.
The <al-input> tag now supports the treefold="expr", treeselect="expr", and treeellipsis="expr" attributes. The expression specifies a tree node that is used to construct a tree iterator input value.
The following methods have been added to the LazyTreeIterator class; load_children(), is_selected(), select_alias(), open_alias().
The <al-lookup> tag now registers the lookup during template parsing rather than during evaluation. This allows template code to make use of lookups that are defined later in the same file. The item dictionary is created the first time that the lookup is used rather than when the template is interpreted.
Macro arguments are now evaluated when they are referenced rather than before they are passed to a macro.
This removes a limitation where you could not define macros including <al-form> tags that retrieved <al-input> tags from their arguments. Previously the <al-input> tags passed as macro arguments would have been evaluated outside of the context of the form defined in the macro. This effectively made the input tags invisible to the form recorder.
The <al-option> and <al-select> tags always write </option> close tags.
The noescape attribute has been added to the <al-input>, <al-img>, <al-select>, and <al-textarea> tags.
The templates reference documentation has been completely restructured to improve clarity. All attributes of each tag have been documented.
In some circumstances exceptions would leave a content trap in place that prevented an error report from being written to the browser.
More exceptions are trapped by the session unpickling code to make error handling more robust.
Fixed a bug where an import error inside a page module loaded by the RandomPageModuleMixin was being handled as if page module could not be located.
Fixed cookie handling which previously could not cope with missing session id when the cookie was present.
Fixed bug in checkbox.
Only prevent the generation of the value attribute when the value is None.
The apacheapp Request class now works for mod_python 2.3 and 3.0.