Skip to content

Commit da187a9

Browse files
Add stubs for Flask-SocketIO (#10735)
Co-authored-by: AlexWaygood <alex.waygood@gmail.com>
1 parent 4c4278e commit da187a9

File tree

6 files changed

+256
-0
lines changed

6 files changed

+256
-0
lines changed

pyrightconfig.stricter.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"stubs/dateparser",
3636
"stubs/docutils",
3737
"stubs/Flask-Migrate",
38+
"stubs/Flask-SocketIO",
3839
"stubs/fpdf2",
3940
"stubs/google-cloud-ndb",
4041
"stubs/html5lib",
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# private attributes / methods, not present in docs
2+
flask_socketio.test_client.SocketIOTestClient.clients
3+
flask_socketio.gevent_socketio_found
4+
flask_socketio.call

stubs/Flask-SocketIO/METADATA.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version = "5.3.*"
2+
requires = ["Flask>=0.9"]
3+
upstream_repository = "https://github.com/miguelgrinberg/flask-socketio"
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
from _typeshed import Incomplete
2+
from collections.abc import Callable
3+
from threading import Thread
4+
from typing import Any, Protocol, TypeVar, overload
5+
from typing_extensions import ParamSpec, TypeAlias
6+
7+
from flask import Flask
8+
from flask.testing import FlaskClient
9+
10+
from .namespace import Namespace
11+
from .test_client import SocketIOTestClient
12+
13+
_P = ParamSpec("_P")
14+
_R_co = TypeVar("_R_co", covariant=True)
15+
_ExceptionHandler: TypeAlias = Callable[[BaseException], _R_co]
16+
_Handler: TypeAlias = Callable[_P, _R_co]
17+
18+
class _HandlerDecorator(Protocol):
19+
def __call__(self, handler: _Handler[_P, _R_co]) -> _Handler[_P, _R_co]: ...
20+
21+
class _ExceptionHandlerDecorator(Protocol):
22+
def __call__(self, exception_handler: _ExceptionHandler[_R_co]) -> _ExceptionHandler[_R_co]: ...
23+
24+
class SocketIO:
25+
# Many instance attributes are deliberately not included here,
26+
# as the maintainer of Flask-SocketIO considers them private, internal details:
27+
# https://github.com/python/typeshed/pull/10735#discussion_r1330768869
28+
def __init__(
29+
self,
30+
app: Flask | None = None,
31+
*,
32+
# SocketIO options
33+
manage_session: bool = True,
34+
message_queue: str | None = None,
35+
channel: str = "flask-socketio",
36+
path: str = "socket.io",
37+
resource: str = "socket.io",
38+
**kwargs, # TODO: Socket.IO server options, Engine.IO server config
39+
) -> None: ...
40+
def init_app(
41+
self,
42+
app: Flask,
43+
*,
44+
# SocketIO options
45+
manage_session: bool = True,
46+
message_queue: str | None = None,
47+
channel: str = "flask-socketio",
48+
path: str = "socket.io",
49+
resource: str = "socket.io",
50+
**kwargs, # TODO: Socket.IO server options, Engine.IO server config: ...
51+
) -> None: ...
52+
def on(self, message: str, namespace: str | None = None) -> _HandlerDecorator: ...
53+
def on_error(self, namespace: str | None = None) -> _ExceptionHandlerDecorator: ...
54+
def on_error_default(self, exception_handler: _ExceptionHandler[_R_co]) -> _ExceptionHandler[_R_co]: ...
55+
def on_event(self, message: str, handler: _Handler[[Incomplete], object], namespace: str | None = None) -> None: ...
56+
@overload
57+
def event(self, __event_handler: _Handler[_P, _R_co]) -> _Handler[_P, _R_co]: ...
58+
@overload
59+
def event(self, namespace: str | None = None, *args, **kwargs) -> _HandlerDecorator: ...
60+
def on_namespace(self, namespace_handler: Namespace) -> None: ...
61+
def emit(
62+
self,
63+
event: str,
64+
*args,
65+
namespace: str = "/", # / is the default (global) namespace
66+
to: str | None = None,
67+
include_self: bool = True,
68+
skip_sid: str | list[str] | None = None,
69+
callback: Callable[..., Incomplete] | None = None,
70+
) -> None: ...
71+
def call(
72+
self,
73+
event: str,
74+
*args,
75+
namespace: str = "/", # / is the default (global) namespace
76+
to: str | None = None,
77+
timeout: int = 60, # seconds
78+
ignore_queue: bool = False,
79+
): ...
80+
def send(
81+
self,
82+
data: Any,
83+
json: bool = False,
84+
namespace: str | None = None,
85+
to: str | None = None,
86+
callback: Callable[..., Incomplete] | None = None,
87+
include_self: bool = True,
88+
skip_sid: list[str] | str | None = None,
89+
**kwargs,
90+
) -> None: ...
91+
def close_room(self, room: str, namespace: str | None = None) -> None: ...
92+
def run(
93+
self,
94+
app,
95+
host: str | None = None,
96+
port: int | None = None,
97+
*,
98+
debug: bool = True,
99+
use_reloader: bool,
100+
reloader_options: dict[str, Incomplete] = {},
101+
log_output: bool,
102+
allow_unsafe_werkzeug: bool = False,
103+
**kwargs,
104+
) -> None: ...
105+
def stop(self) -> None: ...
106+
def start_background_task(self, target: Callable[_P, None], *args: _P.args, **kwargs: _P.kwargs) -> Thread: ...
107+
def sleep(self, seconds: int = 0): ...
108+
def test_client(
109+
self,
110+
app: Flask,
111+
namespace: str | None = None,
112+
query_string: str | None = None,
113+
headers: dict[str, Incomplete] | None = None,
114+
auth: dict[str, Incomplete] | None = None,
115+
flask_test_client: FlaskClient | None = None,
116+
) -> SocketIOTestClient: ...
117+
118+
def emit(
119+
event,
120+
*args,
121+
namespace: str = "/", # / is the default (global) namespace
122+
to: str | None = None,
123+
include_self: bool = True,
124+
skip_sid: str | list[str] | None = None,
125+
callback: Callable[..., Incomplete] | None = None,
126+
broadcast: bool = False,
127+
) -> None: ...
128+
def send(message: str, **kwargs) -> None: ...
129+
def join_room(room, sid: str | None = None, namespace: str | None = None) -> None: ...
130+
def leave_room(room, sid: str | None = None, namespace: str | None = None) -> None: ...
131+
def close_room(room, namespace: str | None = None) -> None: ...
132+
def rooms(sid: str | None = None, namespace: str | None = None) -> list[str]: ...
133+
def disconnect(sid: str | None = None, namespace: str | None = None, silent: bool = False) -> None: ...
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from _typeshed import Incomplete
2+
from collections.abc import Callable
3+
from typing import Any, Protocol, TypeVar
4+
5+
_T = TypeVar("_T")
6+
7+
# at runtime, socketio.namespace.BaseNamespace, but socketio isn't py.typed
8+
class _BaseNamespace(Protocol):
9+
def is_asyncio_based(self) -> bool: ...
10+
def trigger_event(self, event: str, *args): ...
11+
12+
# at runtime, socketio.namespace.BaseNamespace, but socketio isn't py.typed
13+
class _Namespace(_BaseNamespace, Protocol):
14+
def emit(
15+
self,
16+
event: str,
17+
data: Incomplete | None = None,
18+
to=None,
19+
room: str | None = None,
20+
skip_sid=None,
21+
namespace: str | None = None,
22+
callback: Callable[..., Incomplete] | None = None,
23+
ignore_queue: bool = False,
24+
): ...
25+
def send(
26+
self,
27+
data: Incomplete,
28+
to=None,
29+
room: str | None = None,
30+
skip_sid=None,
31+
namespace: str | None = None,
32+
callback: Callable[..., Incomplete] | None = None,
33+
ignore_queue: bool = False,
34+
) -> None: ...
35+
def call(
36+
self,
37+
event: str,
38+
data: Incomplete | None = None,
39+
to=None,
40+
sid=None,
41+
namespace: str | None = None,
42+
timeout=None,
43+
ignore_queue: bool = False,
44+
): ...
45+
def enter_room(self, sid, room: str, namespace: str | None = None): ...
46+
def leave_room(self, sid, room: str, namespace: str | None = None): ...
47+
def close_room(self, room: str, namespace: str | None = None): ...
48+
def rooms(self, sid, namespace: str | None = None): ...
49+
def get_session(self, sid, namespace: str | None = None): ...
50+
def save_session(self, sid, session, namespace: str | None = None): ...
51+
def session(self, sid, namespace: str | None = None): ...
52+
def disconnect(self, sid, namespace: str | None = None): ...
53+
54+
class Namespace(_Namespace):
55+
def __init__(self, namespace: str | None = None) -> None: ...
56+
def trigger_event(self, event: str, *args): ...
57+
def emit( # type: ignore[override]
58+
self,
59+
event: str,
60+
data: Incomplete | None = None,
61+
room: str | None = None,
62+
include_self: bool = True,
63+
namespace: str | None = None,
64+
callback: Callable[..., _T] | None = None,
65+
) -> _T | tuple[str, int]: ...
66+
def send( # type: ignore[override]
67+
self,
68+
data: Incomplete,
69+
room: str | None = None,
70+
include_self: bool = True,
71+
namespace: str | None = None,
72+
callback: Callable[..., Any] | None = None,
73+
) -> None: ...
74+
def close_room(self, room: str, namespace: str | None = None) -> None: ...
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from _typeshed import Incomplete
2+
from typing import Any
3+
from typing_extensions import TypedDict
4+
5+
from flask import Flask
6+
from flask.testing import FlaskClient
7+
8+
class _Packet(TypedDict):
9+
name: str
10+
args: Any
11+
namespace: str
12+
13+
class SocketIOTestClient:
14+
def __init__(
15+
self,
16+
app: Flask,
17+
socketio,
18+
namespace: str | None = None,
19+
query_string: str | None = None,
20+
headers: dict[str, Incomplete] | None = None,
21+
auth: dict[str, Incomplete] | None = None,
22+
flask_test_client: FlaskClient | None = None,
23+
) -> None: ...
24+
def is_connected(self, namespace: str | None = None) -> bool: ...
25+
def connect(
26+
self,
27+
namespace: str | None = None,
28+
query_string: str | None = None,
29+
headers: dict[str, Incomplete] | None = None,
30+
auth: dict[str, Incomplete] | None = None,
31+
) -> None: ...
32+
def disconnect(self, namespace: str | None = None) -> None: ...
33+
def emit(self, event: str, *args, callback: bool = True, namespace: str | None = None) -> Incomplete | None: ...
34+
def send(
35+
self,
36+
data: str | dict[str, Incomplete] | list[Incomplete],
37+
json: bool = False,
38+
callback: bool = False,
39+
namespace: str | None = None,
40+
): ...
41+
def get_received(self, namespace: str | None = None) -> list[_Packet]: ...

0 commit comments

Comments
 (0)