@@ -17,6 +17,15 @@ class Elink:
1717 Defines a set of access points for E-Link API endpoints.
1818
1919 Construct an api access object, defining the desired API target and supplying the user-specific API key token.
20+ Note that Review and Production are entirely separate instances, with Production being the default target if not
21+ specified.
22+
23+ These endpoint targets are:
24+ review: https://review.osti.gov/elink2api/
25+ production: https://www.osti.gov/elink2api/
26+
27+ >>> from elinkapi import Elink
28+ >>> api = Elink(target = "https://review.osti.gov/elink2api/", token=MYUSERTOKEN)
2029
2130 Use this to access functions, including:
2231
@@ -30,6 +39,23 @@ class Elink:
3039 post_media -- add a new media set to the OSTI ID
3140 put_media -- replace an existing media set with new content
3241
42+ Record creation methods (reserve_doi, post_new_record, update_record) may provide a user-supplied Record, a dict
43+ containing required key elements, or as keyword arguments.
44+ >>> api.post_new_record(title="My dataset", product_type="DA")
45+ or
46+ >>> api.post_new_record({ "title": "New Technical Report", "product_type" : "TR" })
47+ or
48+ >>> api.post_new_record(Record(title="Example journal", product_type="JA", journal_name="Science", doi="10.11578/23423"))
49+
50+ Record instances contain a reference function dict() to obtain a dictionary from its content. Supply optional
51+ "exclude_none=True" argument to obtain only elements with values if desired:
52+ >>> myrecord.dict(exclude_none=True)
53+
54+ Individual values in Record instances are directly accessible and may be set in the same way; e.g.,
55+ >>> myrecord.title = "New Title Here"
56+ or
57+ >>> print (myrecord.doi)
58+
3359 """
3460 def __init__ (self , token = None , target = None ):
3561 """
@@ -100,7 +126,10 @@ def record_to_json(self, record):
100126
101127 # Record Methods
102128 def get_single_record (self , osti_id : int ):
103- """Obtain the metadata JSON for a record at OSTI
129+ """Obtain the metadata JSON for a record at OSTI.
130+
131+ >>> record = api.get_single_record(2009785)
132+ >>> print (record.title)
104133
105134 Arguments:
106135 osti_id -- ID that uniquely identifies an E-link 2.0 Record
@@ -116,7 +145,14 @@ def get_single_record(self, osti_id: int):
116145 return self ._convert_response_to_records (response )[0 ]
117146
118147 def query_records (self , ** kwargs ):
119- """Query for records using a variety of query params
148+ """Query for records using a variety of query search parameters.
149+
150+ Example:
151+ >>> query = api.query_records(title="Science", product_type = "JA")
152+ >>> query.total_rows
153+ 1738
154+ >>> for record in query:
155+ ... print (record.title)
120156
121157 Arguments:
122158 params -- See https://www.osti.gov/elink2api/#tag/records/operation/getRecords for
@@ -138,38 +174,72 @@ def query_records(self, **kwargs):
138174
139175 return Query (response , target = self .target , token = self .token )
140176
141- def reserve_doi (self , record ):
142- """ Save a Record with minimal validations:
143- Required:
177+ def reserve_doi (self , r = None , ** kwargs ):
178+ """ Save a Record with minimal validations.
179+
180+ Required data elements, either via a Record or keyword arguments:
144181 title
145182 site_ownership_code
146183 product_type
147184
185+ Provided as a convenience; functionally equivalent to post_new_record method, with
186+ state="save".
187+
188+ >>> reservation = api.reserve_doi(title="Sample dataset from 2012", product_type = "DA")
189+ >>> print (reservation.doi)
190+ '10.11578/2003824'
191+
148192 Arguments:
149- record -- Metadata record that you wish to save to E-Link 2.0
193+ record -- Metadata record that you wish to save to E-Link 2.0 (optional)
194+
195+ Keyword Arguments:
196+ if record is not provided, these will be used to construct a new one for DOI reservation.
150197
151198 Returns:
152199 Record - metadata of a single record that has been saved to E-Link 2.0
153200 """
154- response = requests .post (self .target + "records/save" , headers = {"Authorization" : f"Bearer { self .token } " },
155- json = json .loads (record .model_dump_json (exclude_none = True )))
201+ # perform a minimal new record POST
202+ return self .post_new_record (r = r , ** kwargs )
203+
204+ def _convert_record (self , record = None , ** kwargs ) -> Record :
205+ """
206+ Accept either a Record or a dict, which we convert to a Record for consistency. Will
207+ take appropriately-named keyword arguments if record is not provided to construct one.
156208
157- Validation .handle_response (response )
209+ Arguments:
210+ record -- either a dict to convert, or already a Record (optional)
211+
212+ Keyword arguments:
213+ if record not provided, use these to construct one
214+
215+ Returns:
216+ a Record, possibly from the dict if possible.
158217
159- return self ._convert_response_to_records (response )[0 ]
218+ """
219+ if record and isinstance (record , dict ):
220+ return Record (** record )
221+ elif record and isinstance (record , Record ):
222+ return record
223+ else :
224+ return Record (** kwargs )
160225
161- def post_new_record (self , record , state = "save" ):
226+ def post_new_record (self , r = None , state = "save" , ** kwargs ):
162227 """Create a new metadata Record with OSTI
163228
164229 Arguments:
165- record -- Metadata record that you wish to send ("save" or "submit") to E-Link 2.0
230+ record -- Metadata record that you wish to send ("save" or "submit") to E-Link 2.0. May provide as
231+ Record or dict, or as keyword arguments.
166232
167233 Keyword Arguments:
168234 state -- The desired submission state of the record ("save" or "submit") (default: {"save"})
235+ if record not provided, takes rest of keyword arguments to construct a Record
169236
170237 Returns:
171238 Record - metadata of a single record saved (or submitted) to E-Link 2.0
172239 """
240+ # make a Record from provided arguments
241+ record = self ._convert_record (record = r , ** kwargs )
242+ # post it as a new record
173243 response = requests .post (f"{ self .target } records/{ state } " ,
174244 headers = {
175245 "Authorization" : f"Bearer { self .token } " ,
@@ -184,7 +254,9 @@ def post_new_record(self, record, state="save"):
184254
185255 def patch_record (self , osti_id , patch , state = "save" ):
186256 """
187- Update record via partial-patch-json method endpoint
257+ Update record via partial-patch-json method endpoint. Provide only the JSON you wish to alter.
258+
259+ >>> api.patch_record(2008590, { "title": "This title is new", "description": "As is this description" })
188260
189261 Arguments:
190262 osti_id -- the OSTI ID of the record to patch
@@ -209,41 +281,52 @@ def patch_record(self, osti_id, patch, state="save"):
209281
210282 def patch_json (self , osti_id , jsonpatch , state = "save" ):
211283 """
212- Update record via a JSON-patch set of command operations.
213-
214- :param osti_id: The OSTI ID of the record to patch
215- :type osti_id: int
284+ Update record via a JSON-patch set of command operations. Note the jsonpatch is intended to be
285+ an array of one or more operations to perform; those including "add", "replace", "copy", "move", or
286+ "remove". See details at https://www.osti.gov/elink2api/#operation/patchRecord.
216287
217- :param jsonpatch: The JSON or dict containing array of patch operations to perform
218- :param state: The desired workflow state of the new revision ("save" or "submit") default: "save"
288+ >>> api.patch_json(2007439, [{"op": "add", "path": "/description", "value": "A new description."}])
289+
290+ Arguments:
291+ osti_id -- The OSTI ID of the record to patch
292+ jsonpatch -- JSON or dict containing any operations to perform on the record
219293
220- :return: a Record of the new revision if successful
294+ Keyword arguments:
295+ state -- Desired workflow state of the new revision ("save" or "submit") default: "save"
221296
297+ Returns:
298+ Record -- the metadata of the new revision with operations performed if successful
222299 """
223300 response = requests .patch (f"{ self .target } /records/{ osti_id } /{ state } " ,
224301 headers = {
225302 "Authorization" : f"Bearer { self .token } " ,
226303 "Content-Type" : "application/json-patch+json"
227304 },
228- data = str (jsonpatch ))
305+ data = json . dumps (jsonpatch ))
229306
230307 Validation .handle_response (response )
231308
232309 return self ._convert_response_to_records (response )[0 ]
233310
234- def update_record (self , osti_id , record , state = "save" ):
235- """Update existing records at OSTI by unique OSTI ID
311+ def update_record (self , osti_id , r = None , state = "save" , ** kwargs ):
312+ """Update existing records at OSTI by unique OSTI ID. Note this REPLACES the record entirely;
313+ the provided record details will become the new revision of the record on file; all required
314+ information must therefore be provided as applicable.
236315
237316 Arguments:
238317 osti_id -- ID that uniquely identifies an E-link 2.0 Record
239- record -- Metadata record that you wish to make the new revision of OSTI ID
318+ record -- Metadata record that you wish to make the new revision of OSTI ID (optional, as Record or dict)
240319
241320 Keyword Arguments:
242321 state -- The desired submission state of the record ("save" or "submit") (default: {"save"})
322+ if record not specified, rest of the keyword arguments are used to construct one
243323
244324 Returns:
245325 Record - Metadata of record updated with the given information, creating a new revision
246326 """
327+ # get a record
328+ record = self ._convert_record (record = r , ** kwargs )
329+ # send the UPDATE
247330 response = requests .put (f"{ self .target } records/{ osti_id } /{ state } " ,
248331 headers = {
249332 "Authorization" : f"Bearer { self .token } "
@@ -489,7 +572,8 @@ def __post_media_no_stream(self, osti_id, file_path=None, query_params=None):
489572
490573 def put_media (self , osti_id , media_id , file_path = None , title = None , stream = False ):
491574 """Replace a given media set with a new basis file.
492- This will replace the previous media set.
575+ This will replace the previous media set. Both osti_id and media_id (of the set to replace)
576+ are required.
493577
494578 Arguments:
495579 osti_id -- ID that uniquely identifies an E-link 2.0 Record
0 commit comments