canonicalwebteam.store-api 4.11.1__tar.gz → 4.11.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: canonicalwebteam.store-api
3
- Version: 4.11.1
3
+ Version: 4.11.3
4
4
  Summary:
5
5
  License: LGPL-3.0
6
6
  Author: Canonical Web Team
@@ -95,8 +95,12 @@ class Publisher:
95
95
  return headers.get("WWW-Authenticate") == ("Macaroon needs_refresh=1")
96
96
 
97
97
  def get_account(self, session):
98
+ """
99
+ Documentation:
100
+ https://dashboard.snapcraft.io/docs/reference/v1/account.html#get--dev-api-account
101
+ Endpoint: [GET] https://dashboard.snapcraft.io/dev/api/account
102
+ """
98
103
  headers = self._get_authorization_header(session)
99
-
100
104
  response = self.session.get(
101
105
  url=self.get_endpoint_url("account"), headers=headers
102
106
  )
@@ -104,11 +108,21 @@ class Publisher:
104
108
  return self.process_response(response)
105
109
 
106
110
  def get_account_snaps(self, session):
111
+ """
112
+ Returns the snaps associated with a user account
113
+ Documentation:
114
+ https://dashboard.snapcraft.io/docs/reference/v1/account.html#get--dev-api-account
115
+ Endpoint: [GET] https://dashboard.snapcraft.io/dev/api/account
116
+ """
107
117
  return self.get_account(session).get("snaps", {}).get("16", {})
108
118
 
109
119
  def get_agreement(self, session):
120
+ """
121
+ Documentation:
122
+ https://dashboard.snapcraft.io/docs/reference/v1/snap.html#release-a-snap-build-to-a-channel
123
+ Endpoint: [GET] https://dashboard.snapcraft.io/dev/api/agreement
124
+ """
110
125
  headers = self._get_authorization_header(session)
111
-
112
126
  agreement_response = self.session.get(
113
127
  url=self.get_endpoint_url("agreement/"), headers=headers
114
128
  )
@@ -119,6 +133,11 @@ class Publisher:
119
133
  return agreement_response.json()
120
134
 
121
135
  def post_agreement(self, session, agreed):
136
+ """
137
+ Documentation:
138
+ https://dashboard.snapcraft.io/docs/reference/v1/snap.html#release-a-snap-build-to-a-channel
139
+ Endpoint: [POST] https://dashboard.snapcraft.io/dev/api/agreement
140
+ """
122
141
  headers = self._get_authorization_header(session)
123
142
 
124
143
  json = {"latest_tos_accepted": agreed}
@@ -129,6 +148,11 @@ class Publisher:
129
148
  return self.process_response(agreement_response)
130
149
 
131
150
  def post_username(self, session, username):
151
+ """
152
+ Documentation:
153
+ https://dashboard.snapcraft.io/docs/reference/v1/account.html#get--dev-api-account
154
+ Endpoint: [PATCH] https://dashboard.snapcraft.io/dev/api/account
155
+ """
132
156
  headers = self._get_authorization_header(session)
133
157
  json = {"short_namespace": username}
134
158
  username_response = self.session.patch(
@@ -141,6 +165,11 @@ class Publisher:
141
165
  return self.process_response(username_response)
142
166
 
143
167
  def get_publisher_metrics(self, session, json):
168
+ """
169
+ Documentation:
170
+ https://dashboard.snapcraft.io/docs/reference/v1/snap.html#fetch-metrics-for-snaps
171
+ Endpoint: [POST] https://dashboard.snapcraft.io/dev/api/snaps/metrics
172
+ """
144
173
  headers = self._get_authorization_header(session)
145
174
  headers["Content-Type"] = "application/json"
146
175
 
@@ -160,6 +189,11 @@ class Publisher:
160
189
  is_private=False,
161
190
  store=None,
162
191
  ):
192
+ """
193
+ Documentation:
194
+ https://dashboard.snapcraft.io/docs/reference/v1/snap.html#register-a-snap-name
195
+ Endpoint: [POST] https://dashboard.snapcraft.io/dev/api/register-name/
196
+ """
163
197
  json = {"snap_name": snap_name}
164
198
 
165
199
  if registrant_comment:
@@ -180,6 +214,12 @@ class Publisher:
180
214
  return self.process_response(response)
181
215
 
182
216
  def post_register_name_dispute(self, session, snap_name, claim_comment):
217
+ """
218
+ Documentation:
219
+ https://dashboard.snapcraft.io/docs/reference/v1/snap.html#register-a-snap-name-dispute
220
+ Endpoint: [POST]
221
+ https://dashboard.snapcraft.io/dev/api/register-name-dispute
222
+ """
183
223
  json = {"snap_name": snap_name, "comment": claim_comment}
184
224
 
185
225
  response = self.session.post(
@@ -191,6 +231,12 @@ class Publisher:
191
231
  return self.process_response(response)
192
232
 
193
233
  def get_snap_info(self, snap_name, session):
234
+ """
235
+ Documentation:
236
+ https://dashboard.snapcraft.io/docs/reference/v1/snap.html#obtaining-information-about-a-snap
237
+ Endpoint: [GET]
238
+ https://dashboard.snapcraft.io/dev/api/snaps/info/{snap_name}
239
+ """
194
240
  response = self.session.get(
195
241
  url=self.get_endpoint_url(f"snaps/info/{snap_name}"),
196
242
  headers=self._get_authorization_header(session),
@@ -199,6 +245,11 @@ class Publisher:
199
245
  return self.process_response(response)
200
246
 
201
247
  def get_package_upload_macaroon(self, session, snap_name, channels):
248
+ """
249
+ Documentation:
250
+ https://dashboard.snapcraft.io/docs/reference/v1/macaroon.html#request-a-macaroon
251
+ Endpoint: [POST] https://dashboard.snapcraft.io/dev/api/acl/
252
+ """
202
253
  json = {
203
254
  "packages": [{"name": snap_name, "series": "16"}],
204
255
  "permissions": ["package_upload"],
@@ -214,11 +265,22 @@ class Publisher:
214
265
  return self.process_response(response)
215
266
 
216
267
  def get_snap_id(self, snap_name, session):
268
+ """
269
+ Documentation:
270
+ https://dashboard.snapcraft.io/docs/reference/v1/snap.html#obtaining-information-about-a-snap
271
+ Endpoint: https://dashboard.snapcraft.io/dev/api/snaps/info/{snap_name}
272
+ """
217
273
  snap_info = self.get_snap_info(snap_name, session)
218
274
 
219
275
  return snap_info["snap_id"]
220
276
 
221
277
  def snap_metadata(self, snap_id, session, json=None):
278
+ """
279
+ Documentation:
280
+ https://dashboard.snapcraft.io/docs/reference/v1/snap.html#managing-snap-metadata
281
+ Endpoint: [PUT]
282
+ https://dashboard.snapcraft.io/dev/api/snaps/{snap_id}/metadata
283
+ """
222
284
  method = "PUT" if json is not None else None
223
285
 
224
286
  metadata_response = self.session.request(
@@ -232,6 +294,12 @@ class Publisher:
232
294
  return self.process_response(metadata_response)
233
295
 
234
296
  def snap_screenshots(self, snap_id, session, data=None, files=None):
297
+ """
298
+ Documentation:
299
+ https://dashboard.snapcraft.io/docs/reference/v1/snap.html#managing-snap-metadata
300
+ Endpoint: [GET, PUT]
301
+ https://dashboard.snapcraft.io/dev/api/snaps/{snap_id}/binary-metadata
302
+ """
235
303
  method = "GET"
236
304
  files_array = None
237
305
  headers = self._get_authorization_header(session)
@@ -264,6 +332,12 @@ class Publisher:
264
332
  return self.process_response(screenshot_response)
265
333
 
266
334
  def get_snap_revision(self, session, snap_id, revision_id):
335
+ """
336
+ Documentation:
337
+ https://dashboard.snapcraft.io/docs/reference/v1/macaroon.html#request-a-macaroon
338
+ Endpoint: [GET]
339
+ https://dashboard.snapcraft.io/api/v2/snaps/{snap_id}/revisions/{revision_id}
340
+ """
267
341
  response = self.session.get(
268
342
  url=self.get_endpoint_url(
269
343
  f"snaps/{snap_id}/revisions/{revision_id}", 2
@@ -274,6 +348,12 @@ class Publisher:
274
348
  return self.process_response(response)
275
349
 
276
350
  def snap_revision_history(self, session, snap_id):
351
+ """
352
+ Documentation:
353
+ https://dashboard.snapcraft.io/docs/reference/v1/snap.html#list-all-revisions-of-a-snap
354
+ Endpoint: [GET]
355
+ https://dashboard.snapcraft.io/dev/api/snaps/{snap_id}/history
356
+ """
277
357
  response = self.session.get(
278
358
  url=self.get_endpoint_url(f"snaps/{snap_id}/history"),
279
359
  headers=self._get_authorization_header(session),
@@ -282,6 +362,12 @@ class Publisher:
282
362
  return self.process_response(response)
283
363
 
284
364
  def snap_release_history(self, session, snap_name, page=1):
365
+ """
366
+ Documentation:
367
+ https://dashboard.snapcraft.io/docs/reference/v2/en/snaps.html#snap-releases
368
+ Endpoint: [GET]
369
+ https://dashboard.snapcraft.io/api/v2/snaps/{snap_name}/releases
370
+ """
285
371
  response = self.session.get(
286
372
  url=self.get_endpoint_url(f"snaps/{snap_name}/releases", 2),
287
373
  params={"page": page},
@@ -291,6 +377,12 @@ class Publisher:
291
377
  return self.process_response(response)
292
378
 
293
379
  def snap_channel_map(self, session, snap_name):
380
+ """
381
+ Documentation:
382
+ https://dashboard.snapcraft.io/docs/reference/v2/en/snaps.html#snap-channel-map
383
+ Endpoint: [GET]
384
+ https://dashboard.snapcraft.io/api/v2/snaps/{snap_name}/channel-map
385
+ """
294
386
  response = self.session.get(
295
387
  url=self.get_endpoint_url(f"snaps/{snap_name}/channel-map", 2),
296
388
  headers=self._get_authorization_header(session),
@@ -299,6 +391,11 @@ class Publisher:
299
391
  return self.process_response(response)
300
392
 
301
393
  def post_snap_release(self, session, snap_name, json):
394
+ """
395
+ Documentation:
396
+ https://dashboard.snapcraft.io/docs/reference/v1/snap.html#release-a-snap-build-to-a-channel
397
+ Endpoint: [POST] https://dashboard.snapcraft.io/dev/api/snap-release
398
+ """
302
399
  response = self.session.post(
303
400
  url=self.get_endpoint_url("snap-release/"),
304
401
  headers=self._get_authorization_header(session),
@@ -308,6 +405,12 @@ class Publisher:
308
405
  return self.process_response(response)
309
406
 
310
407
  def post_close_channel(self, session, snap_id, json):
408
+ """
409
+ Documentation:
410
+ https://dashboard.snapcraft.io/docs/reference/v1/snap.html#close-a-channel-for-a-snap-package
411
+ Endpoint: [POST]
412
+ https://dashboard.snapcraft.io/dev/api/snaps/{snap_id}/close
413
+ """
311
414
  response = self.session.post(
312
415
  url=self.get_endpoint_url(f"snaps/{snap_id}/close"),
313
416
  headers=self._get_authorization_header(session),
@@ -66,6 +66,10 @@ class Store:
66
66
  arch="wide",
67
67
  api_version=1,
68
68
  ):
69
+ """
70
+ Documentation: https://api.snapcraft.io/docs/search.html#snap_search
71
+ Endpoint: https://api.snapcraft.io/api/v1/snaps/search
72
+ """
69
73
  url = self.get_endpoint_url("search", api_version)
70
74
  headers = self.config[api_version].get("headers")
71
75
 
@@ -113,6 +117,10 @@ class Store:
113
117
  )
114
118
 
115
119
  def get_all_items(self, size, api_version=1):
120
+ """
121
+ Documentation: https://api.snapcraft.io/docs/search.html#snap_search
122
+ Endpoint: https://api.snapcraft.io/api/v1/snaps/search
123
+ """
116
124
  url = self.get_endpoint_url("search", api_version)
117
125
 
118
126
  return self.process_response(
@@ -124,6 +132,10 @@ class Store:
124
132
  )
125
133
 
126
134
  def get_category_items(self, category, size=10, page=1, api_version=1):
135
+ """
136
+ Documentation: https://api.snapcraft.io/docs/search.html#snap_search
137
+ Endpoint: https://api.snapcraft.io/api/v1/snaps/search
138
+ """
127
139
  return self.search(
128
140
  search="",
129
141
  category=category,
@@ -133,6 +145,10 @@ class Store:
133
145
  )
134
146
 
135
147
  def get_featured_items(self, size=10, page=1, api_version=1):
148
+ """
149
+ Documentation: https://api.snapcraft.io/docs/search.html#snap_search
150
+ Endpoint: https://api.snapcraft.io/api/v1/snaps/search
151
+ """
136
152
  return self.search(
137
153
  search="",
138
154
  category="featured",
@@ -142,6 +158,10 @@ class Store:
142
158
  )
143
159
 
144
160
  def get_publisher_items(self, publisher, size=500, page=1, api_version=1):
161
+ """
162
+ Documentation: https://api.snapcraft.io/docs/search.html#snap_search
163
+ Endpoint: https://api.snapcraft.io/api/v1/snaps/search
164
+ """
145
165
  return self.search(
146
166
  search="publisher:" + publisher,
147
167
  size=size,
@@ -150,8 +170,12 @@ class Store:
150
170
  )
151
171
 
152
172
  def get_item_details(self, name, channel=None, fields=[], api_version=2):
173
+ """
174
+ Documentation: https://api.snapcraft.io/docs/info.html
175
+ Endpoint: [GET]
176
+ https://api.snapcraft.io/api/v2/{name_space}/info/{package_name}
177
+ """
153
178
  url = self.get_endpoint_url("info/" + name, api_version)
154
-
155
179
  params = {"fields": ",".join(fields)}
156
180
 
157
181
  if channel:
@@ -166,6 +190,10 @@ class Store:
166
190
  )
167
191
 
168
192
  def get_public_metrics(self, json, api_version=1):
193
+ """
194
+ Documentation: https://api.snapcraft.io/docs/metrics.html
195
+ Endpoint: https://api.snapcraft.io/api/v1/snaps/metrics
196
+ """
169
197
  url = self.get_endpoint_url("metrics")
170
198
 
171
199
  headers = self.config[api_version].get("headers", {})
@@ -176,8 +204,11 @@ class Store:
176
204
  )
177
205
 
178
206
  def get_categories(self, api_version=2, type="shared"):
207
+ """
208
+ Documentation: https://api.snapcraft.io/docs/categories.html
209
+ Endpoint: https://api.snapcraft.io/api/v2/{name_space}/categories
210
+ """
179
211
  url = self.get_endpoint_url("categories", api_version)
180
-
181
212
  return self.process_response(
182
213
  self.session.get(
183
214
  url,
@@ -187,6 +218,12 @@ class Store:
187
218
  )
188
219
 
189
220
  def get_resource_revisions(self, name, resource_name, api_version=2):
221
+ """
222
+ Documentation:
223
+ https://api.snapcraft.io/docs/charms.html#list_resource_revisions
224
+ Endpoint:
225
+ https://api.snapcraft.io/api/v2/charms/resources/{package_name}/{resource_name}/revisions
226
+ """
190
227
  url = self.get_endpoint_url(
191
228
  f"resources/{name}/{resource_name}/revisions", api_version
192
229
  )
@@ -67,11 +67,16 @@ class CharmPublisher(Publisher):
67
67
  self.session.headers.update({"Bakery-Protocol-Version": "2"})
68
68
 
69
69
  def _get_authorization_header(self, publisher_auth):
70
+ """
71
+ Return the formatted Authorization header for the publisher API.
72
+ """
70
73
  return {"Authorization": f"Macaroon {publisher_auth}"}
71
74
 
72
75
  def get_macaroon(self):
73
76
  """
74
77
  Return a bakery v2 macaroon from the publisher API to be discharged
78
+ Documentation: https://api.charmhub.io/docs/default.html#get_macaroon
79
+ Endpoint URL: [GET] https://api.charmhub.io/v1/tokens
75
80
  """
76
81
  response = self.session.get(url=self.get_endpoint_url("tokens"))
77
82
 
@@ -80,6 +85,8 @@ class CharmPublisher(Publisher):
80
85
  def issue_macaroon(self, permissions, description=None, ttl=None):
81
86
  """
82
87
  Return a bakery v2 macaroon from the publisher API to be discharged
88
+ Documentation: https://api.charmhub.io/docs/default.html#issue_macaroon
89
+ Endpoint URL: [POST] https://api.charmhub.io/v1/tokens
83
90
  """
84
91
  data = {"permissions": permissions}
85
92
 
@@ -99,6 +106,9 @@ class CharmPublisher(Publisher):
99
106
  def exchange_macaroons(self, issued_macaroon):
100
107
  """
101
108
  Return an exchanged snapstore-only authentication macaroon.
109
+ Documentation:
110
+ https://api.charmhub.io/docs/default.html#exchange_macaroons
111
+ Endpoint URL: [POST] https://api.charmhub.io/v1/tokens/exchange
102
112
  """
103
113
 
104
114
  response = self.session.post(
@@ -112,6 +122,8 @@ class CharmPublisher(Publisher):
112
122
  def macaroon_info(self, publisher_auth):
113
123
  """
114
124
  Return information about the authenticated macaroon token.
125
+ Documentation: https://api.charmhub.io/docs/default.html#macaroon_info
126
+ Endpoint URL: [GET] https://api.charmhub.io/v1/tokens/whoami
115
127
  """
116
128
  response = self.session.get(
117
129
  url=self.get_endpoint_url("tokens/whoami"),
@@ -121,6 +133,11 @@ class CharmPublisher(Publisher):
121
133
  return self.process_response(response)
122
134
 
123
135
  def whoami(self, publisher_auth):
136
+ """
137
+ Return information about the authenticated macaroon token.
138
+ Documentation: 'DEPRECATED'
139
+ Endpoint URL: [GET] https://api.charmhub.io/v1/whoami
140
+ """
124
141
  response = self.session.get(
125
142
  url=self.get_endpoint_url("whoami"),
126
143
  headers=self._get_authorization_header(publisher_auth),
@@ -137,6 +154,8 @@ class CharmPublisher(Publisher):
137
154
  ):
138
155
  """
139
156
  Return publisher packages
157
+ Documentation: https://api.charmhub.io/docs/default.html
158
+ Endpoint URL: [GET] https://api.charmhub.io/v1/charm
140
159
 
141
160
  Args:
142
161
  publisher_auth: Serialized macaroon to consume the API.
@@ -174,6 +193,11 @@ class CharmPublisher(Publisher):
174
193
  def get_package_metadata(self, publisher_auth, package_type, name):
175
194
  """
176
195
  Get general metadata for a package.
196
+ Documentation:
197
+ https://api.charmhub.io/docs/default.html#package_metadata
198
+ Endpoint URL: [GET] https://api.charmhub.io/v1/charm/<name>
199
+ namespace: charm for both charms and bundles
200
+ name: Package name
177
201
 
178
202
  Args:
179
203
  publisher_auth: Serialized macaroon to consume the API.
@@ -201,6 +225,12 @@ class CharmPublisher(Publisher):
201
225
  ):
202
226
  """
203
227
  Update general metadata for a package.
228
+ Documentation:
229
+ https://api.charmhub.io/docs/default.html#update_package_metadata
230
+ Endpoint URL: [PATCH]
231
+ https://api.charmhub.io/v1/charm/<name>
232
+ namespace: charm for both charms and bundles
233
+ name: Package name
204
234
 
205
235
  Args:
206
236
  publisher_auth: Serialized macaroon to consume the API.
@@ -229,6 +259,8 @@ class CharmPublisher(Publisher):
229
259
  def register_package_name(self, publisher_auth, data):
230
260
  """
231
261
  Register a package name.
262
+ Documentation: https://api.charmhub.io/docs/default.html#register_name
263
+ Endpoint URL: [POST] https://api.charmhub.io/v1/charm
232
264
 
233
265
  Args:
234
266
  publisher_auth: Serialized macaroon to consume the API.
@@ -249,6 +281,9 @@ class CharmPublisher(Publisher):
249
281
  def unregister_package_name(self, publisher_auth, name):
250
282
  """
251
283
  Unregister a package name.
284
+ Documentation:
285
+ https://api.charmhub.io/docs/default.html#unregister_package
286
+ Endpoint URL: [DELETE] https://api.charmhub.io/v1/charm/<name>
252
287
 
253
288
  Args:
254
289
  publisher_auth: Serialized macaroon to consume the API.
@@ -265,6 +300,12 @@ class CharmPublisher(Publisher):
265
300
  return response
266
301
 
267
302
  def get_charm_libraries(self, charm_name):
303
+ """
304
+ Get libraries for a charm.
305
+ Documentation:
306
+ https://api.charmhub.io/docs/libraries.html#fetch_libraries
307
+ Endpoint URL: [POST] https://api.charmhub.io/v1/charm/libraries/bulk
308
+ """
268
309
  response = self.session.post(
269
310
  url=self.get_endpoint_url("charm/libraries/bulk"),
270
311
  json=[{"charm-name": charm_name}],
@@ -273,6 +314,18 @@ class CharmPublisher(Publisher):
273
314
  return self.process_response(response)
274
315
 
275
316
  def get_charm_library(self, charm_name, library_id, api_version=None):
317
+ """
318
+ Get library metadata and content
319
+ Documentation:
320
+ https://api.charmhub.io/docs/libraries.html#fetch_library
321
+ Endpoint URL: [GET]
322
+ https://api.charmhub.io/v1/charm/libraries/<charm_name>/<library_id>
323
+
324
+ Args:
325
+ charm_name: Name of the charm
326
+ library_id: ID of the library
327
+ api_version: API version to use
328
+ """
276
329
  params = {}
277
330
 
278
331
  if api_version is not None:
@@ -290,6 +343,14 @@ class CharmPublisher(Publisher):
290
343
  def get_collaborators(self, publisher_auth, name):
291
344
  """
292
345
  Get collaborators (accepted invites) for the given package.
346
+ Documentation:
347
+ https://api.charmhub.io/docs/collaborator.html#get_collaborators
348
+ Endpoint URL: [GET]
349
+ https://api.charmhub.io/v1/charm/<name>/collaborators
350
+
351
+ Args:
352
+ publisher_auth: Serialized macaroon to consume the API.
353
+ name: Name of the package
293
354
  """
294
355
  response = self.session.get(
295
356
  url=self.get_endpoint_url(f"charm/{name}/collaborators"),
@@ -300,6 +361,14 @@ class CharmPublisher(Publisher):
300
361
  def get_pending_invites(self, publisher_auth, name):
301
362
  """
302
363
  Get pending collaborator invites for the given package.
364
+ Documentation:
365
+ https://api.charmhub.io/docs/collaborator.html#get_pending_invites
366
+ Endpoint URL: [GET]
367
+ https://api.charmhub.io/v1/charm/<name>/collaborators/invites
368
+
369
+ Args:
370
+ publisher_auth: Serialized macaroon to consume the API.
371
+ name: Name of the package
303
372
  """
304
373
  response = self.session.get(
305
374
  url=self.get_endpoint_url(f"charm/{name}/collaborators/invites"),
@@ -310,6 +379,15 @@ class CharmPublisher(Publisher):
310
379
  def invite_collaborators(self, publisher_auth, name, emails):
311
380
  """
312
381
  Invite one or more collaborators for a package.
382
+ Documentation:
383
+ https://api.charmhub.io/docs/collaborator.html#invite_collaborators
384
+ Endpoint URL: [POST]
385
+ https://api.charmhub.io/v1/charm/<name>/collaborators/invites
386
+
387
+ Args:
388
+ publisher_auth: Serialized macaroon to consume the API.
389
+ name: Name of the package
390
+ emails: List of emails to invite
313
391
  """
314
392
  payload = {"invites": []}
315
393
 
@@ -326,6 +404,15 @@ class CharmPublisher(Publisher):
326
404
  def revoke_invites(self, publisher_auth, name, emails):
327
405
  """
328
406
  Revoke invites to the specified emails for the package.
407
+ Documentation:
408
+ https://api.charmhub.io/docs/collaborator.html#revoke_invites
409
+ Endpoint URL: [POST]
410
+ https://api.charmhub.io/v1/charm/<name>/collaborators/invites/revoke
411
+
412
+ Args:
413
+ publisher_auth: Serialized macaroon to consume the API.
414
+ name: Name of the package
415
+ emails: List of emails to revoke
329
416
  """
330
417
  payload = {"invites": []}
331
418
 
@@ -344,6 +431,15 @@ class CharmPublisher(Publisher):
344
431
  def accept_invite(self, publisher_auth, name, token):
345
432
  """
346
433
  Accept a collaborator invite.
434
+ Documentation:
435
+ https://api.charmhub.io/docs/collaborator.html#accept_invite
436
+ Endpoint URL: [POST]
437
+ https://api.charmhub.io/v1/charm/<name>/collaborators/invites/accept
438
+
439
+ Args:
440
+ publisher_auth: Serialized macaroon to consume the API.
441
+ name: Name of the package
442
+ token: Invite token
347
443
  """
348
444
  response = self.session.post(
349
445
  url=self.get_endpoint_url(
@@ -357,6 +453,15 @@ class CharmPublisher(Publisher):
357
453
  def reject_invite(self, publisher_auth, name, token):
358
454
  """
359
455
  Reject a collaborator invite.
456
+ Documentation:
457
+ https://api.charmhub.io/docs/collaborator.html#reject_invite
458
+ Endpoint URL: [POST]
459
+ https://api.charmhub.io/v1/charm/<name>/collaborators/invites/reject
460
+
461
+ Args:
462
+ publisher_auth: Serialized macaroon to consume the API.
463
+ name: Name of the package
464
+ token: Invite token
360
465
  """
361
466
  response = self.session.post(
362
467
  url=self.get_endpoint_url(
@@ -370,6 +475,14 @@ class CharmPublisher(Publisher):
370
475
  def create_track(self, publisher_auth, charm_name, track_name):
371
476
  """
372
477
  Create a track for a charm base on the charm's guardrail pattern.
478
+ Documentation: https://api.charmhub.io/docs/default.html#create_tracks
479
+ Endpoint URL: [POST]
480
+ https://api.charmhub.io/v1/charm/<charm_name>/tracks
481
+
482
+ Args:
483
+ publisher_auth: Serialized macaroon to consume the API.
484
+ charm_name: Name of the charm
485
+ track_name: Name of the track
373
486
  """
374
487
  response = self.session.post(
375
488
  url=self.get_endpoint_url(f"charm/{charm_name}/tracks"),
@@ -69,6 +69,10 @@ class SnapStore(Store):
69
69
  featured="false",
70
70
  fields=[],
71
71
  ):
72
+ """
73
+ Documentation: https://api.snapcraft.io/docs/search.html#snaps_find
74
+ Endpoint: [GET] https://api.snapcraft.io/v2/snaps/find
75
+ """
72
76
  url = self.get_endpoint_url("find", 2)
73
77
  headers = self.config[2].get("headers")
74
78
  params = {
@@ -96,6 +100,9 @@ class SnapPublisher(Publisher):
96
100
  def get_macaroon(self, permissions):
97
101
  """
98
102
  Return a bakery v2 macaroon from the publisher API to be discharged
103
+ Documemntation:
104
+ https://dashboard.snapcraft.io/docs/reference/v1/macaroon.html
105
+ Endpoint: [POST] https://dashboard.snapcraft.iodev/api/acl
99
106
  """
100
107
  response = self.session.post(
101
108
  url=self.get_endpoint_url("tokens", 2),
@@ -105,6 +112,12 @@ class SnapPublisher(Publisher):
105
112
  return self.process_response(response)["macaroon"]
106
113
 
107
114
  def whoami(self, session):
115
+ """
116
+ Get the authenticated user details.
117
+ Documentation:
118
+ https://dashboard.snapcraft.io/docs/reference/v2/en/tokens.html#api-tokens-whoami
119
+ Endpoint: [GET] https://dashboard.snapcraft.io/api/v2/tokens/whoami
120
+ """
108
121
  response = self.session.get(
109
122
  url=self.get_endpoint_url("tokens/whoami", 2),
110
123
  headers=self._get_authorization_header(session),
@@ -121,6 +134,9 @@ class SnapPublisher(Publisher):
121
134
  def exchange_dashboard_macaroons(self, session):
122
135
  """
123
136
  Exchange dashboard.snapcraft.io SSO discharged macaroons
137
+ Documentation:
138
+ https://api.charmhub.io/docs/default.html#exchange_dashboard_macaroons
139
+ Endpoint: [POST] https://api.charmhub.io/v1/tokens/dashboard/exchange
124
140
  """
125
141
  response = self.session.post(
126
142
  url=self.get_publisherwg_endpoint_url("tokens/dashboard/exchange"),
@@ -133,6 +149,10 @@ class SnapPublisher(Publisher):
133
149
  def get_collaborators(self, session, name):
134
150
  """
135
151
  Get collaborators (accepted invites) for the given package.
152
+ Documentation:
153
+ https://api.charmhub.io/docs/collaborator.html#get_collaborators
154
+ Endpoint: [GET]
155
+ https://api.charmhub.io/v1/snap/{snap_name}/collaborators
136
156
  """
137
157
  response = self.session.get(
138
158
  url=self.get_publisherwg_endpoint_url(
@@ -145,6 +165,10 @@ class SnapPublisher(Publisher):
145
165
  def get_pending_invites(self, session, name):
146
166
  """
147
167
  Get pending collaborator invites for the given package.
168
+ Documentation:
169
+ https://api.charmhub.io/docs/collaborator.html#get_pending_invites
170
+ Endpoint: [GET]
171
+ https://api.charmhub.io/v1/snap/{snap_name}/collaborators/invites
148
172
  """
149
173
  response = self.session.get(
150
174
  url=self.get_publisherwg_endpoint_url(
@@ -157,6 +181,10 @@ class SnapPublisher(Publisher):
157
181
  def invite_collaborators(self, session, name, emails):
158
182
  """
159
183
  Invite one or more collaborators for a package.
184
+ Documentation:
185
+ https://api.charmhub.io/docs/collaborator.html#invite_collaborators
186
+ Endpoint: [POST]
187
+ https://api.charmhub.io/v1/snap/{snap_name}/collaborators/invites
160
188
  """
161
189
  payload = {"invites": []}
162
190
 
@@ -175,6 +203,10 @@ class SnapPublisher(Publisher):
175
203
  def revoke_invites(self, session, name, emails):
176
204
  """
177
205
  Revoke invites to the specified emails for the package.
206
+ Documentation:
207
+ https://api.charmhub.io/docs/collaborator.html#revoke_invites
208
+ Endpoint: [POST]
209
+ https://api.charmhub.io/v1/snap/{snap_name}/collaborators/invites/revoke
178
210
  """
179
211
  payload = {"invites": []}
180
212
 
@@ -193,6 +225,10 @@ class SnapPublisher(Publisher):
193
225
  def accept_invite(self, session, name, token):
194
226
  """
195
227
  Accept a collaborator invite.
228
+ Documentation:
229
+ https://api.charmhub.io/docs/collaborator.html#accept_invite
230
+ Endpoint: [POST]
231
+ https://api.charmhub.io/v1/snap/{snap_name}/collaborators/invites/accept
196
232
  """
197
233
  response = self.session.post(
198
234
  url=self.get_publisherwg_endpoint_url(
@@ -206,6 +242,10 @@ class SnapPublisher(Publisher):
206
242
  def reject_invite(self, session, name, token):
207
243
  """
208
244
  Reject a collaborator invite.
245
+ Documentation:
246
+ https://api.charmhub.io/docs/collaborator.html#reject_invite
247
+ Endpoint: [POST]
248
+ https://api.charmhub.io/v1/snap/{snap_name}/collaborators/invites/reject
209
249
  """
210
250
  response = self.session.post(
211
251
  url=self.get_publisherwg_endpoint_url(
@@ -219,6 +259,8 @@ class SnapPublisher(Publisher):
219
259
  def create_track(self, session, snap_name, track_name):
220
260
  """
221
261
  Create a track for a snap base on the snap's guardrail pattern.
262
+ Documentation: https://api.charmhub.io/docs/default.html#create_tracks
263
+ Endpoint: [POST] https://api.charmhub.io/v1/snap/{snap_name}/tracks
222
264
  """
223
265
  response = self.session.post(
224
266
  url=self.get_publisherwg_endpoint_url(f"snap/{snap_name}/tracks"),
@@ -227,9 +269,29 @@ class SnapPublisher(Publisher):
227
269
  )
228
270
  return response
229
271
 
272
+ def get_package_metadata(self, publisher_auth, package_type, snap_name):
273
+ """
274
+ Get general metadata for a package.
275
+ Args:
276
+ publisher_auth: Serialized macaroon to consume the API.
277
+ package_type: Type of packages to obtain.
278
+ Returns:
279
+ Package general metadata
280
+ """
281
+ response = self.session.get(
282
+ url=self.get_publisherwg_endpoint_url(
283
+ f"{package_type}/{snap_name}"
284
+ ),
285
+ headers=self._get_publisherwg_authorization_header(publisher_auth),
286
+ )
287
+
288
+ return self.process_response(response)["metadata"]
289
+
230
290
  def unregister_package_name(self, publisher_auth, snap_name):
231
291
  """
232
292
  Unregister a package name.
293
+ Documentation: https://api.charmhub.io/docs/default.html#register_name
294
+ Endpoint: [DELETE] https://api.charmhub.io/v1/snap/{snap_name}
233
295
 
234
296
  Args:
235
297
  publisher_auth: Serialized macaroon to consume the API.
@@ -252,6 +314,9 @@ class SnapStoreAdmin(SnapPublisher):
252
314
 
253
315
  def get_stores(self, session, roles=["admin", "review", "view", "access"]):
254
316
  """Return a list a stores with the given roles
317
+ Documentation:
318
+ https://dashboard.snapcraft.io/docs/reference/v1/account.html#get--dev-api-account
319
+ Endpoint: [GET] https://dashboard.snapcraft.io/dev/api/account
255
320
 
256
321
  :return: A list of stores
257
322
  """
@@ -273,6 +338,10 @@ class SnapStoreAdmin(SnapPublisher):
273
338
 
274
339
  def get_store(self, session, store_id):
275
340
  """Return a store where the user is an admin
341
+ Documentation:
342
+ https://dashboard.snapcraft.io/docs/reference/v2/en/stores.html#list-the-details-of-a-brand-store
343
+ Endpoint: [GET]
344
+ https://dashboard.snapcraft.io/api/v2/stores/{store_id}
276
345
 
277
346
  :return: Store details
278
347
  """
@@ -287,6 +356,12 @@ class SnapStoreAdmin(SnapPublisher):
287
356
  def get_store_snaps(
288
357
  self, session, store_id, query=None, allowed_for_inclusion=None
289
358
  ):
359
+ """
360
+ Documentation:
361
+ https://dashboard.snapcraft.io/docs/reference/v2/en/stores.html#get
362
+ Endpoint: [GET]
363
+ https://dashboard.snapcraft.io/api/v2/stores/{store_id}/snaps
364
+ """
290
365
  headers = self._get_authorization_header(session)
291
366
  params = {}
292
367
 
@@ -305,6 +380,11 @@ class SnapStoreAdmin(SnapPublisher):
305
380
  return self.process_response(response).get("snaps", [])
306
381
 
307
382
  def get_store_members(self, session, store_id):
383
+ """
384
+ Documentation:
385
+ https://dashboard.snapcraft.io/docs/reference/v2/en/stores.html#list-the-details-of-a-brand-store
386
+ Endpoint: [GET] https://dashboard.snapcraft.io/api/v2/stores/{store_id}
387
+ """
308
388
  headers = self._get_authorization_header(session)
309
389
 
310
390
  response = self.session.get(
@@ -315,6 +395,12 @@ class SnapStoreAdmin(SnapPublisher):
315
395
  return self.process_response(response).get("users", [])
316
396
 
317
397
  def update_store_members(self, session, store_id, members):
398
+ """
399
+ Documentation:
400
+ https://dashboard.snapcraft.io/docs/reference/v2/en/stores.html#add-remove-or-edit-users-roles
401
+ Endpoint: [POST]
402
+ https://dashboard.snapcraft.io/api/v2/stores/{store_id}/users
403
+ """
318
404
  headers = self._get_authorization_header(session)
319
405
 
320
406
  response = self.session.post(
@@ -326,6 +412,12 @@ class SnapStoreAdmin(SnapPublisher):
326
412
  return self.process_response(response)
327
413
 
328
414
  def invite_store_members(self, session, store_id, members):
415
+ """
416
+ Documentation:
417
+ https://dashboard.snapcraft.io/docs/reference/v2/en/stores.html#manage-store-invitations
418
+ Endpoint: [POST]
419
+ https://dashboard.snapcraft.io/api/v2/stores/{store_id}/invites
420
+ """
329
421
  headers = self._get_authorization_header(session)
330
422
 
331
423
  response = self.session.post(
@@ -337,6 +429,12 @@ class SnapStoreAdmin(SnapPublisher):
337
429
  return self.process_response(response)
338
430
 
339
431
  def change_store_settings(self, session, store_id, settings):
432
+ """
433
+ Documentation:
434
+ https://dashboard.snapcraft.io/docs/reference/v2/en/stores.html#change-store-settings
435
+ Endpoint: [PUT]
436
+ https://dashboard.snapcraft.io/api/v2/stores/{store_id}/settings
437
+ """
340
438
  headers = self._get_authorization_header(session)
341
439
 
342
440
  response = self.session.put(
@@ -348,6 +446,12 @@ class SnapStoreAdmin(SnapPublisher):
348
446
  return self.process_response(response)
349
447
 
350
448
  def update_store_snaps(self, session, store_id, snaps):
449
+ """
450
+ Documentation:
451
+ https://dashboard.snapcraft.io/docs/reference/v2/en/stores.html#post
452
+ Endpoint: [POST]
453
+ https://dashboard.snapcraft.io/api/v2/stores/{store_id}/snaps
454
+ """
351
455
  headers = self._get_authorization_header(session)
352
456
 
353
457
  response = self.session.post(
@@ -359,6 +463,12 @@ class SnapStoreAdmin(SnapPublisher):
359
463
  return self.process_response(response)
360
464
 
361
465
  def update_store_invites(self, session, store_id, invites):
466
+ """
467
+ Documentation:
468
+ https://dashboard.snapcraft.io/docs/reference/v2/en/stores.html#manage-store-invitations
469
+ Endpoint: [PUT]
470
+ https://dashboard.snapcraft.io/api/v2/stores/{store_id}/invites
471
+ """
362
472
  headers = self._get_authorization_header(session)
363
473
 
364
474
  response = self.session.put(
@@ -370,6 +480,11 @@ class SnapStoreAdmin(SnapPublisher):
370
480
  return self.process_response(response)
371
481
 
372
482
  def get_store_invites(self, session, store_id):
483
+ """
484
+ Documentation:
485
+ https://dashboard.snapcraft.io/docs/reference/v2/en/stores.html#list-the-details-of-a-brand-store
486
+ Endpoint: [GET] https://dashboard.snapcraft.io/api/v2/stores/{store_id}
487
+ """
373
488
  headers = self._get_authorization_header(session)
374
489
 
375
490
  response = self.session.get(
@@ -381,6 +496,11 @@ class SnapStoreAdmin(SnapPublisher):
381
496
 
382
497
  # MODEL SERVICE ADMIN
383
498
  def get_store_models(self, session, store_id):
499
+ """
500
+ Documentation:
501
+ https://api.charmhub.io/docs/model-service-admin.html#read_models
502
+ Endpoint: [GET] https://api.charmhub.io/v1/brand/{store_id}/model
503
+ """
384
504
  response = self.session.get(
385
505
  url=self.get_publisherwg_endpoint_url(f"brand/{store_id}/model"),
386
506
  headers=self._get_publisherwg_authorization_header(session),
@@ -389,6 +509,11 @@ class SnapStoreAdmin(SnapPublisher):
389
509
  return self.process_response(response)
390
510
 
391
511
  def create_store_model(self, session, store_id, name, api_key=None):
512
+ """
513
+ Documentation:
514
+ https://api.charmhub.io/docs/model-service-admin.html#create_model
515
+ Endpoint: [POST] https://api.charmhub.io/v1/brand/{store_id}/model
516
+ """
392
517
  if api_key:
393
518
  payload = {"name": name, "api-key": api_key, "series": "16"}
394
519
  else:
@@ -402,6 +527,12 @@ class SnapStoreAdmin(SnapPublisher):
402
527
  return self.process_response(response)
403
528
 
404
529
  def update_store_model(self, session, store_id, model_name, api_key):
530
+ """
531
+ Doucumentation:
532
+ https://api.charmhub.io/docs/model-service-admin.html#update_model
533
+ Endpoint: [PATCH]
534
+ https://api.charmhub.io/v1/brand/{store_id}/model/{model_name}
535
+ """
405
536
  response = self.session.patch(
406
537
  url=self.get_publisherwg_endpoint_url(
407
538
  f"brand/{store_id}/model/{model_name}"
@@ -413,6 +544,12 @@ class SnapStoreAdmin(SnapPublisher):
413
544
  return self.process_response(response)
414
545
 
415
546
  def get_store_model_policies(self, session, store_id, model_name):
547
+ """
548
+ Documentation:
549
+ https://api.charmhub.io/docs/model-service-admin.html#read_serial_policies
550
+ Endpoint: [GET]
551
+ https://api.charmhub.io/v1/brand/{store_id}/model/<model_name>/serial_policy
552
+ """
416
553
  response = self.session.get(
417
554
  url=self.get_publisherwg_endpoint_url(
418
555
  f"brand/{store_id}/model/{model_name}/serial_policy"
@@ -425,6 +562,12 @@ class SnapStoreAdmin(SnapPublisher):
425
562
  def create_store_model_policy(
426
563
  self, session, store_id, model_name, signing_key
427
564
  ):
565
+ """
566
+ Documentation:
567
+ https://api.charmhub.io/docs/model-service-admin.html#create_serial_policy
568
+ Endpoint: [POST]
569
+ https://api.charmhub.io/v1/brand/{store_id}/model/{model_name}/serial_policy
570
+ """
428
571
  response = self.session.post(
429
572
  url=self.get_publisherwg_endpoint_url(
430
573
  f"brand/{store_id}/model/{model_name}/serial_policy"
@@ -438,6 +581,12 @@ class SnapStoreAdmin(SnapPublisher):
438
581
  def delete_store_model_policy(
439
582
  self, session, store_id, model_name, revision
440
583
  ):
584
+ """
585
+ Documentation:
586
+ https://api.charmhub.io/docs/model-service-admin.html#delete_serial_policy
587
+ Endpoint: [DELETE]
588
+ https://api.charmhub.io/v1/brand/{store_id}/model/{model_name}/serial_policy/{serial_policy_revision}
589
+ """
441
590
  response = self.session.delete(
442
591
  url=self.get_publisherwg_endpoint_url(
443
592
  f"brand/{store_id}/model/{model_name}/serial_policy/{revision}"
@@ -448,6 +597,11 @@ class SnapStoreAdmin(SnapPublisher):
448
597
  return response
449
598
 
450
599
  def get_store_signing_keys(self, session, store_id):
600
+ """
601
+ Documentation:
602
+ https://api.charmhub.io/docs/model-service-admin.html#read_signing_keys
603
+ Endpoint: [GET] https://api.charmhub.io/v1/brand/{store_id}/signing_key
604
+ """
451
605
  headers = self._get_publisherwg_authorization_header(session)
452
606
  url = self.get_publisherwg_endpoint_url(
453
607
  f"brand/{store_id}/signing_key"
@@ -459,6 +613,12 @@ class SnapStoreAdmin(SnapPublisher):
459
613
  return self.process_response(response)
460
614
 
461
615
  def create_store_signing_key(self, session, store_id, name):
616
+ """
617
+ Documentation:
618
+ https://api.charmhub.io/docs/model-service-admin.html#create_signing_key
619
+ Endpoint: [POST]
620
+ https://api.charmhub.io/v1/brand/{store_id}/signing_key
621
+ """
462
622
  headers = self._get_publisherwg_authorization_header(session)
463
623
  url = self.get_publisherwg_endpoint_url(
464
624
  f"brand/{store_id}/signing_key"
@@ -473,6 +633,12 @@ class SnapStoreAdmin(SnapPublisher):
473
633
  def delete_store_signing_key(
474
634
  self, session, store_id, signing_key_sha3_384
475
635
  ):
636
+ """
637
+ Documentation:
638
+ https://api.charmhub.io/docs/model-service-admin.html#delete_signing_key
639
+ Endpoint: [DELETE]
640
+ https://api.charmhub.io/v1/brand/{store_id}/signing_key/<signing_key_sha3_384}
641
+ """
476
642
  headers = self._get_publisherwg_authorization_header(session)
477
643
  url = self.get_publisherwg_endpoint_url(
478
644
  f"brand/{store_id}/signing_key/{signing_key_sha3_384}"
@@ -485,6 +651,11 @@ class SnapStoreAdmin(SnapPublisher):
485
651
  return response
486
652
 
487
653
  def get_brand(self, session, store_id):
654
+ """
655
+ Documentation:
656
+ https://api.charmhub.io/docs/model-service-admin.html#read_brand
657
+ Endpoint: [GET] https://api.charmhub.io/v1/brand/{store_id}
658
+ """
488
659
  headers = self._get_publisherwg_authorization_header(session)
489
660
  url = self.get_publisherwg_endpoint_url(f"brand/{store_id}")
490
661
  response = self.session.get(
@@ -496,6 +667,11 @@ class SnapStoreAdmin(SnapPublisher):
496
667
 
497
668
  # FEATURED SNAPS AUTOMATION
498
669
  def delete_featured_snaps(self, session, snaps):
670
+ """
671
+ Documentation: (link to spec)
672
+ https://docs.google.com/document/d/1UAybxuZyErh3ayqb4nzL3T4BbvMtnmKKEPu-ixcCj_8
673
+ Endpoint: [DELETE] https://api.charmhub.io/v1/snap/featured
674
+ """
499
675
  headers = self._get_publisherwg_authorization_header(session)
500
676
  url = self.get_publisherwg_endpoint_url("snap/featured")
501
677
  response = self.session.delete(
@@ -506,6 +682,11 @@ class SnapStoreAdmin(SnapPublisher):
506
682
  return response
507
683
 
508
684
  def update_featured_snaps(self, session, snaps):
685
+ """
686
+ Documentation: (link to spec)
687
+ https://docs.google.com/document/d/1UAybxuZyErh3ayqb4nzL3T4BbvMtnmKKEPu-ixcCj_8
688
+ Endpoint: [PUT] https://api.charmhub.io/v1/snap/featured
689
+ """
509
690
  headers = self._get_publisherwg_authorization_header(session)
510
691
  url = self.get_publisherwg_endpoint_url("snap/featured")
511
692
  response = self.session.put(
@@ -515,15 +696,20 @@ class SnapStoreAdmin(SnapPublisher):
515
696
  )
516
697
  return response
517
698
 
518
- def get_featured_snaps(self, session, api_version=1):
519
- url = "https://api.staging.snapcraft.io/api/v1/snaps/search"
699
+ def get_featured_snaps(self, session, api_version=1, fields="snap_id"):
700
+ """
701
+ Documentation: (link to spec)
702
+ https://docs.google.com/document/d/1UAybxuZyErh3ayqb4nzL3T4BbvMtnmKKEPu-ixcCj_8/edit
703
+ Endpoint: https://api.snapcraft.io/api/v1/snaps/search
704
+ """
705
+ url = f"{SNAPSTORE_API_URL}api/v1/snaps/search"
520
706
  headers = self.config[api_version].get("headers")
521
707
 
522
708
  params = {
523
709
  "scope": "wide",
524
710
  "arch": "wide",
525
711
  "confinement": "strict,classic,devmode",
526
- "fields": "snap_id",
712
+ "fields": fields,
527
713
  "section": "featured",
528
714
  }
529
715
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = 'canonicalwebteam.store-api'
3
- version = '4.11.1'
3
+ version = '4.11.3'
4
4
  description = ''
5
5
  authors = ['Canonical Web Team <webteam@canonical.com>']
6
6
  license = 'LGPL-3.0'