@@ -41,6 +41,10 @@ class ZenodoLinkImp(LinkAddonHttpRequestorImp):
41
41
"""
42
42
43
43
async def build_url_for_id (self , item_id : str ) -> str :
44
+ """
45
+ This method is used by ConfiguredLinkAddon to construct user-facing url,
46
+ which will take them to the configured resource web page
47
+ """
44
48
if match := DEPOSITION_REGEX .match (item_id ):
45
49
return self ._build_deposition_url (match ["id" ])
46
50
elif match := FILE_REGEX .match (item_id ):
@@ -55,26 +59,30 @@ def _build_deposition_url(self, deposition_id: str):
55
59
return f"{ self .config .external_web_url } /deposition/{ deposition_id } "
56
60
57
61
async def get_external_account_id (self , _ : dict [str , str ]) -> str :
58
- try :
59
- async with self .network .GET ("api/deposit/depositions" ) as response :
60
- if not response .http_status .is_success :
61
- raise ValidationError (
62
- "Could not get Zenodo account id, check your API Token"
63
- )
64
- # Zenodo doesn't have a specific endpoint for user info
65
- # Using the first deposition's owner as the account ID
66
- content = await response .json_content ()
67
- if content and len (content ) > 0 :
68
- return str (content [0 ].get ("owner" , "" ))
69
- return "zenodo_user" # Fallback if no depositions found
70
- except ValueError as exc :
71
- if "relative url may not alter the base url" in str (exc ).lower ():
62
+ """
63
+ This method fetches external account's id on the provider side, and is meant for use internally.
64
+
65
+ For Zenodo it has to fetch user's depositions and take owner id form it,
66
+ as Zenodo API does not provide direct way to fetch user's internal id
67
+ """
68
+ async with self .network .GET ("api/deposit/depositions" ) as response :
69
+ if not response .http_status .is_success :
72
70
raise ValidationError (
73
- "Invalid host URL. Please check your Zenodo base URL. "
71
+ "Could not get Zenodo account id, check your API Token "
74
72
)
75
- raise
73
+ content = await response .json_content ()
74
+ if content and len (content ) > 0 :
75
+ return str (content [0 ].get ("owner" , "" ))
76
+ return "zenodo_user" # Fallback if no depositions found
76
77
77
78
async def list_root_items (self , page_cursor : str = "" ) -> ItemSampleResult :
79
+ """
80
+ This method lists root (top level ) from external provider.
81
+ Please note that it must return only public items.
82
+
83
+ For Zenodo it fetches user's depositions and filters them to be public on client's side
84
+ (as the API does not such filtering)
85
+ """
78
86
page = 1
79
87
if page_cursor :
80
88
try :
@@ -95,6 +103,7 @@ def _parse_depositions_list(
95
103
"""Parse the response from the depositions endpoint.
96
104
97
105
The depositions endpoint returns a list of depositions directly, not wrapped in a hits object.
106
+ Also filter only public (only published) depositions.
98
107
"""
99
108
items = []
100
109
for deposition in raw_content :
@@ -115,6 +124,9 @@ def _parse_depositions_list(
115
124
)
116
125
117
126
async def get_item_info (self , item_id : str ) -> ItemResult :
127
+ """
128
+ This method fetches desired item from an API
129
+ """
118
130
if not item_id :
119
131
return ItemResult (item_id = "" , item_name = "" , item_type = ItemType .FOLDER )
120
132
elif match := DEPOSITION_REGEX .match (item_id ):
@@ -130,6 +142,11 @@ async def list_child_items(
130
142
page_cursor : str = "" ,
131
143
item_type : ItemType | None = None ,
132
144
) -> ItemSampleResult :
145
+ """
146
+ This method lists children items of requested id. Used to navigate item tree (if there is one).
147
+
148
+ For Zenodo it fetches files for given depositions, as there is no apparent item tree
149
+ """
133
150
if not item_id :
134
151
return await self .list_root_items (page_cursor )
135
152
elif match := DEPOSITION_REGEX .match (item_id ):
@@ -142,6 +159,9 @@ async def list_child_items(
142
159
return ItemSampleResult (items = [], total_count = 0 )
143
160
144
161
async def _fetch_record_files (self , record_id : str ) -> list [ItemResult ]:
162
+ """
163
+ Helper used to fetch deposition's files
164
+ """
145
165
async with self .network .GET (
146
166
f"api/deposit/depositions/{ record_id } /files"
147
167
) as response :
@@ -151,6 +171,9 @@ async def _fetch_record_files(self, record_id: str) -> list[ItemResult]:
151
171
return [self ._parse_file (file , record_id ) for file in files ]
152
172
153
173
async def _fetch_file (self , record_id : str , file_id : str ) -> ItemResult :
174
+ """
175
+ Helper used to fetch deposition's file
176
+ """
154
177
async with self .network .GET (
155
178
f"api/deposit/depositions/{ record_id } /files/{ file_id } "
156
179
) as response :
@@ -161,7 +184,10 @@ async def _fetch_file(self, record_id: str, file_id: str) -> ItemResult:
161
184
162
185
return self ._parse_file (file , record_id )
163
186
164
- def _parse_file (self , file , record_id ):
187
+ def _parse_file (self , file : dict , record_id : str ) -> ItemResult :
188
+ """
189
+ Helper which parses file response into ItemResult
190
+ """
165
191
return ItemResult (
166
192
item_id = f"file/{ record_id } /{ file .get ('id' )} " ,
167
193
item_name = file .get ("filename" ),
@@ -170,6 +196,9 @@ def _parse_file(self, file, record_id):
170
196
)
171
197
172
198
async def _fetch_deposition (self , deposition_id : str ) -> ItemResult :
199
+ """
200
+ Helper used to fetch deposition
201
+ """
173
202
async with self .network .GET (
174
203
f"api/deposit/depositions/{ deposition_id } "
175
204
) as response :
@@ -178,7 +207,10 @@ async def _fetch_deposition(self, deposition_id: str) -> ItemResult:
178
207
content = await response .json_content ()
179
208
return self ._parse_deposition (content )
180
209
181
- def _parse_deposition (self , raw ):
210
+ def _parse_deposition (self , raw : dict ) -> ItemResult :
211
+ """
212
+ Helper which parses deposition response into ItemResult
213
+ """
182
214
deposition_id = raw .get ("id" )
183
215
184
216
metadata = raw .get ("metadata" , {})
0 commit comments