icat.client — Provide the Client class

This module defines the Client class that manages the interaction with an ICAT service as a client.

class icat.client.Client(url, idsurl=None, checkCert=True, caFile=None, caPath=None, sslContext=None, proxy=None, **kwargs)

Bases: Client

A client accessing an ICAT service.

This is a subclass of suds.client.Client and inherits most of its behavior. It adds methods for the instantiation of ICAT entities and implementations of the ICAT API methods.

Parameters:
  • url (str) – The URL pointing to the WSDL of the ICAT service. If the URL does not contain a path, e.g. contains only a URL scheme and network location part, a default path is assumend.

  • idsurl (str) – The URL pointing to the IDS service. If set, an icat.ids.IDSClient instance will be created.

  • checkCert (bool) – Flag whether the server’s SSL certificate should be verified if connecting ICAT with HTTPS.

  • caFile (str) – Path to a file of concatenated trusted CA certificates. If neither caFile nor caPath is set, the system’s default certificates will be used.

  • caPath (str) – Path to a directory containing trusted CA certificates. If neither caFile nor caPath is set, the system’s default certificates will be used.

  • sslContext (ssl.SSLContext) – A SSL context describing various SSL options to be used in HTTPS connections. If set, this will override checkCert, caFile, and caPath.

  • proxy (dict) – HTTP proxy settings. A map with the keys http_proxy and https_proxy and the URL of the respective proxy to use as values.

  • kwargs – additional keyword arguments that will be passed to suds.client.Client, see suds.options.Options for details.

Class attributes

Register = <WeakValueDictionary>

The register of all active clients.

Changed in version 1.1.0: changed type to weakref.WeakValueDictionary.

AutoRefreshRemain = 30

Number of minutes to leave in the session before automatic refresh should be called.

Instance attributes

url

The URL to the web service description of the ICAT server.

kwargs

A copy of the kwargs used in the constructor.

apiversion

Version of the ICAT server this client connects to.

Changed in version 1.0.0: changed type to icat.helper.Version

autoLogout

Flag whether the client should logout automatically on exit.

ids

The icat.ids.IDSClient instance used for IDS calls.

sessionId

The session id as returned from login().

sslContext

The ssl.SSLContext instance that has been used to establish the HTTPS conection to the ICAT and IDS server. This is None for old Python versions that do not have the ssl.SSLContext class.

typemap

A dict that maps type names from the ICAT WSDL schema to the corresponding classes in the icat.entity.Entity hierarchy.

Class and instance methods

classmethod cleanupall()

Cleanup all class instances.

Call cleanup() on all registered class instances, e.g. on all clients that have not yet been cleaned up.

cleanup()

Release resources allocated by the client.

Logout from the active ICAT session (if autoLogout is True). The client should not be used any more after calling this method.

add_ids(url, proxy=None)

Add the URL to an ICAT Data Service.

clone()

Create a clone.

Return a clone of the Client object. That is, a client that connects to the same ICAT server and has been created with the same kwargs. The clone will be in the state as returned from the constructor. In particular, it does not share the same session if this client object is logged in.

Returns:

a clone of the client object.

Return type:

Client

new(obj, **kwargs)

Instantiate a new icat.entity.Entity object.

If obj is a Suds instance object or a string, lookup the corresponding entity class in the typemap. If obj is a string, this lookup is case insensitive and a new entity object is instantiated. If obj is a Suds instance object, an entity object corresponding to this instance object is instantiated. If obj is None, do nothing and return None.

Parameters:
  • obj (suds.sudsobject.Object or str) – either a Suds instance object, a name of an instance type, or None.

  • kwargs – attributes passed to the constructor of icat.entity.Entity.

Returns:

the new entity object or None.

Return type:

icat.entity.Entity

Raises:

EntityTypeError – if obj is neither a valid instance object, nor a valid name of an entity type, nor None.

Changed in version 1.0.0: if the obj argument is a string, it is taken case insensitive.

getEntityClass(name)

Return the Entity class corresponding to a BeanName.

getEntity(obj)

Get the corresponding icat.entity.Entity for an object.

if obj is a fieldSet, return a tuple of the fields. If obj is any other Suds instance object, create a new entity object with new(). Otherwise do nothing and return obj unchanged.

Parameters:

obj (suds.sudsobject.Object or any type) – either a Suds instance object or anything.

Returns:

the new entity object or obj.

Return type:

tuple or icat.entity.Entity or any type

Changed in version 0.18.0: add support of fieldSet.

Changed in version 0.18.1: changed the return type from list to tuple in the case of fieldSet.

ICAT API methods

These methods implement the low level API calls of the ICAT server. See the documentation in the ICAT SOAP Manual. (Note: the Python examples in that manual are based on plain Suds, not on python-icat.)

login(auth, credentials)
logout()
create(bean)
createMany(beans)
delete(bean)
deleteMany(beans)
get(query, primaryKey)
getApiVersion()
getAuthenticatorInfo()
getEntityInfo(beanName)
getEntityNames()
getProperties()
getRemainingMinutes()
getUserName()
getVersion()
isAccessAllowed(bean, accessType)
refresh()
search(query)
update(bean)

Custom API methods

These higher level methods build on top of the ICAT API methods.

autoRefresh()

Call refresh() only if needed.

Call refresh() if less then AutoRefreshRemain minutes remain in the current session. Do not make any client calls if not. This method is supposed to be very cheap if enough time remains in the session so that it may be called often in a loop without causing too much needless load.

assertedSearch(query, assertmin=1, assertmax=1)

Search with an assertion on the result.

Perform a search and verify that the number of items found lies within the bounds of assertmin and assertmax. Raise an error if this assertion fails.

Parameters:
  • query (icat.query.Query or str) – the search query.

  • assertmin (int) – minimum number of expected results.

  • assertmax (int) – maximum number of expected results. A value of None is treated as infinity.

Returns:

search result.

Return type:

list

Raises:
searchChunked(query, skip=0, count=None, chunksize=100)

Search the ICAT server.

Call the ICAT search() API method, limiting the number of results in each call and repeat the call as often as needed to retrieve all the results.

This can be used as a drop in replacement for the search API method most of the times. It avoids the error if the number of items in the result exceeds the limit imposed by the ICAT server. There are a few subtle differences though: the query must not contain a LIMIT clause (use the skip and count arguments instead) and should contain an ORDER BY clause. The return value is a generator yielding successively the items in the search result rather than a list. The individual search calls are done lazily, e.g. they are not done until needed to yield the next item from the generator.

Note

The result may be defective (omissions, duplicates) if the content in the ICAT server changes between individual search calls in a way that would affect the result. It is a common mistake when looping over items returned from this method to have code with side effects on the search result in the body of the loop. Example:

# Mark all datasets as complete
# This will *not* work as expected!
query = Query(client, "Dataset", conditions={
    "complete": "= False"
}, includes="1", order=["id"])
for ds in client.searchChunked(query):
    ds.complete = True
    ds.update()

This should rather be formulated as:

# Mark all datasets as complete
# This version works!
query = Query(client, "Dataset", includes="1", order=["id"])
for ds in client.searchChunked(query):
    if not ds.complete:
        continue
    ds.complete = True
    ds.update()
Parameters:
  • query (icat.query.Query or str) – the search query.

  • skip (int) – offset from within the full list of available results.

  • count (int) – maximum number of items to return. A value of None means no limit.

  • chunksize (int) – number of items to query in each search call. This is an internal tuning parameter and does not affect the result.

Returns:

a generator that successively yields the items in the search result.

Return type:

generator

searchUniqueKey(key, objindex=None)

Search the object that belongs to a unique key.

This is in a sense the inverse method to icat.entity.Entity.getUniqueKey(), the key must previously have been generated by it. This method searches the entity object that the key has been generated for from the server.

if objindex is not None, it is used as a cache of previously retrieved objects. It must be a dict that maps keys to entity objects. The object retrieved by this method call will be added to this index.

Parameters:
  • key (str) – the unique key of the object to search for.

  • objindex (dict) – cache of entity objects.

Returns:

the object corresponding to the key.

Return type:

icat.entity.Entity

Raises:
searchMatching(obj, includes=None)

Search the matching object.

Search the object from the ICAT server that matches the given object in the uniqueness constraint.

>>> dataset = client.new("Dataset", investigation=inv, name=dsname)
>>> dataset = client.searchMatching(dataset)
>>> dataset.id
172383
Parameters:
  • obj (icat.entity.Entity) – an entity object having the attrinutes for the uniqueness constraint set accordingly.

  • includes (iterable of str) – list of related objects to add to the INCLUDE clause of the search query. See icat.query.Query.addIncludes() for details.

Returns:

the corresponding object.

Return type:

icat.entity.Entity

Raises:
  • SearchResultError – if the object has not been found.

  • ValueError – if the object’s class does not have a uniqueness constraint or if any attribute needed for the constraint is not set.

createUser(name, search=False, **kwargs)

Search a user by name or create a new user.

If search is True search a user by the given name. If search is False or no user is found, create a new user.

Parameters:
  • name (str) – username.

  • search (bool) – flag whether a user should be searched first.

  • kwargs – attributes of the user passed to new.

Returns:

the user.

Return type:

icat.entity.Entity

createGroup(name, users=())

Create a group and add users to it.

Parameters:
Returns:

the group.

Return type:

icat.entity.Entity

createRules(crudFlags, what, group=None)

Create access rules.

Parameters:
  • crudFlags (str) – access mode.

  • what (list) – list of items subject to the rule. The items must be either ICAT search expression strings or icat.query.Query objects.

  • group (icat.entity.Entity) – the group that should be granted access or None for everybody.

Returns:

list of the ids of the created rules.

Return type:

list of int

Custom IDS methods

These methods provide the most commonly needed IDS functionality and build on top of the low level IDS API methods provided by icat.ids.IDSClient.

putData(infile, datafile)

Upload a datafile to IDS.

The content of the file to upload is read from infile, either directly if it is an open file, or a file by that name will be opened for reading.

The datafile object must be initialized but not yet created at the ICAT server. It will be created by the IDS. The ids of the Dataset and the DatafileFormat as well as the attributes description, doi, datafileCreateTime, and datafileModTime will be taken from datafile. If datafileModTime is not set, the method will try to os.fstat() infile and use the last modification time from the file system, if available. If datafileCreateTime is not set, it will be set to datafileModTime.

Note that only the attributes datafileFormat, dataset, description, doi, datafileCreateTime, and datafileModTime of datafile will be taken into account as described above. All other attributes are ignored and the Datafile object created in the ICAT server might end up with different values for those other attribues.

Parameters:
  • infile (file or Path or str) – either a file opened for reading or a file name.

  • datafile (icat.entity.Entity) – A Datafile object.

Returns:

The Datafile object created by IDS.

Return type:

icat.entity.Entity

Changed in version 1.0.0: the infile parameter also accepts a Path object.

getData(objs, compressFlag=False, zipFlag=False, outname=None, offset=0)

Retrieve the requested data from IDS.

The data objects to retrieve are given in objs. This can be any combination of single Datafiles, Datasets, or complete Investigations.

Parameters:
  • objs (dict, list of icat.entity.Entity, icat.ids.DataSelection, or str) – either a dict having some of the keys investigationIds, datasetIds, and datafileIds with a list of object ids as value respectively, or a list of entity objects, or a data selection, or an id returned by prepareData().

  • compressFlag (bool) – flag whether to use a zip format with an implementation defined compression level, otherwise use no (or minimal) compression.

  • zipFlag (bool) – flag whether return a single datafile in zip format. For multiple files zip format is always used.

  • outname (str) – the preferred name for the downloaded file to specify in the Content-Disposition header.

  • offset (int) – if larger then zero, add Range header to the HTTP request with the indicated bytes offset.

Returns:

a file-like object as returned by urllib.request.OpenerDirector.open().

Changed in version 0.17.0: accept a prepared id in objs.

getDataUrl(objs, compressFlag=False, zipFlag=False, outname=None)

Get the URL to retrieve the requested data from IDS.

The data objects to retrieve are given in objs. This can be any combination of single Datafiles, Datasets, or complete Investigations.

Note that the URL contains the session id of the current ICAT session. It will become invalid if the client logs out.

Parameters:
  • objs (dict, list of icat.entity.Entity, icat.ids.DataSelection, or str) – either a dict having some of the keys investigationIds, datasetIds, and datafileIds with a list of object ids as value respectively, or a list of entity objects, or a data selection, or an id returned by prepareData().

  • compressFlag (bool) – flag whether to use a zip format with an implementation defined compression level, otherwise use no (or minimal) compression.

  • zipFlag (bool) – flag whether return a single datafile in zip format. For multiple files zip format is always used.

  • outname (str) – the preferred name for the downloaded file to specify in the Content-Disposition header.

Returns:

the URL for the data at the IDS.

Return type:

str

Changed in version 0.17.0: accept a prepared id in objs.

prepareData(objs, compressFlag=False, zipFlag=False)

Prepare data at IDS to be retrieved in subsequent calls.

The data objects to retrieve are given in objs. This can be any combination of single Datafiles, Datasets, or complete Investigations.

Parameters:
  • objs (dict, list of icat.entity.Entity, or icat.ids.DataSelection) – either a dict having some of the keys investigationIds, datasetIds, and datafileIds with a list of object ids as value respectively, or a list of entity objects, or a data selection.

  • compressFlag (bool) – flag whether to use a zip format with an implementation defined compression level, otherwise use no (or minimal) compression.

  • zipFlag (bool) – flag whether return a single datafile in zip format. For multiple files zip format is always used.

Returns:

preparedId, an opaque string which may be used as an argument to isDataPrepared() and getData() calls.

Return type:

str

isDataPrepared(preparedId)

Check if prepared data is ready at IDS.

Parameters:

preparedId (str) – the id returned by prepareData().

Returns:

True if the data is ready, otherwise False.

Return type:

bool

deleteData(objs)

Delete data from IDS.

The data objects to delete are given in objs. This can be any combination of single Datafiles, Datasets, or complete Investigations.

Parameters:

objs (dict, list of icat.entity.Entity, or icat.ids.DataSelection) – either a dict having some of the keys investigationIds, datasetIds, and datafileIds with a list of object ids as value respectively, or a list of entity objects, or a data selection.