Skip to content

Commit cf0821c

Browse files
implement bookmark methods in Transfer v2 client
Added the following methods to the experimental TransferClientV2: * create_bookmark() * update_bookmark() * get_bookmark() * delete_bookmark() * list_bookmarks() This provides access to the new Transfer v2 API operations for boomkark management, which includes support for high assurance collections. Functional unit tests are provided for all methods.
1 parent f8a4a27 commit cf0821c

16 files changed

Lines changed: 599 additions & 4 deletions
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Added
2+
-----
3+
4+
- Support for managing bookmarks via the Transfer v2 client (:pr:`NUMBER`)

src/globus_sdk/experimental/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import typing as t
44

55
__all__ = (
6+
"BookmarkCreateDocument",
7+
"BookmarkUpdateDocument",
68
"TransferClientV2",
79
"TunnelCreateDocument",
810
"TunnelUpdateDocument",
@@ -14,13 +16,17 @@
1416
# components which do not need it
1517
if t.TYPE_CHECKING:
1618
from .transfer_v2 import (
19+
BookmarkCreateDocument,
20+
BookmarkUpdateDocument,
1721
TransferClientV2,
1822
TunnelCreateDocument,
1923
TunnelUpdateDocument,
2024
)
2125
else:
2226
_LAZY_IMPORT_TABLE = {
2327
"transfer_v2": {
28+
"BookmarkCreateDocument",
29+
"BookmarkUpdateDocument",
2430
"TransferClientV2",
2531
"TunnelCreateDocument",
2632
"TunnelUpdateDocument",

src/globus_sdk/experimental/transfer_v2/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
from .client import TransferClientV2
2-
from .data import TunnelCreateDocument, TunnelUpdateDocument
2+
from .data import (
3+
BookmarkCreateDocument,
4+
BookmarkUpdateDocument,
5+
TunnelCreateDocument,
6+
TunnelUpdateDocument,
7+
)
38

49
__all__ = (
10+
"BookmarkCreateDocument",
11+
"BookmarkUpdateDocument",
512
"TransferClientV2",
613
"TunnelCreateDocument",
714
"TunnelUpdateDocument",

src/globus_sdk/experimental/transfer_v2/client.py

Lines changed: 144 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010
from globus_sdk.services.transfer.errors import TransferAPIError
1111
from globus_sdk.transport import RetryConfig
1212

13-
from .data import TunnelCreateDocument, TunnelUpdateDocument
13+
from .data import (
14+
BookmarkCreateDocument,
15+
BookmarkUpdateDocument,
16+
TunnelCreateDocument,
17+
TunnelUpdateDocument,
18+
)
1419
from .transport import TRANSFER_V2_DEFAULT_RETRY_CHECKS
1520

1621
log = logging.getLogger(__name__)
@@ -131,7 +136,7 @@ def get_tunnel(
131136
.. code-block:: python
132137
133138
tc = globus_sdk.experimental.TrasferClientV2(...)
134-
result = tc.show_tunnel(tunnel_id)
139+
result = tc.get_tunnel(tunnel_id)
135140
print(result["data"])
136141
137142
.. tab-item:: API Info
@@ -290,3 +295,140 @@ def list_stream_access_points(
290295
log.debug(f"TransferClientV2.list_stream_access_points({query_params})")
291296
r = self.get("/v2/stream_access_points", query_params=query_params)
292297
return IterableJSONAPIResponse(r)
298+
299+
def create_bookmark(
300+
self, data: dict[str, t.Any] | BookmarkCreateDocument
301+
) -> response.GlobusHTTPResponse:
302+
"""
303+
:param data: Parameters for bookmark creation
304+
305+
.. tab-set::
306+
307+
.. tab-item:: Example Usage
308+
309+
.. code-block:: python
310+
311+
tc = globus_sdk.experimental.TrasferClientV2(...)
312+
data = globus_sdk.experimental.BookmarkCreateDocument(...)
313+
result = tc.create_bookmark(data)
314+
print(result["data"]["id"])
315+
316+
.. tab-item:: API Info
317+
318+
``POST /v2/bookmarks``
319+
"""
320+
log.debug("TransferClientV2.create_bookmark(...)")
321+
r = self.post("/v2/bookmarks", data=data)
322+
return r
323+
324+
def update_bookmark(
325+
self,
326+
bookmark_id: uuid.UUID | str,
327+
update_document: dict[str, t.Any] | BookmarkUpdateDocument,
328+
) -> response.GlobusHTTPResponse:
329+
r"""
330+
:param bookmark_id: The ID of the Bookmark.
331+
:param update_document: The document that will be sent to the patch API.
332+
333+
.. tab-set::
334+
335+
.. tab-item:: Example Usage
336+
337+
.. code-block:: python
338+
339+
tc = globus_sdk.experimental.TrasferClientV2(...)
340+
data = globus_sdk.experimental.BookmarkUpdateDocument(...)
341+
result = tc.update_bookmark(bookmark_id, data)
342+
print(result["data"])
343+
344+
.. tab-item:: API Info
345+
346+
``PATCH /v2/bookmarks/<bookmark_id>``
347+
"""
348+
log.debug(f"TransferClientV2.update_bookmark({bookmark_id}, {update_document})")
349+
r = self.patch(f"/v2/bookmarks/{bookmark_id}", data=update_document)
350+
return r
351+
352+
def get_bookmark(
353+
self,
354+
bookmark_id: uuid.UUID | str,
355+
*,
356+
query_params: dict[str, t.Any] | None = None,
357+
) -> response.GlobusHTTPResponse:
358+
"""
359+
:param bookmark_id: The ID of the Bookmark for which we are fetching details.
360+
:param query_params: Any additional parameters will be passed through
361+
as request parameters on the URL.
362+
363+
.. tab-set::
364+
365+
.. tab-item:: Example Usage
366+
367+
.. code-block:: python
368+
369+
tc = globus_sdk.experimental.TrasferClientV2(...)
370+
query_params = {"include": "collection"}
371+
result = tc.get_bookmark(bookmark_id, query_params)
372+
print(result["data"])
373+
374+
.. tab-item:: API Info
375+
376+
``GET /v2/bookmarks/<bookmark_id>``
377+
"""
378+
log.debug(f"TransferClientV2.get_bookmark({bookmark_id}, {query_params})")
379+
r = self.get(f"/v2/bookmarks/{bookmark_id}", query_params=query_params)
380+
return r
381+
382+
def delete_bookmark(
383+
self,
384+
bookmark_id: uuid.UUID | str,
385+
) -> response.GlobusHTTPResponse:
386+
"""
387+
:param bookmark_id: The ID of the Bookmark to be deleted.
388+
389+
.. tab-set::
390+
391+
.. tab-item:: Example Usage
392+
393+
.. code-block:: python
394+
395+
tc = globus_sdk.experimental.TrasferClientV2(...)
396+
tc.delete_bookmark(bookmark_id)
397+
398+
.. tab-item:: API Info
399+
400+
``DELETE /v2/bookmarks/<bookmark_id>``
401+
"""
402+
log.debug(f"TransferClientV2.delete_bookmark({bookmark_id})")
403+
r = self.delete(f"/v2/bookmarks/{bookmark_id}")
404+
return r
405+
406+
def list_bookmarks(
407+
self,
408+
*,
409+
query_params: dict[str, t.Any] | None = None,
410+
) -> IterableJSONAPIResponse:
411+
"""
412+
:param query_params: Any additional parameters will be passed through
413+
as request parameters on the URL.
414+
415+
This will list all Bookmarks created by the authenticated user's primary
416+
and linked identities.
417+
418+
.. tab-set::
419+
420+
.. tab-item:: Example Usage
421+
422+
.. code-block:: python
423+
424+
tc = globus_sdk.experimental.TrasferClientV2(...)
425+
query_params = {"include": "collection"}
426+
tc.list_bookmarks(query_params)
427+
428+
.. tab-item:: API Info
429+
430+
``GET /v2/bookmarks``
431+
"""
432+
log.debug("TransferClientV2.list_bookmarks({query_params})")
433+
r = self.get("/v2/bookmarks", query_params=query_params)
434+
return IterableJSONAPIResponse(r)

src/globus_sdk/experimental/transfer_v2/data/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44
:class:`TransferClient <globus_sdk.TransferClient>` methods without conversion.
55
"""
66

7+
from .bookmark_documents import BookmarkCreateDocument, BookmarkUpdateDocument
78
from .tunnel_documents import TunnelCreateDocument, TunnelUpdateDocument
89

9-
__all__ = ("TunnelCreateDocument", "TunnelUpdateDocument")
10+
__all__ = (
11+
"BookmarkCreateDocument",
12+
"BookmarkUpdateDocument",
13+
"TunnelCreateDocument",
14+
"TunnelUpdateDocument",
15+
)
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
from __future__ import annotations
2+
3+
import logging
4+
import typing as t
5+
import uuid
6+
7+
from globus_sdk._missing import MISSING, MissingType
8+
from globus_sdk._payload import GlobusPayload
9+
10+
log = logging.getLogger(__name__)
11+
12+
13+
class BookmarkCreateDocument(GlobusPayload):
14+
"""
15+
Convenience class for constructing a bookmark document to use as the
16+
``data`` parameter to
17+
:meth:`create_bookmark <globus_sdk.TransferClientV2.create_bookmark>`.
18+
"""
19+
20+
def __init__(
21+
self,
22+
collection: uuid.UUID | str,
23+
name: str,
24+
path: str,
25+
*,
26+
pinned: bool | MissingType = MISSING,
27+
additional_fields: dict[str, t.Any] | None = None,
28+
) -> None:
29+
super().__init__()
30+
log.debug("Creating a new BookmarkCreateDocument object")
31+
32+
relationships = {
33+
"collection": {
34+
"data": {
35+
"type": "Collection",
36+
"id": collection,
37+
}
38+
}
39+
}
40+
41+
attributes = {
42+
"name": name,
43+
"path": path,
44+
"pinned": pinned,
45+
}
46+
47+
if additional_fields is not None:
48+
attributes.update(additional_fields)
49+
50+
self["data"] = {
51+
"type": "Bookmark",
52+
"attributes": attributes,
53+
"relationships": relationships,
54+
}
55+
56+
57+
class BookmarkUpdateDocument(GlobusPayload):
58+
"""
59+
Convenience class for constructing a bookmark document to use as the
60+
``data`` parameter to
61+
:meth:`update_bookmark <globus_sdk.TransferClientV2.update_bookmark>`.
62+
"""
63+
64+
def __init__(
65+
self,
66+
name: str,
67+
path: str,
68+
*,
69+
pinned: bool | MissingType = MISSING,
70+
additional_fields: dict[str, t.Any] | None = None,
71+
) -> None:
72+
super().__init__()
73+
log.debug("Creating a new BookmarkUpdateDocument")
74+
75+
attributes = {
76+
"name": name,
77+
"path": path,
78+
"pinned": pinned,
79+
}
80+
81+
if additional_fields is not None:
82+
attributes.update(additional_fields)
83+
84+
self["data"] = {
85+
"type": "Bookmark",
86+
"attributes": attributes,
87+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import uuid
2+
3+
from globus_sdk.testing.models import RegisteredResponse, ResponseSet
4+
5+
BOOKMARK_ID = str(uuid.uuid4())
6+
7+
_collection_id = str(uuid.uuid4())
8+
_name = "public datasets"
9+
_path = "/data_repository/public"
10+
11+
12+
RESPONSES = ResponseSet(
13+
default=RegisteredResponse(
14+
service="transfer",
15+
method="POST",
16+
path="/v2/bookmarks",
17+
status=201,
18+
json={
19+
"meta": {"request_id": "nDZoeEMPI"},
20+
"data": {
21+
"type": "Bookmark",
22+
"id": BOOKMARK_ID,
23+
"attributes": {
24+
"name": _name,
25+
"path": _path,
26+
"pinned": False,
27+
},
28+
"relationships": {
29+
"collection": {
30+
"data": {
31+
"type": "Collection",
32+
"id": _collection_id,
33+
}
34+
}
35+
},
36+
},
37+
},
38+
metadata={
39+
"bookmark_id": BOOKMARK_ID,
40+
"collection": _collection_id,
41+
"name": _name,
42+
"path": _path,
43+
},
44+
)
45+
)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import uuid
2+
3+
from globus_sdk.testing.models import RegisteredResponse, ResponseSet
4+
5+
BOOKMARK_ID = str(uuid.uuid4())
6+
7+
8+
RESPONSES = ResponseSet(
9+
default=RegisteredResponse(
10+
service="transfer",
11+
method="DELETE",
12+
path=f"/v2/bookmarks/{BOOKMARK_ID}",
13+
status=200,
14+
json={"meta": {"request_id": "nH45vUMpD"}},
15+
metadata={
16+
"bookmark_id": BOOKMARK_ID,
17+
},
18+
)
19+
)

0 commit comments

Comments
 (0)