Release History

 IMPORTANT NOTES FOR 0.4.2

  * Zope 2.1.x support has officially ceased as of this release.  DynPersist is still
    required at the moment, however, and none of the 2.1.x support code has been
    removed.  All that's happened so far is that we're no longer coding with 2.1.x
    support in mind.

  * The Acquired Attribute Provider and Acquired Sheet Provider classes have been
    removed, and any instances you may have in your site will show up as "broken".
    Please replace them as described in the "Preparing for future versions" section
    above.

  * GenericAttributeProviders and GenericTriggers will be deprecated once the
    SkinScript grammar has been fully documented.


 Bug fixes and enhancements in 0.4.2a3

  - External attribute providers now correctly advertise their "getattr"
    functionality, and DataManagers should now handle internal slots correctly
    even if there is an external provider providing '*'.

  - SkinScript now reports syntax errors in a more meaningful way.

  - Generic Attribute Providers (including those generated by SkinScript) now
    report an attribute as non-existent (rather than None) if an error occurs
    during their calculation.

  - Triggers now have a HAS_CHANGED() function available to replace the
    CHANGED() function, since CHANGED is a reserved keyword in SkinScript.

  - Links to Parent Data Plug-ins should now handle the situation where the excludePIs
    property is set to the wrong datatype (e.g. string instead of list/tuple).

  - SkinScript methods now have a friendlier edit screen, similar to Python
    Methods and DTML Methods.


  Bug fixes in 0.4.2a2

   - Specialists can now be placed inside other specialists.  In general, adding a
     PlugInContainer to another PlugInContainer did not work.

   - Attribute providers which returned objects which possessed __of__ methods
     (i.e. virtually all Zope objects) were broken because DynPersist called the
     __of__ method without its parameters.  (oops!)

   - Transaction machinery was truly screwed up with respect to subtransactions.
     An abort of a transaction which had a subtransaction did not actually abort,
     and commiting a subtransaction could foul up important data structures.  

   - The SkinScript compiler removed spaces between tokens in Python expressions;
     this doesn't work when "a or b" becomes "aorb", however.  :(  Now it places
     at least one space between all tokens in the output.

   - PlugIns had a missing import in its new implementation of the ObjectManager
     "__replaceable__" protocol.


 New Features/Bug Fixes in 0.4.2a1

  - Improved SkinScript editing features, such as upload

  - Added "Persistent External Attribute Provider" which allows persistent attributes
    to be stored for non-persistent objects (such as items in a virtual Rack)

  - All known/reported bugs from 0.4.1snap1 have been fixed
 

 New Features/Bug Fixes in 0.4.1snap1

  - SkinScript Methods let you write your object specifications in a simple
    declarative language that is (of course) not yet documented.  But that's
    why this is a snapshot...

  - Proxy settings tab for providers and triggers, where applicable, so that
    you can set proxy roles.


 New Features/Bug Fixes in 0.4.0alpha5

  - Property Sheets for DataSkin-based ZClasses.  Now you can put define
    property sheets on a ZClass and still use AttributeProviders for the
    properties.  Just add a "DataSkin Property Sheet" to your ZClass
    instead of a "Common Instance Property Sheet".  (Note: you can only do
    this with *new* DataSkin-derived ZClasses.  If you have an already
    existing ZClass, you must either re-create it by hand or do the 
    "setbasesholdontoyourbutts" hack to re-create the ZClass.)

  - GenericTriggers now also pass a variable "ORIGINAL" which is a dictionary
    of the original values of changed attributes (or NOT_FOUND if the attribute
    did not exist before changing).  Note that if the values are complex or
    mutable, they cannot be guaranteed to be truly the same as their starting
    state, so this should really only be used for simple atomic values like
    strings and numbers.

  - Numerous bug fixes, including:

    - Specialists were always returning the result from the first Rack

    - setuid support for LoginManager was broken, and also didn't deal
      with executable-owner masking

    - _DelAttributeFor() was broken for persistently-stored attributes

    - Deleting a non-existent attribute no longer flags the attribute as changed

    - _constructPlugIn() was broken with latest 2.2 version that binds constructors
      to their factories

    - In the latest Zope, setting ownership after adding was causing a Changed
      event to fire instead of an Added event.

 New Features in 0.4.0

  - Attributes and Triggers

    - Added the "Generic Trigger" plug-in, which executes a DTML expression
      when selected (Add,Change,Delete) events occur, and can save pre-change
      or pre-delete values of expressions involving the changed/deleted object,
      for use in the executed expression.  It can also be used as an attribute
      set/delete handler.

    - Added the "Generic Attribute Provider", which computes attribute values
      using DTML expressions - and can call SQL or other methods to get groups
      of attributes.

    - Introduced support for "Agents" (triggers and indexes).  Not yet fully
      functional, and can't be properly supported before Zope 2.2 due to
      the way transactions currently work in Zope.

  - Using RackMountables outside Racks

    - Added "DataSkins", which are like the old RackMountable except that they
      can work in regular ZODB folders (so long as their path includes a
      "Folder w/Customization Support" in it).  Note that DataSkins do not support
      cut-and-paste (move) under Zope versions prior to 2.2 due to an issue with
      Moniker binding which is fixed in 2.2.  You can use copy-and-paste, however.

    - Added "Customizer" and "Folder w/Customization Support" products.  Customizer
      plugs into "Folder w/Customization Support" to add attributes, sheets,
      triggers, and/or indexes to DataSkins contained anywhere under the
      "Folder w/Customization Support".

  - Racks

    - Racks now cache retrieved items by key for the duration of a transaction

    - Racks now support two ways to store objects: "real", by storing them in
      the ZODB, and "virtual", by creating an empty object and then trying to
      read a specified attribute.  (If the attribute doesn't exist, the rack
      considers the object not to exist.)  This eliminates the need to create
      subclasses of Rack to support different kinds of non-ZODB storage, since
      any AttributeProvider can now be the primary source of data for an object.

    - Racks offer a "getPersistentItemIDs()" method which returns the ids of
      all items which have data stored persistently in the rack.  (Note that
      not all of these objects may exist if "virtual" storage is in use.

    - Racks now can "pack" and remove unused slots (since slots can be orphaned
      in "virtual" mode if an object is deleted from a foreign database).

  - PlugIns

    - The constructor protocols for PlugIns have been further simplified, to
      the point that plugins whose add forms only ask for id and title can now
      have their constructors generated automatically.  See any of the places
      where PlugIns (other than Racks) are registered for examples.

  - Other

    - There is a new "Transactions" module with handy classes for interacting with
      Zope's transaction system.  Subclassing 'Transactional' lets you receive
      transaction-related events in your object, and the 'TransientMapping' class
      lets you have a dictionary-like object that is automatically cleared after
      every transaction.


 API/Structural Changes in 0.4.0

  - We went back to having Rack._RawItem() not being deprecated.  It turned
    out that it was a perfect place to ensure the new structural invariants
    for DataSkins.  Go figure.  :)

  - RackMountables became DataSkins.  Please change your objects/code to get
    rid of references to the RackMountable class, it will go away altogether
    in 0.5.0

  - The namesForRegistration() API has changed to allow Providers/Agents to
    register as providing a variety of things (e.g. attributes and sheets
    from the same provider).

  - Attribute Providers, Sheet Providers, etc. all got merged into one tab,
    "Data plug-ins", to avoid having a bunch more tabs for triggers, indexes,
    etc.


 Upgrading from Version 0.2.0

  - ZClasses based on RackMountable and its subclasses (such as LoginUser)
    may need to be recreated to take advantage of dynamic properties and
    propertysheets, and possibly to work at all.  You can use either the
    setBasesHoldOnToYourButts method or the "make a new class and copy
    stuff" method.  RackMountable (or a subclass of RackMountable such as
    LoginUser) **must** be listed first in your base classes to ensure
    proper interaction with the new DynPersist C extension module.


 New Features in 0.3.0

  - DynPersist C extension that lets you put __get/set/del_attr__ hooks
    on persistent objects.  Used by RackMountable to support AttributeProviders.

  - The Rack base class is now actually useful in its own right, providing
    a persistent object store, and the ability to add arbitrary propertysheets
    to RackMountables.

  - Racks can now store items which are Python classes (i.e., as well as
    ZClasses) as long as they register as ZClass base classes.


 API/Structural Changes in 0.3.0

  - The SheetProvider API has changed quite a bit, mostly because it's been
    fleshed out enough to actually work.  :)

  - The 'PropertySheets()' and 'PropertySheet()' methods on RackMountable are
    now deprecated, because the standard 'propertysheets' attribute now works
    fine, even on ZClasses derived from RackMountable and its successors.

  - Rack._RawItem() is deprecated in favor of Rack._v_itemConstructor() as the
    preferred way of creating an "empty" RackMountable of the Rack's chosen
    class.  (The change is for efficiency of retrieval when using non-ZODB
    data sources, since _v_itemConstructor is the cached, actual constructor
    rather than a method to look up the constructor.)

  - PlugIns and PlugInContainers now have a _setup() hook that gets called by
    manage_afterAdd.  This is intended to allow an opportunity to configure
    default sub-objects such as attribute and sheet providers.  If using the
    _setup() hook, you should make sure it only executes once.  (The Rack
    _setup() method sets a self._initialized flag to keep track.)

  - The PlugIn base class now subclasses SimpleItem.Item, Persistent, and
    Acquisition.Implicit for you.  If you need the old pure mixin class, it's
    now PlugInBase.

  - Many other internal structure changes occurred which we won't document
    because they're things you probably shouldn't have been messing with.  :)
    And if you did know enough to be *able* to mess with them, you probably
    won't have much trouble figuring out what we changed anyway.  :)

