diff --git a/.flake8 b/.flake8 index 2ccbf95..6e7cd96 100644 --- a/.flake8 +++ b/.flake8 @@ -1,7 +1,7 @@ [flake8] extend-ignore = Q0, E501, C812, E203, W503, # These default to arguing with Black. We might configure some of them eventually - ANN101, # Ignore self annotation + ANN1, # Ignore self and cls annotations ANN204, ANN206, # return annotations for special methods and class methods D105, D107, # Missing Docstrings in magic method and __init__ S311, # Standard pseudo-random generators are not suitable for security/cryptographic purposes. diff --git a/jarvis/__init__.py b/jarvis/__init__.py index 4ab5999..9766919 100644 --- a/jarvis/__init__.py +++ b/jarvis/__init__.py @@ -31,8 +31,8 @@ __version__ = "2.0.0a0" async def on_ready() -> None: """Lepton on_ready override.""" global restart_ctx - print(" Logged in as {0.user}".format(jarvis)) - print(" Connected to {} guild(s)".format(len(jarvis.guilds))) + print(" Logged in as {0.user}".format(jarvis)) # noqa: T001 + print(" Connected to {} guild(s)".format(len(jarvis.guilds))) # noqa: T001 @listen() @@ -60,7 +60,7 @@ def run() -> None: for extension in utils.get_extensions(): jarvis.load_extension(extension) - print( + print( # noqa: T001 " https://discord.com/api/oauth2/authorize?client_id=" "{}&permissions=8&scope=bot%20applications.commands".format(jconfig.client_id) ) diff --git a/jarvis/cogs/admin/ban.py b/jarvis/cogs/admin/ban.py index 906f444..d72dd08 100644 --- a/jarvis/cogs/admin/ban.py +++ b/jarvis/cogs/admin/ban.py @@ -15,7 +15,7 @@ from dis_snek.models.snek.application_commands import ( from dis_snek.models.snek.command import check from jarvis.db.models import Ban, Unban -from jarvis.utils import build_embed, find +from jarvis.utils import build_embed, find, find_all from jarvis.utils.cachecog import CacheCog from jarvis.utils.permissions import admin_or_permissions @@ -219,7 +219,7 @@ class BanCog(CacheCog): bans, ) else: - results = [x for x in filter(lambda x: x.user.username == user, bans)] + results = find_all(lambda x: x.user.username == user, bans) if results: if len(results) > 1: active_bans = [] diff --git a/jarvis/cogs/dbrand.py b/jarvis/cogs/dbrand.py index a6f0f41..9a14251 100644 --- a/jarvis/cogs/dbrand.py +++ b/jarvis/cogs/dbrand.py @@ -174,7 +174,6 @@ class DbrandCog(Scale): elif search == "🏳️": search = "fr" else: - print(search) await ctx.send("Please use text to search for shipping.") return if len(search) > 2: diff --git a/jarvis/cogs/verify.py b/jarvis/cogs/verify.py index 1202ea4..2d1db38 100644 --- a/jarvis/cogs/verify.py +++ b/jarvis/cogs/verify.py @@ -26,8 +26,7 @@ def create_layout() -> list: custom_id=f"verify_button||{id}", ) ) - action_row = spread_to_rows(*buttons, max_in_row=3) - return action_row + return spread_to_rows(*buttons, max_in_row=3) class VerifyCog(Scale): diff --git a/jarvis/config.py b/jarvis/config.py index 1146155..c2b9983 100644 --- a/jarvis/config.py +++ b/jarvis/config.py @@ -65,8 +65,7 @@ class Config(object): @classmethod def from_yaml(cls, y: dict) -> "Config": """Load the yaml config file.""" - instance = cls(**y) - return instance + return cls(**y) def get_config(path: str = "config.yaml") -> Config: diff --git a/jarvis/tasks/twitter.py b/jarvis/tasks/twitter.py index 3167e32..46638f5 100644 --- a/jarvis/tasks/twitter.py +++ b/jarvis/tasks/twitter.py @@ -21,8 +21,8 @@ __api = tweepy.API(__auth) async def _tweets() -> None: """J.A.R.V.I.S. twitter blocking task.""" - guild_cache = dict() - channel_cache = dict() + guild_cache = {} + channel_cache = {} twitters = Twitter.objects(active=True) for twitter in twitters: try: diff --git a/jarvis/utils/__init__.py b/jarvis/utils/__init__.py index 5c9a3c9..11318e1 100644 --- a/jarvis/utils/__init__.py +++ b/jarvis/utils/__init__.py @@ -1,8 +1,7 @@ """J.A.R.V.I.S. Utility Functions.""" from datetime import datetime -from operator import attrgetter from pkgutil import iter_modules -from typing import Any, Callable, Iterable, Optional, TypeVar +from typing import Any, Callable, Iterable, List, Optional, TypeVar import git from dis_snek.models.discord.embed import Embed @@ -88,25 +87,101 @@ def get_repo_hash() -> str: return repo.head.object.hexsha -def find(predicate: Callable[[T], Any], seq: Iterable[T]) -> Optional[T]: - for element in seq: - if predicate(element): - return element +def find(predicate: Callable, sequence: Iterable) -> Optional[Any]: + """ + Find the first element in a sequence that matches the predicate. + + ??? Hint "Example Usage:" + ```python + member = find(lambda m: m.name == "UserName", guild.members) + ``` + Args: + predicate: A callable that returns a boolean value + sequence: A sequence to be searched + + Returns: + A match if found, otherwise None + + """ + for el in sequence: + if predicate(el): + return el return None -def get(iterable: Iterable[T], **attrs: Any) -> Optional[T]: - if len(attrs) == 1: - k, v = attrs.popitem() - pred = attrgetter(k.replace("__", ".")) - for elem in iterable: - if pred(elem) == v: - return elem - return None +def find_all(predicate: Callable, sequence: Iterable) -> List[Any]: + """ + Find all elements in a sequence that match the predicate. - converted = [(attrgetter(attr.replace("__", ".")), value) for attr, value in attrs.items()] + ??? Hint "Example Usage:" + ```python + members = find_all(lambda m: m.name == "UserName", guild.members) + ``` + Args: + predicate: A callable that returns a boolean value + sequence: A sequence to be searched - for elem in iterable: - if all(pred(elem) == value for pred, value in converted): - return elem - return None + Returns: + A list of matches + + """ + matches = [] + for el in sequence: + if predicate(el): + matches.append(el) + return matches + + +def get(sequence: Iterable, **kwargs: Any) -> Optional[Any]: + """ + Find the first element in a sequence that matches all attrs. + + ??? Hint "Example Usage:" + ```python + channel = get(guild.channels, nsfw=False, category="General") + ``` + + Args: + sequence: A sequence to be searched + kwargs: Keyword arguments to search the sequence for + + Returns: + A match if found, otherwise None + """ + if not kwargs: + return sequence[0] + + for el in sequence: + if any(not hasattr(el, attr) for attr in kwargs.keys()): + continue + if all(getattr(el, attr) == value for attr, value in kwargs.items()): + return el + return None + + +def get_all(sequence: Iterable, **kwargs: Any) -> List[Any]: + """ + Find all elements in a sequence that match all attrs. + + ??? Hint "Example Usage:" + ```python + channels = get_all(guild.channels, nsfw=False, category="General") + ``` + + Args: + sequence: A sequence to be searched + kwargs: Keyword arguments to search the sequence for + + Returns: + A list of matches + """ + if not kwargs: + return sequence + + matches = [] + for el in sequence: + if any(not hasattr(el, attr) for attr in kwargs.keys()): + continue + if all(getattr(el, attr) == value for attr, value in kwargs.items()): + matches.append(el) + return matches