Skip to content

Commit

Permalink
Merge branch 'main' into fix/paginator-options
Browse files Browse the repository at this point in the history
  • Loading branch information
Shivansh-007 authored Dec 2, 2021
2 parents 170fa3a + 7347f59 commit 2c779b6
Show file tree
Hide file tree
Showing 9 changed files with 259 additions and 232 deletions.
57 changes: 0 additions & 57 deletions .codecov.yml

This file was deleted.

51 changes: 47 additions & 4 deletions .github/workflows/lint_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,14 @@ jobs:
# black and flake8 action. As pre-commit does not support user installs,
# we set PIP_USER=0 to not do a user install.
- name: Run pre-commit hooks
id: pre-commit
run: export PIP_USER=0; SKIP="no-commit-to-branch,black,flake8" pre-commit run --all-files

# Run black seperately as we don't want to reformat the files
# just error if something isn't formatted correctly.
- name: Check files with black
id: black
if: always() && (steps.pre-commit.outcome == 'success' || steps.pre-commit.outcome == 'failure')
run: black . --check --diff --color

# Run flake8 and have it format the linting errors in the format of
Expand All @@ -108,6 +111,8 @@ jobs:
# Format used:
# ::error file={filename},line={line},col={col}::{message}
- name: Run flake8
id: flake8
if: always() && (steps.pre-commit.outcome == 'success' || steps.pre-commit.outcome == 'failure')
run: "flake8 \
--format='::error file=%(path)s,line=%(row)d,col=%(col)d::\
[flake8] %(code)s: %(text)s'"
Expand Down Expand Up @@ -162,12 +167,50 @@ jobs:
# This is saved to ./.coverage to be used by codecov to link a
# coverage report to github.
- name: Run tests and generate coverage report
run: python -m pytest -n auto --dist loadfile --cov --disable-warnings -q
id: run_tests
run: python -m pytest tests -n auto --dist loadfile --cov --disable-warnings -q

# This step will publish the coverage reports to codecov.io and
# This step will publish the coverage reports to coveralls.io and
# print a "job" link in the output of the GitHub Action
- name: Publish coverage report to codecov.io
run: python -m codecov
- name: Publish coverage report to coveralls.io
# upload coverage even if a test run failed
# this is a test, and may be removed in the future
if: always() && (steps.run_tests.outcome == 'success' || steps.run_tests.outcome == 'failure')
# important that we don't fail the workflow when coveralls is down
continue-on-error: true
env:
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_FLAG_NAME: coverage-${{ runner.os }}-python-${{ env.PYTHON_VERSION }}
COVERALLS_PARALLEL: true
COVERALLS_SERVICE_NAME: github
run: python -m coveralls

coveralls-finish:
name: Indicate completion to coveralls.io
runs-on: ubuntu-latest
needs: test
# we don't want to fail the workflow when coveralls is down
continue-on-error: true
# we always want to ensure we attempt to send a finish to coveralls
if: always()
steps:
# Set up a consistent version of Python
- name: Set up Python 3.9
id: python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Coveralls Finished
continue-on-error: true
env:
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_SERVICE_NAME: github
# NOTE: this has a small thing where this will not always be the same with the poetry.lock file
# given how this is installed for one api request, its not worth pinning to me.
# any bugs caused by this can be solved when they occur
run: |
python3 -m pip install --upgrade coveralls
python3 -m coveralls --finish
artifact:
name: Generate Artifact
Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# Discord Modmail

[![Lint & Test](https://img.shields.io/github/workflow/status/discord-modmail/modmail/Lint%20&%20Test/main?label=Lint+%26+Test&logo=github&style=flat)](https://github.com/discord-modmail/modmail/actions/workflows/lint_test.yml "Lint and Test")
[![Code Coverage](https://img.shields.io/codecov/c/gh/discord-modmail/modmail/main?logo=codecov&style=flat&label=Code+Coverage)](https://app.codecov.io/gh/discord-modmail/modmail "Code Coverage")
[![Codacy Grade](https://img.shields.io/codacy/grade/78be21a49835484595aea556d5920638?logo=codacy&style=flat&label=Code+Quality)](https://www.codacy.com/gh/discord-modmail/modmail/dashboard "Codacy Grade")
[![Code Coverage](https://img.shields.io/coveralls/github/discord-modmail/modmail?logo=coveralls&style=flat&label=Code+Coverage)](https://coveralls.io/github/discord-modmail/modmail)
[![Python](https://img.shields.io/static/v1?label=Python&message=3.8+%7C+3.9&color=blue&logo=Python&style=flat)](https://www.python.org/downloads/ "Python 3.8 | 3.9")
[![License](https://img.shields.io/github/license/discord-modmail/modmail?style=flat&label=License)](./LICENSE "License file")
[![Code Style](https://img.shields.io/static/v1?label=Code%20Style&message=black&color=000000&style=flat)](https://github.com/psf/black "The uncompromising python formatter")
Expand Down
8 changes: 8 additions & 0 deletions modmail/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import asyncio
import logging
import logging.handlers
import os
from pathlib import Path

import coloredlogs

from modmail.log import ModmailLogger


# On windows aiodns's asyncio support relies on APIs like add_reader (which aiodns uses)
# are not guaranteed to be available, and in particular are not available when using the
# ProactorEventLoop on Windows, this method is only supported with Windows SelectorEventLoop
if os.name == "nt":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

logging.TRACE = 5
logging.NOTICE = 25
logging.addLevelName(logging.TRACE, "TRACE")
Expand Down
41 changes: 34 additions & 7 deletions modmail/bot.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import asyncio
import logging
import signal
import socket
import typing as t
from typing import Any

import aiohttp
import arrow
import discord
from aiohttp import ClientSession
from discord import Activity, AllowedMentions, Intents
from discord.client import _cleanup_loop
from discord.ext import commands
Expand Down Expand Up @@ -41,9 +41,12 @@ class ModmailBot(commands.Bot):
def __init__(self, **kwargs):
self.config = CONFIG
self.start_time: t.Optional[arrow.Arrow] = None # arrow.utcnow()
self.http_session: t.Optional[ClientSession] = None
self.http_session: t.Optional[aiohttp.ClientSession] = None
self.dispatcher = Dispatcher()

self._connector = None
self._resolver = None

status = discord.Status.online
activity = Activity(type=discord.ActivityType.listening, name="users dming me!")
# listen to messages mentioning the bot or matching the prefix
Expand All @@ -65,6 +68,24 @@ def __init__(self, **kwargs):
**kwargs,
)

async def create_connectors(self, *args, **kwargs) -> None:
"""Re-create the connector and set up sessions before logging into Discord."""
# Use asyncio for DNS resolution instead of threads so threads aren't spammed.
self._resolver = aiohttp.AsyncResolver()

# Use AF_INET as its socket family to prevent HTTPS related problems both locally
# and in production.
self._connector = aiohttp.TCPConnector(
resolver=self._resolver,
family=socket.AF_INET,
)

# Client.login() will call HTTPClient.static_login() which will create a session using
# this connector attribute.
self.http.connector = self._connector

self.http_session = aiohttp.ClientSession(connector=self._connector)

async def start(self, token: str, reconnect: bool = True) -> None:
"""
Start the bot.
Expand All @@ -74,8 +95,8 @@ async def start(self, token: str, reconnect: bool = True) -> None:
"""
try:
# create the aiohttp session
self.http_session = ClientSession(loop=self.loop)
self.logger.trace("Created ClientSession.")
await self.create_connectors()
self.logger.trace("Created aiohttp.ClientSession.")
# set start time to when we started the bot.
# This is now, since we're about to connect to the gateway.
# This should also be before we load any extensions, since if they have a load time, it should
Expand Down Expand Up @@ -122,7 +143,7 @@ def run(self, *args, **kwargs) -> None:
except NotImplementedError:
pass

def stop_loop_on_completion(f: Any) -> None:
def stop_loop_on_completion(f: t.Any) -> None:
loop.stop()

future = asyncio.ensure_future(self.start(*args, **kwargs), loop=loop)
Expand Down Expand Up @@ -164,10 +185,16 @@ async def close(self) -> None:
except Exception:
self.logger.error(f"Exception occured while removing cog {cog.name}", exc_info=True)

await super().close()

if self.http_session:
await self.http_session.close()

await super().close()
if self._connector:
await self._connector.close()

if self._resolver:
await self._resolver.close()

def load_extensions(self) -> None:
"""Load all enabled extensions."""
Expand Down
Loading

0 comments on commit 2c779b6

Please sign in to comment.