0.22:
2013-06-10

Fix bug in the Log constructor.

Make formatting of history a pretty table.

Adjust Crumbs and Titles for exports in CategoryUI.

When rendering a plain Table for server side sorting, work the sort query
into any existing query string.

Allow client side sorting for much larger tables.  For large tables, the
sorting may take longer on the client side, but I think it still saves time
because you don't deliver the giant table again.

Add extra stored_file_widget argument so that the stored_file UI can be used for
for other "stored-file-like" things.

Don't expose the stored-file "Order" control in the stored_file UI export unless
there are at least 2 items.


0.21: 
2012-11-01

Move stored_file module to qp in DurusWorks.

Move PieSlice out of svg module since it is not really an SVG Element.

Revise CallbackSelect Widgets and move them to DurusWorks.

Fix Table to avoid 3-state sorting caused when some of the computed keys are
numeric and some are not.

Work harder to get useful sort keys from table cells in the Table class.

Add add_mailing_list_widget and process_mailing_list_widget and implement
add_mailing_list_widgets and process_mailing_list_widgets in terms of new
functions.

Create a mini_edit_mailing_list form template that presents a form
for subscribing and unsubscribing from a specified mailing list.

Add initial version of CallbackSelectWidget.

Add support for a database containing parsed log data.

Make sure that the csv download of a Table does not fail when there are other
values in the row (attributes, for example).

If a Table row contains keys that are not in headings, pass them through to
be used as attributes of the tr element.

Add see_hover and hide_hover keywords to expandable_div and collapsible_div.

Use Python 3k syntax. 

Add a two small mailman modules useful for controlling a mailman list from 
Python.

Add a pdf page for the splitting of pdf files.

Add support for thumbnails of the first page of a pdf.

Add new concept of "variants" to StoredFile.
A video/mp4 stored file can have a video/ogg variant.
An application/pdf stored file can have png-page variants.

Add icon support to StoredFileWidget.

Add make_pdf module that uses phantomjs to generate a pdf of the current page.

Add display_block(id) and display_none(id) to genlib.

Add pop_id keyword to element functions. If provided, the pop_id value is the id
of an element whose display is to be toggled by mouseover and mouseout events.

When there is a compiler exception, put the name of the file in the exception
text.

Add a DateSelectPairWidget which uses two the the DateSelectWidgets together to
allow the specification of a period of days.

Add get_date_select_pair_form which is a for with a DateSelectPairWidget and 
Cancel and Search submits. It allows the preloading of the start and end dates
via keyword args.

Add get_default_start_end and set_default_start_end which are functions handy
for saving and retrieving the last used date_pair on a users session.

Add get_date_range_text which is useful when creating filenames for CSV output
created with a table that uses a date_select_pair_form.

Add ability to turn off the "Browse" button in the attachment UI.  

Factor format_attachment_list out of format_attachments.  This allows
you to format a subset of a list of attachments.

Add __iter__ and gen_reversed() to History.

If an onclick argument is provided to BigMultipleSelect, execute it
after the widget's own onclick function is executed.

Add get_html_risks(), a function that produces warnings about html
strings that contain patterns that are risky.

Use renaming instead of copying for uploaded attachments.

Use named temporary files for Uploads. This creates the possibility of saving 
uploads by renaming instead of by copying them again. The new files are saved 
in the value returned by Site.get_directory_for_temporary_files(). This value
can be configured on the Publisher.

Support a "Move up" action in AttachmentUI for all attachments that can
be moved up.
 - Add Attachable.move_attachment method that takes an attachment and
   an index to move it to.
 - Stop sorting attachments by date in AttachableUI index page.
   Reverse instead. This shows most recent attachments at the top.

Add an optional sha512_hash attribute to StoredFile.
The value is computed and set the first time someone calls the getter.

Protect against IOError when producing thumbnails from TIF images.

Add NearZipFile to work around problems decoding "extra" headers in ZipFile.
Add Archive.get_member()

0.20: 34166
2011-07-15

The main purpose of this release is to synch with the
DurusWorks release and catch up on many small changes.

Remove the ability for the publisher's 'ensure_signed_in' to 
take keyword arguments.  If a specific realm is needed, then 
the publisher's version of ensure_signed_in should be overridden 
to provide the realm in calls to ensure_signed_in_using_form, 
ensure_signed_in_using_basic, ensure_signed_in_using_digest or
one of the concrete implentations of ensure_signed_in.

Change dulcinea implementation of ensure_signed_in keyword 'msg' 
to 'title' to match other concrete implementations in qp.

Add a 'sign_in_page' key to the Hit info if we need to have the user
sign in.  This allows the header and footer parts to be customized for
the login page.

Don't delete the part BTree in Partition.remove if the part becomes empty.
(partition.py)

Do not try to produce a thumbnail for Photoshop files.  PIL can't do it.
(browse.py)

Expand the list of safe tags for format_text.

Add a css "popup" class to lots of pages.

When formatting a note.  Call nlnl2brbr to convert any two newlines
in a row to two br tags.  This makes non-html note formatting look
better. (note.qpy)

FileStream keyword arg 'size' -> 'length'

Add a module level function "static" that returns a path based on the
path of the passed in module object. (util.py)

Provide length of archive file to FileStream constructor.
This allows range requests to apply to archive files. (browse.py)

Add a new mixin Surveyed to dulcinea.survey which contains a ref to 
a single survey.

Add a new UI component SurveyedSurveysAndQuestionsUI which is a 
SurveysAndQuestionsUI but also updates the reference on the passed
in Surveyed if provided.

Use standard mimetypes module pattern for customizing guess_type() for use
with attachments.

In javascript_headers, if there is both javascript src and javascript
script, split the HTML output into two separate script tags.

Don't require stored files to have mimetype in the predefined list.

Add support for browsing into apk and jar files.

Make thumbnails work, even without PIL.

Avoid repeated categories in category.py.

Add a SingleSelectAndString composite widget... which is really just the
two widgets put together.  Nothing fancy.

Add get_stat() and get_mtime() methods to stored_file.

Refactor some of the Table methods.

Add Pager, a subclass of Table, intended to display search results that
are paged and sortable.

Simplify the display of the TableSearchForm form.

Refactor SearchForm and TableSearchForm to have a 'format_matches' method
to match the existing 'format_no_matches'.  Implement SearchForm.render
and TableSearchForm.render in terms of format_matches.

Use "durus_id" as the name of the Durus persistent identifier.  The old
name was "oid".

Add a show_grants module level function to dulcinea.ui.permission which
when there's a granter, renders a table showing users granted any 
permission by this granter.  The rendering of the user also includes
a link to "Edit Permissions" for that user.

Make the edit permission_form a component that must be custom if you need 
special behavour for get_valid_permissions or for side effects to grant
and ungrant.


0.19: 31795
2009-08-19

Add undo_percent_quoting function that locates % quoted bytes and 
substitutes with unquoted byte values.  This is useful when trying
to eliminated overquoting.

Attempt to make the TarfileWrapper has_member() method work in a variety
of python versions, where there seems to be some variation in the way
directory names are located in the archive.

Change the Attachment UI so that the filename is used is both the alt tag and 
the source tag.

Change the _q_lookup of DataUI to only browse if the filename is not an image 
and the component is "browse", otherwise return the formatted thumbnail. 

Separate show_name_size_type into show_name, and show_size_type in 
attachment ui.  Include file name in the file link.

Change the 'required' widget from CheckboxWidget to RadiobuttonsWidget.
CheckboxWidget is not added to the fields of the request if the box is
not checked.  This made turning off the requiredness of a property broken.
This is in property_widget.py.

Remove assertion about values in BigMultipleSelectWidget.
The behavior should be the same as for MultipleSelectWidget.

Make the default be to allow uploading of all types of files.

Remove default 100% width for pretty table css.

Add a get_form_keywords_matches method to SearchForm that returns the form 
object, keywords entered and the matches found for the entered keywords.

Split out the __init__ of SearchForm to call get_form_keywords_matches.

Remove 'match_substrings' keyword from SearchForm and all calls to it.
The behavior now is to not match substrings and rather match on whole 
word boundaries always.

Move format_interaction_summary from dulcinea.ui.inquiry to
dulcinea.ui.user.interaction.

0.18: svn revision 31367
2008-12-03

Convert stored datetimes to all be tz-aware.  Existing databases
that use these classes must be converted to work with this revision.

Convert to be compatible with py3k.

Convert code to use the newer names and template syntax of the 
latest qpy.

Add expandable_div and collapsible_div functions with supporting javascript.

Add a Period class.

Update RSSTab and RSSFeed to display an item's pubDate attribute.

Add __hash__() methods where necessary.
In py3k, __eq__() kills any inherited __hash__().

Change date_select_fix javascript to work with DateTimeSelectWidgets
that are constructed with 'show_hour_min' is True.

Make Dulcinea safe for installations without sancho.

Add a simple script for checking the URLs associated with links.

Add charset attribute to StoredFile.

Add Propertied Mixin for objects with a PropertyList.
Revise some PropertyList methods.

Factor out the code that inserts javascript into the head portion of a page into
a 'javascript_headers' function.  Add this to the ui.utils module.
Use javascript_headers function in DulcineaPublisher.header

Add a highlight_keywords function that wraps any words present in keywords 
arg in a span with a "match" class.

Make sortable headings work for server-side sorting.
Add ability to make some columns not-sortable.
Add even and odd classes to rows.

0.17: svn revision 29799
2007-05-02

Use metaclass-loaded base classes, Specified, and Mixin, to nail down 
slot names for all data classes.  Note that Specified base classes
should come before Mixin base classes in a class definition.  If they
don't, you'll see an error about the class you are loading already having
a __slots__ value.  Instances of classes that derive from Dulcinea data 
classes will not have __dict__ attributes.

Add an example update_db.py script to the qp demo site (in dulcinea/site).
If anyone has an existing Durus database for a Dulcinea application, you
should look at this.  It shows how you can update a database to repickle
objects that refer to, for example, 'Events', that now use slots for attributes
and do not define their own __setstate__ methods.  Without an update like
this, existing applications will have unpickling errors.  If you need help
with this, please post questions to the qp mailing list.

Add search capability to wiki.

Add an 'invertable' keyword argument to BigMultipleSelectWidget that
defaults to False.  When invertable is True an "invert" button is
added to the widget that when pressed inverts the selected and 
available lists.

Care must be taken when using invertable BigMultipleSelectWidgets in
forms, since pressing invert will cause form.is_submitted() to return
True. 

Let the Master Property widget have a None value.  The default is very
unlikely to be the one that is desired.

Improve CSS for PhysicalValueWidget and ToleranceWidget particularly
for IE.

Use the agent class as a css class in the BODY element.

Make Categorized new-style.

Make DulcineaUser specified.

Make StoredFile slotted.

Add search capability to wiki.

Remove DulcineaSessionManager.

Make Partition Persistent.

Make sure that Specified comes before Mixin in every base class sequence.

Add __eq__ and __ne__ to DulcineaPersistent.
Add PropertyList.__eq__().
Change PhysicalUnit __cmp__ to __eq__.

Make Copyable new-style, and simplify it.
Implement copy() and __copy__() directly on DulcineaPersistent,
and make DulcineaPersistent be a PersistentObject.
This should allow some classes that are subclasses of DulcineaPersistent
to use slotted attributes.

Enhance the search for inquiries to look at the contact for the inquiry.

Add placeholder file so that demo site has a var directory.

Drop support for quixote applications.  Dulcinea is all-QP now.
This eliminates lots of complexity and redundant code.  
Applications that need to keep using quixote should stick to
previous versions of Dulcinea.

All files that were ptl files are now qpy files.

datetime.strftime() needs a real str.

Make the widgets of a BigMultipleSelect float left.
This seems to make the qp rendering look like the quixote one.

Make PersonNameWidget look the same on qp as it does on quixote.
The three subwidgets should float left.

allow the socket for the urlopen in an RSSFeed to timeout quickly if
not available.

Disable abort in the test environment, so that a test session does
not get tossed before a test request can be processed.

Make page loader qp friendly.
Don't write entire response body on failure.

Add a 'user' keyword argument to the constructor of PageLoader

Fix DateTimeSelectWidget.is_submitted()

Make the signin_link float right.
This fixes a display problem on IE.

Remove open_connection().
Use Site() to open database.

Change
redirect(get_base_path() + x) -> redirect(x)
Redirects always prepend the script name to paths that start with '/'.
Prepending it in cases like this will cause it to appear twice in the
Location header.

Remove get_base_path().  (We now have complete_path() instead.)

Move special SITE handling into set_test_environment().
Don't depend on SITE in scripts.  It is just for tests.
Add an optional site_name keyword to the PageTest and CommonTest
constructors.
Import get_publisher and get_connection from qp.

Remove access_denied and invalid_query.

Use PersistentObject as the base class of more persistent classes.

Don't make show_sidebar' keyword argument to hierarchy_header required.

In lookup_user if matching on an email address and there are multiple matches,
return the match that contains the user_id similar to the email address
if it exists.

0.16: svn revision 29023

Use slots on some classes to save memory.

Rename Parameter to Property.

Make sure that the publisher's add_user function is called on registration.

Convert dulcinea Item and ItemFolder to be based on Keyed and Keep.

Make Dulcinea Applications use the same Sessions with QP or Quixote.
Remove the persistent SessionManager.
Add get_time_zone() to DulcineaPublisher.

Add site_now() to common.

Add an open_connection() in the QP branch.

Use users BTree instead of UserDatabase.
The Publisher is the authoritative source, through get_users(),
of the user mapping.

Add MiscDatabase.

Move get_matching_user to the module level.

Move gen_users_granted() to the module level.

Make list_users() a module level function.

Remove get_all_users().

Put a create_user on the Quixote Dulcinea Publisher.

Export full sized PNG version of images.

The user for password change history is also the logged in user not the user
whos password is being changed.

Add features to the debug UI.

Move form2 to form.

Make DulcineaUser use the qp hash function when running under qp.
Under qp, if the digest matches using the dulcinea hash function,
use the qp hash function to set a new, qp-compliant hash value.
The qp hash function is preferred because it allows for http 
digest authentication.

Improve SearchSelectOneWidget.
Suppress errors when search is submitted.
Reverse widget order.
When there is exactly one match, go ahead and select it.
Add format_search_select_css().

Fix css font family typo.

Add the From Field of an inquiry to the searchable fields.

Add search capability to links.

Make html2txt more resilient to UnicodeDecodeError.

Use the latin1 charset for the password reset email.



0.15: svn revision 28637
2006-08-22

Fix a chicken/egg error in the setup.py.  It imports __version__
from __init__.py, and __init__.py expected dulcinea to already be
on the path.

Use set instead of Set.

Revise Note class.

Cache date_pair form pages.

Add wiki code.

Add DulcineaUserDatabase.get().

Make user code more qp-compatible.

Remove _q_index() from DynamicExportingDirectory.
This would only be used in a case where we export ('', '_q_index', None, None)
and don't provide any explicit '_q_index'.  If there are index pages that
don't load after this change, those directories should implement _q_index,
perhaps by calling index_page() as was done here.

Add a QP Dulcinea demo.

Implement a quixote-compatible version of Directory and put it in common.
Change all imports of DynamicExportingDirectory to import Directory from
common.

Put get_directory_tree() in common.

Remove enabling_cookies template and calls.

0.14: svn revision 28488
2006-08-16

Make Attachment Persistent.  To convert our databases containing attachments
to the new form, we ran this function in our update script.
    def touch_attachables():
        from dulcinea.attachable import Attachment, Attachable
        Attachment.__init__ = lambda x: None
        for attachable in gen_every_instance(get_connection(), Attachable):
            attachable._p_note_change()

Fix a bug in the change user password form that was not properly
removing the user's password.

Simplify the logic for SearchSelectOneWidget.

Update get_crumb_tree to use a get_crumb_tree_menu_items generator function
and to return, in addition, a derived css_class.

Remove module level get_exports function from dulcinea.ui.crumbs.  Instead
assume all directories have get_exports methods.

Move dulcinea.ui.crumbs.get_crumb_tree to dulcinea.ui.directory so it
can be more easily used by code not using qpy.

Make a StaticDirectory in dulcinea.common for quixote derived from the
quixote StaticDirectory that has a get_exports method.

Change all imports of StaticDirectory and StaticFile to go through 
duclinea.common.

Add page_size selection to search form.

When the permission form change a permission granted by a granter
to a user, call the granter's update_permission_cache() method, if it
exists.  This allows granters to maintain sets of users derived
from permissions.

Don't use tokens on the date_pair_form, since it is ordinarily used
for forms that are really just queries.


0.13: svn revision 27891
2006-02-01

This is a kind of transitional release as we are using qp more.  
Our existing dulcinea-based applications are still using quixote and ptl.

Define dulcinea.common to provide commonly used functions, and, in particular,
to provide the quixote version to quixote applications and the qp version to
qp applications.

Remove the ObjectDatabase class.  Just call get_connection() and you
get a connection to the durus storage that is configured for the 
site (and the site is determined by the SITE environment variable).
If you want a file storage connection instead, call 
open_connection('foo.durus').  When the Connection is made, so is
a site-specific Publisher.

Make DulcineaUser class inherit from qp's User class.  Existing DulcineaUser
instances must be converted because the password digests are stored differently.
A revise_users() function is provided for this conversion.
Also make DulcineaUserDatabase inherit from qp's UserDatabase.

Remove use of local_ui and local in dulcinea, although dulcinea.local
is still be defined when the site provides a local module.

Use get_publisher().get_site_title() instead of local.SITE_NAME.

Use dulcinea.common.CommonTest for unit tests involving a Connection.

dulcinea.sendmail.sendmail() uses publisher.get_webmaster_address() instead
of local.MAIL_SMTP_SENDER.

Database root accessors are now defined on the site-specific publisher,
and used through access functions.  For example, get_news_db() is defined
in news.py.  It calls the method on the publisher, and the DulcineaPublisher
provides a default implementation.

Add a dulcinea.uiqp package that mirrors the dulcinea.ui package,
except using the qpy compiler instead of the ptl compiler.

Make stronger attribute specification on History class so that Event
instances can be more easily verified.

LinkTripleDatabase business code and UI was separated from the 
LinkDatabase code.

Use sorted() instead of function_sort().

Remove the keyed, permission modules.

Revise debug session browser.

Use randbytes from qp.

0.12: svn revision 27720
2005-12-13

Dulcinea now requires the qp and qpy packages. 
Some Persistent classes that were in Dulcinea are now being used
from qp instead, and more will move in future releases of Dulcinea
as Dulcinea evolves to adapt to qp.
Keeping up with these changes will involve changing imports and
writing database update scripts.

The keyed module is gone: where it was used, we are now using qp.lib.keep.
Upgrading a database with KeyedMap instances will require a conversion
script that converts them to Persistent Keep instances.

The spec module is now imported from qp.
The typeutils module, deprecated in the last release, is now gone.

The code_utils module, and the utilities that used it are all removed, since
the same functionality is available from qpy's qpcheck.py script.
The DulcineaBase class is now named "Copyable".

The Publisher class can be named in the site_config file now.
This prepares the way for site-specific Publisher classes.

wrap_text() is now safer for non-ascii str instances.


0.11: svn revision 27556
2005-10-18

Change the DulcineaPublisher to set quixote's default encoding to utf8.
This means form values are unicode, not strs.  That means that non-ascii
str instances are hazardous, since they won't be automatically decoded
when they are combined in some way with unicode instances.  It also means
that calls to str() are hazardous, since the argument may now be a
unicode instance that can't be encoded as ascii.  We tried to identify
these hazards and change them into calls to stringify().  Note also that
"%s" % x is hazardous if x is an object with a __str__ method that may
return a unicode instance.  Code like this should be changed to 
u"%s" % x.

Add functions to dulcinea.util that we used to try to recover characters
from str instances with unknown encodings.  Purge the old replace_characters()
function that made this task more difficult.

Add a "string" spec that includes ascii-only str instances and all
unicode instances.  Change attribute specifications everywhere from
"str" to "string".

This release includes a revision to the way permissions are stored.
The permissions.py module is deprecated, but for now it includes 
a function that may be helpful in converting an existing database
to the new model.  In short, the new model stores permissions on
the users instead of on the objects that "grant" the permissions.
The new model also uses PermissionSet, a class that is new in
Durus-3.1.

Use require() instead of typecheck() everywhere.  The typeutils.py module
is still included, but deprecated.

Alter Keyed class to keep a counter on a separate persistent instance.  

Add a "pattern" spec.  Thanks to Mario Ruggier for the idea. 

0.10: svn revision 27465
2005-09-27

Use specified attributes more.

Add add_getters(), add_setters(), and add_getters_and_setters() to
the spec module.  Use these to add trivial get_<name> and set_<name>
methods as needed for classes with specified attributes.

Add a PersistentSet implementation.

Add an Outline implementation.

Convert spec's 'any' to 'either' and 'all' to 'both'
to avoid collision with new builtins 'any' and 'all' in python 2.5.

Allow some attributes that were specified as 'str' to be 'basestring'.

Expand Phone number fields in the registration form to 20 chars

Use a factored out module level function from dulcinea.address
to determine if a phone number is valid.

Add Item.can_modify().

Use default value in get_cache_size().

Add utilities 'set_environment' and 'clear_environment' to help test ui code.
 - set_environment sets up a Quixote publisher with a request
 - script_name, path_info, and other variables may be passed in as keywords
   to set_environment

Remove special handling of TIDY_CHECK in site scripts.

Replace ._p_changed = 1 with ._p_note_change() in lots of places.

Change crumb javascript section so that it does not do anything except when
it is actually required to get the right behavior.

Change check_durus.py so that it no longer depends on grouch.
It now expects all attributes to be specified using the spec pattern.

Make a new general-purpose composite-widget PairWidget.

Make DatePairWidget subclass from PairWidget

In the browse module, force the mime-type for Python source code files
to be text/plain

Enhance enabling_cookies template to *not* assume that the version
returned from HTTPRequest.guess_browser_version is always a string
with at least one character.

Use SCGIMount in dulcinea site script for apache.

0.9: svn revision 27188
2005-08-09


Remove extent module.  Durus (>2.0) has a gen_every_instance() function that 
serves this purpose.

Add life_cycle_util module.

Add note module.

Add size statistics to the check_durus output.

Remove code-coverage stuff from dulcinea that is duplicated in the sancho
package.

Use decorators in the category ui code.

Change spec's match() function so that a tuple containing None or
a numeric or string literal is treated as a disjunction.
This makes (None, int) mean the same thing as any(None, int), 
and it has the advantage of not requiring an import from the spec
module.

Add DatePairWidget.

Add render_csv() to Table.


0.8: svn revision 26679
2005-05-26

Add rss support for tabbed views.

Avoid parsing date fields as floats in javascript in Table.

Make all calls to format_user go through local_ui.

Show 5 most recent history when formatting a user's profile if the
logged in user is admin.

Show [browse] link for browsable attachments.

Add set_utils.

Provide a default local and local_ui for tests.

Add material classes.
Add parameter classes.

0.7: svn revision 26535
2005-04-12

Add browse.ptl, with support for browsing down into stored files
that are tar or zip archives.

Add get_module_directory() to dulcinea.util.

Move thumbnail-generation code from attachment.ptl to thumbnail.ptl.

Allow zip files to be uploaded as stored files.

Simplify decoration-related parameters of Interactable mixin class.

Restore reset_password to the profile page.

Remove references to SessionError.

Put revised signin handling in dulcinea.ui.user.util.
Stop dropping userid cookies.
Stop supporting insecure_login.

Add safe_respond() to use for error responses.

Change finish_interrupted_request() to make sure that cookies, set by the
session manager, make it into the response.

Make 'profile' a top-level directory that leads to individual user profiles
through a lookup.

Add a page() utility in dulcinea.ui.util.

Add HUB-based scgi restart to site command.  This is fast, but it does
not always work,


0.6: svn revision 26293
2005-03-07

Use a Dulcinea version of Quixote Directory class.  Instead of using
_q_exports, the new DynamicExportingDirectory classes implement a
get_exports() method, which generates a sequence of
(url_component, attribute_name, crumb, crumb_title) tuples
for the exports.  See dulcinea.ui.directory for the implementation.

Implement RespondNow handling behavior for the Dulcinea Publisher
and use it for redirects, not signed in, invalid query, and 
not found responses.  This is now the only PublishError subclass
provided in Dulcinea. The error-handling changes can be found in
in dulcinea.ui.publisher and dulcinea.ui.errors.

Add a new Table class for rendering data tables that sort by
column.  The Table class supports sorting on the client side or
on the server side.

Make opendb functional when readline is not available.

Use the word "category" everywhere we are talking about Category 
instances.  Stop using "group" for this purpose.

Use not_found(), invalid_query() and access_error() instead of raising
special exceptions.
Use ensure_signed_in instead of NotLoggedInError.

Remove dulcinea.errors.

Make is_running() more portable.

Use format_date() and format_date_time() from local_ui.

Change none_quote() to return '' if the value is false.

Call str on the method name so that method_sort can be called from templates,
where the method name will normally be an htmltext instance.

Use new quixote html_url function to generate url's with querystrings.

Add a general page_loader: see dulcinea.ui.page_loader.
This allows for sancho-style unit tests for a site.

Revise the crumb formatting to include drop-down crumb menus and
a menu of exports from the current Directory.

Expand output of start-apache.py to include the interfaces for each site.

Add a Message-of-the-day capability to DulcineaUser and DulcineaUserUI.

0.5: svn revision 25738
2004-12-09

  * Use Timestamped mixin for Survey, Comment, and Item.

  * 'get_url' -> 'get_local_url'

  * Use Quixote 2.  Make all Quixote namespaces Directory instances.
    Use quixote.server.scgi_server module.

  * Move most of the code from sitecheck.py into dulcinea.traversal.
    Change the behavior so that it does not complain about missing 
    attributes when there is a _q_resolve present.

  * Move utest.py to sancho.
    Add convert.py script in sancho.
    Add utest_* for each test_* in durus/test and dulcinea/lib/test

  * Add a configurable 'base_path' that will be prepended to absolute
    URLs.  Use relative paths when possible.

  * Make stored_file more portable and improve attachment mime type handling.

  * Make DateTimeSelectWidget more resilient to unusual dates.
    datetime.strftime only works for year >= 1900

  * Add a browse page that lists all urls reachable without _q_lookup, and
    makes a little form for each significant _q_lookup that it finds.

  * Make QuestionDatabase persistent.

  * For consistency, change get_*_database() to get_*_db().

  * In site_util, add get_docroot() and change _import_class() to import_class().

  * Remove comma_format and test.  Add a test for csv().

  * Add news.

  * Improve BigMultipleSelectWidget behavior.

  * Remove immutable_list module and test.  Use ImmutableSet instead.

  * Add the ability to disable DulcineaUser.

  * After a successful partial registration, redirect to the newly added
    user's profile, not the login page.

  * Get format_user from local_ui.
    Add experimental DurusDirectory for browsing the durus database.
    The browsing is disabled when is_live() is true.

  * Allow users to sign in using either there user id or email address.
    Add capability to disable login by email address 

  * Rename LazyModule class as SiteModule.
    Protect import of site_config so that it is possible to import from
    dulcinea without any installed site_config (as long as SITE is not set).

  * Ensure absorbed objects get repicked since we bypass the persistence hook

  * Fix sorting on ItemFolder.get_recent_items

  * Create an html2txt() to util module

  * Add interaction logging support.

0.4: svn revision >25025
2004-09-14

  * Revise site_utils to get site configuration information from
    a "site_config.py" module, expected on the normal python path,
    instead of from the site.conf file.  If you are using the site-related
    code, you must write a site_config.py file for your site(s).
    See site_util.get_config_value.__doc__ for a description of what 
    must be in your site_config.py file.  Notably, the site configuration
    variable names that included '-' are all converted to use '_' instead.

  * Added pages for viewing publihser and site config values to the
    debug ui.

  * Allow address widget and contact address widget to work with a None value.

  * Add site support for specifying the ability to do anonymous registration

  * Cleanup URL space for attachment DataUI and allow multiple files
    to be copied to the clipboard.  

  * Treat Address and ContactAddress as immutable.

  * Remove FileDatabase class because our external files are always
    accessed through attachments. Refactor code in the stored_file
    module, making new_file() and guess_mime_type() functions instead
    of methods.
  
  * Rewrite get_url() function.  Behavior is now slightly different
    but clearer and probably better.  If 'secure' is false then don't
    bother monkeying with the port, just return a full URL.  If
    'secure' is true then attempt to use SSL.  Note that if you want
    SSL then site_config.config  must provide a value for 'https_address'.

  * Start Apache if 'httpd' is defined as a site_config value..
    
  * Remove local.SUPPRESS_EMAIL flag and replace it by
    site_util.is_email_enabled().  If email is not not enabled then
    the dulcinea.sendmail module never sends mail.  This is less
    confusing than the SUPPRESS_EMAIL flag.

  * Add Attachable.is_image() .  Don't provide thumbnails for
    non-images.

  * Use optional 'apache_version' directive so that start-apache.py
    generates a config that can work with apache2, and the apache2
    mod_scgi module.

0.3: svn revision >24702
2004-07-16

  * More use of Form2 forms.

  * Replaced all use of mx.DateTime with the standard datetime.

0.2.1: svn revision >23475
~2004-02-16

  * Since 0.2, there are some classes to support a survey capability,
    and improved unit test coverage.

0.2: svn revision ~23344
2004-01-21

  * Second release.  Many changes since 0.1.

0.1: svn revision ~21750
2003-05-29

  * Initial release.