2020from requests import Request
2121import os
2222from uuid import UUID
23- from enum import Enum
2423
2524
2625class DSpaceObject :
@@ -39,13 +38,17 @@ class DSpaceObject:
3938 type = None
4039 parent = None
4140
42- def __init__ (self , api_resource = None ):
41+ def __init__ (self , api_resource = None , dso = None ):
4342 """
4443 Default constructor
4544 @param api_resource: optional API resource (JSON) from a GET response or successful POST can populate instance
4645 """
46+
4747 self .type = None
48- self .metadata = {}
48+ self .metadata = dict ()
49+
50+ if dso is not None :
51+ api_resource = dso .as_dict ()
4952 if api_resource is not None :
5053 if 'id' in api_resource :
5154 self .id = api_resource ['id' ]
@@ -63,6 +66,10 @@ def __init__(self, api_resource=None):
6366 # alternatively - each item could implement getters, or a public method to return links
6467 if '_links' in api_resource :
6568 self .links = api_resource ['_links' ]
69+ else :
70+ # TODO - write 'construct self URI method'... all we need is type, UUID and some mapping of type
71+ # to the URI type segment eg community -> communities
72+ self .links = {'self' : {'href' : '' }}
6673
6774 def add_metadata (self , field , value , language = None , authority = None , confidence = - 1 , place = None ):
6875 """
@@ -111,8 +118,6 @@ def clear_metadata(self, field=None, value=None):
111118 updated .append (v )
112119 self .metadata [field ] = updated
113120
114-
115-
116121 def as_dict (self ):
117122 """
118123 Return custom dict of this DSpaceObject with specific attributes included (no _links, etc.)
@@ -134,7 +139,14 @@ def to_json_pretty(self):
134139 return json .dumps (self , default = lambda o : o .__dict__ , sort_keys = True , indent = 4 )
135140
136141
137- class Item (DSpaceObject ):
142+ class SimpleDSpaceObject (DSpaceObject ):
143+ """
144+ Objects that share similar simple API methods eg. PUT update for full metadata replacement, can have handles, etc.
145+ By default this is Item, Community, Collection classes
146+ """
147+
148+
149+ class Item (SimpleDSpaceObject ):
138150 """
139151 Extends DSpaceObject to implement specific attributes and functions for items
140152 """
@@ -143,13 +155,17 @@ class Item(DSpaceObject):
143155 discoverable = False
144156 withdrawn = False
145157
146- def __init__ (self , api_resource = None ):
158+ def __init__ (self , api_resource = None , dso = None ):
147159 """
148160 Default constructor. Call DSpaceObject init then set item-specific attributes
149161 @param api_resource: API result object to use as initial data
150162 """
163+ if dso is not None :
164+ api_resource = dso .as_dict ()
165+
166+ super (Item , self ).__init__ (api_resource )
167+
151168 if api_resource is not None :
152- super (Item , self ).__init__ (api_resource )
153169 self .type = 'item'
154170 self .inArchive = api_resource ['inArchive' ] if 'inArchive' in api_resource else False
155171 self .discoverable = api_resource ['discoverable' ] if 'discoverable' in api_resource else False
@@ -176,15 +192,15 @@ def as_dict(self):
176192 return {** dso_dict , ** item_dict }
177193
178194 @classmethod
179- def from_DSpaceObject (cls , dso : DSpaceObject ):
180- # Create new b_obj
195+ def from_dso (cls , dso : DSpaceObject ):
196+ # Create new Item and copy everything over from this dso
181197 item = cls ()
182198 for key , value in dso .__dict__ .items ():
183199 item .__dict__ [key ] = value
184200 return item
185201
186202
187- class Community (DSpaceObject ):
203+ class Community (SimpleDSpaceObject ):
188204 """
189205 Extends DSpaceObject to implement specific attributes and functions for communities
190206 """
@@ -209,7 +225,7 @@ def as_dict(self):
209225 return {** dso_dict , ** community_dict }
210226
211227
212- class Collection (DSpaceObject ):
228+ class Collection (SimpleDSpaceObject ):
213229 """
214230 Extends DSpaceObject to implement specific attributes and functions for collections
215231 """
@@ -629,23 +645,53 @@ def create_dso(self, url, params, data):
629645 print (f'create operation failed: { r .status_code } : { r .text } ({ url } )' )
630646 return r
631647
632- def update_dso (self , url , params = None , data = None ):
648+ def update_dso (self , dso , params = None ):
633649 """
634- Base 'update DSpace Object' function.
635- @param url: DSpace REST API URL
636- @ param params : Any parameters to pass in the request.
637- @ param data : JSON data to apply in teh update - note, this is not a patch operation, this is the full data
638- @ return: Raw API response. Updated DSO *could* be returned but for error checking purposes, raw response
639- is nice too and can always be parsed from this response later.
650+ Update DSpaceObject. Takes a DSpaceObject and any optional parameters. Will send a PUT update to the remote
651+ object and return the updated object, typed correctly.
652+ : param dso : DSpaceObject with locally updated data, to send in PUT request
653+ : param params : Optional parameters
654+ : return:
655+
640656 """
641- r = self .api_put (url , params = params , json = data )
642- if r .status_code == 200 :
643- # 200 OK - success!
644- updated_dso = r .json ()
645- print (f'{ updated_dso ["type" ]} { updated_dso ["uuid" ]} updated sucessfully!' )
646- else :
647- print (f'update operation failed: { r .status_code } : { r .text } ({ url } )' )
648- return r
657+ if dso is None :
658+ return None
659+ dso_type = type (dso )
660+ if not isinstance (dso , SimpleDSpaceObject ):
661+ print (f'Only SimpleDSpaceObject types (eg Item, Collection, Community) '
662+ f'are supported by generic update_dso PUT.' )
663+ return dso
664+ try :
665+ # Get self URI from HAL links
666+ url = dso .links ['self' ]['href' ]
667+ # Get and clean data - there are some unalterable fields that could cause errors
668+ data = dso .as_dict ()
669+
670+ if 'lastModified' in data :
671+ data .pop ('lastModified' )
672+ """
673+ if 'id' in data:
674+ data.pop('id')
675+ if 'handle' in data:
676+ data.pop('handle')
677+ if 'uuid' in data:
678+ data.pop('uuid')
679+ if 'type' in data:
680+ data.pop('type')
681+ """
682+ r = self .api_put (url , params = params , json = data )
683+ if r .status_code == 200 :
684+ # 200 OK - success!
685+ updated_dso = dso_type (parse_json (r ))
686+ print (f'{ updated_dso .type } { updated_dso .uuid } updated sucessfully!' )
687+ return updated_dso
688+ else :
689+ print (f'update operation failed: { r .status_code } : { r .text } ({ url } )' )
690+ return None
691+
692+ except ValueError as e :
693+ print (f'{ e } ' )
694+ return None
649695
650696 def get_bundles (self , parent = None , uuid = None ):
651697 """
@@ -926,8 +972,7 @@ def update_item(self, item):
926972 if not isinstance (item , Item ):
927973 print ('Need a valid item' )
928974 return None
929- url = f'{ self .API_ENDPOINT } /core/items/{ item .uuid } '
930- return Item (api_resource = parse_json (self .update_dso (url , params = None , data = item .as_dict ())))
975+ return self .update_dso (item , params = None )
931976
932977 def add_metadata (self , dso , field , value , language = None , authority = None , confidence = - 1 , place = '' ):
933978 """
0 commit comments