Change Log for PLIB Version 0.6.1

:Author:        Peter A. Donis
:Last Updated:  14 December 2009

Version 0.6.1
-------------

- Added KDE 4 GUI toolkit support. Also fixed a number of
  bugs in the Qt/KDE 4 toolkits (much of the code is common
  between these two).

- Added detection of KDE 4 in logic to select GUI toolkit.

- Added ``COLORNAMES`` global to ``plib.gui.defs`` so the
  string names of all supported colors are accessible as
  a single list.

- Extended widget enable and focus functionality to a
  wider range of widgets in ``plib.gui``.

- Added support for focus in and focus out widget events
  in ``plib.gui``.

- Added ``panelclass`` class field to the panel mixin
  class underlying ``PAutoPanel`` in ``plib.gui``, to
  fix bug in handling of sub-panels that are derived
  from ``PPanel`` but not ``PAutoPanel``.

- Fixed potential bugs in list view code where signatures
  of toolkit-specific list view items did not match the
  standard ``PListViewItemBase`` signature.

- Updated to version 0.4.4 of ``SetupHelper``.

- Added support for authentication and TLS when sending
  reminder e-mails in the ``scrips.py`` example program.

Version 0.6
-----------

- Added the ``NotifierClient`` class to ``plib.classes``
  and the ``PSocketNotifier`` class to ``plib.gui``. These
  classes work together to allow asynchronous socket I/O
  events to be multiplexed in with GUI event loops. (Note:
  these classes work best with the Qt-derived toolkits--Qt,
  Qt 4, and KDE. The other toolkits don't provide anything
  like Qt's ``QSocketNotifier`` class, so the multiplexing
  is done the kludgy way with timeouts.)

- Added the ``RecursiveTransition`` exception to the
  ``StateMachine`` class in ``plib.classes`` to flag when
  state transitions overlap. Added tests to correspond.

- Added the ``default_appclass`` global variable to the
  ``main`` module in ``plib.gui``; this allows overriding
  the ``PApplication`` default with something else. This is
  mainly for internal use (e.g., by the kludgy method of
  multiplexing socket I/O described above), but it is
  available if desired. (Note, however, that the actual
  ``default_appclass`` variable must *not* be overwritten,
  since it is a container; instead, assign your new class to
  index 0, thus: ``gui.default_appclass[0] = MyAppClass``.
  This is necessary for now because of how the ``ModuleProxy``
  class retrieves attributes from the module it wraps; at
  some point I may fix that so this hack is no longer
  needed.)

- Added the ``SerialPseudoSocket`` and ``SerialTelnet``
  classes to ``plib.classes``.

- Refactored the I/O classes in ``plib.stdlib`` to make the
  overall API and inheritance tree easier to use. This is a
  significant API change; see the ``README`` file and the
  ``plib.stdlib.io`` sub-package docstring for information
  about how it works. The ``ModuleProxy`` class is used
  throughout the new sub-package layout to make classes
  automatically appear in the proper namespace, and also to
  generate "standard" mixin classes on the fly when needed.

- Added the ``ShutdownReadWrite`` alternate data handling
  class.

- The socket I/O class ``close`` methods now catch more
  exceptions.

- Added test cases to more thoroughly exercise multiple and
  concurrent requests for the socket I/O classes.

- Much expansion of docstrings.

Version 0.5.2
-------------

- Where Python 2.4 and later syntax is used
  (mainly generator expressions), added alternate
  implementations (selected based on ``sys.version``)
  to support versions 2.2 and 2.3.

- Changed behavior of the abstract container
  classes to match Python 2.6/3.0 semantics in the
  handling of extended slices; extended slices
  with ``step == 1`` are now treated exactly
  the same as non-extended slices. The
  ``normalize_slice`` function in ``plib.stdlib``
  also changes its semantics to correspond.

- Added the ``__reversed__`` method to the abstract
  container types if the Python version is 2.6 or
  later.

- The abstract container types are now registered
  with the appropriate abstract base classes if the
  Python version is 2.6 or later; added test case
  to confirm that this works.

- Added the ``first`` and ``last`` functions in
  ``plib.stdlib``, and corresponding tests.

- The ``insert_sorted`` method of the ``SortMixin``
  class in ``plib.stdlib`` now has a ``key``
  argument, which works the same as the ``key``
  argument for the ``sorted`` builtin. Also,
  added a backport implementation of the ``sorted``
  builtin for Python versions < 2.4.

- Changed the ``SigSocketServer`` module in
  ``plib.stdlib`` to provide a complete alternate
  implementation of a forking TCP server and base
  request handler, instead of subclassing the Python
  standard library classes.

- Fixed the ``ClientServer`` blocking I/O mixin
  classes in ``plib.stdlib`` to ensure that sockets
  are closed even if an exception occurs.

- Made a number of improvements to the I/O classes
  to increase robustness.

- Modified the ``chat_replies`` class in
  ``plib.utils.chatgen`` to not send any data
  on startup if the first item in its data
  queue is ``None``; instead, just listen for
  an initial message from the server. Added a
  test case for this behavior.

- Added unit tests for the ``StateMachine`` class.

- Changed the test cases for the abstract
  containers to test for the new semantics for
  extended slices with ``step == 1``.

- Added test cases for the I/O classes to test for
  handling of multiple/concurrent requests and
  small I/O buffer sizes. 

Version 0.5.1
-------------

- Added the ``ReadWriteMonitor`` class to
  ``plib.classes``. This is a useful testing
  class for client/server I/O channels; it
  prints notifications of significant read
  and write method calls to standard output.

- Set the default for the ``use_poll`` global
  in ``plib.stdlib.async`` to ``True``; there
  is no reason to default to ``False`` since the
  ``loop`` function still checks to make sure
  the running OS supports the ``poll`` function,
  and falls back to ``select`` if it doesn't.

- Added the ``chatgen`` module to ``plib.utils``,
  containing the ``chat_replies`` class; this
  wraps an asynchronous I/O client in a generator
  that sends messages to the server one by one
  and yields the replies. The ``pyidserver.py``
  example program now uses this class to do its
  communication to the server; the generator
  form makes the code for the display of the
  results much easier.

- Made improvements to the behavior of instances
  of the ``ModuleProxy`` class from ``plib.utils``;]
  the builtin ``help`` command now correctly displays
  docstrings of proxy modules, and their ``repr``
  output is more informative.

- Added tests for the ``chat_replies`` class and
  the ``fork_wait`` and ``fork_socketpair``
  functions to the test suite.

- Added tests of the asynchronous I/O classes
  with the ``poll`` function disabled (see the
  item on ``async.use_poll`` above.

- Added unit tests for the ``ModuleProxy`` class.

Version 0.5
-----------

- The ``PTCPClient`` class in ``plib.classes``
  is simplified, using the refactored socket
  I/O functionality in ``plib.stdlib`` (see
  below).

- The ``PRequestHandler`` and ``SendReceiveMixin``
  classes are removed from ``plib.classes``;
  their functionality is no longer needed with
  the refactoring of the socket I/O classes
  in ``plib.stdlib`` (see below).

- Added the ``PListBox`` control to ``plib.gui``,
  a list view specialized for use in dialogs.
  This class also includes convenience methods to
  add items to the list box for common special
  cases (no child items, and single-column with
  no child items).

- Added ``PersistentMixin`` class to the
  ``plib.stdlib.async`` module, to handle cases
  where a persistent, full-duplex connection is
  desired instead of a pure client or server.
  This class supports overlapping reads and writes
  and implements a simple queue for write data to
  ensure all writes are in the correct order and
  no data is clobbered. Added corresponding
  persistent classes to the asynchronous I/O
  modules based on ``async``.

- Added the ``io`` module to the ``plib.stdlib``
  sub-package to provide common base classes
  for all I/O modes, factored out from the
  asynchronous and serial I/O classes.

- Added the ``pyserial`` module to the
  ``plib.stdlib`` sub-package to provide
  a thin wrapper around the ``Serial`` class
  and give a common base class for the
  ``SerialIO`` and ``AsyncSerial`` modules.
  The thin wrapper also adds the option to
  choose blocking or non-blocking mode for
  the serial device (the ``SerialIO`` and
  ``AsyncSerial`` modules each make the
  appropriate choice).

- Added the ``socketio`` module to ``plib.stdlib``
  to factor out socket-specific I/O functionality
  that is useful for both blocking and non-blocking
  I/O modes.

- Added the ``ClientServer`` module to ``plib.stdlib``
  to implement common functionality for blocking I/O
  clients and servers. This also factors out some
  code that was duplicated in other modules.

- Added the ``SocketClient`` module to ``plib.stdlib``
  to implement a simple blocking socket I/O client.

- Added the ``BaseRequestHandler`` class to the
  ``SigSocketServer`` module in ``plib.stdlib``; same
  functionality as the corresponding class from the
  Python standard library, but using the ``ClientServer``
  module blocking I/O scheme.

- Standardized the API for the various client/server
  classes: ``self.client_communicate(data)`` now
  always works for clients (possibly with the address
  socket clients or the device ID for serial clients,
  and a callback for async clients), and
  ``self.serve_forever()`` now always works for
  servers (possibly with a callback for async servers).

- Ensured that the ``close`` method of all async
  I/O classes is idempotent, since it is called from
  several places to ensure that it gets called at
  least once for any event that should trigger a
  close, but we don't want to call ``handle_close``
  multiple times.

- Removed the ``sitepath`` variable from the
  ``plib.stdlib`` sub-package globals; nothing
  in PLIB uses it and the heuristics for making
  sure it was correct were too hairy.

- Removed much cruft from the abstract container
  classes in ``plib.stdlib``, and added the
  ``basecontainer`` class to provide a partial
  implementation of ``abstractcontainer``. Also
  made the APIs of the abstract containers more
  complete and logical, and fixed logic to ensure
  the same semantics as list and tuple, including
  end case behavior.

- Added the ``closure`` function to ``plib.stdlib``,
  returns a simple closure of the given function with
  the given args and kwargs.

- Added the ``slice_len`` function to ``plib.stdlib``,
  returns the number of indexes that would be affected
  if the slice were used as a sequence index.

- Added the ``coll`` module to ``plib.stdlib``, with
  two convenience collection classes, ``fifo`` (based
  on ``collections.deque``) and ``stack`` (based on
  ``list``); the only changes are to define the ``next``
  method for each to retrieve the "next" object in
  the collection, as appropriate (i.e., the first item
  for ``fifo`` and the last item for ``stack``).

- Added tests in ``plib.test`` for most of the functions,
  classes, and modules in ``plib.stdlib``, and the
  ``specs`` module in ``plib.gui``.

- Added the ``forkwait``, ``forkserver``, and ``socketpair``
  modules to ``plib.utils``, containing the ``fork_wait``,
  ``fork_server``, and ``fork_socketpair`` functions. These
  fork subprocesses with extra functionality: ``fork_wait``
  waits until the subprocess has signaled successful startup
  before continuing, ``fork_server`` is a convenience function
  to do the same with a server class and its appropriate
  parameters given, and ``fork_socketpair`` lets the subprocess
  and the parent communicate via a socket pair.

- Fixed the ``plib-setup-paths.py`` post-install
  script to more reliably find paths, particularly
  on Mac OS X.

- The ``pyidserver.py`` example program now uses the
  asynchronous socket I/O ``ClientCommunicator`` class
  from ``plib.stdlib``.

- Minor refactoring of the ``scrips.py`` example
  progam (so it doesn't define the email-related
  code unless it's sending notification e-mail).

- Most docstrings now have more complete information than
  before.

Version 0.4.7
-------------

- Added new ``StateMachine`` class to
  ``plib.classes``, implements a simple
  state machine using a mapping of states
  to maps of input/output relations.

- Changed base async I/O classes to raise
  exceptions instead of logging warnings
  (e.g., raise NotImplementedError if a
  necessary event handler is not overridden).
  This also eliminates logging from the base
  classes--logging functionality is left as
  a "policy" for higher-level classes (such
  as ``plib.classes.PServerBase``).

- Made changes to async ``BaseDispatcher`` to
  mirror improvements made in Python 2.6 to
  ``asyncore.dispatcher``.

- Added exception handling to ``do_loop`` method
  of the async serial server classes; the
  ``close`` method is now called whenever an
  exception breaks out of the loop (similar to
  the protection added in ``SigSocketServer``).

- Added a new module in ``plib.stdlib`` for
  blocking serial I/O (i.e., no async/select
  loop). This module is now called ``SerialIO``;
  the async serial classes are now in the
  ``AsyncSerial`` module.

Version 0.4.6
-------------

- Refactored the ``plib.stdlib.async`` and
  ``plib.stdlib.AsyncServer`` modules to allow
  the core asynchronous I/O logic to be used with
  any object that has a Unix file descriptor;
  the classes in ``plib.stdlib.AsyncServer`` now
  inherit the core functionality and specialize
  it for network sockets.

- Added a global ``loop`` function to the ``async``
  module to allow a callback function (instead of
  requiring the use of ``AsyncBase.do_loop`` to
  get this functionality). Otherwise gives the same
  functionality as ``asyncore.loop``.

- Added the ``SerialIO`` module to ``plib.stdlib``
  to provide an asynchronous serial port I/O
  handler based on ``AsyncBase``. Note that this
  class requires the ``pyserial`` package, which
  is available from SourceForge.

- Moved the ``ReadWrite`` class from ``plib.classes``
  to ``plib.stdlib`` and made ``ReadWrite`` a
  module containing all the various mixin classes
  for data read/write handling.

- Fixed bug in the ``plib-setup-paths.py`` post-install
  script that was prepending the drive letter twice
  on Windows.

Version 0.4.5
-------------

- Fixed bugs in the post-install scripts: the
  boolean variables in the generated file
  ``plib.gui._setup.py`` were being incorrectly
  written as strings, and ``plib-setup-examples.py``
  was scanning too many directories in the
  ``$PREFIX/share`` tree.

Version 0.4.4
-------------

- Fixed minor errors in output from the
  ``plib.setuputils`` post-install script
  helper function, and made some other
  enhancements in script outputs.

Version 0.4.3
-------------

- Added a ``plib-setup-paths.py`` post-install
  script to determine the standard path names
  that are exported in ``plib.stdlib``, instead
  of determining them on the fly each time that
  package is imported (which is overkill since
  they should not change). Also added some new
  heuristics for determining the path names.

- Added a ``setuputils`` module in the base
  ``plib`` package to provide common code for
  the post-install scripts.

- Added code to the ``BaseDispatcher`` class in
  ``plib.stdlib.async`` to fix a number of minor
  issues with ``asyncore.dispatcher``.

- Moved the ``ReadWrite`` mixin class from
  ``plib.stdlib.async`` to ``plib.classes``, and
  moved the other async classes in ``plib.stdlib``
  into a new ``AsyncServer`` module. The client
  and server communicator classes are now mixins
  so that they can be used with different protocol
  read/write mixin classes.

Version 0.4.2
-------------

- Added support for Qt 4 as a GUI toolkit (it is
  different enough from Qt 3 that it's easier to make
  it separate than to try and extend the current Qt
  support to cover it). *NOTE: Qt 4 support is still
  experimental; some widgets (in particular the table
  widget) are still buggy.*

- Added ``process_events`` method to ``PApplication``
  objects to allow GUI events to be handled while
  other processing is going on--the typical use case
  is to call this method as a callback from an
  asynchronous I/O loop. Note that this method should
  not be called from event handlers or any other code
  that might recursively call into the GUI event loop.

- Added action images for the ``darwin`` platform to
  the GUI images available.

Version 0.4.1
-------------

- Added ``PServerBase`` class to ``plib.classes`` to
  factor out functionality common to all types of
  servers (sync, async, and forking).

- Added ``PAsyncServer`` class to ``plib.classes``,
  mixes ``PServerBase`` and ``ServerDispatcher`` from
  the ``plib.stdlib.async`` module.

- Added a clause in the ``do_loop`` method of
  ``BaseDispatcher`` in ``plib.stdlib.async`` to
  allow the callback function to break out of the
  polling loop by returning ``False``.

- Added ``AsyncRequestHandler`` class to the
  ``plib.stdlib.async`` module so that the
  ``ServerCommunicator`` class can remain general.

- Added a ``try/finally`` clause to the ``serve_forever``
  method of ``ServerDispatcher`` in ``plib.stdlib.async``
  and added a similar method to ``SigMixin`` in
  ``plib.stdlib.SigSocketServer`` to ensure that
  ``server_close`` gets called if an exception is thrown
  (previously only ``PTCPServer`` had this included).

- Added ``_panels.py`` unit to ``plib.gui``, containing
  the ``PMainPanel`` class, a ``PAutoPanel`` specialized
  for use as the main panel of your application (i.e.,
  the client widget of the main window). Changed the
  ``pyidserver-gui.py`` example program to use the new
  main panel class.

- Added ``PTextFile`` class to ``plib.gui.classes`` to
  allow read/write to a PTextDisplay as a file-like
  object (this was previously implemented only in the
  ``pyidserver-gui`` example program).

Version 0.4
-----------

- ``PTCPServer`` now correctly calls ``server_close``
  whenever it receives a signal that is in its list of
  terminating signals; this ensures that it shuts
  itself down properly and also ensures that the
  inherited ``server_close`` gets called to close the
  socket.

- Added ``PGroupBox`` widget to ``plib.gui``: basically
  a ``PPanel`` with a box and caption around its child
  widgets. Also added ``PAutoGroupBox`` to allow
  specification of child widgets using Python data
  structures.

- Added ``PTextDisplay`` widget, which is basically a
  read-only version of PEditControl. The example program
  ``pyidserver-gui.py`` now uses this widget to display
  output.

- Changed ``PTopWindow`` class fields for window
  placement on screen: the ``placement`` class field
  is now a 2-tuple ``(size_type, pos_type)``, whereUTILS
  the ``size_type`` can be:
  
  * ``SIZE_NONE``,
  * ``SIZE_CLIENTWRAP``,
  * ``SIZE_MAXIMIZED``,
  * ``SIZE_OFFSET``,
  
  and the ``pos_type`` can be:
  
  * ``MOVE_NONE``,
  * ``MOVE_CENTER``.

- Enabled font settings on all widgets (previously only
  "control" type widgets had them).

- The ``plib.gui.specs`` module now allows you to use
  custom widget classes when building specs, by setting
  module variables.

- Also added ``get_listview`` to ``plib.gui.specs``.

- ``PPrefsDialog`` now supports all three types of INI
  file option specs.

- The preferences dialog now also allows two choices
  for the section grouping: each section can be a tab
  in a tab widget (the default), or a group box (just
  pass ``SECTION_GROUPBOX`` as the ``style`` parameter
  to the constructor).

- Added a ``gui_test`` variable in ``plib.gui._gui`` to
  allow testing of experimental additional toolkits that
  are not installed in PLIB. See the comments in the
  ``plib.gui._gui`` module for details.

- Fixed bug in ``plib.ini`` where int and boolean values
  were not being written correctly to INI files.

- Added ``async.py`` module in ``plib.stdlib``, providing
  basic asynchronous client/server classes (building on
  the ``asyncore`` module in the Python standard library).

- Updated to version 0.4.2 of ``SetupHelper``.

Version 0.3
-----------

- Added ``__version__`` variable to the
  top-level ``plib`` namespace. All of the
  example programs now use the plib version
  as their version number by importing this
  variable.

- Added ``PPrefsDialog`` to ``PLIB.GUI``: a
  preferences dialog that automatically builds
  its interface from a ``PIniFile``. Added a
  preferences dialog to the ``scrips-edit``
  example program to demonstrate this
  functionality.

- Added ``specs`` module to ``PLIB.GUI`` to provide
  helper variables and functions for specifying
  GUI layouts. The ``PPrefsDialog`` class above
  uses this module, and the ``pyidserver-gui.py``
  example program is also modified to use this
  functionality.

- Added ``clientwrap`` class field to ``PTopWindow``
  to automatically size the window to fit its
  client widget; this is now the default behavior.

- Added ``SIGNAL_CLOSING`` signal in ``PLIB.GUI``
  to allow notification when window has accepted
  a close but has not yet closed.

- Moved the ``ModuleProxy`` class from
  ``PLIB.CLASSES`` to ``PLIB.UTILS``, since the
  latter is intended to be closer to the 'root'
  of the dependency tree.

- Added the ``dotted_import`` function to
  ``PLIB.STDLIB`` for convenience when using the
  ``__import__`` builtin with dotted names (the
  code for this function originally came from
  the Python 2.6 documentation).

- Moved the ``options`` module from ``PLIB.UTILS``
  to ``PLIB.STDLIB`` since it basically wraps
  the standard library ``optparse`` module.

- Added the ``version`` module to ``PLIB.UTILS``,
  providing some extensions of the Python
  distutils version number functionality. Also
  added a doctest for this module.

- Added support in ``PLIB.XML`` for manually
  controlling the XML declaration and doctype
  string during serialization.

- The protocol and port number controls in the
  ``pyidserver-gui.py`` example are now disabled
  if DNS only is checked (this alerts the user
  that protocol and port number parameters are
  ignored by ``pyidserver`` in DNS only mode).

- The license for ``plib/test/runtests.py``, the
  generic test-running script, is changed to the
  PSF license so it can be detached from the rest
  of PLIB and used in non-GPL projects.

- Updated to version 0.4 of ``SetupHelper``.

Version 0.2.1
-------------

- Fixed bug in ``PLIB.GUI`` that was appending
  spurious text to ``PMainWindow`` captions.

- Updated to version 0.3.1 of ``SetupHelper``.

Version 0.2
-----------

- Added status bar to ``PMainWindow``, and added demo
  functionality for the status bar to ``pxmlview``.

- Added support for more widget signals (selection
  changed signals for combo box, list view, and tab
  widget), and ensured that all signal-handling
  widgets derive from either ``_PDialogControl`` or
  ``_PNotifyControl``.

- Corrected tab add/delete behavior for tab widget.

- Added private ``_parent`` class field to tab widget,
  for consistency with other non-dialog control
  widgets.

- Added checks to ``PEditor`` to make sure main widget
  supports the editor protocol.

- Improved handling of widget geometry; passing ``None``
  as one of the geometry parameters means that
  parameter doesn't get changed from its previous
  value (which will usually be the default).

- Changed ``PLabel`` to ``PHeaderLabel``, and made
  ``plib.gui.classes`` and ``plib.gui.edit`` into
  private modules; their classes now appear in the
  ``plib.gui.main`` namespace with all the others.

- Added support in ``PIniFile`` for linking options to
  named attributes on the ``PIniFile`` object, instead of
  having get/set functions.

- Added tab widget to ``pxmlview.py`` example program to
  allow viewing multiple files; added support for
  passing multiple file names on the command line.

- Added basic URL parsing to the pyidserver.py example
  program; it now extracts the protocol and port
  number from URLs of the form::

    <protocol>://<url>:<port>

  Protocol and port specifiers in the URL override
  any specifiers in command-line options.

- Added new example program, ``scrips.py``, and its GUI,
  ``scrips-edit.py``; these are programs to keep track
  of prescriptions, demonstrating the table widget
  and INI file functionality in PLIB.

- The ``setup.py`` script now uses a 'generic' helper
  module, ``SetupHelper``; all that is done in setup.py
  itself is to define variables and then call the
  helper module entry point. The SetupHelper module
  is available as its own PyPI project, ``setuphelper``.

- Since SetupHelper handles running post-install
  scripts, the ``install-all`` shell script is no longer
  needed and has been removed.

Version 0.1
-----------

Initial release.
