Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def run_tests(self):

cmdclass["build_docs"] = BuildDoc

requires = ["requests>=2.23.0"]
requires = ["aiohttp>=3.7.4.post0"]

test_requirements = [
"black==20.8b1",
Expand Down
64 changes: 32 additions & 32 deletions tests/api/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def test_get_request_headers_includes_authorization():


@responses.activate
def test_request_get_returns_dictionary_if_successful():
async def test_request_get_returns_dictionary_if_successful():
responses.add(
responses.GET,
BASE_URL,
Expand All @@ -45,14 +45,14 @@ def test_request_get_returns_dictionary_if_successful():
)

api = TwitchAPI(client_id="client")
response = api._request_get("")
response = await api._request_get("")

assert isinstance(response, dict)
assert response == dummy_data


@responses.activate
def test_request_get_sends_headers_with_the_request():
async def test_request_get_sends_headers_with_the_request():
responses.add(
responses.GET,
BASE_URL,
Expand All @@ -62,14 +62,14 @@ def test_request_get_sends_headers_with_the_request():
)

api = TwitchAPI(client_id="client")
api._request_get("")
await api._request_get("")

assert "Client-ID" in responses.calls[0].request.headers
assert "Accept" in responses.calls[0].request.headers


@responses.activate
def test_request_get_binary_body():
async def test_request_get_binary_body():
responses.add(
responses.GET,
BASE_URL,
Expand All @@ -79,14 +79,14 @@ def test_request_get_binary_body():
)

api = TwitchAPI(client_id="client")
response = api._request_get("", json=False)
response = await api._request_get("", json=False)

assert response.content == b"binary"


@responses.activate
@pytest.mark.parametrize("status", [(500), (400)])
def test_request_get_raises_exception_if_not_200_response(status, monkeypatch):
async def test_request_get_raises_exception_if_not_200_response(status, monkeypatch):
responses.add(
responses.GET, BASE_URL, status=status, content_type="application/json"
)
Expand All @@ -99,11 +99,11 @@ def mockreturn(path):
api = TwitchAPI(client_id="client")

with pytest.raises(exceptions.HTTPError):
api._request_get("")
await api._request_get("")


@responses.activate
def test_request_put_returns_dictionary_if_successful():
async def test_request_put_returns_dictionary_if_successful():
responses.add(
responses.PUT,
BASE_URL,
Expand All @@ -113,25 +113,25 @@ def test_request_put_returns_dictionary_if_successful():
)

api = TwitchAPI(client_id="client")
response = api._request_put("", dummy_data)
response = await api._request_put("", dummy_data)

assert isinstance(response, dict)
assert response == dummy_data


@responses.activate
def test_request_put_sends_headers_with_the_request():
async def test_request_put_sends_headers_with_the_request():
responses.add(responses.PUT, BASE_URL, status=204, content_type="application/json")

api = TwitchAPI(client_id="client")
api._request_put("", dummy_data)
await api._request_put("", dummy_data)

assert "Client-ID" in responses.calls[0].request.headers
assert "Accept" in responses.calls[0].request.headers


@responses.activate
def test_request_put_does_not_raise_exception_if_successful_and_returns_json():
async def test_request_put_does_not_raise_exception_if_successful_and_returns_json():
responses.add(
responses.PUT,
BASE_URL,
Expand All @@ -141,35 +141,35 @@ def test_request_put_does_not_raise_exception_if_successful_and_returns_json():
)

api = TwitchAPI(client_id="client")
response = api._request_put("", dummy_data)
response = await api._request_put("", dummy_data)
assert response == dummy_data


@responses.activate
@pytest.mark.parametrize("status", [(500), (400)])
def test_request_put_raises_exception_if_not_200_response(status):
async def test_request_put_raises_exception_if_not_200_response(status):
responses.add(
responses.PUT, BASE_URL, status=status, content_type="application/json"
)

api = TwitchAPI(client_id="client")

with pytest.raises(exceptions.HTTPError):
api._request_put("", dummy_data)
await api._request_put("", dummy_data)


@responses.activate
def test_request_delete_does_not_raise_exception_if_successful():
async def test_request_delete_does_not_raise_exception_if_successful():
responses.add(
responses.DELETE, BASE_URL, status=204, content_type="application/json"
)

api = TwitchAPI(client_id="client")
api._request_delete("")
await api._request_delete("")


@responses.activate
def test_request_delete_does_not_raise_exception_if_successful_and_returns_json():
async def test_request_delete_does_not_raise_exception_if_successful_and_returns_json():
responses.add(
responses.DELETE,
BASE_URL,
Expand All @@ -179,38 +179,38 @@ def test_request_delete_does_not_raise_exception_if_successful_and_returns_json(
)

api = TwitchAPI(client_id="client")
response = api._request_delete("")
response = await api._request_delete("")
assert response == dummy_data


@responses.activate
def test_request_delete_sends_headers_with_the_request():
async def test_request_delete_sends_headers_with_the_request():
responses.add(
responses.DELETE, BASE_URL, status=204, content_type="application/json"
)

api = TwitchAPI(client_id="client")
api._request_delete("")
await api._request_delete("")

assert "Client-ID" in responses.calls[0].request.headers
assert "Accept" in responses.calls[0].request.headers


@responses.activate
@pytest.mark.parametrize("status", [(500), (400)])
def test_request_delete_raises_exception_if_not_200_response(status):
async def test_request_delete_raises_exception_if_not_200_response(status):
responses.add(
responses.DELETE, BASE_URL, status=status, content_type="application/json"
)

api = TwitchAPI(client_id="client")

with pytest.raises(exceptions.HTTPError):
api._request_delete("")
await api._request_delete("")


@responses.activate
def test_request_post_returns_dictionary_if_successful():
async def test_request_post_returns_dictionary_if_successful():
responses.add(
responses.POST,
BASE_URL,
Expand All @@ -220,22 +220,22 @@ def test_request_post_returns_dictionary_if_successful():
)

api = TwitchAPI(client_id="client")
response = api._request_post("", dummy_data)
response = await api._request_post("", dummy_data)

assert isinstance(response, dict)
assert response == dummy_data


@responses.activate
def test_request_post_does_not_raise_exception_if_successful():
async def test_request_post_does_not_raise_exception_if_successful():
responses.add(responses.POST, BASE_URL, status=204, content_type="application/json")

api = TwitchAPI(client_id="client")
api._request_post("")
await api._request_post("")


@responses.activate
def test_request_post_sends_headers_with_the_request():
async def test_request_post_sends_headers_with_the_request():
responses.add(
responses.POST,
BASE_URL,
Expand All @@ -245,23 +245,23 @@ def test_request_post_sends_headers_with_the_request():
)

api = TwitchAPI(client_id="client")
api._request_post("", dummy_data)
await api._request_post("", dummy_data)

assert "Client-ID" in responses.calls[0].request.headers
assert "Accept" in responses.calls[0].request.headers


@responses.activate
@pytest.mark.parametrize("status", [(500), (400)])
def test_request_post_raises_exception_if_not_200_response(status):
async def test_request_post_raises_exception_if_not_200_response(status):
responses.add(
responses.POST, BASE_URL, status=status, content_type="application/json"
)

api = TwitchAPI(client_id="client")

with pytest.raises(exceptions.HTTPError):
api._request_post("", dummy_data)
await api._request_post("", dummy_data)


def test_base_reads_backoff_config_from_file(monkeypatch):
Expand Down
2 changes: 1 addition & 1 deletion twitch/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .client import TwitchClient # noqa
from .helix.api import TwitchHelix # noqa

__version__ = "0.7.1"
__version__ = "2.0-async"
92 changes: 42 additions & 50 deletions twitch/api/base.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import time

import requests
from requests.compat import urljoin
# import requests
# from requests.compat import urljoin
import aiohttp

from twitch.conf import backoff_config
from twitch.constants import BASE_URL
Expand Down Expand Up @@ -31,65 +32,56 @@ def _get_request_headers(self):

return headers

def _request_get(self, path, params=None, json=True, url=BASE_URL):
async def _request_get(self, path, params=None, json=True, url=BASE_URL):
"""Perform a HTTP GET request."""
url = urljoin(url, path)
url = f"{url}{path}"
headers = self._get_request_headers()

response = requests.get(url, params=params, headers=headers)
if response.status_code >= 500:

backoff = self._initial_backoff
for _ in range(self._max_retries):
time.sleep(backoff)
backoff_response = requests.get(
url, params=params, headers=headers, timeout=DEFAULT_TIMEOUT
)
if backoff_response.status_code < 500:
response = backoff_response
break
backoff *= 2

response.raise_for_status()
if json:
return response.json()
else:
return response

def _request_post(self, path, data=None, params=None, url=BASE_URL):
async with aiohttp.ClientSession(raise_for_status=True) as session:
async with session.request("GET", url, params=params, headers=headers) as response:
if response.status >= 500:

backoff = self._initial_backoff
for _ in range(self._max_retries):
time.sleep(backoff)
async with session.request("GET", url, params=params, headers=headers, timeout=DEFAULT_TIMEOUT) as backoff_response:
if backoff_response.status < 500:
response = backoff_response
break
backoff *= 2

if json:
return await response.json()
else:
return response

async def _request_post(self, path, data=None, params=None, url=BASE_URL):
"""Perform a HTTP POST request.."""
url = urljoin(url, path)
url = f"{url}{path}"

headers = self._get_request_headers()

response = requests.post(
url, json=data, params=params, headers=headers, timeout=DEFAULT_TIMEOUT
)
response.raise_for_status()
if response.status_code == 200:
return response.json()
async with aiohttp.ClientSession() as session:
async with session.request("POST", url, data=data, params=params, headers=headers, raise_for_status=True) as response:
if response.status == 200:
return await response.json()

def _request_put(self, path, data=None, params=None, url=BASE_URL):
async def _request_put(self, path, data=None, params=None, url=BASE_URL):
"""Perform a HTTP PUT request."""
url = urljoin(url, path)
url = f"{url}{path}"

headers = self._get_request_headers()
response = requests.put(
url, json=data, params=params, headers=headers, timeout=DEFAULT_TIMEOUT
)
response.raise_for_status()
if response.status_code == 200:
return response.json()

def _request_delete(self, path, params=None, url=BASE_URL):
async with aiohttp.ClientSession() as session:
async with session.request("PUT", url, data=data, params=params, headers=headers, raise_for_status=True) as response:
if response.status == 200:
return await response.json()

async def _request_delete(self, path, params=None, url=BASE_URL):
"""Perform a HTTP DELETE request."""
url = urljoin(url, path)
url = f"{url}{path}"

headers = self._get_request_headers()

response = requests.delete(
url, params=params, headers=headers, timeout=DEFAULT_TIMEOUT
)
response.raise_for_status()
if response.status_code == 200:
return response.json()
async with aiohttp.ClientSession() as session:
async with session.request("DELETE", url, params=params, headers=headers, raise_for_status=True) as response:
if response.status == 200:
return await response.json()
Loading