		  History of changes to python-icat
		  =================================

* Version 0.11.0 (2016-06-01)

** New features

 + Issues #12 and #23: add support for ICAT 4.7.0 and IDS 1.6.0.  ICAT
   4.7.0 had some small schema changes that have been taken into
   account.

** Incompatible changes

 + Remove the autoget argument from Entity.getUniqueKey().
   Deprecated since 0.9.0.

** Bug fixes and minor changes

 + Issue #21: configuration variable promptPass is ignored when set in
   the configuration file.

 + Issue #18: Documentation: missing stuff in the module index.

 + Issue #20: add test on compatibility with icat.server.

 + Issues #24 and #25: test failures caused by different timezone
   settings of the test server.

 + Use a separate module distutils_pytest for "setup.py test".

 + icat.icatcheck: move checking of exceptions into a separate method
   checkExceptions().  Do not report exceptions defined in the client,
   but not found in the schema.

 + Many fixes in the example script wipeicat.py.

 + Fix a missing import in the icatexport.py example script.

 + Somewhat clearer error messages for some special cases of
   SearchAssertionError.

** Misc

 + Change license to Apache 2.0.

* Version 0.10.0 (2015-12-06)

** New features

 + Add a method Entity.copy().

 + Implement setting an "INCLUDE 1" clause equivalent in class Query.

 + Add an optional argument includes to Client.searchMatching().

 + Add a hook for a custom method to validate entity objects before
   creating them at the ICAT server.

 + Add support for ids.server 1.5.0:
   - Add getDatafileIds() and getPreparedDatafileIds() calls.
   - IDSClient.getStatus() allows sessionId to be None.

 + Add new exception class ICATNotImplementedError that is supposed to
   be raised by the upcoming version 4.6.0 of icat.server.

** Bug fixes and minor changes

 + Issue #13: Client.searchChunked() raises exception if the query
   contains a percent character.

 + Issue #15: icatdump raises DataConsistencyError for
   DataCollectionParameter.

 + Issue #14: Entity.__sortkey__() may raise RuntimeError "maximum
   recursion depth exceeded".

 + Allow a DataSelection to be created from (almost) any Iterator, not
   just a Sequence.  Store the object ids in DataSelection internally
   in a set rather then a list.

 + Add optional arguments objindex to DumpFileReader.getobjs() and
   keyindex to DumpFileWriter.writedata() to allow the caller to
   control these internal indices.

 + Add optional argument chunksize to DumpFileWriter.writedata().

 + The constructor of class Query checks the version of the ICAT
   server and raises an error if too old.

 + The getIcatUrl() call checks the version of the IDS server.

 + Some changes in the test suite, add more tests.

* Version 0.9.0 (2015-08-13)

** New features

 + Issue #4: Extend icatrestore to become a generic ingestion tool.

   Rename icatrestore.py to icatingest.py.

   Allow referencing of objects by attribute rather then by unique key
   in the input file for icatingest.py (only in the XML backend).

   Allow adding references to already existing objects in the input
   file for icatingest.py (only in the XML backend).

   Change the name of the root element in the input file for
   icatingest.py (and the output of icatdump.py) from "icatdump" to
   "icatdata" (only in the XML backend).

 + Implement upload of Datafiles to IDS rather then only creating the
   ICAT object from icatingest.py.

 + Implement handling of duplicates in icatingest.py.  The same
   options ("THROW", "IGNORE", "CHECK", and "OVERWRITE") as in the
   import call in the ICAT restful interface are supported.

 + Issue #1: add a test suite.

 + Issue #3: use Sphinx to generate the API documentation.

 + Add a searchMatching() client method.

 + Add the getIcatUrl() call introduced with IDS 1.4.0.

** Incompatible changes and deprecations

 + The Lucene calls that have been removed in ICAT 4.5.0 are also
   removed from the client.

 + Deprecate the use of the autoget argument in Entity.getUniqueKey().

** Bug fixes and minor changes

 + Issue #6: Query: adding a condition on a meta attribute fails.

 + Issue #10: client.putData: IDSInternalError is raised if
   datafile.datafileCreateTime is set.

 + Ignore import errors from the backend modules in icatingest.py and
   icatdump.py.  This means one can use the scripts also if the
   prerequisites for some backends are not fulfilled, only the
   concerned backends are not available then.

 + Issue #5, compatibility with ICAT 4.5: entity ids are not
   guaranteed to be unique among all entities, but only for entities
   of the same type.

 + Issue #5, compatibility with ICAT 4.5: getEntityInfo() also lists
   "createId", "createTime", "modId", and "modTime" as attributes.
   This need to be taken into account in module icat.icatcheck.

 + The last fix in 0.8.0 on the string representation operator
   __str__() of Query was not complete, the operator still had
   unwanted side effects.

 + Fix a bug in the handling of errors raised from the ICAT or the
   IDS server.  This bug affected only Python 3.

 + Add proper type checking and conversion for setting an attribute
   that corresponds to a one to many relationship in class Entity.
   Accept any iterable of entities as value.

 + Issue #9: icatingest with duplicate=CHECK may fail when attributes
   are not strings.  Note that this bug was only present in an alpha
   version, but not in any earlier release version.

 + Source repository moved to Git.  This gives rise to a few tiny
   changes.  To name the most visible ones: python2_6.patch is now
   auto generated by comparing two source branches and must be applied
   with '-p1' instead of '-p0', the format of the icat module variable
   __revision__ has changed.

 + Review default exports of modules.  Mark some helper functions as
   internal.

* Version 0.8.0 (2015-05-08)

** New features

 + Enable verification of the SSL server certificate in HTTPS
   connections.  Add a new configuration variable "checkCert" to
   control this.  It is set to True by default.

   Note that this requires either Python 2.7.9 or 3.2 or newer.  With
   older Python version, this configuration option has no effect.

 + Add type conversion of configuration variables.

 + Add substituting the values of configuration variables in other
   variables.

 + Add another derived configuration variable configDir.

 + Default search path for the configuration file: add an appropriate
   path on Windows, add /etc/icat and ~/.config/icat to the path if
   not on Windows.

 + Add icatexport.py and icatimport.py example scripts that use the
   corresponding calls to the ICAT RESTful interface to dump and
   restore the ICAT content.

 + The constructor of ICATError and the translateError() function are
   now able to construct exceptions based on a dict such as those
   returned by the ICAT RESTful interface in case of an error.

   Unified handling of errors raised from the ICAT and the IDS server.

** Incompatible changes

 + As a consequence of the unified handling of errors, the exception
   class hierarchy has been reviewed, with a somewhat more clear
   separation of exceptions raised by other libraries, exceptions
   raised by the server, and exceptions raised by python-icat
   respectively.

   If you put assumptions on the exception hierarchy in your code,
   this might need a review.  In particular, IDSResponseError is not
   derived from IDSError any more.  IDSServerError has been removed.

   I.e., replace all references to IDSServerError by IDSError in your
   code.  Furthermore, if you catch IDSError in your code with the
   intention to catch both, errors from the IDS server and
   IDSResponseError in one branch, replace:

     try:
         # ...
     except IDSError:
         # ...

   by

     try:
         # ...
     except (IDSError, IDSResponseError):
         # ...

** Bug fixes and minor changes

 + The Query class now checks the attributes referenced in conditions
   and includes for validity.

 + Fix a regression introduced with version 0.7.0 that caused
   non-ASCII characters in queries not to work.

 + Fix ICATError and IDSError to gracefully deal with non-ASCII
   characters in error messages.  Add a common abstract base class
   ICATException that cares about this.

 + Fix: the string representation operator __str__() of Query should
   not modify the query object.

 + Cosmetic improvement in the formal representation operator
   __repr__() of Query.

* Version 0.7.0 (2015-02-11)

** New features

 + Add a module icat.query with a class Query that can be used to
   build ICAT search expressions.  Instances of the class may be used
   in place of search expression strings where appropriate.

   Numerous examples on how to use this new class can be found in
   querytest.py in the examples.

 + Add a class method getNaturalOrder() to Entity that returns a list
   of attributes suitable to be used in an ORDER BY clause in an ICAT
   search expression.

 + Add a class method getAttrInfo() to Entity that queries the
   EntityInfo from the ICAT server and extracts the information on an
   attribute.

 + Add a method getEntityClass() that returns the Entity class
   corresponding to a name.

 + Add a warning class QueryNullableOrderWarning.

 + Add an optional argument username to the getLink() IDS method.

* Version 0.6.0 (2014-12-15)

** New features

 + Add support for ICAT 4.4.0: add new Entity type InvestigationGroup,
   role has been added to the constraint in InvestigationUser.

 + Add new IDSClient API method getApiVersion() that will be
   introduced with the upcoming version 1.3.0 of IDS.  This method may
   also be called with older IDS servers: if it is not available
   because the server does not support it yet, the server version is
   guessed from visible features in the API.

   IDSClient checks the API version on init.

 + Add new IDSClient API methods isReadOnly(), isTwoLevel(),
   getLink(), and getSize() introduced with IDS 1.2.0.

 + Add no_proxy support.  The proxy configuration variables,
   http_proxy, https_proxy, and no_proxy are set in the environment.
   [Suggested by Alistair Mills]

 + Rework the dump file backend API for icatdump and icatrestore.  As
   a result, writing custom dump or restore scripts is much cleaner
   and easier now.

   This may cause compatibility issues for users who either wrote
   their own dump file backend or for users who wrote custom dump or
   restore scripts, using the XML or YAML backends.  In the first
   case, compare the old XML and YAML backends with the new versions
   and you'll easily see what needs to get adapted.  In the latter
   case, have a look into the new versions of icatdump and icatrestore
   to see how to use the new backend API.

 + Add method searchChunked() to Client.

 + Add method getAttrType() to Entity.

** Incompatible changes

 + Move the group argument to the Client method createRules() to the
   last position and make it optional, having default None.

   In the client code, replace:

     client.createRules(group, crudFlags, what)

   by

     client.createRules(crudFlags, what, group)

 + The Client method putData() returns the new Datafile object created
   by IDS rather then only its id.

   If you depend on the old behavior in the client code, replace:

     dfid = client.putData(file, datafile)

   by

     df = client.putData(file, datafile)
     dfid = df.id

** Minor changes and fixes

 + The searchText() and luceneSearch() client method have been
   deprecated.  They are destined to be dropped from the ICAT server
   or at least changed in version 4.5.0 and might get removed from
   python-icat in a future release as well.

   The methods now emit a deprecation warning when called.  Note
   however that Python by default ignores deprecation warnings, so you
   won't see this unless you switch them on.

 + Fixed overly strict type checking in the constructor arguments of
   DataSelection and as a consequence also in the arguments of the
   ICAT client methods getData(), getDataUrl(), prepareData(), and
   deleteData(): now, any Sequence of entity objects will be accepted,
   in particular an EntityList.

 + Change IDSClient API methods archive() and restore() to not to
   return anything.  While formally, this might be considered an
   incompatible change, these methods never returned anything
   meaningful in the past.

 + Slightly modified the "==" and "!=" operator for Entity objects.
   Add a __hash__() method to the Entity class.  The latter means
   that you will more likely get what you expect when you create a
   set of Entity objects or use them as keys in a dict.

 + The module icat.eval now only does its work (parsing command line
   arguments and connecting to an ICAT server) when called from the
   Python command line.  When imported as a regular module, it will
   essentially do nothing.  This avoids errors to occur when imported.

 + setup.py raises an error with Python 2.6 if python2_6.patch has not
   been applied.

 + Add missing MANIFEST.in in the source distribution.

 + Remove the work around the Suds datetime value bug (setting the
   environment variable TZ to "UTC") from __init__.py.  Instead,
   document it along with other known issues in the README.

 + Minor fixes in the sorting of entity objects.

 + Add an optional argument args to Config.getconfig().  If set to a
   list of strings, it replaces sys.argv.  Mainly useful for testing.

 + Add comparison operators to class ListProxy.

* Version 0.5.1 (2014-07-07)

 + Add a module icat.eval that is intended to be run using the "-m"
   command line switch to Python.  It allows to evaluate Python
   expressions within an ICAT session as one liners directly from the
   command line, as for example:

     # get all Dataset ids
     $ python -m icat.eval -e 'client.search("Dataset.id")' -s root
     [102284L, 102288L, 102289L, 102293L]

 + Fix an issue in the error handling in the IDS client that caused an
   urllib2.HTTPError to be raised instead of an IDSServerError in the
   case of an error from the IDS server and thus the loss of all
   details about the error reported in the reply from the server.

 + Add specific exception classes for the different error codes raised
   by the IDS server.

 + Fix compatibility issue with Python 3.3 that caused the HTTP method
   to be set to "None" in some IDS methods, which in turn caused an
   internal server error to be raised in the IDS server.

 + Fix compatibility issues with Python 3.4: some methods have been
   removed from class urllib.request.Request which caused an
   AttributeError in the IDSClient.

 + Fix: failed to connect to an ICAT server if it advertises a version
   number having a trailing "-SNAPSHOT" in getApiVersion().  For
   compatibility, a trailing "-SNAPSHOT" will be replaced by "a1" in
   the client.apiversion attribute.

 + Suppress misleading context information introduced with Python 3
   (PEP 3134) from the traceback in some error messages.
   Unfortunately, the fix only works for Python 3.3 and newer.

 + Make example files compatible across Python versions without
   modifications, such as running 2to3 on them.

* Version 0.5.0 (2014-06-24)

 + Integrate an IDS client in the ICAT client.

 + Improved icatdump.py and icatrestore.py:

   - Changed the logical structure of the dump file format which
     significantly simplified the scripts.  Note that old dump files
     are not compatible with the new versions.

   - Add support for XML dump files.  A XML Schema Definition for the
     dump file format is provided in the doc directory.

   The scripts are now considered to be legitimate tools (though still
   alpha) rather then mere examples.  Consequently, they will be
   installed into the bin directory.

 + Implicitly set a one to many relation to an empty list if it is
   accessed but not present in an Entity object rather then raising an
   AttributeError.  See ICAT Issue 130.

 + Allow setting one to many relationship attributes and deletion of
   attributes in Entity.  Add method truncateRelations() to Entity.
   Truncate dummy relations set by the factory in newly created entity
   objects.

 + Cache the result from getEntityInfo() in the client.

 + Add a method Entity.__sortkey__() that return a key that when used
   as a sorting key in list.sort() allows any list of entity objects
   to have a well defined order.  Sorting is based on the Constraint
   attributes.  Add a class variable SortAttrs that overrides this and
   will be set as a fall back for those entity classes that do not
   have a suitable Constraint.

* Version 0.4.0 (2014-02-11)

 + Add support for the jurko fork of Suds and for Python 3.

 + Add a new method Client.searchUniqueKey().

 + Add an optional argument keyindex to method Entity.getUniqueKey()
   that is used as a cache of previously generated keys.  Remove the
   argument addbean.  addbean had been documented as for internal use
   only, so this is not considered an incompatible change.

 + Add a new exception class DataConsistencyError.  Raise
   DataConsistencyError in Entity.getUniqueKey() if a relation that is
   required in a constraint is not set.

 + Rename SearchResultError to SearchAssertionError.
   SearchResultError was a misnomer here, as this exception class is
   very specific to Client.assertedSearch().  Add a new generic
   exception class SearchResultError and derive SearchAssertionError
   from it.  This way, the change should not create any compatibility
   problems in client programs.

 + Add a check in icatcheck that the ICATErrors as defined in
   icat.exceptions are in sync with icatExceptionType as defined in
   the schema.

 + Bugfix: The code dealing with exceptions raised by the ICAT server
   did require all attributes in IcatException sent by the server to
   be set, although some of these attributes are marked as optional in
   the schema.

 + Do not delete the Suds cache directory in Client.cleanup().  

 + Installation: python-icat requires Python 2.6 or newer.  Raise an
   error if setup.py is run by a too old Python version.

 + Move some internal routines in a separate module icat.helper.

 + Greatly improved example scripts icatdump.py and icatrestore.py.

* Version 0.3.0 (2014-01-10)

 + Add support for ICAT 4.3.1.  (Compatibility with ICAT 4.3.2 has
   also been tested but did not require any changes.)

 + Implement alias names for entity attributes.  This facilitates
   compatibility of client programs to different ICAT versions.
   E.g. a client program may use rule.grouping regardless of the ICAT
   version, for ICAT 4.2.* this is aliased to rule.group.

 + Add a client method assertedSearch().

 + Add a method getUniqueKey() for all entities.

 + Add entity methods Group.getUsers() and
   Instrument.getInstrumentScientists().

 + WARNING, incompatible change!
   Changed entity methods Instrument.addInstrumentScientist() and
   Investigation.addInvestigationUser() to not to create the
   respective user any more, but rather expect a list of existing
   users as argument.  Renamed Group.addUser(),
   Instrument.addInstrumentScientist(), and
   Investigation.addInvestigationUser() to addUsers(),
   addInstrumentScientists(), and addInvestigationUsers() (note the
   plural "s") respectively.

   In the client code, replace:

     pi = investigation.addInvestigationUser(uid, fullName=userName, 
                                             search=True, 
                                             role="Principal Investigator")

   by

     pi = client.createUser(uid, fullName=userName, search=True)
     investigation.addInvestigationUsers([pi], role="Principal Investigator")

 + Work around a bug in the way SUDS deals with datetime values: set
   the local time zone to UTC.

 + Add example scripts icatdump.py and icatrestore.py.

* Version 0.2.0 (2013-11-18)

 + Rework internals of icat.config.

 + Bugfix: Config required a password to be set even if prompt for
   password was requested.

 + Add support for configuration via environment variables.

 + Add support of HTTP proxy settings.  [Suggested by Alistair Mills]

 + WARNING, incompatible change!
   The configuration read by icat.config is not stored as attributes
   on the Config object itself, but rather getconf() returns an object
   with these attributes set.  This keeps the configuration values
   cleanly separated from the attributes of the Config object.

   In the client code, replace:

     conf = icat.config.Config()
     conf.getconfig()

   by

     config = icat.config.Config()
     conf = config.getconfig()

 + Move ConfigError from icat.config to icat.exception.

 + Move GenealogyError from icat.icatcheck to icat.exception.

 + Review export of symbols.  Most client programs should only need to
   import icat and icat.config.

* Version 0.1.0 (2013-11-01)

 + Initial version


# Local Variables:
# mode: org
# End:
