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.