Passed
Pull Request — main (#390)
by
unknown
03:21 queued 01:38
created

pincer.cog.load_cog()   A

Complexity

Conditions 2

Size

Total Lines 16
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 16
rs 10
c 0
b 0
f 0
cc 2
nop 2
1
# Copyright Pincer 2021-Present
0 ignored issues
show
introduced by
Missing module docstring
Loading history...
2
# Full MIT License can be found in `LICENSE` at the project root.
3
4
from __future__ import annotations
5
from asyncio import ensure_future
6
7
from importlib import reload, import_module
8
from types import ModuleType
9
from typing import TYPE_CHECKING
10
11
from . import client as _client
0 ignored issues
show
Bug introduced by
The name client does not seem to exist in module pincer.
Loading history...
12
from .commands.chat_command_handler import ChatCommandHandler
13
from .commands.interactable import Interactable
14
from .exceptions import CogAlreadyExists, CogNotFound
15
16
if TYPE_CHECKING:
17
    from typing import Type
18
    from .client import Client
0 ignored issues
show
introduced by
Cannot import 'client' due to syntax error 'invalid syntax (<unknown>, line 49)'
Loading history...
19
20
21
def get_cog_name(cog: Type[Cog]):
22
    """Gets the path to import a cog. This is used as a unique identifier"""
23
    try:
24
        return f"{cog.__module__}.{cog.__name__}"
25
    except AttributeError:
26
        return f"{cog.__module__}.{cog.__class__.__name__}"
27
28
29
def load_cog(client: Client, cog: Type[Cog]):
30
    """Loads a cog
31
32
    Parameters
33
    ----------
34
    cog : Type[:class:`~pincer.cog.Cog`]
35
        The cog to load.
36
    """
37
    if cog in ChatCommandHandler.managers:
38
        raise CogAlreadyExists(
39
            f"Cog `{cog}` is trying to be loaded but already exists."
40
        )
41
42
    cog_manager = cog(client)
43
44
    ChatCommandHandler.managers.append(cog_manager)
45
46
47
def load_module(client: Client, module: ModuleType):
48
    """Loads the cogs from a module recursively.
49
50
    Parameters
51
    ----------
52
    module : :class:`~types.ModuleType`
53
        The module to load.
54
    """
55
    for item in module.__dict__.values():
56
        if isinstance(item, ModuleType):
57
            load_module(client, item)
58
        elif Cog in getattr(item, "__bases__", []):
59
            load_cog(client, item)
60
61
62
def reload_cog(client: Client, cog: Type[Cog]):
63
    """Reloads a cog.
64
65
    Parameters
66
    ----------
67
    cog : Type[:class:`~pincer.cog.Cog`]
68
        The cog to load.
69
    """
70
71
    # Remove application commands registered to this cog
72
    for item in ChatCommandHandler.managers:
73
        if get_cog_name(item) == get_cog_name(cog):
74
            old_cog = item
75
            break
76
    else:
77
        raise CogNotFound(f"Cog `{cog}` could not be found!")
78
79
    to_pop = []
80
81
    for key, command in ChatCommandHandler.register.items():
82
        if not command:
83
            continue
84
        if command.manager == old_cog:
85
            to_pop.append(key)
86
87
    for pop in to_pop:
88
        ChatCommandHandler.register.pop(pop)
89
90
    ChatCommandHandler.managers.remove(old_cog)
91
92
    # Remove events registered to this cog
93
    for event in type(old_cog).__dict__.values():
94
        if isinstance(event, _client.PartialEvent):
95
            _client._events.pop(event.func.__name__)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _events was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
96
97
    mod = reload(import_module(cog.__module__))
98
    new_cog = getattr(mod, cog.__name__)
99
    client.load_cog(new_cog)
100
    ChatCommandHandler.has_been_initialized = False
101
    ensure_future(ChatCommandHandler().initialize())
0 ignored issues
show
Bug introduced by
It seems like a value for argument client is missing in the constructor call.
Loading history...
102
103
104
class Cog(Interactable):
105
    """A cog object
106
    This is an object that store commands that isn't a Client. It also can be loaded
107
    and unloaded in runtime so commands can be changed without restarting the bot.
108
    """
109
110
    def __init__(self, client: Client) -> None:
111
        self.client = client
112
113
        super().__init__()
114