From 056a5313121648cba899b020fbf1a6058634f04c Mon Sep 17 00:00:00 2001 From: Aleksei Maslakov Date: Tue, 10 Mar 2020 12:00:21 +0300 Subject: [PATCH 1/4] Use certifi as default CA bundle for aiohttp driver --- docs/drivers.rst | 4 ++-- pyproject.toml | 3 ++- src/apiwrappers/drivers/aiohttp.py | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/drivers.rst b/docs/drivers.rst index c1979da..ab125a1 100644 --- a/docs/drivers.rst +++ b/docs/drivers.rst @@ -93,8 +93,8 @@ SSL Verification ================ You can enable/disable SSL verification or provide custom SSL certs -when creating a driver. Note that default trusted CAs depends on a -driver you're using. +upon driver instantiation. Default CA bundle provided by +`certifi `_ library. By default SSL verification is enabled. diff --git a/pyproject.toml b/pyproject.toml index 5db00e3..169b740 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,7 @@ classifiers = [ [tool.poetry.dependencies] python = "^3.7" aiohttp = {version = "^3.6.2", optional = true} +certifi = {version = ">= 2017.4.17", optional = true} requests = {version = "^2.22.0", optional = true} typing-extensions = {version = "^3.7.4", python = "~3.7"} @@ -29,7 +30,7 @@ typing-extensions = {version = "^3.7.4", python = "~3.7"} tox = "^3.14.3" [tool.poetry.extras] -aiohttp = ["aiohttp"] +aiohttp = ["aiohttp", "certifi"] requests = ["requests"] [build-system] diff --git a/src/apiwrappers/drivers/aiohttp.py b/src/apiwrappers/drivers/aiohttp.py index 8891aeb..5fed665 100644 --- a/src/apiwrappers/drivers/aiohttp.py +++ b/src/apiwrappers/drivers/aiohttp.py @@ -7,6 +7,7 @@ from typing import Iterable, List, Optional, Tuple, Type, Union, cast import aiohttp +import certifi from aiohttp import FormData from apiwrappers import exceptions @@ -127,7 +128,7 @@ def _prepare_data(request: Request) -> Optional[Union[Data, FormData]]: def _prepare_ssl(self) -> SSLContext: if self.verify is True: - context = ssl.create_default_context() + context = ssl.create_default_context(cafile=certifi.where()) elif self.verify is False: context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) else: From c2ab7364d295e618ab1aebdf1ee81e7d3e8a9b3c Mon Sep 17 00:00:00 2001 From: Aleksei Maslakov Date: Tue, 10 Mar 2020 12:03:04 +0300 Subject: [PATCH 2/4] Use quotes for 'pip install' because of the zsh --- README.rst | 5 ++--- docs/index.rst | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index 52a1ff2..2611226 100644 --- a/README.rst +++ b/README.rst @@ -58,10 +58,9 @@ Installation .. code-block:: bash - pip install apiwrappers[requests,aiohttp] + pip install 'apiwrappers[aiohttp,requests]' -*Note: extras are optional and mainly needed for the final -user of your future API wrapper* +*Note: extras are mainly needed for the final user of your API client* QuickStart ========== diff --git a/docs/index.rst b/docs/index.rst index 5e4e927..dfc13f9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -29,10 +29,9 @@ Installation .. code-block:: bash - pip install apiwrappers[requests,aiohttp] + pip install 'apiwrappers[aiohttp,requests]' -*Note: extras are optional and mainly needed for the final -user of your future API wrapper* +*Note: extras are mainly needed for the final user of your API client* Getting Started =============== From 7f6cb8cf3064be042de63aa2c99edc6b42676d8d Mon Sep 17 00:00:00 2001 From: Aleksei Maslakov Date: Tue, 10 Mar 2020 12:20:09 +0300 Subject: [PATCH 3/4] Rewrite auth flow test --- tests/test_drivers/httpbin_client.py | 8 ++++---- tests/test_drivers/httpbin_client.pyi | 6 ++++-- tests/test_drivers/test_aiohttp.py | 9 +++++---- tests/test_drivers/test_requests.py | 9 +++++---- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/tests/test_drivers/httpbin_client.py b/tests/test_drivers/httpbin_client.py index 2b1aee6..49060c2 100644 --- a/tests/test_drivers/httpbin_client.py +++ b/tests/test_drivers/httpbin_client.py @@ -63,12 +63,12 @@ def bearer_auth(self, token): request = Request(Method.GET, self.url("/bearer"), auth=TokenAuth(token)) return self.driver.fetch(request) - def complex_auth_flow(self): - """Gets a UUID4 and uses it for bearer authentication.""" + def complex_auth_flow(self, token: str): + """Echoes passed token and uses it for bearer authentication.""" def auth_flow(): - response = yield Request(Method.GET, self.url("/uuid")) - return TokenAuth(response.json()["uuid"])() + response = yield Request(Method.POST, self.url("/anything"), data=token) + return TokenAuth(response.json()["data"])() request = Request(Method.GET, self.url("/bearer"), auth=auth_flow) return self.driver.fetch(request) diff --git a/tests/test_drivers/httpbin_client.pyi b/tests/test_drivers/httpbin_client.pyi index f4a0582..6736416 100644 --- a/tests/test_drivers/httpbin_client.pyi +++ b/tests/test_drivers/httpbin_client.pyi @@ -82,6 +82,8 @@ class HttpBin(Generic[T]): @overload def bearer_auth(self: HttpBin[AsyncDriver], token: str) -> Awaitable[Response]: ... @overload - def complex_auth_flow(self: HttpBin[Driver]) -> Response: ... + def complex_auth_flow(self: HttpBin[Driver], token: str) -> Response: ... @overload - def complex_auth_flow(self: HttpBin[AsyncDriver]) -> Awaitable[Response]: ... + def complex_auth_flow( + self: HttpBin[AsyncDriver], token: str + ) -> Awaitable[Response]: ... diff --git a/tests/test_drivers/test_aiohttp.py b/tests/test_drivers/test_aiohttp.py index 5c9a1f1..d8e113e 100644 --- a/tests/test_drivers/test_aiohttp.py +++ b/tests/test_drivers/test_aiohttp.py @@ -4,7 +4,6 @@ import json import ssl -import uuid from http.cookies import SimpleCookie from pathlib import Path from typing import TYPE_CHECKING, Type @@ -350,6 +349,8 @@ async def test_token_auth(httpbin) -> None: async def test_complex_auth_flow(httpbin) -> None: client = HttpBin(httpbin.url, driver=aiohttp_driver()) - response = await client.complex_auth_flow() - assert response.json()["authenticated"] is True # type: ignore - assert uuid.UUID(response.json()["token"]) # type: ignore + response = await client.complex_auth_flow("vF9dft4qmT") + assert response.json() == { # type: ignore + "authenticated": True, + "token": "vF9dft4qmT", + } diff --git a/tests/test_drivers/test_requests.py b/tests/test_drivers/test_requests.py index 549bd60..cb032ed 100644 --- a/tests/test_drivers/test_requests.py +++ b/tests/test_drivers/test_requests.py @@ -4,7 +4,6 @@ import json import ssl -import uuid from http.cookies import SimpleCookie from pathlib import Path from typing import TYPE_CHECKING, Type @@ -337,6 +336,8 @@ def test_token_auth(httpbin) -> None: def test_complex_auth_flow(httpbin) -> None: client = HttpBin(httpbin.url, driver=requests_driver()) - response = client.complex_auth_flow() - assert response.json()["authenticated"] is True # type: ignore - assert uuid.UUID(response.json()["token"]) # type: ignore + response = client.complex_auth_flow("vF9dft4qmT") + assert response.json() == { # type: ignore + "authenticated": True, + "token": "vF9dft4qmT", + } From 46eef13784a66a4a3ed22a3f872970973d9909b9 Mon Sep 17 00:00:00 2001 From: Aleksei Maslakov Date: Tue, 10 Mar 2020 12:20:41 +0300 Subject: [PATCH 4/4] Bump version to 0.3.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 169b740..361c059 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "apiwrappers" -version = "0.2.0" +version = "0.3.0" description = "apiwrappers is a library for building API clients that work both with regular and async code" keywords = ["api", "wrapper", "http", "client"] readme = "README.rst"