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_ and set_ 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.