Skip to content

Commit a872c79

Browse files
committed
Don't use the asyncio loop outside of async context
1 parent 54fe6a6 commit a872c79

File tree

5 files changed

+28
-52
lines changed

5 files changed

+28
-52
lines changed

cloudbot/util/async_util.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"""
44

55
import asyncio
6-
import sys
76
from asyncio import AbstractEventLoop
87
from asyncio.tasks import Task
98
from functools import partial
@@ -56,19 +55,10 @@ def run_coroutine_threadsafe(coro, loop):
5655
if not asyncio.iscoroutine(coro):
5756
raise TypeError("A coroutine object is required")
5857

59-
if sys.version_info < (3, 5, 1):
60-
loop.call_soon_threadsafe(partial(wrap_future, coro, loop=loop))
61-
else:
62-
asyncio.run_coroutine_threadsafe(coro, loop)
63-
64-
65-
def create_future(loop=None) -> asyncio.Future:
66-
if loop is None:
67-
loop = asyncio.get_event_loop()
58+
asyncio.run_coroutine_threadsafe(coro, loop)
6859

69-
if sys.version_info < (3, 5, 2):
70-
return asyncio.Future(loop=loop)
7160

61+
def create_future(loop) -> asyncio.Future:
7262
return loop.create_future()
7363

7464

cloudbot/util/mapping.py

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import weakref
22
from collections import defaultdict
3-
from typing import Generic, Mapping, MutableMapping, Type, TypeVar, cast
3+
from typing import TYPE_CHECKING, Generic, MutableMapping, TypeVar, cast
44

55
__all__ = (
66
"KeyFoldDict",
@@ -13,54 +13,48 @@
1313
K = TypeVar("K", bound=str)
1414
V = TypeVar("V")
1515

16+
if TYPE_CHECKING:
1617

17-
class KeyFoldMixin(Generic[K, V]):
18+
class MapBase(MutableMapping[K, V]):
19+
...
20+
21+
else:
22+
23+
class MapBase(Generic[K, V]):
24+
...
25+
26+
27+
class KeyFoldMixin(MapBase[K, V]):
1828
"""
1929
A mixin for Mapping to allow for case-insensitive keys
2030
"""
2131

22-
@classmethod
23-
def get_class(cls) -> Type[MutableMapping[K, V]]:
24-
raise NotImplementedError
25-
2632
def __getitem__(self, item: K) -> V:
27-
return self.get_class().__getitem__(
28-
cast(Mapping[K, V], self), cast(K, item.casefold())
29-
)
33+
return super().__getitem__(cast(K, item.casefold()))
3034

3135
def __setitem__(self, key: K, value: V) -> None:
32-
return self.get_class().__setitem__(
33-
cast(MutableMapping[K, V], self), cast(K, key.casefold()), value
34-
)
36+
return super().__setitem__(cast(K, key.casefold()), value)
3537

3638
def __delitem__(self, key: K) -> None:
37-
return self.get_class().__delitem__(
38-
cast(MutableMapping[K, V], self), cast(K, key.casefold())
39-
)
39+
return super().__delitem__(cast(K, key.casefold()))
4040

4141
def pop(self, key: K, *args) -> V:
4242
"""
4343
Wraps `dict.pop`
4444
"""
45-
return self.get_class().pop(
46-
cast(MutableMapping[K, V], self), cast(K, key.casefold()), *args
47-
)
45+
return super().pop(cast(K, key.casefold()), *args)
4846

4947
def get(self, key: K, default=None):
5048
"""
5149
Wrap `dict.get`
5250
"""
53-
return self.get_class().get(
54-
cast(Mapping[K, V], self), cast(K, key.casefold()), default
55-
)
51+
return super().get(cast(K, key.casefold()), default)
5652

5753
def setdefault(self, key: K, default=None):
5854
"""
5955
Wrap `dict.setdefault`
6056
"""
61-
return self.get_class().setdefault(
62-
cast(MutableMapping[K, V], self), cast(K, key.casefold()), default
63-
)
57+
return super().setdefault(cast(K, key.casefold()), default)
6458

6559
def update(self, *args, **kwargs):
6660
"""
@@ -84,26 +78,14 @@ class KeyFoldDict(KeyFoldMixin, dict):
8478
KeyFolded dict type
8579
"""
8680

87-
@classmethod
88-
def get_class(cls) -> Type[MutableMapping[K, V]]:
89-
return dict
90-
9181

9282
class DefaultKeyFoldDict(KeyFoldMixin, defaultdict):
9383
"""
9484
KeyFolded defaultdict
9585
"""
9686

97-
@classmethod
98-
def get_class(cls) -> Type[MutableMapping[K, V]]:
99-
return defaultdict
100-
10187

10288
class KeyFoldWeakValueDict(KeyFoldMixin, weakref.WeakValueDictionary):
10389
"""
10490
KeyFolded WeakValueDictionary
10591
"""
106-
107-
@classmethod
108-
def get_class(cls) -> Type[MutableMapping[K, V]]:
109-
return weakref.WeakValueDictionary

requirements-dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
coverage == 6.1.2
22
freezegun == 1.1.0
3-
mypy == 0.910
3+
mypy ~= 0.910
44
pre-commit == 2.17.0
55
pylint == 2.11.1
66
pytest == 6.2.5

tests/plugin_tests/test_brew.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from typing import Any, Dict
12
from unittest.mock import MagicMock
23

34
import pytest
@@ -108,7 +109,7 @@ def test_results(
108109
if website:
109110
brewery["website"] = website
110111

111-
beer = {
112+
beer: Dict[str, Any] = {
112113
"breweries": [
113114
brewery,
114115
],

tests/util/mock_bot.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,15 @@ def __init__(
2222
):
2323
self.old_db = None
2424
self.do_db_migrate = False
25+
self.loop = loop
2526
self.base_dir = base_dir
2627
self.data_path = self.base_dir / "data"
2728
self.data_dir = str(self.data_path)
2829
self.plugin_dir = self.base_dir / "plugins"
29-
self.stopped_future: Awaitable[bool] = create_future()
30+
if self.loop:
31+
self.stopped_future: Awaitable[bool] = create_future(self.loop)
32+
else:
33+
self.stopped_future = None
3034

3135
if db:
3236
self.db_engine = db.engine
@@ -35,7 +39,6 @@ def __init__(
3539

3640
self.running = True
3741
self.logger = logging.getLogger("cloudbot")
38-
self.loop = loop
3942
self.config = MockConfig(self)
4043

4144
if config is not None:

0 commit comments

Comments
 (0)