From f8b29e4d1a393e625f56b513165634aab213db3b Mon Sep 17 00:00:00 2001 From: Rey Abolofia Date: Fri, 20 Dec 2024 17:54:55 -0800 Subject: [PATCH 1/3] Provide urllib3 implementation of HTTPClient. --- datadog/api/http_client.py | 61 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/datadog/api/http_client.py b/datadog/api/http_client.py index f058393d9..b55ad9fa4 100644 --- a/datadog/api/http_client.py +++ b/datadog/api/http_client.py @@ -27,6 +27,11 @@ except ImportError: urlfetch, urlfetch_errors = None, None +try: + import urllib3 +except ImportError: + urllib3 = None + # datadog from datadog.api.exceptions import ProxyError, ClientError, HTTPError, HttpTimeout @@ -178,6 +183,58 @@ def raise_on_status(cls, result): raise HTTPError(status_code) +class Urllib3Client(HTTPClient): + """ + HTTP client based on 3rd party `urllib3` module. + """ + + _pool = None + _pool_lock = Lock() + + @classmethod + def request(cls, method, url, headers, params, data, timeout, proxies, verify, max_retries): + """ + Wrapper around `urllib3.PoolManager.request` method. This method will raise + exceptions for HTTP status codes that are not 2xx. + """ + try: + with cls._pool_lock: + if cls._pool is None: + cls._pool = urllib3.PoolManager( + retries=max_retries, + timeout=timeout, + cert_reqs="CERT_REQUIRED" if verify else "CERT_NONE", + ) + + newheaders = copy.deepcopy(headers) + newheaders["User-Agent"] = _get_user_agent_header() + response = cls._pool.request( + method, url, body=data, fields=params, headers=newheaders + ) + cls.raise_on_status(response) + + except urllib3.exceptions.ProxyError as e: + raise _remove_context(ProxyError(method, url, e)) + except urllib3.exceptions.MaxRetryError as e: + raise _remove_context(ClientError(method, url, e)) + except urllib3.exceptions.TimeoutError as e: + raise _remove_context(HttpTimeout(method, url, e)) + except urllib3.exceptions.HTTPError as e: + raise _remove_context(HTTPError(e)) + + return response + + @classmethod + def raise_on_status(cls, response): + """ + Raise on HTTP status code errors. + """ + status_code = response.status + if status_code < 200 or status_code >= 300: + if status_code not in (400, 401, 403, 404, 409, 429): + raise HTTPError(status_code, response.reason) + + def resolve_http_client(): """ Resolve an appropriate HTTP client based the defined priority and user environment. @@ -190,6 +247,10 @@ def resolve_http_client(): log.debug(u"Use `urlfetch` based HTTP client.") return URLFetchClient + if urllib3: + log.debug(u"Use `urllib3` based HTTP client.") + return Urllib3Client + raise ImportError( u"Datadog API client was unable to resolve a HTTP client. " u" Please install `requests` library." ) From 58b93ed4aa3042b859add8702e1fe0118ae87007 Mon Sep 17 00:00:00 2001 From: Kevin Zou Date: Tue, 24 Dec 2024 12:26:17 -0500 Subject: [PATCH 2/3] pin ubuntu version and urllib version --- .github/workflows/test.yml | 2 +- tox.ini | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f86f06175..9364437c7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -47,7 +47,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest] + os: [ubuntu-22.04] python-version: ['pypy2.7', '3.7', 'pypy3.8'] # os: [ubuntu-latest, windows-latest, macos-latest] # python-version: ['2.7', '3.7', '3.8', '3.9', '3.10', 'pypy-2.7', 'pypy-3.8'] diff --git a/tox.ini b/tox.ini index 15301e64b..1099f29f6 100644 --- a/tox.ini +++ b/tox.ini @@ -58,6 +58,7 @@ basepython = python3.8 skip_install = true deps = mypy==0.770 + urllib3==2.2.3 commands = mypy --config-file mypy.ini datadog mypy --config-file mypy.ini --py2 datadog From 3d084acbafd9597e06eee418aea0cba7be57bf78 Mon Sep 17 00:00:00 2001 From: Rey Abolofia Date: Tue, 24 Dec 2024 10:19:51 -0800 Subject: [PATCH 3/3] Fix linting error. --- datadog/api/http_client.py | 2 +- tox.ini | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/datadog/api/http_client.py b/datadog/api/http_client.py index b55ad9fa4..8831aff15 100644 --- a/datadog/api/http_client.py +++ b/datadog/api/http_client.py @@ -28,7 +28,7 @@ urlfetch, urlfetch_errors = None, None try: - import urllib3 + import urllib3 # type: ignore except ImportError: urllib3 = None diff --git a/tox.ini b/tox.ini index 1099f29f6..15301e64b 100644 --- a/tox.ini +++ b/tox.ini @@ -58,7 +58,6 @@ basepython = python3.8 skip_install = true deps = mypy==0.770 - urllib3==2.2.3 commands = mypy --config-file mypy.ini datadog mypy --config-file mypy.ini --py2 datadog