Version 1.9.1: 20 November 2006

Fix bug in parsing of submit widgets.

Add another submit widget to proto forms demo.

Make DurusDirectory work with slotted persistent objects.

Make Session.owner spec more direct.

Remove repeated "the" from form token notice.

Simplify qp script.  
Avoid imports of sites that are not used.
Remove --site option.  Just give the site name as an argument.
Note that "start", "stop", and "restart" are reserved, so don't
use those as site names.
Remove --build option.
Remove --base option.

Note about time zones.  Release 1.9 changed Session times to
be time zone aware.  If you are upgrading an existing QP
application to 1.9 or 1.9.1, you should open your database
in an interactive session, remove all sessions with
"sessions.clear()" and commit().  This will terminate
all open sessions, but the newer sessions will have the
time zone aware timestamps.  If you want to work harder,
you can replace the timestamps on your current sessions
with time zone aware versions.

Version 1.9: 15 November 2006

Revise the qp script to provide more flexibility in where site
packages are found.
Run qp --help for details.

Add lookup_user() and add_user() methods to the DurusPublisher.

Add Site.make_file_connection() for use by database update scripts.

Add a trace() decorator. (Useful in database update scripts.)

Change semantics of form.is_submitted to be true if any widget
name appears in the fields of the request.  If the form has 
been submitted, form.is_submitted *modifies* the request fields 
as necessary to make sure that every widget of the form has a 
key in the fields dictionary.

Add Site.get_live_host_name().

Add Publisher.is_live_host().
Don't send exception email except on the live host.
Suppress exception display on the live host.
Don't provide a debug address when on the live host.

Make interaction work when there is no durus server running yet,
and for sites that have no durus server.

Use basename of path as the index crumb for a static directory.

Always add a Content-type line to email.  (Mario)

Verify the operation of the Publisher constructor before forking.

Add a qp.lib.tz, a module with classes that are tzinfo instances
for 4 US timezones, UTC, and fixed offsets from UTC.

Add Publisher.get_time_zone(), which returns the site's default.
The default implementation uses UTC.
Add site_now(), which returns the current time with the Publisher's
time zone.  Use timezone-aware times on sessions.

Add datetime_with_tz and datetime_without_tz specs.

If a FileWidget is added, make sure the Form's enctype is correct.

Add --showmax option to qpcensus.py.  If the option is on, the
output includes a string that describes the location of an instance 
of maximal size for each class.

Update passfd.c to the scgi 1.11 version, plus the Solaris 8 patch
posted by James McDonald to quixote-users.

Add Specified, a class with a metaclass that makes a __slots__ from
the *_is attributes, including those from base classes.

Add get_memory_usage(), a utility that uses ps to return the
resident and virtual memory usage of the current process, in
units of 1024 bytes.  (uses "ps").

Add persistent_vars(), which works like vars(), except that it also
works on persistent instances that use slots instead of __dict__.

Add a --showpath option to qpcensus.py.  By default, just show 
oids instead of a fancy path.  This is faster and reduces memory
requirements by about 50%.

Reduce loading required by qpcensus.py.

Pass keyword arguments through make_file_connection to the FileStorage
constructor, in case a readonly storage is desired.

Add Form.__iter__() and Widget.__iter__()
and use them in the Form methods that should
also deal with subwidgets.  Previously, these
methods used Form.get_all_widgets(), which 
does not traverse down into subwidgets.

Version 1.8: 22 August 2006

Simplify Site.get_durus_address().

Add a delegation module.  This provides delegate(), a method for
adding methods to a class that delegate to methods on instance
attributes.

Version 1.7: 16 August 2006

Add set support to the spec module.  A spec that is a set matches
a set whose elements match any element of the spec.  For example,
set([int]) matches set([2,3,5]), but not set([2, 'S']).
set([int, str]) matches set([2, 'S']), but not set([2.0, 'S']).

Change the implementation of the "anything" spec so that it works
properly when used directly as a class attribute.

Make run_durus() defer to a Publisher method so that it can
be customized more easily.

Don't sleep when the server is already dead.

Add a "prefix" keyword argument to the Form  constructor.
If a prefix is provided, use it as a prefix for widget internal names.

Add is_submitted() to widgets, and use it in Form.is_submitted().

Add Profile, a class for profiling the processing of a request.

Make -u stop the durus server, since -q is provided for quick restart.

Remove HUP handling and do_restart() from dispatcher.
Add quick restart option to qp that sends a HUP to the
web dispatcher process of a particular named site.
Modify web server so that it execs new processes 
but recycles the bound sockets, whose file numbers
are made available to the new process through an
environment variable.

Add a line to the hello page that reports the time that this
python module was loaded.

Attempt to parse form values from querystrings that have html quoted
ampersands.

Version 1.6: 18 May 2006

    Revise get_crumb_tree() to provide css_class information.
    
    Change the widget subname divider from $ to __ so that the widget name
    is a valid value for an HTMl id.
    
    Revise form rendering and css so that we can produce forms with the
    same appearance as our Quixote-based forms.  Add an empty
    '<div class="close"></div>' at the end of sections that might 
    commonly enclose floating elements.  This gives non-floating 
    containers a chance of enclosing floating components.
    Insert newlines in lots of places in form rendering so that the
    raw source is easier to read.
    
    When the qp site management tool runs, put QP=1 in the environment.
    
    Make the HTTP server provide the correct Server: header in responses.
    
    Delay calling root directory constructor so that publisher subclass
    constructors can avoid initialization circuits.
    
    Add support for using durus through a unix domain socket.
    
    Add hello and hello_user exports to the proto demo.  Remove
    authentication from the demo's "request" page.
    
    Revise readme notes about stunnel.
    
    Add apache notes to the readme.
    
    Remove name="" from the noscript input tag rendered for OptionSelectWidget.
    
    Change the behavior of the publisher when PATH_INFO is the empty string.
    
    Change access log format.  Add access log line parsing method to the
    publisher.
    
    Make site start_web() defer to the publisher for the details of launching
    the web server(s).  This should make it possible to customize the web 
    servers on a per-site basis.  This tricky customization should not, 
    however, be undertaken unless there is a compelling reason for it.
    Note that Publisher.run_web is a staticmethod so that it can be called
    before there is a publisher instance, which is very desirable if you want
    child processes to run with separate connections to the Durus server.
    
    Separate start_durus_logging() method so that it can be used by clients.
    
    Add a javascript callback demo to proto.
    
    Put the parameters of spec's format_expected_got() in the right order.
    
    Initialize tmpbuf contents in passfd.  Jonathan Corbet posted this as a
    fix for trouble on an x86-64bit machine.
    
    Move the symlink test to the __call__ of StaticFile.  The not_found() call
    can't operate until there is a Publisher.  If the file is not found,
    just return with not_found() instead of a traceback.
    
    Change spec matching algorithm so that, if True or False appears in a
    spec tuple, it is treated as an OR.
    
    Use a definite site, instead of a random one, for testing Publishers.
    
    Don't do anything in send_mail_to_administrator() if is_email_enabled()
    returns False.
    
    If process_hit() is called with a PATH_INFO that  does not start with a
    slash, the response is now a 500.  Note that Publisher.process() provides
    the SCRIPT_NAME -> PATH_INFO hack that is required by some SCGI clients.
    
    Factor generate_visibile_names() from the get_exports() of StaticDirectory.
    Override this if you want to exclude certain patterns.  The default is
    to exclude ".svn" and names that end in "~".
    
    Include a static directory in the proto demo.
    
    Rename qp.web.util to scgi_util and make it usable as a script for testing 
    an scgi server.
    
    Make complete_url() use the hostname from the request if the hostname in
    the https_address is empty.
    
    Make url_with_query call stringify on keys and values provided for the
    query.
    
    Fix default Publisher.header() so that it can't put style outside of the
    head.
    
    Always change the owner of the session to the authenticated user, not just
    if there is no previous owner, when set_authenticated() is called.
    
    Make sure that the rows of list and dict widgets appear in rows.
    
    When the client rapid-fires requests and closes the connection before 
    getting the response, the web server was crashing with a socket.err.  The
    web server now catches these errors so that the server can keep running.
    
    Add an --all flag to qpcensus to cause it to report all spec errors for a
    given class, instead of just the first one found.
    
    Fix a bug in _generate_keys() that caused bad keys for SelectWidgets with 
    non-Persistent values().
    
    Make Form._get_default_action() return the value it computes.
    
    Don't quote the ampersand in url_with_query().
    
    Add a Redirector to qp.  This allows _q_lookups to consume the remainder
    of the path and redirect.
    
Version 1.5: 15 March 2006

    Separate Publisher class by pushing the Durus-using methods into a
    DurusPublisher subclass.  This clears the path for using QP for applications
    that use other databases, and for those that use no database at all.

    Obtain "SitePublisher" from the module named "slash" in the site
    directory instead of from the site package itself.  The extra
    redirection seemed pointless.
    
    Obtain "SiteDirectory" from the module named "slash" in the site
    directory instead of getting "SiteRootDirectory" from the site package 
    itself.   If you have an existing QP site, make sure that the root
    directory class is qp.sites.<site_name>.slash.SiteDirectory .
    Because some sites may not use Directory-based traversal at all,
    the SiteDirectory is now optional.
    
    Change the "hello" demo to show how to make an application that does
    not use any of the normal QP traversal or page generation patterns.

    Change the "echo" demo to be a Durus-less QP application.
    
    Store the global publisher in a dictionary by thread id.  This should
    make it easier for people to experiment with using a QP publisher in
    a multi-threaded server.  
    
    Add a __call__ to the Publisher class so that a Publisher instance can
    act as a wsgi application.  This should make it easier for people to
    try using a Publisher within a wsgi server.
    
    Make the core QP server class usable when passfd is not available.  The
    server reverts to a non-forking mode, so the performance is expected to
    be lower.  This should, however, make it possible for people to use QP on 
    Windows machines.
    

Version 1.4: 2 February 2006

    Add an email field to the qp user.
    Specify the email and id attributes using a pattern.
    
    Add charset and mime_type options to sendmail options and 
    use them to add a Content-Type header.

    Add access_time recording to qp sessions.
    
    Remove side-effect from is_valid(), the caller takes care of this.
    
    Add "proper" spec operator so that we can say something like
    [proper(Answer)] to specify a list of spec-correct Answer instances.
    
    Remove cruft from is_granted() that Mario Ruggier found.

    Allow calls to footer to have non-keyword arguments.
      
Version 1.3: 13 December 2005

	Add form demo to proto site.
	
	Add add_javascript_code() and get_javascript_code()  utilities to the form
	module.
	
	Simplify basic form css.  Change form widget rendering to conform to 
	xhtml-strict.  Remove render_br keyword option.
	
	Add DOCTYPE to the default header.
	
	Add style and doctype keyword options to header().	

	Add HTTPRequest.get_content_type().
	
	Use "User Name" instead of "Email" as the widget title on the default login
	form.
	
	Use / instead of "" for the path, when there is no script name.

	Change secure() so that it does not raise an exception when there is no
	https_address.
	
	Set site in Publisher.__init__() before calling 
	ensure_database_initialized(), (formerly named ensure_initialized()).
	
	In redirect(), use the existing response instead of making a new one.
	This allows cookie headers to be part of a redirect response.
	
	In DurusDirectory._q_lookup, call self.__class__ instead of DurusDirectory.
	
Version 1.2: 4 November 2005

	Add read_body() and get_content_length() methods to the request class.

Version 1.1: 2 November 2005
    
    Change request default charset from 'iso-8859-1' to 'utf-8'.  In qp, html
    pages will use utf-8 encoding, so we will assume, in the absence of other 
    information, that requests use utf-8.  
    
    Allow for sessions when there is no https support.
    
    Remove Persistent from the __bases__ of Keyed and Keep so that they can
    be used as mixins with classes that already inherit from Persistent.


Version 1.0: 20 October 2005
    
    First release.

