Skip to content

Commit

Permalink
Devex: Update dependencies for v3.0.0 (#12402)
Browse files Browse the repository at this point in the history
GitOrigin-RevId: a103f20662c5911984f88a77c7056b2ced4128c5
  • Loading branch information
stephencpope authored and Descartes Labs Build committed Jan 22, 2024
1 parent acd67bc commit e51d8dc
Show file tree
Hide file tree
Showing 10 changed files with 28 additions and 131 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/public-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.8', '3.9', '3.10', '3.11']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ Changelog
- *Breaking Change*: The deprecated `Metadata` client API has been removed.
- The minimum required version of `urllib3` has been bumped to 1.26.18 to address a security vulnerability.
- The minimum required version of `shapely` has been bumped to 2.0.0 to address thread safety issues.
- Python 3.7, formerly deprecated, is no longer supported.
- Python 3.12 is now supported.
- Urllib3 2.X is now supported.

## [2.1.2] - 2023-10-31

Expand Down
21 changes: 1 addition & 20 deletions descarteslabs/core/catalog/tests/test_image_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import warnings
import responses
from unittest.mock import patch

Expand Down Expand Up @@ -425,20 +424,6 @@ def test_wait_for_completion(self):
"jsonapi": {"version": "1.0"},
},
)
self.mock_response(
responses.GET,
{
"errors": [
{
"detail": "Something went wrong",
"status": "500",
"title": "Server Error",
}
],
"jsonapi": {"version": "1.0"},
},
status=500,
)

self.mock_response(
responses.GET,
Expand Down Expand Up @@ -490,11 +475,7 @@ def test_wait_for_completion(self):
assert u.status == ImageUploadStatus.PENDING
assert u.state == DocumentState.SAVED

with warnings.catch_warnings(record=True) as w:
u.wait_for_completion(15)

assert len(w) == 1
assert "Something went wrong" in str(w[0].message)
u.wait_for_completion(15)

assert u.status == ImageUploadStatus.SUCCESS
assert len(u.events) == 3
Expand Down
14 changes: 4 additions & 10 deletions descarteslabs/core/catalog/tests/test_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,16 +376,10 @@ def test_no_objects_to_delete(self):
p = Product(id="p1", name="Test Product", client=self.client)
self.mock_response(
responses.POST,
{
"errors": [
{
"status": "204",
"detail": "A 'delete related objects' operation is not needed: p1",
"title": "No related objects found",
}
],
"jsonapi": {"version": "1.0"},
},
# For some reason, responses doesn't like returning a 204 with a body
# (it forcibly sets a content-length of 0, which then blows up requests/urllib3)
# The body returned by the actual service doesn't matter for this test.
None,
status=204,
)
r = p.delete_related_objects()
Expand Down
10 changes: 2 additions & 8 deletions descarteslabs/core/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,13 @@
import sys
import warnings

if sys.version_info < (3, 7):
if sys.version_info < (3, 8):
msg = "Python version {}.{} not supported by the descarteslabs client".format(
sys.version_info.major, sys.version_info.minor
)
raise ImportError(msg)

if sys.version_info < (3, 8):
msg = "Support for Python version {}.{} has been deprecated and will be removed in a future version.".format(
sys.version_info.major, sys.version_info.minor
)
warnings.warn(msg, FutureWarning)

if sys.version_info >= (3, 12):
if sys.version_info >= (3, 13):
msg = "Python version {}.{} is not supported yet. You may encounter unexpected errors.".format(
sys.version_info.major, sys.version_info.minor
)
Expand Down
28 changes: 6 additions & 22 deletions descarteslabs/core/common/http/retry.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@


class Retry(Urllib3Retry):
"""Retry configuration that extends `urllib3.util.retry` to support retry-after.
"""Retry configuration that allows configuration of retry-after support.
This retry configuration class derives from
`urllib3.util.retry.Retry
Expand All @@ -27,12 +27,12 @@ class Retry(Urllib3Retry):
retry_after_status_codes : list
The http status codes that should support the
`Retry-After <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After>`_
header.
header. This is in lieu of the hardwired urllib3 Retry.RETRY_AFTER_STATUS_CODES.
"""

DEFAULT_RETRY_AFTER_STATUS_CODES = frozenset([403, 413, 429, 503])

def __init__(self, retry_after_status_codes=None, *args, **kwargs):
def __init__(self, *args, retry_after_status_codes=None, **kwargs):
super().__init__(*args, **kwargs)

if retry_after_status_codes is None:
Expand All @@ -41,22 +41,6 @@ def __init__(self, retry_after_status_codes=None, *args, **kwargs):
if not isinstance(retry_after_status_codes, frozenset):
retry_after_status_codes = frozenset(retry_after_status_codes)

self.retry_after_status_codes = retry_after_status_codes

def is_retry(self, method, status_code, has_retry_after=True):
if not self._is_method_retryable(method):
return False

if self.status_forcelist and status_code in self.status_forcelist:
return True

return (
self.total
and self.respect_retry_after_header
and has_retry_after
and (status_code in self.retry_after_status_codes)
)

@classmethod
def parse_retry_after_header(cls, retry_after):
return Retry.parse_retry_after(cls, retry_after)
# Overrides the urllib3.util.retry.Retry.RETRY_AFTER_STATUS_CODES
# class variable.
self.RETRY_AFTER_STATUS_CODES = retry_after_status_codes
69 changes: 3 additions & 66 deletions descarteslabs/core/common/http/tests/test_retry.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,89 +13,26 @@
# limitations under the License.

import unittest
from http import HTTPStatus
from http.client import HTTPMessage
from unittest import mock

from requests import Session
from requests.adapters import HTTPAdapter

from ..retry import Retry


def mock_response(status, headers=None):
if headers is None:
headers = dict()

msg = HTTPMessage()

for key, value in headers.items():
msg.add_header(key, value)

return mock.Mock(status=status, msg=msg)


# unfortunately we cannot use responses here
# it does not support retries properly until 0.22.0
@mock.patch("urllib3.connectionpool.HTTPConnectionPool._put_conn")
@mock.patch("urllib3.connectionpool.HTTPConnectionPool._get_conn")
class TestRetry(unittest.TestCase):
url = "https://example.com/some-service"

def setUp(self):
adapter = HTTPAdapter(max_retries=Retry(total=3))
client = Session()
client.mount("http://", adapter)
client.mount("https://", adapter)

self.client = client

def test_retry_sets_status_codes(self, *mocks):
retry = Retry()
assert retry.retry_after_status_codes == Retry.DEFAULT_RETRY_AFTER_STATUS_CODES
assert retry.RETRY_AFTER_STATUS_CODES == Retry.DEFAULT_RETRY_AFTER_STATUS_CODES

for code in Retry.DEFAULT_RETRY_AFTER_STATUS_CODES:
assert retry.is_retry("GET", code, has_retry_after=True) is True
assert retry.is_retry("GET", code, has_retry_after=False) is False

retry = Retry(retry_after_status_codes=[])
assert retry.retry_after_status_codes == frozenset([])
assert retry.RETRY_AFTER_STATUS_CODES == frozenset([])
assert retry.is_retry("GET", 403, has_retry_after=True) is False
assert retry.is_retry("GET", 403, has_retry_after=False) is False

retry = Retry(retry_after_status_codes=[400])
assert retry.retry_after_status_codes == frozenset([400])
assert retry.RETRY_AFTER_STATUS_CODES == frozenset([400])
assert retry.is_retry("GET", 403, has_retry_after=True) is False
assert retry.is_retry("GET", 400, has_retry_after=True) is True
assert retry.is_retry("GET", 400, has_retry_after=False) is False

def test_retry_after_not_present(self, mock_conn, *mocks):
mock_conn.return_value.getresponse.side_effect = [
mock_response(status=HTTPStatus.FORBIDDEN)
]

r = self.client.get(self.url)
assert r.status_code == HTTPStatus.FORBIDDEN
assert mock_conn.call_count == 1

def test_retry_after_wrong_status(self, mock_conn, *mocks):
mock_conn.return_value.getresponse.side_effect = [
mock_response(
status=HTTPStatus.INTERNAL_SERVER_ERROR,
headers={"Retry-After": "1"},
)
]

r = self.client.get(self.url)
assert r.status_code == HTTPStatus.INTERNAL_SERVER_ERROR
assert mock_conn.call_count == 1

def test_retry_after(self, mock_conn, *mocks):
mock_conn.return_value.getresponse.side_effect = [
mock_response(status=HTTPStatus.FORBIDDEN, headers={"Retry-After": "1"}),
mock_response(status=HTTPStatus.OK),
]

r = self.client.get(self.url)
assert r.status_code == HTTPStatus.OK
assert mock_conn.call_count == 2
4 changes: 4 additions & 0 deletions descarteslabs/core/common/threading/tests/test_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@

import multiprocessing
import os
import platform
import sys
import unittest
import threading

from ..local import ThreadLocalWrapper

if platform.system() == "Darwin":
multiprocessing.set_start_method("fork")


class ThreadLocalWrapperTest(unittest.TestCase):
def setUp(self):
Expand Down
2 changes: 1 addition & 1 deletion descarteslabs/core/compute/tests/test_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,7 @@ def request_callback(request: PreparedRequest):
call_count += 1

if call_count > 1:
return (500, {}, None)
return (400, {}, None)

payload: dict = json.loads(request.body)
jobs = []
Expand Down
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ def do_setup():
classifiers=[
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
],
license="Apache 2.0",
download_url=(
Expand All @@ -91,7 +91,7 @@ def do_setup():
"descarteslabs = descarteslabs.core.client.scripts.__main__:main"
]
},
python_requires="~=3.7",
python_requires="~=3.8",
install_requires=[
"affine>=2.2.2",
"blosc>=1.10.6",
Expand All @@ -115,7 +115,7 @@ def do_setup():
"tifffile==2023.4.12;python_version=='3.8'",
"tifffile>=2023.9.26;python_version>='3.9'",
"tqdm>=4.32.1",
"urllib3>=1.26.18,<2",
"urllib3>=1.26.18",
],
extras_require={
"visualization": viz_requires,
Expand Down

0 comments on commit e51d8dc

Please sign in to comment.