@@ -487,7 +487,7 @@ def search_objects(
487487 size = 20 ,
488488 sort = None ,
489489 dso_type = None ,
490- configuration = ' default' ,
490+ configuration = " default" ,
491491 embeds = None ,
492492 ):
493493 """
@@ -521,7 +521,7 @@ def search_objects(
521521 if sort is not None :
522522 params ["sort" ] = sort
523523 if configuration is not None :
524- params [' configuration' ] = configuration
524+ params [" configuration" ] = configuration
525525
526526 r_json = self .fetch_resource (url = url , params = {** params , ** filters })
527527
@@ -552,7 +552,7 @@ def search_objects_iter(
552552 filters = None ,
553553 dso_type = None ,
554554 sort = None ,
555- configuration = ' default' ,
555+ configuration = " default" ,
556556 embeds = None ,
557557 ):
558558 """
@@ -579,7 +579,7 @@ def search_objects_iter(
579579 if sort is not None :
580580 params ["sort" ] = sort
581581 if configuration is not None :
582- params [' configuration' ] = configuration
582+ params [" configuration" ] = configuration
583583
584584 return do_paginate (url , {** params , ** filters })
585585
@@ -1255,6 +1255,86 @@ def update_item(self, item, embeds=None):
12551255 return None
12561256 return self .update_dso (item , params = parse_params (embeds = embeds ))
12571257
1258+ def patch_item (
1259+ self ,
1260+ item_uuid ,
1261+ operation ,
1262+ field ,
1263+ value = None ,
1264+ language = None ,
1265+ authority = None ,
1266+ confidence = - 1 ,
1267+ place = "" ,
1268+ ):
1269+ """
1270+ Patch item. This method performs a partial update operation (PATCH) on the given Item object.
1271+ Supports operations: 'add', 'remove', 'replace'. Does not support 'move'.
1272+
1273+ @param item: Python Item object containing all the necessary data, identifiers, and links.
1274+ @param operation: Operation to perform ('add', 'remove', 'replace').
1275+ @param path: Path to the field or property to patch.
1276+ @param value: New value for the specified path (required for 'add' and 'replace'). Ignored for 'remove'.
1277+ @return: The API response or None in case of an error.
1278+ """
1279+ try :
1280+ if not item_uuid :
1281+ logging .error ("Item UUID is required" )
1282+ return None
1283+
1284+ if not field or not value :
1285+ logging .error ("Field and value are required" )
1286+ return None
1287+
1288+ if not operation or operation not in [
1289+ self .PatchOperation .ADD ,
1290+ self .PatchOperation .REPLACE ,
1291+ self .PatchOperation .REMOVE ,
1292+ ]:
1293+ logging .error ("Unsupported operation: %s" , operation )
1294+ return None
1295+
1296+ if (
1297+ operation in [self .PatchOperation .ADD , self .PatchOperation .REPLACE ]
1298+ and value is None
1299+ ):
1300+ logging .error ("Value is required for 'add' and 'replace' operations" )
1301+ return None
1302+
1303+ # Construct the item URI
1304+ item_uri = f"{ self .API_ENDPOINT } /core/items/{ item_uuid } "
1305+
1306+ path = f"/metadata/{ field } /{ place } "
1307+ patch_value = {
1308+ "value" : value ,
1309+ "language" : language ,
1310+ "authority" : authority ,
1311+ "confidence" : confidence ,
1312+ }
1313+
1314+ # Perform the patch operation
1315+ response = self .api_patch (
1316+ url = item_uri ,
1317+ operation = operation ,
1318+ path = path ,
1319+ value = patch_value ,
1320+ )
1321+
1322+ if response .status_code in [200 , 204 ]:
1323+ logging .info ("Successfully patched item: %s" , item_uuid )
1324+ return response
1325+ else :
1326+ logging .error (
1327+ "Failed to patch item: %s (Status: %s, Response: %s)" ,
1328+ item_uuid ,
1329+ response .status_code ,
1330+ response .text ,
1331+ )
1332+ return None
1333+
1334+ except ValueError :
1335+ logging .error ("Error processing patch operation" , exc_info = True )
1336+ return None
1337+
12581338 def add_metadata (
12591339 self ,
12601340 dso ,
@@ -1468,13 +1548,15 @@ def resolve_identifier_to_dso(self, identifier=None):
14681548 @return: resolved DSpaceObject or error
14691549 """
14701550 if identifier is not None :
1471- url = f' { self .API_ENDPOINT } /pid/find'
1472- r = self .api_get (url , params = {'id' : identifier })
1551+ url = f" { self .API_ENDPOINT } /pid/find"
1552+ r = self .api_get (url , params = {"id" : identifier })
14731553 if r .status_code == 200 :
14741554 r_json = parse_json (r )
1475- if r_json is not None and ' uuid' in r_json :
1555+ if r_json is not None and " uuid" in r_json :
14761556 return DSpaceObject (api_resource = r_json )
14771557 elif r .status_code == 404 :
14781558 logging .error (f"Not found: { identifier } " )
14791559 else :
1480- logging .error (f"Error resolving identifier { identifier } to DSO: { r .status_code } " )
1560+ logging .error (
1561+ f"Error resolving identifier { identifier } to DSO: { r .status_code } "
1562+ )
0 commit comments