Skip to content

Commit d70f1b9

Browse files
authored
Merge pull request #674 from TotallyNotRobots/hook-dict
Move plugin hooks to typed dict
2 parents 134a2fe + bd42e49 commit d70f1b9

File tree

8 files changed

+113
-41
lines changed

8 files changed

+113
-41
lines changed

.devcontainer/Dockerfile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
FROM mcr.microsoft.com/devcontainers/python:3.11
2+
3+
RUN \
4+
pipx uninstall pydocstyle \
5+
&& pipx uninstall pycodestyle \
6+
&& pipx uninstall mypy \
7+
&& pipx uninstall pylint \
8+
&& pipx uninstall pytest \
9+
&& pipx uninstall flake8 \
10+
&& pipx uninstall black
11+
12+
ENV SHELL /bin/bash

.devcontainer/devcontainer.json

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,50 @@
11
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
22
// README at: https://github.com/devcontainers/templates/tree/main/src/python
33
{
4-
"name": "Python 3",
5-
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
6-
"image": "mcr.microsoft.com/devcontainers/python:0-3.9",
7-
"features": {
8-
"ghcr.io/devcontainers-contrib/features/zsh-plugins:0": {
9-
"plugins": "ssh-agent",
10-
"omzPlugins": "https://github.com/zsh-users/zsh-autosuggestions"
11-
}
12-
},
4+
"name": "Python 3",
5+
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
6+
"dockerFile": "./Dockerfile",
7+
"context": "..",
8+
"features": {
9+
"ghcr.io/devcontainers-contrib/features/zsh-plugins:0": {
10+
"plugins": "ssh-agent",
11+
"omzPlugins": "https://github.com/zsh-users/zsh-autosuggestions"
12+
}
13+
},
1314

14-
// Features to add to the dev container. More info: https://containers.dev/features.
15-
// "features": {},
15+
// Features to add to the dev container. More info: https://containers.dev/features.
16+
// "features": {},
1617

17-
// Use 'forwardPorts' to make a list of ports inside the container available locally.
18-
// "forwardPorts": [],
18+
// Use 'forwardPorts' to make a list of ports inside the container available locally.
19+
// "forwardPorts": [],
1920

20-
// Use 'postCreateCommand' to run commands after the container is created.
21-
// "postCreateCommand": "pip3 install -Ur requirements-dev.txt",
22-
"postStartCommand": "pip3 install -Ur requirements-dev.txt",
23-
// Configure tool-specific properties.
24-
// "customizations": {},
21+
// Use 'postCreateCommand' to run commands after the container is created.
22+
// "postCreateCommand": "pip3 install -Ur requirements-dev.txt",
23+
"postCreateCommand": "pip3 install -Ur requirements-dev.txt",
24+
// Configure tool-specific properties.
25+
// "customizations": {},
2526

26-
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
27-
"remoteUser": "root",
28-
"customizations": {
29-
"vscode": {
30-
"extensions": [
31-
"tamasfe.even-better-toml",
32-
"ms-python.python",
33-
"ms-python.vscode-pylance",
34-
"EditorConfig.EditorConfig"
35-
]
36-
}
37-
}
27+
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
28+
// "remoteUser": "root",
29+
"customizations": {
30+
"vscode": {
31+
"extensions": [
32+
"tamasfe.even-better-toml",
33+
"ms-python.python",
34+
"ms-python.vscode-pylance",
35+
"EditorConfig.EditorConfig",
36+
"GitHub.vscode-pull-request-github"
37+
],
38+
"settings": {
39+
"python.pythonPath": "/usr/local/bin/python",
40+
"python.testing.pytestArgs": ["--no-cov"],
41+
"terminal.integrated.profiles.linux": {
42+
"zsh": {
43+
"path": "/usr/bin/zsh"
44+
}
45+
},
46+
"terminal.integrated.defaultProfile.linux": "zsh"
47+
}
48+
}
49+
}
3850
}

.vscode/extensions.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{
22
"recommendations": [
3-
"github.vscode-github-actions",
43
"github.vscode-pull-request-github"
54
]
65
}

cloudbot/plugin.py

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,16 @@
77
from functools import partial
88
from operator import attrgetter
99
from pathlib import Path
10-
from typing import Dict, List, MutableMapping, Optional, Tuple, Type, cast
10+
from typing import (
11+
Dict,
12+
List,
13+
MutableMapping,
14+
Optional,
15+
Tuple,
16+
Type,
17+
TypedDict,
18+
cast,
19+
)
1120
from weakref import WeakValueDictionary
1221

1322
import sqlalchemy
@@ -19,8 +28,18 @@
1928
CommandHook,
2029
ConfigHook,
2130
EventHook,
31+
IrcOutHook,
32+
OnCapAckHook,
33+
OnCapAvaliableHook,
34+
OnConnectHook,
35+
OnStartHook,
36+
OnStopHook,
37+
PeriodicHook,
38+
PermHook,
39+
PostHookHook,
2240
RawHook,
2341
RegexHook,
42+
SieveHook,
2443
hook_name_to_plugin,
2544
)
2645
from cloudbot.util import HOOK_ATTR, LOADED_ATTR, async_util, database
@@ -29,7 +48,25 @@
2948
logger = logging.getLogger("cloudbot")
3049

3150

32-
def find_hooks(parent, module):
51+
class HookDict(TypedDict):
52+
command: List[CommandHook]
53+
on_connect: List[OnConnectHook]
54+
on_start: List[OnStartHook]
55+
on_stop: List[OnStopHook]
56+
on_cap_available: List[OnCapAvaliableHook]
57+
on_cap_ack: List[OnCapAckHook]
58+
sieve: List[SieveHook]
59+
event: List[EventHook]
60+
regex: List[RegexHook]
61+
periodic: List[PeriodicHook]
62+
irc_raw: List[RawHook]
63+
irc_out: List[IrcOutHook]
64+
post_hook: List[PostHookHook]
65+
config: List[ConfigHook]
66+
perm_check: List[PermHook]
67+
68+
69+
def find_hooks(parent, module) -> HookDict:
3370
hooks = defaultdict(list)
3471
for func in module.__dict__.values():
3572
if hasattr(func, HOOK_ATTR) and not hasattr(func, "_not_" + HOOK_ATTR):
@@ -44,7 +81,7 @@ def find_hooks(parent, module):
4481
# delete the hook to free memory
4582
delattr(func, HOOK_ATTR)
4683

47-
return hooks
84+
return cast(HookDict, hooks)
4885

4986

5087
def find_tables(code):
@@ -351,7 +388,7 @@ async def load_plugin(self, path):
351388
self._sort_hooks()
352389

353390
# we don't need this anymore
354-
del plugin.hooks["on_start"]
391+
plugin.hooks["on_start"].clear()
355392

356393
def _sort_hooks(self) -> None:
357394
def _sort_list(hooks):

cloudbot/util/web.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,13 @@
2020
from typing import Dict, Optional, Union
2121

2222
import requests
23-
from requests import HTTPError, PreparedRequest, RequestException, Response
24-
from requests import Request
23+
from requests import (
24+
HTTPError,
25+
PreparedRequest,
26+
Request,
27+
RequestException,
28+
Response,
29+
)
2530

2631
# Constants
2732
DEFAULT_SHORTENER = "is.gd"
@@ -163,7 +168,9 @@ def paste(data, ext="txt", service=DEFAULT_PASTEBIN, raise_on_no_paste=False):
163168

164169

165170
class ServiceError(Exception):
166-
def __init__(self, request: Union[Request, PreparedRequest], message: str) -> None:
171+
def __init__(
172+
self, request: Union[Request, PreparedRequest], message: str
173+
) -> None:
167174
super().__init__(message)
168175
self.request = request
169176

tests/conftest.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import datetime
2+
import importlib
23
import logging
34
from typing import List
45
from unittest.mock import MagicMock, patch
@@ -30,13 +31,13 @@ def caplog_bot(caplog):
3031

3132
@pytest.fixture()
3233
def patch_import_module():
33-
with patch("importlib.import_module") as mocked:
34+
with patch.object(importlib, "import_module") as mocked:
3435
yield mocked
3536

3637

3738
@pytest.fixture()
3839
def patch_import_reload():
39-
with patch("importlib.reload") as mocked:
40+
with patch.object(importlib, "reload") as mocked:
4041
yield mocked
4142

4243

tests/core_tests/test_plugin_manager.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
from cloudbot.util import database
1515
from tests.util.mock_module import MockModule
1616

17-
1817
@pytest.fixture()
1918
def mock_bot(mock_bot_factory, event_loop, tmp_path):
2019
tmp_base = tmp_path / "tmp"
@@ -221,6 +220,8 @@ def test_plugin_with_objs_full_dict_attr(mock_manager, patch_import_module):
221220
def test_plugin_load_disabled(
222221
mock_manager, patch_import_module, patch_import_reload
223222
):
223+
patch_import_module.reset_mock()
224+
patch_import_reload.reset_mock()
224225
patch_import_module.return_value = MockModule()
225226
mock_manager.bot.config.update(
226227
{

tests/plugin_tests/test_chan_log.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
def test_format_exception_chain():
77
def _get_data(exc):
88
yield repr(exc)
9+
if hasattr(exc, 'add_note'):
10+
yield f" add_note = {exc.add_note!r}"
11+
912
yield f" args = {exc.args!r}"
1013
yield f" with_traceback = {exc.with_traceback!r}"
1114
yield ""

0 commit comments

Comments
 (0)