diff --git a/bot/__main__.py b/bot/__main__.py index 9317563c84..0d3fce1803 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -1,11 +1,9 @@ -import logging - import aiohttp import bot from bot import constants from bot.bot import Bot, StartupError -from bot.log import setup_sentry +from bot.log import get_logger, setup_sentry setup_sentry() @@ -21,7 +19,7 @@ message = "Could not connect to Redis. Is it running?" # The exception is logged with an empty message so the actual message is visible at the bottom - log = logging.getLogger("bot") + log = get_logger("bot") log.fatal("", exc_info=e.exception) log.fatal(message) diff --git a/bot/api.py b/bot/api.py index 6ce9481f45..33e612641d 100644 --- a/bot/api.py +++ b/bot/api.py @@ -1,13 +1,13 @@ import asyncio -import logging 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 = logging.getLogger(__name__) +log = get_logger(__name__) class ResponseCodeError(ValueError): diff --git a/bot/bot.py b/bot/bot.py index db3d651a3f..94783a4662 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -1,5 +1,4 @@ import asyncio -import logging import socket import warnings from collections import defaultdict @@ -14,8 +13,9 @@ from bot import api, constants from bot.async_stats import AsyncStatsClient +from bot.log import get_logger -log = logging.getLogger('bot') +log = get_logger('bot') LOCALHOST = "127.0.0.1" diff --git a/bot/constants.py b/bot/constants.py index f99913b17b..f704c9e6a2 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -9,8 +9,6 @@ out in the custom user configuration will stay their default values from `config-default.yml`. """ - -import logging import os from collections.abc import Mapping from enum import Enum @@ -25,8 +23,6 @@ except ModuleNotFoundError: pass -log = logging.getLogger(__name__) - def _env_var_constructor(loader, node): """ @@ -104,7 +100,7 @@ def _recursive_update(original, new): if Path("config.yml").exists(): - log.info("Found `config.yml` file, loading constants from it.") + print("Found `config.yml` file, loading constants from it.") with open("config.yml", encoding="UTF-8") as f: user_config = yaml.safe_load(f) _recursive_update(_CONFIG_YAML, user_config) @@ -123,11 +119,10 @@ def check_required_keys(keys): if lookup is None: raise KeyError(key) except KeyError: - log.critical( + raise KeyError( f"A configuration for `{key_path}` is required, but was not found. " "Please set it in `config.yml` or setup an environment variable and try again." ) - raise try: @@ -186,8 +181,7 @@ def __getattr__(cls, name): (cls.section, cls.subsection, name) if cls.subsection is not None else (cls.section, name) ) - # Only an INFO log since this can be caught through `hasattr` or `getattr`. - log.info(f"Tried accessing configuration variable at `{dotted_path}`, but it could not be found.") + print(f"Tried accessing configuration variable at `{dotted_path}`, but it could not be found.") raise AttributeError(repr(name)) from e def __getitem__(cls, name): diff --git a/bot/converters.py b/bot/converters.py index 0c20f7b108..4a4d3b5441 100644 --- a/bot/converters.py +++ b/bot/converters.py @@ -1,6 +1,5 @@ from __future__ import annotations -import logging import re import typing as t from datetime import datetime @@ -19,13 +18,15 @@ from bot.constants import URLs from bot.errors import InvalidInfraction from bot.exts.info.doc import _inventory_parser +from bot.log import get_logger from bot.utils.extensions import EXTENSIONS, unqualify from bot.utils.regex import INVITE_RE from bot.utils.time import parse_duration_string + if t.TYPE_CHECKING: from bot.exts.info.source import SourceType -log = logging.getLogger(__name__) +log = get_logger(__name__) DISCORD_EPOCH_DT = datetime.utcfromtimestamp(DISCORD_EPOCH / 1000) RE_USER_MENTION = re.compile(r"<@!?([0-9]+)>$") diff --git a/bot/decorators.py b/bot/decorators.py index ee210be260..048a2a09ac 100644 --- a/bot/decorators.py +++ b/bot/decorators.py @@ -1,6 +1,5 @@ import asyncio import functools -import logging import types import typing as t from contextlib import suppress @@ -10,11 +9,12 @@ from discord.ext.commands import Cog, Context from bot.constants import Channels, DEBUG_MODE, RedirectOutput +from bot.log import get_logger from bot.utils import function, scheduling from bot.utils.checks import ContextCheckFailure, in_whitelist_check from bot.utils.function import command_wraps -log = logging.getLogger(__name__) +log = get_logger(__name__) def in_whitelist( diff --git a/bot/exts/backend/branding/_cog.py b/bot/exts/backend/branding/_cog.py index ab0a761ffe..9c5bdbb4ec 100644 --- a/bot/exts/backend/branding/_cog.py +++ b/bot/exts/backend/branding/_cog.py @@ -1,6 +1,5 @@ import asyncio import contextlib -import logging import random import typing as t from datetime import timedelta @@ -17,9 +16,10 @@ from bot.constants import Branding as BrandingConfig, Channels, Colours, Guild, MODERATION_ROLES from bot.decorators import mock_in_debug from bot.exts.backend.branding._repository import BrandingRepository, Event, RemoteObject +from bot.log import get_logger from bot.utils import scheduling -log = logging.getLogger(__name__) +log = get_logger(__name__) class AssetType(Enum): diff --git a/bot/exts/backend/branding/_repository.py b/bot/exts/backend/branding/_repository.py index 7b09d46416..d88ea67f36 100644 --- a/bot/exts/backend/branding/_repository.py +++ b/bot/exts/backend/branding/_repository.py @@ -1,4 +1,3 @@ -import logging import typing as t from datetime import date, datetime @@ -7,6 +6,7 @@ from bot.bot import Bot from bot.constants import Keys from bot.errors import BrandingMisconfiguration +from bot.log import get_logger # Base URL for requests into the branding repository. BRANDING_URL = "https://api.github.com/repos/python-discord/branding/contents" @@ -25,7 +25,7 @@ # Format used to parse date strings after we inject `ARBITRARY_YEAR` at the end. DATE_FMT = "%B %d %Y" # Ex: July 10 2020 -log = logging.getLogger(__name__) +log = get_logger(__name__) class RemoteObject: diff --git a/bot/exts/backend/config_verifier.py b/bot/exts/backend/config_verifier.py index c24cb324f2..dc85a65a2f 100644 --- a/bot/exts/backend/config_verifier.py +++ b/bot/exts/backend/config_verifier.py @@ -1,12 +1,11 @@ -import logging - from discord.ext.commands import Cog from bot import constants from bot.bot import Bot +from bot.log import get_logger from bot.utils import scheduling -log = logging.getLogger(__name__) +log = get_logger(__name__) class ConfigVerifier(Cog): diff --git a/bot/exts/backend/error_handler.py b/bot/exts/backend/error_handler.py index 578c372c30..7644b93ae4 100644 --- a/bot/exts/backend/error_handler.py +++ b/bot/exts/backend/error_handler.py @@ -1,5 +1,4 @@ import difflib -import logging import typing as t from discord import Embed @@ -11,9 +10,10 @@ from bot.constants import Colours, Icons, MODERATION_ROLES from bot.converters import TagNameConverter from bot.errors import InvalidInfractedUserError, LockedResourceError +from bot.log import get_logger from bot.utils.checks import ContextCheckFailure -log = logging.getLogger(__name__) +log = get_logger(__name__) class ErrorHandler(Cog): diff --git a/bot/exts/backend/logging.py b/bot/exts/backend/logging.py index 8f1b8026f3..2d03cd5805 100644 --- a/bot/exts/backend/logging.py +++ b/bot/exts/backend/logging.py @@ -1,13 +1,12 @@ -import logging - from discord import Embed from discord.ext.commands import Cog from bot.bot import Bot from bot.constants import Channels, DEBUG_MODE +from bot.log import get_logger from bot.utils import scheduling -log = logging.getLogger(__name__) +log = get_logger(__name__) class Logging(Cog): diff --git a/bot/exts/backend/sync/_cog.py b/bot/exts/backend/sync/_cog.py index f88dcf538d..80f5750bcd 100644 --- a/bot/exts/backend/sync/_cog.py +++ b/bot/exts/backend/sync/_cog.py @@ -1,4 +1,3 @@ -import logging from typing import Any, Dict from discord import Member, Role, User @@ -9,9 +8,10 @@ from bot.api import ResponseCodeError from bot.bot import Bot from bot.exts.backend.sync import _syncers +from bot.log import get_logger from bot.utils import scheduling -log = logging.getLogger(__name__) +log = get_logger(__name__) class Sync(Cog): diff --git a/bot/exts/backend/sync/_syncers.py b/bot/exts/backend/sync/_syncers.py index 50016df0c8..45301b0980 100644 --- a/bot/exts/backend/sync/_syncers.py +++ b/bot/exts/backend/sync/_syncers.py @@ -1,5 +1,4 @@ import abc -import logging import typing as t from collections import namedtuple @@ -9,9 +8,10 @@ import bot from bot.api import ResponseCodeError +from bot.log import get_logger from bot.utils.members import get_or_fetch_member -log = logging.getLogger(__name__) +log = get_logger(__name__) CHUNK_SIZE = 1000 diff --git a/bot/exts/events/code_jams/_channels.py b/bot/exts/events/code_jams/_channels.py index 34ff0ad419..e8cf5f7bf2 100644 --- a/bot/exts/events/code_jams/_channels.py +++ b/bot/exts/events/code_jams/_channels.py @@ -1,11 +1,11 @@ -import logging import typing as t import discord from bot.constants import Categories, Channels, Roles +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) MAX_CHANNELS = 50 CATEGORY_NAME = "Code Jam" diff --git a/bot/exts/events/code_jams/_cog.py b/bot/exts/events/code_jams/_cog.py index 7b0831ab44..b31d628d56 100644 --- a/bot/exts/events/code_jams/_cog.py +++ b/bot/exts/events/code_jams/_cog.py @@ -1,6 +1,5 @@ import asyncio import csv -import logging import typing as t from collections import defaultdict @@ -11,10 +10,11 @@ from bot.bot import Bot from bot.constants import Emojis, Roles from bot.exts.events.code_jams import _channels +from bot.log import get_logger from bot.utils.members import get_or_fetch_member from bot.utils.services import send_to_paste_service -log = logging.getLogger(__name__) +log = get_logger(__name__) TEAM_LEADERS_COLOUR = 0x11806a DELETION_REACTION = "\U0001f4a5" diff --git a/bot/exts/filters/antimalware.py b/bot/exts/filters/antimalware.py index e708e5149f..d727f79401 100644 --- a/bot/exts/filters/antimalware.py +++ b/bot/exts/filters/antimalware.py @@ -1,4 +1,3 @@ -import logging import typing as t from os.path import splitext @@ -8,8 +7,9 @@ from bot.bot import Bot from bot.constants import Channels, Filter, URLs from bot.exts.events.code_jams._channels import CATEGORY_NAME as JAM_CATEGORY_NAME +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) PY_EMBED_DESCRIPTION = ( "It looks like you tried to attach a Python file - " diff --git a/bot/exts/filters/antispam.py b/bot/exts/filters/antispam.py index d1ab785d84..1787beea54 100644 --- a/bot/exts/filters/antispam.py +++ b/bot/exts/filters/antispam.py @@ -1,5 +1,4 @@ import asyncio -import logging from collections import defaultdict from collections.abc import Mapping from dataclasses import dataclass, field @@ -21,12 +20,12 @@ from bot.converters import Duration from bot.exts.events.code_jams._channels import CATEGORY_NAME as JAM_CATEGORY_NAME from bot.exts.moderation.modlog import ModLog +from bot.log import get_logger from bot.utils import lock, scheduling from bot.utils.message_cache import MessageCache from bot.utils.messages import format_user, send_attachments - -log = logging.getLogger(__name__) +log = get_logger(__name__) RULE_FUNCTION_MAPPING = { 'attachments': rules.apply_attachments, diff --git a/bot/exts/filters/filter_lists.py b/bot/exts/filters/filter_lists.py index a06437f3df..4b5200684b 100644 --- a/bot/exts/filters/filter_lists.py +++ b/bot/exts/filters/filter_lists.py @@ -1,4 +1,3 @@ -import logging from typing import Optional from discord import Colour, Embed @@ -8,10 +7,11 @@ from bot.api import ResponseCodeError from bot.bot import Bot from bot.converters import ValidDiscordServerInvite, ValidFilterListType +from bot.log import get_logger from bot.pagination import LinePaginator from bot.utils import scheduling -log = logging.getLogger(__name__) +log = get_logger(__name__) class FilterLists(Cog): diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py index cb199bb28e..9281eb3433 100644 --- a/bot/exts/filters/filtering.py +++ b/bot/exts/filters/filtering.py @@ -1,5 +1,4 @@ import asyncio -import logging import re from datetime import datetime, timedelta from typing import Any, Dict, List, Mapping, NamedTuple, Optional, Tuple, Union @@ -21,11 +20,12 @@ ) from bot.exts.events.code_jams._channels import CATEGORY_NAME as JAM_CATEGORY_NAME from bot.exts.moderation.modlog import ModLog +from bot.log import get_logger from bot.utils import scheduling from bot.utils.messages import format_user from bot.utils.regex import INVITE_RE -log = logging.getLogger(__name__) +log = get_logger(__name__) # Regular expressions CODE_BLOCK_RE = re.compile( diff --git a/bot/exts/filters/security.py b/bot/exts/filters/security.py index c680c5e274..fe39184234 100644 --- a/bot/exts/filters/security.py +++ b/bot/exts/filters/security.py @@ -1,10 +1,9 @@ -import logging - from discord.ext.commands import Cog, Context, NoPrivateMessage from bot.bot import Bot +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) class Security(Cog): diff --git a/bot/exts/filters/token_remover.py b/bot/exts/filters/token_remover.py index 39abcdf063..520283ba31 100644 --- a/bot/exts/filters/token_remover.py +++ b/bot/exts/filters/token_remover.py @@ -1,6 +1,5 @@ import base64 import binascii -import logging import re import typing as t @@ -11,10 +10,11 @@ from bot.bot import Bot from bot.constants import Channels, Colours, Event, Icons from bot.exts.moderation.modlog import ModLog +from bot.log import get_logger from bot.utils.members import get_or_fetch_member from bot.utils.messages import format_user -log = logging.getLogger(__name__) +log = get_logger(__name__) LOG_MESSAGE = ( "Censored a seemingly valid token sent by {author} in {channel}, " diff --git a/bot/exts/filters/webhook_remover.py b/bot/exts/filters/webhook_remover.py index 2ea1eb1c8a..96334317c8 100644 --- a/bot/exts/filters/webhook_remover.py +++ b/bot/exts/filters/webhook_remover.py @@ -1,4 +1,3 @@ -import logging import re from discord import Colour, Message, NotFound @@ -7,6 +6,7 @@ from bot.bot import Bot from bot.constants import Channels, Colours, Event, Icons from bot.exts.moderation.modlog import ModLog +from bot.log import get_logger from bot.utils.messages import format_user WEBHOOK_URL_RE = re.compile( @@ -21,7 +21,7 @@ "mistake, please let us know." ) -log = logging.getLogger(__name__) +log = get_logger(__name__) class WebhookRemover(Cog): diff --git a/bot/exts/fun/duck_pond.py b/bot/exts/fun/duck_pond.py index 7e279f5430..c51656343d 100644 --- a/bot/exts/fun/duck_pond.py +++ b/bot/exts/fun/duck_pond.py @@ -1,5 +1,4 @@ import asyncio -import logging from typing import Union import discord @@ -9,12 +8,13 @@ from bot import constants from bot.bot import Bot from bot.converters import MemberOrUser +from bot.log import get_logger from bot.utils import scheduling from bot.utils.checks import has_any_role from bot.utils.messages import count_unique_users_reaction, send_attachments from bot.utils.webhooks import send_webhook -log = logging.getLogger(__name__) +log = get_logger(__name__) class DuckPond(Cog): diff --git a/bot/exts/fun/off_topic_names.py b/bot/exts/fun/off_topic_names.py index 2f56aa5baf..427667c665 100644 --- a/bot/exts/fun/off_topic_names.py +++ b/bot/exts/fun/off_topic_names.py @@ -1,5 +1,4 @@ import difflib -import logging from datetime import datetime, timedelta from discord import Colour, Embed @@ -10,11 +9,12 @@ from bot.bot import Bot from bot.constants import Channels, MODERATION_ROLES from bot.converters import OffTopicName +from bot.log import get_logger from bot.pagination import LinePaginator from bot.utils import scheduling CHANNELS = (Channels.off_topic_0, Channels.off_topic_1, Channels.off_topic_2) -log = logging.getLogger(__name__) +log = get_logger(__name__) async def update_names(bot: Bot) -> None: diff --git a/bot/exts/help_channels/__init__.py b/bot/exts/help_channels/__init__.py index 781f404496..beba18aa66 100644 --- a/bot/exts/help_channels/__init__.py +++ b/bot/exts/help_channels/__init__.py @@ -1,10 +1,9 @@ -import logging - from bot import constants from bot.bot import Bot from bot.exts.help_channels._channel import MAX_CHANNELS_PER_CATEGORY +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) def validate_config() -> None: diff --git a/bot/exts/help_channels/_channel.py b/bot/exts/help_channels/_channel.py index f1bcea1710..e43c1e7898 100644 --- a/bot/exts/help_channels/_channel.py +++ b/bot/exts/help_channels/_channel.py @@ -1,4 +1,3 @@ -import logging import typing as t from datetime import timedelta from enum import Enum @@ -10,9 +9,10 @@ import bot from bot import constants from bot.exts.help_channels import _caches, _message +from bot.log import get_logger from bot.utils.channel import get_or_fetch_channel -log = logging.getLogger(__name__) +log = get_logger(__name__) MAX_CHANNELS_PER_CATEGORY = 50 EXCLUDED_CHANNELS = (constants.Channels.cooldown,) diff --git a/bot/exts/help_channels/_cog.py b/bot/exts/help_channels/_cog.py index 7c39bc1326..498305b473 100644 --- a/bot/exts/help_channels/_cog.py +++ b/bot/exts/help_channels/_cog.py @@ -1,5 +1,4 @@ import asyncio -import logging import random import typing as t from datetime import timedelta @@ -14,9 +13,10 @@ from bot.bot import Bot from bot.constants import Channels, RedirectOutput from bot.exts.help_channels import _caches, _channel, _message, _name, _stats +from bot.log import get_logger from bot.utils import channel as channel_utils, lock, members, scheduling -log = logging.getLogger(__name__) +log = get_logger(__name__) NAMESPACE = "help" HELP_CHANNEL_TOPIC = """ diff --git a/bot/exts/help_channels/_message.py b/bot/exts/help_channels/_message.py index 077b20b470..a52c675709 100644 --- a/bot/exts/help_channels/_message.py +++ b/bot/exts/help_channels/_message.py @@ -1,4 +1,3 @@ -import logging import textwrap import typing as t @@ -9,8 +8,9 @@ import bot from bot import constants from bot.exts.help_channels import _caches +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) ASKING_GUIDE_URL = "https://pythondiscord.com/pages/asking-good-questions/" diff --git a/bot/exts/help_channels/_name.py b/bot/exts/help_channels/_name.py index 061f855ae5..a9d9b2df14 100644 --- a/bot/exts/help_channels/_name.py +++ b/bot/exts/help_channels/_name.py @@ -1,5 +1,4 @@ import json -import logging import typing as t from collections import deque from pathlib import Path @@ -8,8 +7,9 @@ from bot import constants from bot.exts.help_channels._channel import MAX_CHANNELS_PER_CATEGORY, get_category_channels +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) def create_name_queue(*categories: discord.CategoryChannel) -> deque: diff --git a/bot/exts/help_channels/_stats.py b/bot/exts/help_channels/_stats.py index eb34e75e13..4698c26de3 100644 --- a/bot/exts/help_channels/_stats.py +++ b/bot/exts/help_channels/_stats.py @@ -1,12 +1,11 @@ -import logging - from more_itertools import ilen import bot from bot import constants from bot.exts.help_channels import _caches, _channel +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) def report_counts() -> None: diff --git a/bot/exts/info/code_snippets.py b/bot/exts/info/code_snippets.py index 4a90a06688..07b1b8a2d8 100644 --- a/bot/exts/info/code_snippets.py +++ b/bot/exts/info/code_snippets.py @@ -10,9 +10,10 @@ from bot.bot import Bot from bot.constants import Channels +from bot.log import get_logger from bot.utils.messages import wait_for_deletion -log = logging.getLogger(__name__) +log = get_logger(__name__) GITHUB_RE = re.compile( r'https://github\.com/(?P[a-zA-Z0-9-]+/[\w.-]+)/blob/' diff --git a/bot/exts/info/codeblock/_cog.py b/bot/exts/info/codeblock/_cog.py index f63a459ffa..a859d8cef2 100644 --- a/bot/exts/info/codeblock/_cog.py +++ b/bot/exts/info/codeblock/_cog.py @@ -1,4 +1,3 @@ -import logging import time from typing import Optional @@ -11,11 +10,12 @@ from bot.exts.filters.token_remover import TokenRemover from bot.exts.filters.webhook_remover import WEBHOOK_URL_RE from bot.exts.info.codeblock._instructions import get_instructions +from bot.log import get_logger from bot.utils import has_lines, scheduling from bot.utils.channel import is_help_channel from bot.utils.messages import wait_for_deletion -log = logging.getLogger(__name__) +log = get_logger(__name__) class CodeBlockCog(Cog, name="Code Block"): diff --git a/bot/exts/info/codeblock/_instructions.py b/bot/exts/info/codeblock/_instructions.py index dadb5e1efa..8fcadeec2a 100644 --- a/bot/exts/info/codeblock/_instructions.py +++ b/bot/exts/info/codeblock/_instructions.py @@ -1,11 +1,11 @@ """This module generates and formats instructional messages about fixing Markdown code blocks.""" -import logging from typing import Optional from bot.exts.info.codeblock import _parsing +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) _EXAMPLE_PY = "{lang}\nprint('Hello, world!')" # Make sure to escape any Markdown symbols here. _EXAMPLE_CODE_BLOCKS = ( diff --git a/bot/exts/info/codeblock/_parsing.py b/bot/exts/info/codeblock/_parsing.py index 73fd11b942..3c193d6c51 100644 --- a/bot/exts/info/codeblock/_parsing.py +++ b/bot/exts/info/codeblock/_parsing.py @@ -1,15 +1,15 @@ """This module provides functions for parsing Markdown code blocks.""" import ast -import logging import re import textwrap from typing import NamedTuple, Optional, Sequence from bot import constants +from bot.log import get_logger from bot.utils import has_lines -log = logging.getLogger(__name__) +log = get_logger(__name__) BACKTICK = "`" PY_LANG_CODES = ("python-repl", "python", "pycon", "py") # Order is important; "py" is last cause it's a subset. diff --git a/bot/exts/info/doc/_batch_parser.py b/bot/exts/info/doc/_batch_parser.py index 51ee29b68f..ac72e5e49c 100644 --- a/bot/exts/info/doc/_batch_parser.py +++ b/bot/exts/info/doc/_batch_parser.py @@ -2,7 +2,6 @@ import asyncio import collections -import logging from collections import defaultdict from contextlib import suppress from operator import attrgetter @@ -13,11 +12,12 @@ import bot from bot.constants import Channels +from bot.log import get_logger from bot.utils import scheduling from . import _cog, doc_cache from ._parsing import get_symbol_markdown -log = logging.getLogger(__name__) +log = get_logger(__name__) class StaleInventoryNotifier: diff --git a/bot/exts/info/doc/_cog.py b/bot/exts/info/doc/_cog.py index ca6af946b3..243e7e4e17 100644 --- a/bot/exts/info/doc/_cog.py +++ b/bot/exts/info/doc/_cog.py @@ -1,7 +1,6 @@ from __future__ import annotations import asyncio -import logging import sys import textwrap from collections import defaultdict @@ -17,6 +16,7 @@ from bot.bot import Bot from bot.constants import MODERATION_ROLES, RedirectOutput from bot.converters import Inventory, PackageName, ValidURL, allowed_strings +from bot.log import get_logger from bot.pagination import LinePaginator from bot.utils import scheduling from bot.utils.lock import SharedEvent, lock @@ -25,7 +25,7 @@ from . import NAMESPACE, PRIORITY_PACKAGES, _batch_parser, doc_cache from ._inventory_parser import InvalidHeaderError, InventoryDict, fetch_inventory -log = logging.getLogger(__name__) +log = get_logger(__name__) # symbols with a group contained here will get the group prefixed on duplicates FORCE_PREFIX_GROUPS = ( diff --git a/bot/exts/info/doc/_html.py b/bot/exts/info/doc/_html.py index 94efd81b79..0e524a6bb3 100644 --- a/bot/exts/info/doc/_html.py +++ b/bot/exts/info/doc/_html.py @@ -1,4 +1,3 @@ -import logging import re from functools import partial from typing import Callable, Container, Iterable, List, Union @@ -6,9 +5,10 @@ from bs4 import BeautifulSoup from bs4.element import NavigableString, PageElement, SoupStrainer, Tag +from bot.log import get_logger from . import MAX_SIGNATURE_AMOUNT -log = logging.getLogger(__name__) +log = get_logger(__name__) _UNWANTED_SIGNATURE_SYMBOLS_RE = re.compile(r"\[source]|\\\\|¶") _SEARCH_END_TAG_ATTRS = ( diff --git a/bot/exts/info/doc/_inventory_parser.py b/bot/exts/info/doc/_inventory_parser.py index 61924d0701..e69246d473 100644 --- a/bot/exts/info/doc/_inventory_parser.py +++ b/bot/exts/info/doc/_inventory_parser.py @@ -1,4 +1,3 @@ -import logging import re import zlib from collections import defaultdict @@ -7,8 +6,9 @@ import aiohttp import bot +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) FAILED_REQUEST_ATTEMPTS = 3 _V2_LINE_RE = re.compile(r'(?x)(.+?)\s+(\S*:\S*)\s+(-?\d+)\s+?(\S*)\s+(.*)') diff --git a/bot/exts/info/doc/_parsing.py b/bot/exts/info/doc/_parsing.py index 1a0d42c474..1b98b122bf 100644 --- a/bot/exts/info/doc/_parsing.py +++ b/bot/exts/info/doc/_parsing.py @@ -1,6 +1,5 @@ from __future__ import annotations -import logging import re import string import textwrap @@ -10,14 +9,16 @@ from bs4 import BeautifulSoup from bs4.element import NavigableString, Tag +from bot.log import get_logger from bot.utils.helpers import find_nth_occurrence from . import MAX_SIGNATURE_AMOUNT from ._html import get_dd_description, get_general_description, get_signatures from ._markdown import DocMarkdownConverter + if TYPE_CHECKING: from ._cog import DocItem -log = logging.getLogger(__name__) +log = get_logger(__name__) _WHITESPACE_AFTER_NEWLINES_RE = re.compile(r"(?<=\n\n)(\s+)") _PARAMETERS_RE = re.compile(r"\((.+)\)") diff --git a/bot/exts/info/doc/_redis_cache.py b/bot/exts/info/doc/_redis_cache.py index ad764816f0..79648893a2 100644 --- a/bot/exts/info/doc/_redis_cache.py +++ b/bot/exts/info/doc/_redis_cache.py @@ -4,6 +4,7 @@ from typing import Optional, TYPE_CHECKING from async_rediscache.types.base import RedisObject, namespace_lock + if TYPE_CHECKING: from ._cog import DocItem diff --git a/bot/exts/info/help.py b/bot/exts/info/help.py index 21a6cf752d..f413caded5 100644 --- a/bot/exts/info/help.py +++ b/bot/exts/info/help.py @@ -1,5 +1,4 @@ import itertools -import logging from collections import namedtuple from contextlib import suppress from typing import List, Union @@ -12,10 +11,11 @@ from bot import constants from bot.constants import Channels, STAFF_PARTNERS_COMMUNITY_ROLES from bot.decorators import redirect_output +from bot.log import get_logger from bot.pagination import LinePaginator from bot.utils.messages import wait_for_deletion -log = logging.getLogger(__name__) +log = get_logger(__name__) COMMANDS_PER_PAGE = 8 PREFIX = constants.Bot.prefix diff --git a/bot/exts/info/information.py b/bot/exts/info/information.py index 3bf2ce5a93..1b3e28e79e 100644 --- a/bot/exts/info/information.py +++ b/bot/exts/info/information.py @@ -1,5 +1,4 @@ import colorsys -import logging import pprint import textwrap from collections import defaultdict @@ -16,13 +15,14 @@ from bot.converters import MemberOrUser from bot.decorators import in_whitelist from bot.errors import NonExistentRoleError +from bot.log import get_logger from bot.pagination import LinePaginator from bot.utils.channel import is_mod_channel, is_staff_channel from bot.utils.checks import cooldown_with_role_bypass, has_no_roles_check, in_whitelist_check from bot.utils.members import get_or_fetch_member from bot.utils.time import TimestampFormats, discord_timestamp, humanize_delta -log = logging.getLogger(__name__) +log = get_logger(__name__) class Information(Cog): diff --git a/bot/exts/info/pep.py b/bot/exts/info/pep.py index bbd112911c..259095b50a 100644 --- a/bot/exts/info/pep.py +++ b/bot/exts/info/pep.py @@ -1,4 +1,3 @@ -import logging from datetime import datetime, timedelta from email.parser import HeaderParser from io import StringIO @@ -9,10 +8,11 @@ from bot.bot import Bot from bot.constants import Keys +from bot.log import get_logger from bot.utils import scheduling from bot.utils.caching import AsyncCache -log = logging.getLogger(__name__) +log = get_logger(__name__) ICON_URL = "https://www.python.org/static/opengraph-icon-200x200.png" BASE_PEP_URL = "http://www.python.org/dev/peps/pep-" diff --git a/bot/exts/info/pypi.py b/bot/exts/info/pypi.py index 62498ce0ba..c3d2e2a3c7 100644 --- a/bot/exts/info/pypi.py +++ b/bot/exts/info/pypi.py @@ -1,5 +1,4 @@ import itertools -import logging import random import re from contextlib import suppress @@ -10,6 +9,7 @@ from bot.bot import Bot from bot.constants import Colours, NEGATIVE_REPLIES, RedirectOutput +from bot.log import get_logger from bot.utils.messages import wait_for_deletion URL = "https://pypi.org/pypi/{package}/json" @@ -20,7 +20,7 @@ ILLEGAL_CHARACTERS = re.compile(r"[^-_.a-zA-Z0-9]+") INVALID_INPUT_DELETE_DELAY = RedirectOutput.delete_delay -log = logging.getLogger(__name__) +log = get_logger(__name__) class PyPi(Cog): diff --git a/bot/exts/info/python_news.py b/bot/exts/info/python_news.py index 2a8b64f32d..2fad9d2ab3 100644 --- a/bot/exts/info/python_news.py +++ b/bot/exts/info/python_news.py @@ -1,4 +1,3 @@ -import logging import re import typing as t from datetime import date, datetime @@ -11,6 +10,7 @@ from bot import constants from bot.bot import Bot +from bot.log import get_logger from bot.utils import scheduling from bot.utils.webhooks import send_webhook @@ -31,7 +31,7 @@ re.DOTALL # required to support multi-line codeblocks ) -log = logging.getLogger(__name__) +log = get_logger(__name__) class PythonNews(Cog): diff --git a/bot/exts/info/site.py b/bot/exts/info/site.py index 28eb558a67..e1f2f5153a 100644 --- a/bot/exts/info/site.py +++ b/bot/exts/info/site.py @@ -1,13 +1,12 @@ -import logging - from discord import Colour, Embed from discord.ext.commands import Cog, Context, Greedy, group from bot.bot import Bot from bot.constants import URLs +from bot.log import get_logger from bot.pagination import LinePaginator -log = logging.getLogger(__name__) +log = get_logger(__name__) BASE_URL = f"{URLs.site_schema}{URLs.site}" diff --git a/bot/exts/info/tags.py b/bot/exts/info/tags.py index bb91a85637..8426475558 100644 --- a/bot/exts/info/tags.py +++ b/bot/exts/info/tags.py @@ -1,4 +1,3 @@ -import logging import re import time from pathlib import Path @@ -10,10 +9,11 @@ from bot import constants from bot.bot import Bot from bot.converters import TagNameConverter +from bot.log import get_logger from bot.pagination import LinePaginator from bot.utils.messages import wait_for_deletion -log = logging.getLogger(__name__) +log = get_logger(__name__) TEST_CHANNELS = ( constants.Channels.bot_commands, diff --git a/bot/exts/moderation/defcon.py b/bot/exts/moderation/defcon.py index 189f8eb31d..80ba101129 100644 --- a/bot/exts/moderation/defcon.py +++ b/bot/exts/moderation/defcon.py @@ -1,4 +1,3 @@ -import logging import traceback from collections import namedtuple from datetime import datetime @@ -8,7 +7,7 @@ from aioredis import RedisError from async_rediscache import RedisCache from dateutil.relativedelta import relativedelta -from discord import Colour, Embed, Forbidden, Member, User +from discord import Colour, Embed, Forbidden, Member, TextChannel, User from discord.ext import tasks from discord.ext.commands import Cog, Context, group, has_any_role @@ -16,6 +15,7 @@ from bot.constants import Channels, Colours, Emojis, Event, Icons, MODERATION_ROLES, Roles from bot.converters import DurationDelta, Expiry from bot.exts.moderation.modlog import ModLog +from bot.log import get_logger from bot.utils import scheduling from bot.utils.messages import format_user from bot.utils.scheduling import Scheduler @@ -23,7 +23,7 @@ TimestampFormats, discord_timestamp, humanize_delta, parse_duration_string, relativedelta_to_timedelta ) -log = logging.getLogger(__name__) +log = get_logger(__name__) REJECTION_MESSAGE = """ Hi, {user} - Thanks for your interest in our server! @@ -176,7 +176,7 @@ async def threshold_command( """ if isinstance(threshold, int): threshold = relativedelta(days=threshold) - await self._update_threshold(ctx.author, threshold=threshold, expiry=expiry) + await self._update_threshold(ctx.author, ctx.channel, threshold, expiry) @defcon_group.command() @has_any_role(Roles.admins) @@ -218,7 +218,13 @@ def _update_channel_topic(self) -> None: scheduling.create_task(self.channel.edit(topic=new_topic)) @defcon_settings.atomic_transaction - async def _update_threshold(self, author: User, threshold: relativedelta, expiry: Optional[Expiry] = None) -> None: + async def _update_threshold( + self, + author: User, + channel: TextChannel, + threshold: relativedelta, + expiry: Optional[Expiry] = None + ) -> None: """Update the new threshold in the cog, cache, defcon channel, and logs, and additionally schedule expiry.""" self.threshold = threshold if threshold == relativedelta(days=0): # If the threshold is 0, we don't need to schedule anything @@ -258,9 +264,13 @@ async def _update_threshold(self, author: User, threshold: relativedelta, expiry else: channel_message = "removed" - await self.channel.send( - f"{action.value.emoji} DEFCON threshold {channel_message}{error}." - ) + message = f"{action.value.emoji} DEFCON threshold {channel_message}{error}." + await self.channel.send(message) + + # If invoked outside of #defcon send to `ctx.channel` too + if channel != self.channel: + await channel.send(message) + await self._send_defcon_log(action, author) self._update_channel_topic() @@ -268,7 +278,7 @@ async def _update_threshold(self, author: User, threshold: relativedelta, expiry async def _remove_threshold(self) -> None: """Resets the threshold back to 0.""" - await self._update_threshold(self.bot.user, relativedelta(days=0)) + await self._update_threshold(self.bot.user, self.channel, relativedelta(days=0)) @staticmethod def _stringify_relativedelta(delta: relativedelta) -> str: diff --git a/bot/exts/moderation/dm_relay.py b/bot/exts/moderation/dm_relay.py index 0051db82f4..566422e292 100644 --- a/bot/exts/moderation/dm_relay.py +++ b/bot/exts/moderation/dm_relay.py @@ -1,14 +1,13 @@ -import logging - import discord from discord.ext.commands import Cog, Context, command, has_any_role from bot.bot import Bot from bot.constants import Emojis, MODERATION_ROLES +from bot.log import get_logger from bot.utils.channel import is_mod_channel from bot.utils.services import send_to_paste_service -log = logging.getLogger(__name__) +log = get_logger(__name__) class DMRelay(Cog): diff --git a/bot/exts/moderation/incidents.py b/bot/exts/moderation/incidents.py index c810925cfa..097fa36f12 100644 --- a/bot/exts/moderation/incidents.py +++ b/bot/exts/moderation/incidents.py @@ -1,5 +1,4 @@ import asyncio -import logging import typing as t from datetime import datetime from enum import Enum @@ -9,10 +8,11 @@ from bot.bot import Bot from bot.constants import Channels, Colours, Emojis, Guild, Webhooks +from bot.log import get_logger from bot.utils import scheduling from bot.utils.messages import sub_clyde -log = logging.getLogger(__name__) +log = get_logger(__name__) # Amount of messages for `crawl_task` to process at most on start-up - limited to 50 # as in practice, there should never be this many messages, and if there are, diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index 21b5348a35..2a27f59c05 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -1,4 +1,3 @@ -import logging import textwrap import typing as t from abc import abstractmethod @@ -16,10 +15,11 @@ from bot.converters import MemberOrUser from bot.exts.moderation.infraction import _utils from bot.exts.moderation.modlog import ModLog +from bot.log import get_logger from bot.utils import messages, scheduling, time from bot.utils.channel import is_mod_channel -log = logging.getLogger(__name__) +log = get_logger(__name__) class InfractionScheduler: @@ -161,11 +161,11 @@ async def apply_infraction( # send DMs to user that it doesn't share a guild with. If we were to # apply kick/ban infractions first, this would mean that we'd make it # impossible for us to deliver a DM. See python-discord/bot#982. - if not infraction["hidden"]: + if not infraction["hidden"] and infr_type in {"ban", "kick"}: dm_result = f"{constants.Emojis.failmail} " dm_log_text = "\nDM: **Failed**" - # Accordingly display whether the user was successfully notified via DM. + # Accordingly update whether the user was successfully notified via DM. if await _utils.notify_infraction(user, infr_type.replace("_", " ").title(), expiry, user_reason, icon): dm_result = ":incoming_envelope: " dm_log_text = "\nDM: Sent" @@ -228,6 +228,16 @@ async def apply_infraction( else: infr_message = f" **{purge}{' '.join(infr_type.split('_'))}** to {user.mention}{expiry_msg}{end_msg}" + # If we need to DM and haven't already tried to + if not infraction["hidden"] and infr_type not in {"ban", "kick"}: + dm_result = f"{constants.Emojis.failmail} " + dm_log_text = "\nDM: **Failed**" + + # Accordingly update whether the user was successfully notified via DM. + if await _utils.notify_infraction(user, infr_type.replace("_", " ").title(), expiry, user_reason, icon): + dm_result = ":incoming_envelope: " + dm_log_text = "\nDM: Sent" + # Send a confirmation message to the invoking context. log.trace(f"Sending infraction #{id_} confirmation message.") await ctx.send(f"{dm_result}{confirm_msg}{infr_message}.") diff --git a/bot/exts/moderation/infraction/_utils.py b/bot/exts/moderation/infraction/_utils.py index b20ef1d06a..89718c8577 100644 --- a/bot/exts/moderation/infraction/_utils.py +++ b/bot/exts/moderation/infraction/_utils.py @@ -1,4 +1,3 @@ -import logging import typing as t from datetime import datetime @@ -9,8 +8,9 @@ from bot.constants import Colours, Icons from bot.converters import MemberOrUser from bot.errors import InvalidInfractedUserError +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) # apply icon, pardon icon INFRACTION_ICONS = { diff --git a/bot/exts/moderation/infraction/infractions.py b/bot/exts/moderation/infraction/infractions.py index a7f7dcb7f7..e495a94b3a 100644 --- a/bot/exts/moderation/infraction/infractions.py +++ b/bot/exts/moderation/infraction/infractions.py @@ -1,4 +1,3 @@ -import logging import textwrap import typing as t @@ -14,10 +13,11 @@ from bot.decorators import respect_role_hierarchy from bot.exts.moderation.infraction import _utils from bot.exts.moderation.infraction._scheduler import InfractionScheduler +from bot.log import get_logger from bot.utils.members import get_or_fetch_member from bot.utils.messages import format_user -log = logging.getLogger(__name__) +log = get_logger(__name__) class Infractions(InfractionScheduler, commands.Cog): diff --git a/bot/exts/moderation/infraction/management.py b/bot/exts/moderation/infraction/management.py index 8c5c83997f..b1c8b64dcc 100644 --- a/bot/exts/moderation/infraction/management.py +++ b/bot/exts/moderation/infraction/management.py @@ -1,4 +1,3 @@ -import logging import textwrap import typing as t from datetime import datetime @@ -16,13 +15,14 @@ from bot.errors import InvalidInfraction from bot.exts.moderation.infraction.infractions import Infractions from bot.exts.moderation.modlog import ModLog +from bot.log import get_logger from bot.pagination import LinePaginator from bot.utils import messages, time from bot.utils.channel import is_mod_channel from bot.utils.members import get_or_fetch_member from bot.utils.time import humanize_delta, until_expiration -log = logging.getLogger(__name__) +log = get_logger(__name__) class ModManagement(commands.Cog): @@ -141,10 +141,11 @@ async def infraction_edit( log_text = "" if duration is not None and not infraction['active']: - if reason is None: + if (infr_type := infraction['type']) in ('note', 'warning'): + await ctx.send(f":x: Cannot edit the expiration of a {infr_type}.") + else: await ctx.send(":x: Cannot edit the expiration of an expired infraction.") - return - confirm_messages.append("expiry unchanged (infraction already expired)") + return elif isinstance(duration, str): request_data['expires_at'] = None confirm_messages.append("marked as permanent") diff --git a/bot/exts/moderation/infraction/superstarify.py b/bot/exts/moderation/infraction/superstarify.py index 17cde68f6e..08c92b8f37 100644 --- a/bot/exts/moderation/infraction/superstarify.py +++ b/bot/exts/moderation/infraction/superstarify.py @@ -1,5 +1,4 @@ import json -import logging import random import textwrap import typing as t @@ -14,11 +13,12 @@ from bot.converters import Duration, Expiry from bot.exts.moderation.infraction import _utils from bot.exts.moderation.infraction._scheduler import InfractionScheduler +from bot.log import get_logger from bot.utils.members import get_or_fetch_member from bot.utils.messages import format_user from bot.utils.time import format_infraction -log = logging.getLogger(__name__) +log = get_logger(__name__) NICKNAME_POLICY_URL = "https://pythondiscord.com/pages/rules/#nickname-policy" SUPERSTARIFY_DEFAULT_DURATION = "1h" diff --git a/bot/exts/moderation/metabase.py b/bot/exts/moderation/metabase.py index 6eadd4badf..ce9c220b38 100644 --- a/bot/exts/moderation/metabase.py +++ b/bot/exts/moderation/metabase.py @@ -1,6 +1,5 @@ import csv import json -import logging from datetime import timedelta from io import StringIO from typing import Dict, List, Optional @@ -14,11 +13,12 @@ from bot.bot import Bot from bot.constants import Metabase as MetabaseConfig, Roles from bot.converters import allowed_strings +from bot.log import get_logger from bot.utils import scheduling, send_to_paste_service from bot.utils.channel import is_mod_channel from bot.utils.scheduling import Scheduler -log = logging.getLogger(__name__) +log = get_logger(__name__) BASE_HEADERS = { "Content-Type": "application/json" diff --git a/bot/exts/moderation/modlog.py b/bot/exts/moderation/modlog.py index 811bac135b..7d80d4ba5c 100644 --- a/bot/exts/moderation/modlog.py +++ b/bot/exts/moderation/modlog.py @@ -1,7 +1,6 @@ import asyncio import difflib import itertools -import logging import typing as t from datetime import datetime from itertools import zip_longest @@ -16,10 +15,11 @@ from bot.bot import Bot from bot.constants import Categories, Channels, Colours, Emojis, Event, Guild as GuildConstant, Icons, Roles, URLs +from bot.log import get_logger from bot.utils.messages import format_user from bot.utils.time import humanize_delta -log = logging.getLogger(__name__) +log = get_logger(__name__) GUILD_CHANNEL = t.Union[discord.CategoryChannel, discord.TextChannel, discord.VoiceChannel] diff --git a/bot/exts/moderation/modpings.py b/bot/exts/moderation/modpings.py index d775cdedf1..a7ccb81623 100644 --- a/bot/exts/moderation/modpings.py +++ b/bot/exts/moderation/modpings.py @@ -1,5 +1,4 @@ import datetime -import logging from async_rediscache import RedisCache from dateutil.parser import isoparse @@ -9,10 +8,11 @@ from bot.bot import Bot from bot.constants import Colours, Emojis, Guild, Icons, MODERATION_ROLES, Roles from bot.converters import Expiry +from bot.log import get_logger from bot.utils import scheduling from bot.utils.scheduling import Scheduler -log = logging.getLogger(__name__) +log = get_logger(__name__) class ModPings(Cog): diff --git a/bot/exts/moderation/silence.py b/bot/exts/moderation/silence.py index aa9f4d7169..5115202524 100644 --- a/bot/exts/moderation/silence.py +++ b/bot/exts/moderation/silence.py @@ -1,5 +1,4 @@ import json -import logging import typing from contextlib import suppress from datetime import datetime, timedelta, timezone @@ -14,11 +13,12 @@ from bot import constants from bot.bot import Bot from bot.converters import HushDurationConverter +from bot.log import get_logger from bot.utils import scheduling from bot.utils.lock import LockedResourceError, lock, lock_arg from bot.utils.scheduling import Scheduler -log = logging.getLogger(__name__) +log = get_logger(__name__) LOCK_NAMESPACE = "silence" diff --git a/bot/exts/moderation/slowmode.py b/bot/exts/moderation/slowmode.py index d8baff76a6..9583597e0e 100644 --- a/bot/exts/moderation/slowmode.py +++ b/bot/exts/moderation/slowmode.py @@ -1,4 +1,3 @@ -import logging from typing import Optional from dateutil.relativedelta import relativedelta @@ -8,9 +7,10 @@ from bot.bot import Bot from bot.constants import Channels, Emojis, MODERATION_ROLES from bot.converters import DurationDelta +from bot.log import get_logger from bot.utils import time -log = logging.getLogger(__name__) +log = get_logger(__name__) SLOWMODE_MAX_DELAY = 21600 # seconds diff --git a/bot/exts/moderation/stream.py b/bot/exts/moderation/stream.py index a179a9acc7..cf58bf5d90 100644 --- a/bot/exts/moderation/stream.py +++ b/bot/exts/moderation/stream.py @@ -1,4 +1,3 @@ -import logging from datetime import timedelta, timezone from operator import itemgetter @@ -14,12 +13,13 @@ STAFF_PARTNERS_COMMUNITY_ROLES, VideoPermission ) from bot.converters import Expiry +from bot.log import get_logger from bot.pagination import LinePaginator from bot.utils import scheduling from bot.utils.members import get_or_fetch_member from bot.utils.time import discord_timestamp, format_infraction_with_duration -log = logging.getLogger(__name__) +log = get_logger(__name__) class Stream(commands.Cog): diff --git a/bot/exts/moderation/verification.py b/bot/exts/moderation/verification.py index bfe9b74b45..ed5571d2a6 100644 --- a/bot/exts/moderation/verification.py +++ b/bot/exts/moderation/verification.py @@ -1,4 +1,3 @@ -import logging import typing as t import discord @@ -7,9 +6,10 @@ from bot import constants from bot.bot import Bot from bot.decorators import in_whitelist +from bot.log import get_logger from bot.utils.checks import InWhitelistCheckFailure -log = logging.getLogger(__name__) +log = get_logger(__name__) # Sent via DMs once user joins the guild ON_JOIN_MESSAGE = """ diff --git a/bot/exts/moderation/voice_gate.py b/bot/exts/moderation/voice_gate.py index 45224277b2..98f0ca5ad1 100644 --- a/bot/exts/moderation/voice_gate.py +++ b/bot/exts/moderation/voice_gate.py @@ -1,5 +1,4 @@ import asyncio -import logging from contextlib import suppress from datetime import datetime, timedelta @@ -8,15 +7,15 @@ 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, Event, MODERATION_ROLES, Roles, VoiceGate as GateConf from bot.decorators import has_no_roles, in_whitelist from bot.exts.moderation.modlog import ModLog +from bot.log import get_logger from bot.utils.checks import InWhitelistCheckFailure -log = logging.getLogger(__name__) +log = get_logger(__name__) # Flag written to the cog's RedisCache as a value when the Member's (key) notification # was already removed ~ this signals both that no further notifications should be sent, diff --git a/bot/exts/moderation/watchchannels/_watchchannel.py b/bot/exts/moderation/watchchannels/_watchchannel.py index df3a8dc4b7..f8b7781c55 100644 --- a/bot/exts/moderation/watchchannels/_watchchannel.py +++ b/bot/exts/moderation/watchchannels/_watchchannel.py @@ -1,5 +1,4 @@ import asyncio -import logging import re import textwrap from abc import abstractmethod @@ -17,12 +16,14 @@ from bot.exts.filters.token_remover import TokenRemover from bot.exts.filters.webhook_remover import WEBHOOK_URL_RE from bot.exts.moderation.modlog import ModLog +from bot.log import CustomLogger +from bot.log import get_logger from bot.pagination import LinePaginator from bot.utils import CogABCMeta, messages, scheduling from bot.utils.members import get_or_fetch_member from bot.utils.time import get_time_delta -log = logging.getLogger(__name__) +log = get_logger(__name__) URL_RE = re.compile(r"(https?://[^\s]+)") @@ -47,7 +48,7 @@ def __init__( webhook_id: int, api_endpoint: str, api_default_params: dict, - logger: logging.Logger, + logger: CustomLogger, *, disable_header: bool = False ) -> None: diff --git a/bot/exts/moderation/watchchannels/bigbrother.py b/bot/exts/moderation/watchchannels/bigbrother.py index 3aa253feae..ab37b1b803 100644 --- a/bot/exts/moderation/watchchannels/bigbrother.py +++ b/bot/exts/moderation/watchchannels/bigbrother.py @@ -1,4 +1,3 @@ -import logging import textwrap from collections import ChainMap @@ -9,8 +8,9 @@ from bot.converters import MemberOrUser from bot.exts.moderation.infraction._utils import post_infraction from bot.exts.moderation.watchchannels._watchchannel import WatchChannel +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) class BigBrother(WatchChannel, Cog, name="Big Brother"): @@ -87,11 +87,11 @@ async def apply_watch(self, ctx: Context, user: MemberOrUser, reason: str) -> No return if not await self.fetch_user_cache(): - await ctx.send(f":x: Updating the user cache failed, can't watch user {user}") + await ctx.send(f":x: Updating the user cache failed, can't watch user {user.mention}") return if user.id in self.watched_users: - await ctx.send(f":x: {user} is already being watched.") + await ctx.send(f":x: {user.mention} is already being watched.") return # discord.User instances don't have a roles attribute @@ -103,7 +103,7 @@ async def apply_watch(self, ctx: Context, user: MemberOrUser, reason: str) -> No if response is not None: self.watched_users[user.id] = response - msg = f":white_check_mark: Messages sent by {user} will now be relayed to Big Brother." + msg = f":white_check_mark: Messages sent by {user.mention} will now be relayed to Big Brother." history = await self.bot.api_client.get( self.api_endpoint, @@ -156,7 +156,7 @@ async def apply_unwatch(self, ctx: Context, user: MemberOrUser, reason: str, sen log.debug(f"Perma-banned user {user} was unwatched.") return log.trace("User is not banned. Sending message to channel") - message = f":white_check_mark: Messages sent by {user} will no longer be relayed." + message = f":white_check_mark: Messages sent by {user.mention} will no longer be relayed." else: log.trace("No active watches found for user.") diff --git a/bot/exts/recruitment/talentpool/_cog.py b/bot/exts/recruitment/talentpool/_cog.py index f9c836bbd3..2fafaec978 100644 --- a/bot/exts/recruitment/talentpool/_cog.py +++ b/bot/exts/recruitment/talentpool/_cog.py @@ -1,4 +1,3 @@ -import logging import textwrap from collections import ChainMap, defaultdict from io import StringIO @@ -14,6 +13,7 @@ from bot.constants import Channels, Emojis, Guild, MODERATION_ROLES, Roles, STAFF_ROLES from bot.converters import MemberOrUser, UnambiguousMemberOrUser from bot.exts.recruitment.talentpool._review import Reviewer +from bot.log import get_logger from bot.pagination import LinePaginator from bot.utils import scheduling, time from bot.utils.members import get_or_fetch_member @@ -22,7 +22,7 @@ AUTOREVIEW_ENABLED_KEY = "autoreview_enabled" REASON_MAX_CHARS = 1000 -log = logging.getLogger(__name__) +log = get_logger(__name__) class TalentPool(Cog, name="Talentpool"): diff --git a/bot/exts/recruitment/talentpool/_review.py b/bot/exts/recruitment/talentpool/_review.py index 14a8dd4c04..dcf73c2cb2 100644 --- a/bot/exts/recruitment/talentpool/_review.py +++ b/bot/exts/recruitment/talentpool/_review.py @@ -1,6 +1,5 @@ import asyncio import contextlib -import logging import random import re import textwrap @@ -16,6 +15,7 @@ from bot.api import ResponseCodeError from bot.bot import Bot from bot.constants import Channels, Colours, Emojis, Guild +from bot.log import get_logger from bot.utils.members import get_or_fetch_member from bot.utils.messages import count_unique_users_reaction, pin_no_system_message from bot.utils.scheduling import Scheduler @@ -24,7 +24,7 @@ if typing.TYPE_CHECKING: from bot.exts.recruitment.talentpool._cog import TalentPool -log = logging.getLogger(__name__) +log = get_logger(__name__) # Maximum amount of days before an automatic review is posted. MAX_DAYS_IN_POOL = 30 diff --git a/bot/exts/utils/bot.py b/bot/exts/utils/bot.py index caad98c90e..a00dc2e67f 100644 --- a/bot/exts/utils/bot.py +++ b/bot/exts/utils/bot.py @@ -7,8 +7,9 @@ from bot.bot import Bot from bot.constants import Guild, MODERATION_ROLES, URLs +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) class BotCog(Cog, name="Bot"): diff --git a/bot/exts/utils/clean.py b/bot/exts/utils/clean.py index 7163e4f590..69cf62f2f7 100644 --- a/bot/exts/utils/clean.py +++ b/bot/exts/utils/clean.py @@ -1,4 +1,3 @@ -import logging import random import re from typing import Iterable, Optional @@ -12,8 +11,9 @@ Channels, CleanMessages, Colours, Event, Icons, MODERATION_ROLES, NEGATIVE_REPLIES ) from bot.exts.moderation.modlog import ModLog +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) class Clean(Cog): diff --git a/bot/exts/utils/extensions.py b/bot/exts/utils/extensions.py index 309126d0e3..fa5d38917c 100644 --- a/bot/exts/utils/extensions.py +++ b/bot/exts/utils/extensions.py @@ -1,5 +1,4 @@ import functools -import logging import typing as t from enum import Enum @@ -11,10 +10,11 @@ from bot.bot import Bot from bot.constants import Emojis, MODERATION_ROLES, Roles, URLs from bot.converters import Extension +from bot.log import get_logger from bot.pagination import LinePaginator from bot.utils.extensions import EXTENSIONS -log = logging.getLogger(__name__) +log = get_logger(__name__) UNLOAD_BLACKLIST = {f"{exts.__name__}.utils.extensions", f"{exts.__name__}.moderation.modlog"} diff --git a/bot/exts/utils/internal.py b/bot/exts/utils/internal.py index 5d2cd7611a..8797359452 100644 --- a/bot/exts/utils/internal.py +++ b/bot/exts/utils/internal.py @@ -1,6 +1,5 @@ import contextlib import inspect -import logging import pprint import re import textwrap @@ -15,9 +14,10 @@ from bot.bot import Bot from bot.constants import DEBUG_MODE, Roles +from bot.log import get_logger from bot.utils import find_nth_occurrence, send_to_paste_service -log = logging.getLogger(__name__) +log = get_logger(__name__) class Internal(Cog): diff --git a/bot/exts/utils/reminders.py b/bot/exts/utils/reminders.py index 95f3661af3..b4f88af05f 100644 --- a/bot/exts/utils/reminders.py +++ b/bot/exts/utils/reminders.py @@ -1,4 +1,3 @@ -import logging import random import textwrap import typing as t @@ -15,6 +14,7 @@ Roles, STAFF_PARTNERS_COMMUNITY_ROLES ) from bot.converters import Duration, UnambiguousUser +from bot.log import get_logger from bot.pagination import LinePaginator from bot.utils import scheduling from bot.utils.checks import has_any_role_check, has_no_roles_check @@ -24,7 +24,7 @@ from bot.utils.scheduling import Scheduler from bot.utils.time import TimestampFormats, discord_timestamp -log = logging.getLogger(__name__) +log = get_logger(__name__) LOCK_NAMESPACE = "reminder" WHITELISTED_CHANNELS = Guild.reminder_whitelist @@ -118,7 +118,7 @@ async def _check_mentions(ctx: Context, mentions: t.Iterable[Mentionable]) -> t. if await has_no_roles_check(ctx, *STAFF_PARTNERS_COMMUNITY_ROLES): return False, "members/roles" elif await has_no_roles_check(ctx, *MODERATION_ROLES): - return all(isinstance(mention, discord.Member) for mention in mentions), "roles" + return all(isinstance(mention, (discord.User, discord.Member)) for mention in mentions), "roles" else: return True, "" diff --git a/bot/exts/utils/snekbox.py b/bot/exts/utils/snekbox.py index 5fb10a25ba..fbfc58d0bf 100644 --- a/bot/exts/utils/snekbox.py +++ b/bot/exts/utils/snekbox.py @@ -1,7 +1,6 @@ import asyncio import contextlib import datetime -import logging import re import textwrap from functools import partial @@ -14,10 +13,11 @@ from bot.bot import Bot from bot.constants import Categories, Channels, Roles, URLs from bot.decorators import redirect_output +from bot.log import get_logger from bot.utils import scheduling, send_to_paste_service from bot.utils.messages import wait_for_deletion -log = logging.getLogger(__name__) +log = get_logger(__name__) ESCAPE_REGEX = re.compile("[`\u202E\u200B]{3,}") FORMATTED_CODE_REGEX = re.compile( diff --git a/bot/exts/utils/utils.py b/bot/exts/utils/utils.py index 0139a6ad34..f69bab781c 100644 --- a/bot/exts/utils/utils.py +++ b/bot/exts/utils/utils.py @@ -1,5 +1,4 @@ import difflib -import logging import re import unicodedata from typing import Tuple, Union @@ -12,11 +11,12 @@ from bot.constants import Channels, MODERATION_ROLES, Roles, STAFF_PARTNERS_COMMUNITY_ROLES from bot.converters import Snowflake from bot.decorators import in_whitelist +from bot.log import get_logger from bot.pagination import LinePaginator from bot.utils import messages from bot.utils.time import time_since -log = logging.getLogger(__name__) +log = get_logger(__name__) ZEN_OF_PYTHON = """\ Beautiful is better than ugly. diff --git a/bot/log.py b/bot/log.py index 4e20c005ed..b3cecdcf2a 100644 --- a/bot/log.py +++ b/bot/log.py @@ -3,6 +3,7 @@ import sys from logging import Logger, handlers from pathlib import Path +from typing import Optional, TYPE_CHECKING, cast import coloredlogs import sentry_sdk @@ -14,11 +15,38 @@ TRACE_LEVEL = 5 +if TYPE_CHECKING: + LoggerClass = Logger +else: + LoggerClass = logging.getLoggerClass() + + +class CustomLogger(LoggerClass): + """Custom implementation of the `Logger` class with an added `trace` method.""" + + def trace(self, msg: str, *args, **kwargs) -> None: + """ + Log 'msg % args' with severity 'TRACE'. + + To pass exception information, use the keyword argument exc_info with + a true value, e.g. + + logger.trace("Houston, we have an %s", "interesting problem", exc_info=1) + """ + if self.isEnabledFor(TRACE_LEVEL): + self.log(TRACE_LEVEL, msg, *args, **kwargs) + + +def get_logger(name: Optional[str] = None) -> CustomLogger: + """Utility to make mypy recognise that logger is of type `CustomLogger`.""" + return cast(CustomLogger, logging.getLogger(name)) + + def setup() -> None: """Set up loggers.""" logging.TRACE = TRACE_LEVEL logging.addLevelName(TRACE_LEVEL, "TRACE") - Logger.trace = _monkeypatch_trace + logging.setLoggerClass(CustomLogger) format_string = "%(asctime)s | %(name)s | %(levelname)s | %(message)s" log_format = logging.Formatter(format_string) @@ -28,7 +56,7 @@ def setup() -> None: file_handler = handlers.RotatingFileHandler(log_file, maxBytes=5242880, backupCount=7, encoding="utf8") file_handler.setFormatter(log_format) - root_log = logging.getLogger() + root_log = get_logger() root_log.addHandler(file_handler) if "COLOREDLOGS_LEVEL_STYLES" not in os.environ: @@ -42,16 +70,16 @@ def setup() -> None: if "COLOREDLOGS_LOG_FORMAT" not in os.environ: coloredlogs.DEFAULT_LOG_FORMAT = format_string - coloredlogs.install(level=logging.TRACE, logger=root_log, stream=sys.stdout) + coloredlogs.install(level=TRACE_LEVEL, logger=root_log, stream=sys.stdout) root_log.setLevel(logging.DEBUG if constants.DEBUG_MODE else logging.INFO) - logging.getLogger("discord").setLevel(logging.WARNING) - logging.getLogger("websockets").setLevel(logging.WARNING) - logging.getLogger("chardet").setLevel(logging.WARNING) - logging.getLogger("async_rediscache").setLevel(logging.WARNING) + get_logger("discord").setLevel(logging.WARNING) + get_logger("websockets").setLevel(logging.WARNING) + get_logger("chardet").setLevel(logging.WARNING) + get_logger("async_rediscache").setLevel(logging.WARNING) # Set back to the default of INFO even if asyncio's debug mode is enabled. - logging.getLogger("asyncio").setLevel(logging.INFO) + get_logger("asyncio").setLevel(logging.INFO) _set_trace_loggers() @@ -73,19 +101,6 @@ def setup_sentry() -> None: ) -def _monkeypatch_trace(self: logging.Logger, msg: str, *args, **kwargs) -> None: - """ - Log 'msg % args' with severity 'TRACE'. - - To pass exception information, use the keyword argument exc_info with - a true value, e.g. - - logger.trace("Houston, we have an %s", "interesting problem", exc_info=1) - """ - if self.isEnabledFor(TRACE_LEVEL): - self._log(TRACE_LEVEL, msg, args, **kwargs) - - def _set_trace_loggers() -> None: """ Set loggers to the trace level according to the value from the BOT_TRACE_LOGGERS env var. @@ -101,13 +116,13 @@ def _set_trace_loggers() -> None: level_filter = constants.Bot.trace_loggers if level_filter: if level_filter.startswith("*"): - logging.getLogger().setLevel(logging.TRACE) + get_logger().setLevel(TRACE_LEVEL) elif level_filter.startswith("!"): - logging.getLogger().setLevel(logging.TRACE) + get_logger().setLevel(TRACE_LEVEL) for logger_name in level_filter.strip("!,").split(","): - logging.getLogger(logger_name).setLevel(logging.DEBUG) + get_logger(logger_name).setLevel(logging.DEBUG) else: for logger_name in level_filter.strip(",").split(","): - logging.getLogger(logger_name).setLevel(logging.TRACE) + get_logger(logger_name).setLevel(TRACE_LEVEL) diff --git a/bot/monkey_patches.py b/bot/monkey_patches.py index 4dbdb5eabc..e56a19da20 100644 --- a/bot/monkey_patches.py +++ b/bot/monkey_patches.py @@ -1,10 +1,11 @@ -import logging from datetime import datetime, timedelta from discord import Forbidden, http from discord.ext import commands -log = logging.getLogger(__name__) +from bot.log import get_logger + +log = get_logger(__name__) class Command(commands.Command): diff --git a/bot/pagination.py b/bot/pagination.py index 26caa7db02..8f4353eb1e 100644 --- a/bot/pagination.py +++ b/bot/pagination.py @@ -1,5 +1,4 @@ import asyncio -import logging import typing as t from contextlib import suppress from functools import partial @@ -9,6 +8,7 @@ from discord.ext.commands import Context, Paginator from bot import constants +from bot.log import get_logger from bot.utils import messages FIRST_EMOJI = "\u23EE" # [:track_previous:] @@ -19,7 +19,7 @@ PAGINATION_EMOJI = (FIRST_EMOJI, LEFT_EMOJI, RIGHT_EMOJI, LAST_EMOJI, DELETE_EMOJI) -log = logging.getLogger(__name__) +log = get_logger(__name__) class EmptyPaginatorEmbedError(Exception): diff --git a/bot/resources/tags/contribute.md b/bot/resources/tags/contribute.md new file mode 100644 index 0000000000..0709756466 --- /dev/null +++ b/bot/resources/tags/contribute.md @@ -0,0 +1,12 @@ +**Contribute to Python Discord's Open Source Projects** +Looking to contribute to Open Source Projects for the first time? Want to add a feature or fix a bug on the bots on this server? We have on-going projects that people can contribute to, even if you've never contributed to open source before! + +**Projects to Contribute to** +• [Sir Lancebot](https://github.com/python-discord/sir-lancebot) - our fun, beginner-friendly bot +• [Python](https://github.com/python-discord/bot) - our utility & moderation bot +• [Site](https://github.com/python-discord/site) - resources, guides, and more + +**Where to start** +1. Read our [contributing guidelines](https://pythondiscord.com/pages/guides/pydis-guides/contributing/) +2. Chat with us in <#635950537262759947> if you're ready to jump in or have any questions +3. Open an issue or ask to be assigned to an issue to work on diff --git a/bot/rules/discord_emojis.py b/bot/rules/discord_emojis.py index 41faf7ee86..d979ac5e77 100644 --- a/bot/rules/discord_emojis.py +++ b/bot/rules/discord_emojis.py @@ -4,7 +4,6 @@ from discord import Member, Message from emoji import demojize - DISCORD_EMOJI_RE = re.compile(r"<:\w+:\d+>|:\w+:") CODE_BLOCK_RE = re.compile(r"```.*?```", flags=re.DOTALL) diff --git a/bot/rules/links.py b/bot/rules/links.py index ec75a19c53..c46b783c56 100644 --- a/bot/rules/links.py +++ b/bot/rules/links.py @@ -3,7 +3,6 @@ from discord import Member, Message - LINK_RE = re.compile(r"(https?://[^\s]+)") diff --git a/bot/utils/channel.py b/bot/utils/channel.py index 6d23566795..b9e2348578 100644 --- a/bot/utils/channel.py +++ b/bot/utils/channel.py @@ -1,12 +1,11 @@ -import logging - import discord import bot from bot import constants from bot.constants import Categories +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) def is_help_channel(channel: discord.TextChannel) -> bool: diff --git a/bot/utils/checks.py b/bot/utils/checks.py index fc0397fd00..34d09349b6 100644 --- a/bot/utils/checks.py +++ b/bot/utils/checks.py @@ -1,5 +1,4 @@ import datetime -import logging from typing import Callable, Container, Iterable, Optional, Union from discord.ext.commands import ( @@ -16,8 +15,9 @@ ) from bot import constants +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) class ContextCheckFailure(CheckFailure): diff --git a/bot/utils/function.py b/bot/utils/function.py index 9bc44e7538..55115d7d3d 100644 --- a/bot/utils/function.py +++ b/bot/utils/function.py @@ -2,11 +2,12 @@ import functools import inspect -import logging import types import typing as t -log = logging.getLogger(__name__) +from bot.log import get_logger + +log = get_logger(__name__) Argument = t.Union[int, str] BoundArgs = t.OrderedDict[str, t.Any] diff --git a/bot/utils/lock.py b/bot/utils/lock.py index ec6f92cd42..c039a4f255 100644 --- a/bot/utils/lock.py +++ b/bot/utils/lock.py @@ -1,6 +1,5 @@ import asyncio import inspect -import logging import types from collections import defaultdict from functools import partial @@ -8,10 +7,11 @@ from weakref import WeakValueDictionary from bot.errors import LockedResourceError +from bot.log import get_logger from bot.utils import function from bot.utils.function import command_wraps -log = logging.getLogger(__name__) +log = get_logger(__name__) __lock_dicts = defaultdict(WeakValueDictionary) _IdCallableReturn = Union[Hashable, Awaitable[Hashable]] diff --git a/bot/utils/members.py b/bot/utils/members.py index 302fe6d632..77ddf1696f 100644 --- a/bot/utils/members.py +++ b/bot/utils/members.py @@ -1,9 +1,10 @@ -import logging import typing as t import discord -log = logging.getLogger(__name__) +from bot.log import get_logger + +log = get_logger(__name__) async def get_or_fetch_member(guild: discord.Guild, member_id: int) -> t.Optional[discord.Member]: diff --git a/bot/utils/messages.py b/bot/utils/messages.py index f4aef7eb3c..e55c07062c 100644 --- a/bot/utils/messages.py +++ b/bot/utils/messages.py @@ -1,5 +1,4 @@ import asyncio -import logging import random import re from functools import partial @@ -11,9 +10,10 @@ import bot from bot.constants import Emojis, MODERATION_ROLES, NEGATIVE_REPLIES +from bot.log import get_logger from bot.utils import scheduling -log = logging.getLogger(__name__) +log = get_logger(__name__) def reaction_check( diff --git a/bot/utils/scheduling.py b/bot/utils/scheduling.py index bb83b5c0d1..7b4c8e2de2 100644 --- a/bot/utils/scheduling.py +++ b/bot/utils/scheduling.py @@ -1,11 +1,12 @@ import asyncio import contextlib import inspect -import logging import typing as t from datetime import datetime from functools import partial +from bot.log import get_logger + class Scheduler: """ @@ -27,7 +28,7 @@ class Scheduler: def __init__(self, name: str): self.name = name - self._log = logging.getLogger(f"{__name__}.{name}") + self._log = get_logger(f"{__name__}.{name}") self._scheduled_tasks: t.Dict[t.Hashable, asyncio.Task] = {} def __contains__(self, task_id: t.Hashable) -> bool: @@ -187,5 +188,5 @@ def _log_task_exception(task: asyncio.Task, *, suppressed_exceptions: t.Tuple[t. exception = task.exception() # Log the exception if one exists. if exception and not isinstance(exception, suppressed_exceptions): - log = logging.getLogger(__name__) + log = get_logger(__name__) log.error(f"Error in task {task.get_name()} {id(task)}!", exc_info=exception) diff --git a/bot/utils/services.py b/bot/utils/services.py index db9c93d0f3..439c8d500e 100644 --- a/bot/utils/services.py +++ b/bot/utils/services.py @@ -1,12 +1,12 @@ -import logging from typing import Optional from aiohttp import ClientConnectorError import bot from bot.constants import URLs +from bot.log import get_logger -log = logging.getLogger(__name__) +log = get_logger(__name__) FAILED_REQUEST_ATTEMPTS = 3 diff --git a/bot/utils/webhooks.py b/bot/utils/webhooks.py index 66f82ec66f..9c916b63aa 100644 --- a/bot/utils/webhooks.py +++ b/bot/utils/webhooks.py @@ -1,12 +1,12 @@ -import logging from typing import Optional import discord from discord import Embed +from bot.log import get_logger from bot.utils.messages import sub_clyde -log = logging.getLogger(__name__) +log = get_logger(__name__) async def send_webhook( diff --git a/tests/__init__.py b/tests/__init__.py index 2228110ad1..c2b9d12dca 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,5 +1,6 @@ import logging +from bot.log import get_logger -log = logging.getLogger() +log = get_logger() log.setLevel(logging.CRITICAL) diff --git a/tests/base.py b/tests/base.py index 79ff5bc7e6..5e304ea9d8 100644 --- a/tests/base.py +++ b/tests/base.py @@ -6,6 +6,7 @@ import discord from discord.ext import commands +from bot.log import get_logger from tests import helpers @@ -42,7 +43,7 @@ def assertNotLogs(self, logger=None, level=None, msg=None): # noqa: N802 manager when we're testing under the assumption that no log records will be emitted. """ if not isinstance(logger, logging.Logger): - logger = logging.getLogger(logger) + logger = get_logger(logger) if level: level = logging._nameToLevel.get(level, level) diff --git a/tests/bot/exts/backend/sync/test_base.py b/tests/bot/exts/backend/sync/test_base.py index 3ad9db9c30..9dc46005ba 100644 --- a/tests/bot/exts/backend/sync/test_base.py +++ b/tests/bot/exts/backend/sync/test_base.py @@ -1,7 +1,6 @@ import unittest from unittest import mock - from bot.api import ResponseCodeError from bot.exts.backend.sync._syncers import Syncer from tests import helpers diff --git a/tests/test_base.py b/tests/test_base.py index a7db4bf3e6..365805a710 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -1,8 +1,7 @@ import logging -import unittest import unittest.mock - +from bot.log import get_logger from tests.base import LoggingTestsMixin, _CaptureLogHandler @@ -15,7 +14,7 @@ class LoggingTestCaseTests(unittest.TestCase): @classmethod def setUpClass(cls): - cls.log = logging.getLogger(__name__) + cls.log = get_logger(__name__) def test_assert_not_logs_does_not_raise_with_no_logs(self): """Test if LoggingTestCase.assertNotLogs does not raise when no logs were emitted.""" @@ -56,15 +55,15 @@ def test_assert_not_logs_restores_old_logging_settings(self): def test_logging_test_case_works_with_logger_instance(self): """Test if the LoggingTestCase captures logging for provided logger.""" - log = logging.getLogger("new_logger") + log = get_logger("new_logger") with self.assertRaises(AssertionError): with LoggingTestCase.assertNotLogs(self, logger=log): log.info("Hello, this should raise an AssertionError") def test_logging_test_case_respects_alternative_logger(self): """Test if LoggingTestCase only checks the provided logger.""" - log_one = logging.getLogger("log one") - log_two = logging.getLogger("log two") + log_one = get_logger("log one") + log_two = get_logger("log two") with LoggingTestCase.assertNotLogs(self, logger=log_one): log_two.info("Hello, this should not raise an AssertionError")