1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
|
.. _upgrading:
Upgrading
=========
This guide covers upgrading and migration between Globus SDK versions.
It is meant to help explain and resolve incompatibilities and breaking
changes, and does not cover all new features.
When upgrading, you should also read the relevant section of the
:ref:`changelog`.
The changelog can also be a source of information about new features
between major releases.
Many explanations are written in terms of ``TransferClient`` for consistency,
but apply to all client classes, including ``AuthClient``,
``NativeAppAuthClient``, ``ConfidentialAppAuthClient``, ``SearchClient``, and
``GroupsClient``.
Version Parsing
---------------
In the event that a codebase must support multiple versions of
the globus-sdk at the same time, consider adding this snippet:
.. code-block:: python
import globus_sdk
GLOBUS_SDK_VERSION = tuple(globus_sdk.__version__.split("."))
GLOBUS_SDK_MAJOR_VERSION = int(GLOBUS_SDK_VERSION[0])
This will parse the Globus SDK version information into a tuple and grab the
first element (the major version number) as an integer.
Then, code can dispatch with
.. code-block:: python
if GLOBUS_SDK_MAJOR_VERSION < 3:
pass # do one thing
else:
pass # do another
From 1.x or 2.x to 3.0
-----------------------
The :ref:`v3 changelog <changelog_version3>` covers the full list of changes
made in version 3 of the Globus SDK.
Because version 2 did not introduce any changes to the SDK code other than
supported python versions, you may also want to view this section when
upgrading from version 1.
Type Annotations
~~~~~~~~~~~~~~~~
The Globus SDK now provides PEP 561 type annotation data.
This means that codebases which use ``mypy`` or similar tools to check type
annotations may see new warnings or errors when using version 3 of the SDK.
.. note::
If you believe an annotation in the SDK is incorrect, please visit our
`issue tracker <https://github.com/globus/globus-sdk-python/issues>`_ to
file a bug report!
Automatic Retries
~~~~~~~~~~~~~~~~~
Globus SDK client methods now automatically retry failing requests when
encountering network errors and certain classes of server errors (e.g. rate
limiting).
For most users, retry logic can be removed.
Change:
.. code-block:: python
import globus_sdk
# globus-sdk v1 or v2
tc = globus_sdk.TransferClient(...)
response = None
count, max_retries = 0, 10
while response is None and count < max_retries:
count += 1
try: # any operation, just an example
response = tc.get_endpoint(foo)
except globus_sdk.NetworkError:
pass
# globus-sdk v3
tc = globus_sdk.TransferClient(...)
response = tc.get_endpoint(foo) # again, just an example operation
Updates to BaseClient Usage
~~~~~~~~~~~~~~~~~~~~~~~~~~~
You may be using the globus-sdk ``BaseClient`` object to implement a custom
client or for type annotations. Firstly, ``BaseClient`` is available from the
base ``globus_sdk`` namespace.
Change:
.. code-block:: python
# globus-sdk v1 or v2
from globus_sdk.base import BaseClient
# globus-sdk v3
from globus_sdk import BaseClient
Secondly, creating a ``BaseClient`` is different. Previously, initializing a
``BaseClient`` had one required positional argument ``service``. Now, this
exists as a class attribute, which subclasses can overwrite.
Change:
.. code-block:: python
# globus-sdk v1 or v2
class MyClient(BaseClient):
pass
MyClient("my-service", **kwargs)
# globus-sdk v3
class MyClient(BaseClient):
service_name = "my-service"
MyClient(**kwargs)
Import exceptions from globus_sdk
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Several exceptions which were available in v2 under ``globus_sdk.exc`` are now
only available from the ``globus_sdk`` namespace.
Change:
.. code-block:: python
# globus-sdk v1 or v2
from globus_sdk.exc import SearchAPIError, TransferAPIError, AuthAPIError
# globus-sdk v3
from globus_sdk import SearchAPIError, TransferAPIError, AuthAPIError
Note that this also may appear in your exception handling, as in:
.. code-block:: python
# globus-sdk v1 or v2
from globus_sdk import exc
try:
...
except exc.TransferAPIError: # by way of example, any error here
...
# globus-sdk v3
import globus_sdk
try:
...
except globus_sdk.TransferAPIError:
...
Low Level API for Passing Data is Improved
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In version 2 of the SDK, passing data to client ``post()``, ``put()``, and
``patch()`` methods required the use of either ``json_body`` or ``text_body``.
Furthermore, ``text_body`` would (confusingly!) send a FORM body if it were
passed a dictionary.
Now, these behaviors are described by ``data`` (a body for these HTTP methods)
and ``encoding`` (an explicit data format parameter). If the ``encoding`` is
not set, the default behavior is that if ``data`` is a dictionary, it will be
sent as JSON. If ``data`` is a string, it will be sent as text.
``encoding`` can be set to ``"json"`` or ``"form"`` to explicitly format the
data.
Change code for a JSON PUT like so:
.. code-block:: python
# globus-sdk v1 or v2
from globus_sdk import TransferClient
tc = TransferClient(...)
tc.put("/some/custom/path", json_body={"a": "dict", "of": "data"})
# globus-sdk v3
from globus_sdk import TransferClient
tc = TransferClient(...)
tc.put("/some/custom/path", data={"a": "dict", "of": "data"})
Or a FORM POST like so:
.. code-block:: python
# globus-sdk v1 or v2
from globus_sdk import TransferClient
tc = TransferClient(...)
tc.post("/some/custom/path", text_body={"a": "dict", "of": "data"})
# globus-sdk v3
from globus_sdk import TransferClient
tc = TransferClient(...)
tc.put("/some/custom/path", data={"a": "dict", "of": "data"}, encoding="form")
Passthrough Parameters are Explicit
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Many methods in version 2 accepted arbitrary keyword arguments which were then
transformed into query or body parameters based on the context. This is no
longer allowed, but methods can still be passed additional query parameters in the
form of a ``query_params`` dict.
For example, if the Transfer API is known to support a query param ``foo=bar``
for ``GET Endpoint``, but the SDK does not include this parameter, the way that
it can be added to a request has changed as follows:
.. code-block:: python
# globus-sdk v1 or v2
from globus_sdk import TransferClient
tc = TransferClient(...)
tc.get_endpoint(epid, foo="bar")
# globus-sdk v3
from globus_sdk import TransferClient
tc = TransferClient(...)
tc.get_endpoint(epid, query_params={"foo": "bar"})
.. note::
If a parameter which you need is not supported by the Globus SDK, use
``query_params`` to work around it! But also, feel free to visit our
`issue tracker <https://github.com/globus/globus-sdk-python/issues>`_ to
request an improvement.
Responses are always GlobusHTTPResponse
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In version 2, ``GlobusHTTPResponse`` inherited from a base class,
``GlobusResponse``. In version 3, the distinction has been eliminated and
responses are only ``GlobusHTTPResponse``.
This may appear in contexts where you type annotate or use ``isinstance`` checks
to check the type of an object.
Change:
.. code-block:: python
# globus-sdk v1 or v2
from globus_sdk.response import GlobusResponse
data = some_complex_func()
if isinstance(data, GlobusResponse):
...
# globus-sdk v3
from globus_sdk import GlobusHTTPResponse
data = some_complex_func()
if isinstance(data, GlobusHTTPResponse):
...
Pagination is now explicit
~~~~~~~~~~~~~~~~~~~~~~~~~~
In version 2, paginated methods of ``TransferClient`` returned a
``PaginatedResource`` iterable type.
In version 3, no methods return paginators by default, and pagination is always
opt-in. See also :ref:`doc on making paginated calls <making_paginated_calls>`.
Change:
.. code-block:: python
# globus-sdk v1 or v2
from globus_sdk import TransferClient
tc = TransferClient(...)
for endpoint_info in tc.endpoint_search("query"):
...
# globus-sdk v3
from globus_sdk import TransferClient
tc = TransferClient(...)
for endpoint_info in tc.paginated.endpoint_search("query").items():
...
Authorizer Methods
~~~~~~~~~~~~~~~~~~
``GlobusAuthorizer`` objects have had their methods modified.
In particular, in version 2, authorizers have a method
``set_authorization_header`` for modifying a dict.
This has been replaced in version 3 with a method ``get_authorization_header``
which returns an ``Authorization`` header value.
Configuration has Changed
~~~~~~~~~~~~~~~~~~~~~~~~~
The Globus SDK no longer reads configuration data from ``/etc/globus.cfg`` or
``~/.globus.cfg``.
If you are using these files to customize the behavior of the SDK, see
:ref:`the configuration documentation <config>`.
Internal Changes to components including Config
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Several modules and components which are considered mostly or entirely internal
have been reorganized.
In particular, if you are using undocumented methods from
``globus_sdk.config``, note that this has been largely rewritten.
(These are not considered public APIs.)
From 1.x to 2.0
---------------
Also see the :ref:`v2 changelog <changelog_version2>`.
When upgrading from version 1 to version 2 of the Globus SDK, no code changes
should be necessary.
Version 2 removed support for python2 but made no other changes.
Simply ensure that you are running python 3.6 or later and update version
specifications to ``globus_sdk>=2,<3``.
|