aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Chris Lovering <[email protected]>2022-03-31 20:46:45 +0100
committerGravatar Chris Lovering <[email protected]>2022-04-18 17:44:59 +0100
commit047705ac91c2997ccb509ea4e1fb3fad38840412 (patch)
tree93a1e38cb3b1719b7e2b6eee2b15f21e1a8526a9
parentDiscord.py breaking changes (diff)
Remove async stats and site api wrapper
We now source them from bot-core, so no need to have them here too.
-rw-r--r--bot/api.py102
-rw-r--r--bot/async_stats.py40
-rw-r--r--bot/converters.py2
-rw-r--r--bot/exts/backend/error_handler.py2
-rw-r--r--bot/exts/backend/sync/_cog.py2
-rw-r--r--bot/exts/backend/sync/_syncers.py2
-rw-r--r--bot/exts/filters/filter_lists.py2
-rw-r--r--bot/exts/filters/filtering.py2
-rw-r--r--bot/exts/fun/off_topic_names.py2
-rw-r--r--bot/exts/info/doc/_cog.py2
-rw-r--r--bot/exts/info/information.py2
-rw-r--r--bot/exts/moderation/infraction/_scheduler.py2
-rw-r--r--bot/exts/moderation/infraction/_utils.py2
-rw-r--r--bot/exts/moderation/voice_gate.py2
-rw-r--r--bot/exts/moderation/watchchannels/_watchchannel.py2
-rw-r--r--bot/exts/recruitment/talentpool/_cog.py2
-rw-r--r--bot/exts/recruitment/talentpool/_review.py2
-rw-r--r--tests/bot/exts/backend/sync/test_base.py3
-rw-r--r--tests/bot/exts/backend/sync/test_cog.py2
-rw-r--r--tests/bot/exts/backend/test_error_handler.py2
-rw-r--r--tests/bot/exts/moderation/infraction/test_utils.py2
-rw-r--r--tests/bot/test_api.py66
-rw-r--r--tests/helpers.py4
23 files changed, 22 insertions, 229 deletions
diff --git a/bot/api.py b/bot/api.py
deleted file mode 100644
index 856f7c865..000000000
--- a/bot/api.py
+++ /dev/null
@@ -1,102 +0,0 @@
-import asyncio
-from typing import Optional
-from urllib.parse import quote as quote_url
-
-import aiohttp
-
-from bot.log import get_logger
-
-from .constants import Keys, URLs
-
-log = get_logger(__name__)
-
-
-class ResponseCodeError(ValueError):
- """Raised when a non-OK HTTP response is received."""
-
- def __init__(
- self,
- response: aiohttp.ClientResponse,
- response_json: Optional[dict] = None,
- response_text: str = ""
- ):
- self.status = response.status
- self.response_json = response_json or {}
- self.response_text = response_text
- self.response = response
-
- def __str__(self):
- response = self.response_json if self.response_json else self.response_text
- return f"Status: {self.status} Response: {response}"
-
-
-class APIClient:
- """Django Site API wrapper."""
-
- # These are class attributes so they can be seen when being mocked for tests.
- # See commit 22a55534ef13990815a6f69d361e2a12693075d5 for details.
- session: Optional[aiohttp.ClientSession] = None
- loop: asyncio.AbstractEventLoop = None
-
- def __init__(self, **session_kwargs):
- auth_headers = {
- 'Authorization': f"Token {Keys.site_api}"
- }
-
- if 'headers' in session_kwargs:
- session_kwargs['headers'].update(auth_headers)
- else:
- session_kwargs['headers'] = auth_headers
-
- # aiohttp will complain if APIClient gets instantiated outside a coroutine. Thankfully, we
- # don't and shouldn't need to do that, so we can avoid scheduling a task to create it.
- self.session = aiohttp.ClientSession(**session_kwargs)
-
- @staticmethod
- def _url_for(endpoint: str) -> str:
- return f"{URLs.site_api_schema}{URLs.site_api}/{quote_url(endpoint)}"
-
- async def close(self) -> None:
- """Close the aiohttp session."""
- await self.session.close()
-
- async def maybe_raise_for_status(self, response: aiohttp.ClientResponse, should_raise: bool) -> None:
- """Raise ResponseCodeError for non-OK response if an exception should be raised."""
- if should_raise and response.status >= 400:
- try:
- response_json = await response.json()
- raise ResponseCodeError(response=response, response_json=response_json)
- except aiohttp.ContentTypeError:
- response_text = await response.text()
- raise ResponseCodeError(response=response, response_text=response_text)
-
- async def request(self, method: str, endpoint: str, *, raise_for_status: bool = True, **kwargs) -> dict:
- """Send an HTTP request to the site API and return the JSON response."""
- async with self.session.request(method.upper(), self._url_for(endpoint), **kwargs) as resp:
- await self.maybe_raise_for_status(resp, raise_for_status)
- return await resp.json()
-
- async def get(self, endpoint: str, *, raise_for_status: bool = True, **kwargs) -> dict:
- """Site API GET."""
- return await self.request("GET", endpoint, raise_for_status=raise_for_status, **kwargs)
-
- async def patch(self, endpoint: str, *, raise_for_status: bool = True, **kwargs) -> dict:
- """Site API PATCH."""
- return await self.request("PATCH", endpoint, raise_for_status=raise_for_status, **kwargs)
-
- async def post(self, endpoint: str, *, raise_for_status: bool = True, **kwargs) -> dict:
- """Site API POST."""
- return await self.request("POST", endpoint, raise_for_status=raise_for_status, **kwargs)
-
- async def put(self, endpoint: str, *, raise_for_status: bool = True, **kwargs) -> dict:
- """Site API PUT."""
- return await self.request("PUT", endpoint, raise_for_status=raise_for_status, **kwargs)
-
- async def delete(self, endpoint: str, *, raise_for_status: bool = True, **kwargs) -> Optional[dict]:
- """Site API DELETE."""
- async with self.session.delete(self._url_for(endpoint), **kwargs) as resp:
- if resp.status == 204:
- return None
-
- await self.maybe_raise_for_status(resp, raise_for_status)
- return await resp.json()
diff --git a/bot/async_stats.py b/bot/async_stats.py
deleted file mode 100644
index 0303de7a1..000000000
--- a/bot/async_stats.py
+++ /dev/null
@@ -1,40 +0,0 @@
-import asyncio
-import socket
-
-from botcore.utils import scheduling
-from statsd.client.base import StatsClientBase
-
-
-class AsyncStatsClient(StatsClientBase):
- """An async transport method for statsd communication."""
-
- def __init__(
- self,
- loop: asyncio.AbstractEventLoop,
- host: str = 'localhost',
- port: int = 8125,
- prefix: str = None
- ):
- """Create a new client."""
- family, _, _, _, addr = socket.getaddrinfo(
- host, port, socket.AF_INET, socket.SOCK_DGRAM)[0]
- self._addr = addr
- self._prefix = prefix
- self._loop = loop
- self._transport = None
-
- async def create_socket(self) -> None:
- """Use the loop.create_datagram_endpoint method to create a socket."""
- self._transport, _ = await self._loop.create_datagram_endpoint(
- asyncio.DatagramProtocol,
- family=socket.AF_INET,
- remote_addr=self._addr
- )
-
- def _send(self, data: str) -> None:
- """Start an async task to send data to statsd."""
- scheduling.create_task(self._async_send(data), event_loop=self._loop)
-
- async def _async_send(self, data: str) -> None:
- """Send data to the statsd server using the async transport."""
- self._transport.sendto(data.encode('ascii'), self._addr)
diff --git a/bot/converters.py b/bot/converters.py
index e819e4713..a3f4630a0 100644
--- a/bot/converters.py
+++ b/bot/converters.py
@@ -8,13 +8,13 @@ from ssl import CertificateError
import dateutil.parser
import discord
from aiohttp import ClientConnectorError
+from botcore.site_api import ResponseCodeError
from botcore.utils.regex import DISCORD_INVITE
from dateutil.relativedelta import relativedelta
from discord.ext.commands import BadArgument, Bot, Context, Converter, IDConverter, MemberConverter, UserConverter
from discord.utils import escape_markdown, snowflake_time
from bot import exts
-from bot.api import ResponseCodeError
from bot.constants import URLs
from bot.errors import InvalidInfraction
from bot.exts.info.doc import _inventory_parser
diff --git a/bot/exts/backend/error_handler.py b/bot/exts/backend/error_handler.py
index fabb2dbb5..5391a7f15 100644
--- a/bot/exts/backend/error_handler.py
+++ b/bot/exts/backend/error_handler.py
@@ -1,10 +1,10 @@
import difflib
+from botcore.site_api import ResponseCodeError
from discord import Embed
from discord.ext.commands import ChannelNotFound, Cog, Context, TextChannelConverter, VoiceChannelConverter, errors
from sentry_sdk import push_scope
-from bot.api import ResponseCodeError
from bot.bot import Bot
from bot.constants import Colours, Icons, MODERATION_ROLES
from bot.errors import InvalidInfractedUserError, LockedResourceError
diff --git a/bot/exts/backend/sync/_cog.py b/bot/exts/backend/sync/_cog.py
index 58aabc141..a5bf82397 100644
--- a/bot/exts/backend/sync/_cog.py
+++ b/bot/exts/backend/sync/_cog.py
@@ -1,11 +1,11 @@
from typing import Any, Dict
+from botcore.site_api import ResponseCodeError
from discord import Member, Role, User
from discord.ext import commands
from discord.ext.commands import Cog, Context
from bot import constants
-from bot.api import ResponseCodeError
from bot.bot import Bot
from bot.exts.backend.sync import _syncers
from bot.log import get_logger
diff --git a/bot/exts/backend/sync/_syncers.py b/bot/exts/backend/sync/_syncers.py
index 45301b098..e1c4541ef 100644
--- a/bot/exts/backend/sync/_syncers.py
+++ b/bot/exts/backend/sync/_syncers.py
@@ -2,12 +2,12 @@ import abc
import typing as t
from collections import namedtuple
+from botcore.site_api import ResponseCodeError
from discord import Guild
from discord.ext.commands import Context
from more_itertools import chunked
import bot
-from bot.api import ResponseCodeError
from bot.log import get_logger
from bot.utils.members import get_or_fetch_member
diff --git a/bot/exts/filters/filter_lists.py b/bot/exts/filters/filter_lists.py
index 3e3f5c562..fc9cfbeca 100644
--- a/bot/exts/filters/filter_lists.py
+++ b/bot/exts/filters/filter_lists.py
@@ -1,11 +1,11 @@
import re
from typing import Optional
+from botcore.site_api import ResponseCodeError
from discord import Colour, Embed
from discord.ext.commands import BadArgument, Cog, Context, IDConverter, group, has_any_role
from bot import constants
-from bot.api import ResponseCodeError
from bot.bot import Bot
from bot.constants import Channels
from bot.converters import ValidDiscordServerInvite, ValidFilterListType
diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py
index cabb7f0b6..6982f5948 100644
--- a/bot/exts/filters/filtering.py
+++ b/bot/exts/filters/filtering.py
@@ -9,6 +9,7 @@ import dateutil.parser
import regex
import tldextract
from async_rediscache import RedisCache
+from botcore.site_api import ResponseCodeError
from botcore.utils import scheduling
from botcore.utils.regex import DISCORD_INVITE
from dateutil.relativedelta import relativedelta
@@ -16,7 +17,6 @@ from discord import ChannelType, Colour, Embed, Forbidden, HTTPException, Member
from discord.ext.commands import Cog
from discord.utils import escape_markdown
-from bot.api import ResponseCodeError
from bot.bot import Bot
from bot.constants import Channels, Colours, Filter, Guild, Icons, URLs
from bot.exts.events.code_jams._channels import CATEGORY_NAME as JAM_CATEGORY_NAME
diff --git a/bot/exts/fun/off_topic_names.py b/bot/exts/fun/off_topic_names.py
index ac172f2a8..d8111bdf5 100644
--- a/bot/exts/fun/off_topic_names.py
+++ b/bot/exts/fun/off_topic_names.py
@@ -2,12 +2,12 @@ import difflib
from datetime import timedelta
import arrow
+from botcore.site_api import ResponseCodeError
from botcore.utils import scheduling
from discord import Colour, Embed
from discord.ext.commands import Cog, Context, group, has_any_role
from discord.utils import sleep_until
-from bot.api import ResponseCodeError
from bot.bot import Bot
from bot.constants import Channels, MODERATION_ROLES
from bot.converters import OffTopicName
diff --git a/bot/exts/info/doc/_cog.py b/bot/exts/info/doc/_cog.py
index 8c3038c5b..bbdc4e82a 100644
--- a/bot/exts/info/doc/_cog.py
+++ b/bot/exts/info/doc/_cog.py
@@ -10,11 +10,11 @@ from typing import Dict, NamedTuple, Optional, Tuple, Union
import aiohttp
import discord
+from botcore.site_api import ResponseCodeError
from botcore.utils import scheduling
from botcore.utils.scheduling import Scheduler
from discord.ext import commands
-from bot.api import ResponseCodeError
from bot.bot import Bot
from bot.constants import MODERATION_ROLES, RedirectOutput
from bot.converters import Inventory, PackageName, ValidURL, allowed_strings
diff --git a/bot/exts/info/information.py b/bot/exts/info/information.py
index b56fd171a..e7d17c971 100644
--- a/bot/exts/info/information.py
+++ b/bot/exts/info/information.py
@@ -6,12 +6,12 @@ from textwrap import shorten
from typing import Any, DefaultDict, Mapping, Optional, Tuple, Union
import rapidfuzz
+from botcore.site_api import ResponseCodeError
from discord import AllowedMentions, Colour, Embed, Guild, Message, Role
from discord.ext.commands import BucketType, Cog, Context, Greedy, Paginator, command, group, has_any_role
from discord.utils import escape_markdown
from bot import constants
-from bot.api import ResponseCodeError
from bot.bot import Bot
from bot.converters import MemberOrUser
from bot.decorators import in_whitelist
diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py
index 137358ec3..9c73bde5f 100644
--- a/bot/exts/moderation/infraction/_scheduler.py
+++ b/bot/exts/moderation/infraction/_scheduler.py
@@ -6,11 +6,11 @@ from gettext import ngettext
import arrow
import dateutil.parser
import discord
+from botcore.site_api import ResponseCodeError
from botcore.utils import scheduling
from discord.ext.commands import Context
from bot import constants
-from bot.api import ResponseCodeError
from bot.bot import Bot
from bot.constants import Colours
from bot.converters import MemberOrUser
diff --git a/bot/exts/moderation/infraction/_utils.py b/bot/exts/moderation/infraction/_utils.py
index c1be18362..3a2485ec2 100644
--- a/bot/exts/moderation/infraction/_utils.py
+++ b/bot/exts/moderation/infraction/_utils.py
@@ -3,10 +3,10 @@ from datetime import datetime
import arrow
import discord
+from botcore.site_api import ResponseCodeError
from discord.ext.commands import Context
import bot
-from bot.api import ResponseCodeError
from bot.constants import Colours, Icons
from bot.converters import MemberOrUser
from bot.errors import InvalidInfractedUserError
diff --git a/bot/exts/moderation/voice_gate.py b/bot/exts/moderation/voice_gate.py
index 33096e7e0..9b1621c01 100644
--- a/bot/exts/moderation/voice_gate.py
+++ b/bot/exts/moderation/voice_gate.py
@@ -5,10 +5,10 @@ from datetime import timedelta
import arrow
import discord
from async_rediscache import RedisCache
+from botcore.site_api import ResponseCodeError
from discord import Colour, Member, VoiceState
from discord.ext.commands import Cog, Context, command
-from bot.api import ResponseCodeError
from bot.bot import Bot
from bot.constants import Channels, MODERATION_ROLES, Roles, VoiceGate as GateConf
from bot.decorators import has_no_roles, in_whitelist
diff --git a/bot/exts/moderation/watchchannels/_watchchannel.py b/bot/exts/moderation/watchchannels/_watchchannel.py
index ab5ce62f9..bc78b3934 100644
--- a/bot/exts/moderation/watchchannels/_watchchannel.py
+++ b/bot/exts/moderation/watchchannels/_watchchannel.py
@@ -7,11 +7,11 @@ from dataclasses import dataclass
from typing import Any, Dict, Optional
import discord
+from botcore.site_api import ResponseCodeError
from botcore.utils import scheduling
from discord import Color, DMChannel, Embed, HTTPException, Message, errors
from discord.ext.commands import Cog, Context
-from bot.api import ResponseCodeError
from bot.bot import Bot
from bot.constants import BigBrother as BigBrotherConfig, Guild as GuildConfig, Icons
from bot.exts.filters.token_remover import TokenRemover
diff --git a/bot/exts/recruitment/talentpool/_cog.py b/bot/exts/recruitment/talentpool/_cog.py
index 8aa124536..24496af54 100644
--- a/bot/exts/recruitment/talentpool/_cog.py
+++ b/bot/exts/recruitment/talentpool/_cog.py
@@ -5,11 +5,11 @@ from typing import Optional, Union
import discord
from async_rediscache import RedisCache
+from botcore.site_api import ResponseCodeError
from botcore.utils import scheduling
from discord import Color, Embed, Member, PartialMessage, RawReactionActionEvent, User
from discord.ext.commands import BadArgument, Cog, Context, group, has_any_role
-from bot.api import ResponseCodeError
from bot.bot import Bot
from bot.constants import Channels, Emojis, Guild, MODERATION_ROLES, Roles, STAFF_ROLES
from bot.converters import MemberOrUser, UnambiguousMemberOrUser
diff --git a/bot/exts/recruitment/talentpool/_review.py b/bot/exts/recruitment/talentpool/_review.py
index d0edf5388..be181d005 100644
--- a/bot/exts/recruitment/talentpool/_review.py
+++ b/bot/exts/recruitment/talentpool/_review.py
@@ -9,12 +9,12 @@ from datetime import datetime, timedelta
from typing import List, Optional, Union
import arrow
+from botcore.site_api import ResponseCodeError
from botcore.utils.scheduling import Scheduler
from dateutil.parser import isoparse
from discord import Embed, Emoji, Member, Message, NotFound, PartialMessage, TextChannel
from discord.ext.commands import Context
-from bot.api import ResponseCodeError
from bot.bot import Bot
from bot.constants import Channels, Colours, Emojis, Guild, Roles
from bot.log import get_logger
diff --git a/tests/bot/exts/backend/sync/test_base.py b/tests/bot/exts/backend/sync/test_base.py
index 9dc46005b..a17c1fa10 100644
--- a/tests/bot/exts/backend/sync/test_base.py
+++ b/tests/bot/exts/backend/sync/test_base.py
@@ -1,7 +1,8 @@
import unittest
from unittest import mock
-from bot.api import ResponseCodeError
+from botcore.site_api import ResponseCodeError
+
from bot.exts.backend.sync._syncers import Syncer
from tests import helpers
diff --git a/tests/bot/exts/backend/sync/test_cog.py b/tests/bot/exts/backend/sync/test_cog.py
index 7dff38f96..4ec36e39f 100644
--- a/tests/bot/exts/backend/sync/test_cog.py
+++ b/tests/bot/exts/backend/sync/test_cog.py
@@ -2,9 +2,9 @@ import unittest
from unittest import mock
import discord
+from botcore.site_api import ResponseCodeError
from bot import constants
-from bot.api import ResponseCodeError
from bot.exts.backend import sync
from bot.exts.backend.sync._cog import Sync
from bot.exts.backend.sync._syncers import Syncer
diff --git a/tests/bot/exts/backend/test_error_handler.py b/tests/bot/exts/backend/test_error_handler.py
index 35fa0ee59..04a018289 100644
--- a/tests/bot/exts/backend/test_error_handler.py
+++ b/tests/bot/exts/backend/test_error_handler.py
@@ -1,9 +1,9 @@
import unittest
from unittest.mock import AsyncMock, MagicMock, call, patch
+from botcore.site_api import ResponseCodeError
from discord.ext.commands import errors
-from bot.api import ResponseCodeError
from bot.errors import InvalidInfractedUserError, LockedResourceError
from bot.exts.backend.error_handler import ErrorHandler, setup
from bot.exts.info.tags import Tags
diff --git a/tests/bot/exts/moderation/infraction/test_utils.py b/tests/bot/exts/moderation/infraction/test_utils.py
index ff81ddd65..5cf02033d 100644
--- a/tests/bot/exts/moderation/infraction/test_utils.py
+++ b/tests/bot/exts/moderation/infraction/test_utils.py
@@ -3,9 +3,9 @@ from collections import namedtuple
from datetime import datetime
from unittest.mock import AsyncMock, MagicMock, call, patch
+from botcore.site_api import ResponseCodeError
from discord import Embed, Forbidden, HTTPException, NotFound
-from bot.api import ResponseCodeError
from bot.constants import Colours, Icons
from bot.exts.moderation.infraction import _utils as utils
from tests.helpers import MockBot, MockContext, MockMember, MockUser
diff --git a/tests/bot/test_api.py b/tests/bot/test_api.py
deleted file mode 100644
index 76bcb481d..000000000
--- a/tests/bot/test_api.py
+++ /dev/null
@@ -1,66 +0,0 @@
-import unittest
-from unittest.mock import MagicMock
-
-from bot import api
-
-
-class APIClientTests(unittest.IsolatedAsyncioTestCase):
- """Tests for the bot's API client."""
-
- @classmethod
- def setUpClass(cls):
- """Sets up the shared fixtures for the tests."""
- cls.error_api_response = MagicMock()
- cls.error_api_response.status = 999
-
- def test_response_code_error_default_initialization(self):
- """Test the default initialization of `ResponseCodeError` without `text` or `json`"""
- error = api.ResponseCodeError(response=self.error_api_response)
-
- self.assertIs(error.status, self.error_api_response.status)
- self.assertEqual(error.response_json, {})
- self.assertEqual(error.response_text, "")
- self.assertIs(error.response, self.error_api_response)
-
- def test_response_code_error_string_representation_default_initialization(self):
- """Test the string representation of `ResponseCodeError` initialized without text or json."""
- error = api.ResponseCodeError(response=self.error_api_response)
- self.assertEqual(str(error), f"Status: {self.error_api_response.status} Response: ")
-
- def test_response_code_error_initialization_with_json(self):
- """Test the initialization of `ResponseCodeError` with json."""
- json_data = {'hello': 'world'}
- error = api.ResponseCodeError(
- response=self.error_api_response,
- response_json=json_data,
- )
- self.assertEqual(error.response_json, json_data)
- self.assertEqual(error.response_text, "")
-
- def test_response_code_error_string_representation_with_nonempty_response_json(self):
- """Test the string representation of `ResponseCodeError` initialized with json."""
- json_data = {'hello': 'world'}
- error = api.ResponseCodeError(
- response=self.error_api_response,
- response_json=json_data
- )
- self.assertEqual(str(error), f"Status: {self.error_api_response.status} Response: {json_data}")
-
- def test_response_code_error_initialization_with_text(self):
- """Test the initialization of `ResponseCodeError` with text."""
- text_data = 'Lemon will eat your soul'
- error = api.ResponseCodeError(
- response=self.error_api_response,
- response_text=text_data,
- )
- self.assertEqual(error.response_text, text_data)
- self.assertEqual(error.response_json, {})
-
- def test_response_code_error_string_representation_with_nonempty_response_text(self):
- """Test the string representation of `ResponseCodeError` initialized with text."""
- text_data = 'Lemon will eat your soul'
- error = api.ResponseCodeError(
- response=self.error_api_response,
- response_text=text_data
- )
- self.assertEqual(str(error), f"Status: {self.error_api_response.status} Response: {text_data}")
diff --git a/tests/helpers.py b/tests/helpers.py
index 9d4988d23..3e6290e58 100644
--- a/tests/helpers.py
+++ b/tests/helpers.py
@@ -9,10 +9,10 @@ from typing import Iterable, Optional
import discord
from aiohttp import ClientSession
+from botcore.async_stats import AsyncStatsClient
+from botcore.site_api import APIClient
from discord.ext.commands import Context
-from bot.api import APIClient
-from bot.async_stats import AsyncStatsClient
from bot.bot import Bot
from tests._autospec import autospec # noqa: F401 other modules import it via this module