Working with objects in the ICAT server
In the previous section of this tutorial, we created two Facility
objects:
$ python -i login.py -s myicat_root
Login to https://icat.example.com:8181 was successful.
User: simple/root
>>> client.search("SELECT f FROM Facility f")
[(facility){
createId = "simple/root"
createTime = 2023-06-28 10:39:26+02:00
id = 1
modId = "simple/root"
modTime = 2023-06-28 10:39:26+02:00
fullName = "Facility 1"
name = "Fac1"
}, (facility){
createId = "simple/root"
createTime = 2023-06-28 10:41:08+02:00
id = 2
modId = "simple/root"
modTime = 2023-06-28 10:41:08+02:00
fullName = "Facility 2"
name = "Fac2"
}]
Let’s see what we can do with these objects.
Editing the attributes of objects
We can edit the attributes of existing objects by assigning values to
the corresponding Entity
object. To write these
changes back into ICAT, we can either call the
icat.client.Client.update()
method, or simply invoke the
object’s own update()
method instead.
Let’s loop over our Facility
objects to add some new attributes
and to edit existing ones:
>>> for facility in client.search("SELECT f FROM Facility f"):
... facility.description = "An example facility"
... facility.daysUntilRelease = 1826
... facility.fullName = "%s Facility" % facility.name
... client.update(facility)
...
We can verify the changes by performing another search:
>>> client.search("SELECT f FROM Facility f")
[(facility){
createId = "simple/root"
createTime = 2023-06-28 10:39:26+02:00
id = 1
modId = "simple/root"
modTime = 2023-06-28 11:25:27+02:00
daysUntilRelease = 1826
description = "An example facility"
fullName = "Fac1 Facility"
name = "Fac1"
}, (facility){
createId = "simple/root"
createTime = 2023-06-28 10:41:08+02:00
id = 2
modId = "simple/root"
modTime = 2023-06-28 11:25:27+02:00
daysUntilRelease = 1826
description = "An example facility"
fullName = "Fac2 Facility"
name = "Fac2"
}]
To remove a particular attribute value, we usually just have to assign
None
to it:
>>> for facility in client.search("SELECT f FROM Facility f"):
... facility.description = None
... facility.update()
...
If we search again now, the descriptions are gone:
>>> client.search("SELECT f FROM Facility f")
[(facility){
createId = "simple/root"
createTime = 2023-06-28 10:39:26+02:00
id = 1
modId = "simple/root"
modTime = 2023-06-28 11:26:31+02:00
daysUntilRelease = 1826
fullName = "Fac1 Facility"
name = "Fac1"
}, (facility){
createId = "simple/root"
createTime = 2023-06-28 10:41:08+02:00
id = 2
modId = "simple/root"
modTime = 2023-06-28 11:26:31+02:00
daysUntilRelease = 1826
fullName = "Fac2 Facility"
name = "Fac2"
}]
Copying objects
By calling the copy()
method on an existing
object, we can create a new object that has all attributes set to a
copy of the corresponding values of the original object. The
relations are copied by reference, i.e. the original and the copy
refer to the same related object.
To demonstrate this, we use one of the Facility
objects we created
earlier, including its referenced ParameterType
objects:
>>> fac = client.get("Facility f INCLUDE f.parameterTypes", 1)
>>> print(fac)
(facility){
createId = "simple/root"
createTime = 2023-06-28 10:39:26+02:00
id = 1
modId = "simple/root"
modTime = 2023-06-28 11:26:31+02:00
daysUntilRelease = 1826
fullName = "Fac1 Facility"
name = "Fac1"
parameterTypes[] =
(parameterType){
createId = "simple/root"
createTime = 2023-06-28 10:43:06+02:00
id = 1
modId = "simple/root"
modTime = 2023-06-28 10:43:06+02:00
applicableToDataCollection = False
applicableToDatafile = False
applicableToDataset = True
applicableToInvestigation = False
applicableToSample = False
enforced = False
name = "Test parameter type 1"
units = "pct"
valueType = "NUMERIC"
verified = False
},
(parameterType){
createId = "simple/root"
createTime = 2023-06-28 10:44:28+02:00
id = 2
modId = "simple/root"
modTime = 2023-06-28 10:44:28+02:00
applicableToDataCollection = False
applicableToDatafile = False
applicableToDataset = True
applicableToInvestigation = False
applicableToSample = False
enforced = False
name = "Test parameter type 2"
units = "N/A"
valueType = "STRING"
verified = False
},
}
Now we create a copy of this object and modify its attributes. The
attributes of the original object remain unchanged. However, any
changes to the referenced ParameterType
objects are reflected in
both the copy and the original:
>>> facc = fac.copy()
>>> print(facc.name)
Fac1
>>> print(facc.parameterTypes[0].name)
Test parameter type 1
>>> facc.name = "Fac0"
>>> facc.parameterTypes[0].name = "Test parameter type 0"
>>> print(fac.name)
Fac1
>>> print(fac.parameterTypes[0].name)
Test parameter type 0
When working with objects from ICAT, it can be a bit cumbersome to
keep the (possibly large) tree of related objects in local memory. If
you only need to keep the object’s attributes, you can use the
truncateRelations()
method to delete all
references to other objects from this object. Note that this is a
local operation on the object in the client only. It does neither
affect the corresponding object at the ICAT server, nor any copies of
the object:
>>> fac.truncateRelations()
>>> print(fac)
(facility){
createId = "simple/root"
createTime = 2023-06-28 10:39:26+02:00
id = 1
modId = "simple/root"
modTime = 2023-06-28 11:26:31+02:00
daysUntilRelease = 1826
fullName = "Fac1 Facility"
name = "Fac1"
}
>>> print(facc)
(facility){
createId = None
createTime = None
id = 1
modId = None
modTime = None
daysUntilRelease = 1826
description = None
fullName = "Fac1 Facility"
name = "Fac0"
parameterTypes[] =
(parameterType){
createId = "simple/root"
createTime = 2023-06-28 10:43:06+02:00
id = 1
modId = "simple/root"
modTime = 2023-06-28 10:43:06+02:00
applicableToDataCollection = False
applicableToDatafile = False
applicableToDataset = True
applicableToInvestigation = False
applicableToSample = False
enforced = False
name = "Test parameter type 0"
units = "pct"
valueType = "NUMERIC"
verified = False
},
(parameterType){
createId = "simple/root"
createTime = 2023-06-28 10:44:28+02:00
id = 2
modId = "simple/root"
modTime = 2023-06-28 10:44:28+02:00
applicableToDataCollection = False
applicableToDatafile = False
applicableToDataset = True
applicableToInvestigation = False
applicableToSample = False
enforced = False
name = "Test parameter type 2"
units = "N/A"
valueType = "STRING"
verified = False
},
url = None
}