CHANGE SUMMARY: Version 1.2: 2013-06-10 Use ImageMagick tools for converting pdf pages to png files if sips is not present. Return an empty list from genlib.node_get_text_data_list in the case of an exception. Add the capability for temporary password expiration for qp Users. The default is 24 hours. Implement session-level affinity in the dispatcher: - We peek at the headers and use the cookie value to distinguish users. This should allow a group of users coming from a single IP address (such as when NAT is used) to utilize multiple worker processes. Add digest computation method to StoredFile. Add support for gradients in the svg module. Add module level functions for table, paragraphs, spans, and header elements to the html module. If a path is not provided when formatting menus, use a default value based on get_path(). In the stored_file UI, when downloading a stored file, if no disposition is specified, and the mime_type is text/html, use disposition = 'attachment', not 'inline'. The intent is to avoid the inline display of the possibly dangerous html in the browser. Attempt to get QPY xml_empty initialized correctly in Python >= 3.3. Add methods to Pager class so that a subclass can maintain a page size preference. Add redecode(), and add a redecode= keyword to Widget that can be used by Widgets to recover multiply-encoded form values. This special handling is implemented for TextWidget, where the errors seem to be most common. In _q_traverse(), remove requirement that the export has exactly 4 components. Add note about list_validation_errors() to qpcensus.py. Use the timeout feature that was added to httplib in Python 2.6 to ensure the Pusher does not hang during a connection attempt. This bumps the minimum Python required for DurusWorks to 2.6. Add a new menu module for carrying the various information we need to build menus. Add a Page class for containing header/body/footer/menu information about rendering a single page. Add Pusher, a class for constructing POST request bodies. These can be used for testing forms or for actually transmitting to a server. Add Upload.move(), which moves the Upload's fp to a new location. Use the new method in stored_file.new_stored_file(). This approach allows requests with Uploads to successfully replay after WriteConflictErrors. Change qpcensus.py to avoid having two Connection instances. Add new_form() to qp.pub.common. This makes it easier for sites to use site-specific Form classes. Provide separate access to the spec and doc of a Specification. Add 'classes' keyword to htmltag. If provided, the argument is expected to be a list of css class names. Because htmltag is used in href(), img() and other templates, they also get support for the 'classes' keyword. Change request input processing. Instead of parsing form requests first, and then processing the request, wait for the page handling code to call get_fields(). This allows for the possibility of other form parsing methods, including forms handled by by cgi programs. Add a 'log_errors' keyword to Form which is False by default. If log_errors is True, then any form errors are printed to standard output, as well as the fields of the form.k Remove dispatcher-level commands. Add support to run https directly with QP when using Python 2.6 or above. Modified qpy as needed to work with python 3.3. Extended qp.html package to include html element formatting functions. Added stored_file and svg modules. Version 1.1: 2011-08-17 This release fixes a long-standing undetected bug in the Durus incremental packing algorithm. Thanks to David Hess for finding and solving this issue. We were raising a KeyError in FileStorage.load_state() Version 1.0: This is the initial DurusWorks release.