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.

