Skip to content

Commit eee1cda

Browse files
committed
more tests fixes for trio
1 parent 29154b9 commit eee1cda

File tree

9 files changed

+249
-76
lines changed

9 files changed

+249
-76
lines changed

.github/workflows/push.yml

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ jobs:
2020
run: pip install -U setuptools wheel
2121
- name: install
2222
run: pip install .[dev,ci]
23+
- name: install async requirements
24+
if: matrix.python != '2.7'
25+
run: pip install trio curio
2326
- name: test
2427
run: python -m pytest --reruns 5 tests/ --cov oscpy/ --cov-branch
2528
- name: coveralls

oscpy/server/__init__.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from time import time
1010
from functools import partial
1111
import socket
12+
from select import select
1213

1314
from oscpy import __version__
1415
from oscpy.parser import read_packet, UNICODE
@@ -263,13 +264,22 @@ def close(self, sock=None):
263264
elif not sock:
264265
raise RuntimeError('no default socket yet and no socket provided')
265266

267+
if sock == self.default_socket:
268+
self.default_socket = None
269+
270+
if sock not in self.sockets:
271+
return
272+
273+
self.sockets.remove(sock)
274+
read = select([sock], [], [], 0)
266275
if platform != 'win32' and sock.family == socket.AF_UNIX:
276+
print(sock.getsockname())
267277
os.unlink(sock.getsockname())
268278
else:
269279
sock.close()
270280

271-
if sock == self.default_socket:
272-
self.default_socket = None
281+
if sock in read:
282+
sock.recvfrom(UDP_MAX_SIZE)
273283

274284
def getaddress(self, sock=None):
275285
"""Wrap call to getsockname.

oscpy/server/curio_server.py

+20
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import logging
22
from typing import Awaitable
3+
from sys import platform
4+
import os
35

46
from curio import TaskGroup, socket
57
from oscpy.server import OSCBaseServer, UDP_MAX_SIZE
@@ -61,6 +63,24 @@ async def process(self):
6163
for s in self.sockets:
6264
await g.spawn(self._listen, s)
6365

66+
async def close(self, sock=None):
67+
"""Close a socket opened by the server."""
68+
if not sock and self.default_socket:
69+
sock = self.default_socket
70+
elif not sock:
71+
raise RuntimeError('no default socket yet and no socket provided')
72+
73+
if sock not in self.sockets:
74+
logger.warning("Ignoring requested to close an unknown socket %s" % sock)
75+
76+
if sock == self.default_socket:
77+
self.default_socket = None
78+
79+
if platform != 'win32' and sock.family == socket.AF_UNIX:
80+
os.unlink(sock.getsockname())
81+
else:
82+
await sock.close()
83+
6484
async def stop_all(self):
6585
await self.tasks_group.cancel_remaining()
6686

oscpy/server/thread_server.py

+1-7
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,7 @@ def stop(self, s=None):
3737
s = self.default_socket
3838

3939
if s in self.sockets:
40-
read = select([s], [], [], 0)
41-
s.close()
42-
if s in read:
43-
s.recvfrom(UDP_MAX_SIZE)
44-
self.sockets.remove(s)
45-
if s is self.default_socket:
46-
self.default_socket = None
40+
self.close(s)
4741
else:
4842
raise RuntimeError('{} is not one of my sockets!'.format(s))
4943

oscpy/server/trio_server.py

+67-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import os
12
import logging
23
from functools import partial
4+
from sys import platform
5+
from typing import Awaitable
36

4-
from trio import socket, open_nursery
7+
from trio import socket, open_nursery, move_on_after
58
from oscpy.server import OSCBaseServer, UDP_MAX_SIZE
69

710
logging.basicConfig()
@@ -33,24 +36,34 @@ async def listen(
3336
"Unknown socket family, accepted values are 'unix' and 'inet'"
3437
)
3538

36-
sock = await self.get_socket(family_, (address, port))
39+
if family == 'unix':
40+
addr = address
41+
else:
42+
addr = (address, port)
43+
sock = await self.get_socket(family_, addr)
3744
self.add_socket(sock, default)
3845
return sock
3946

4047
async def _listen(self, sock):
4148
async with open_nursery() as nursery:
4249
self.nurseries[sock] = nursery
43-
while True:
44-
data, addr = await sock.recvfrom(UDP_MAX_SIZE)
45-
nursery.start_soon(
46-
partial(
47-
self.handle_message,
48-
data,
49-
addr,
50-
drop_late=False,
51-
sender_socket=sock
50+
try:
51+
while True:
52+
data, addr = await sock.recvfrom(UDP_MAX_SIZE)
53+
nursery.start_soon(
54+
partial(
55+
self.handle_message,
56+
data,
57+
addr,
58+
drop_late=False,
59+
sender_socket=sock
60+
)
5261
)
53-
)
62+
finally:
63+
with move_on_after(1) as cleanup_scope:
64+
cleanup_scope.shield = True
65+
logger.info("socket %s cancelled", sock)
66+
await self.stop(sock)
5467

5568
async def handle_message(self, data, sender, drop_late, sender_socket):
5669
for callbacks, values, address in self.callbacks(data, sender, sender_socket):
@@ -60,13 +73,17 @@ async def _execute_callbacks(self, callbacks_list, address, values):
6073
for cb, get_address in callbacks_list:
6174
try:
6275
if get_address:
63-
await cb(address, *values)
76+
result = cb(address, *values)
6477
else:
65-
await cb(*values)
78+
result = cb(*values)
79+
if isinstance(result, Awaitable):
80+
await result
81+
6682
except Exception:
6783
if self.intercept_errors:
68-
logger.error("Unhandled exception caught in oscpy server", exc_info=True)
84+
logger.error("Ignoring unhandled exception caught in oscpy server", exc_info=True)
6985
else:
86+
logger.exception("Unhandled exception caught in oscpy server")
7087
raise
7188

7289
async def process(self):
@@ -80,9 +97,41 @@ async def stop_all(self):
8097
"""
8198
self.nursery.cancel_scope.deadline = 0
8299

83-
async def stop(self, sock):
84-
nursery = self.nurseries.pop(sock)
85-
nursery.cancel_scope.deadline = 0
100+
async def stop(self, sock=None):
101+
if sock is None:
102+
if self.default_socket:
103+
sock = self.default_socket
104+
else:
105+
raise RuntimeError('no default socket yet and no socket provided')
106+
if sock in self.sockets:
107+
self.sockets.remove(sock)
108+
else:
109+
raise RuntimeError("Socket %s is not managed by this server" % sock)
110+
sock.close()
111+
if sock in self.nurseries:
112+
nursery = self.nurseries.pop(sock)
113+
nursery.cancel_scope.deadline = 0
114+
115+
if sock is self.default_socket:
116+
self.default_socket = None
117+
118+
async def close(self, sock=None):
119+
"""Close a socket opened by the server."""
120+
if not sock and self.default_socket:
121+
sock = self.default_socket
122+
elif not sock:
123+
raise RuntimeError('no default socket yet and no socket provided')
124+
125+
if sock not in self.sockets:
126+
logger.warning("Ignoring requested to close an unknown socket %s" % sock)
127+
128+
if sock == self.default_socket:
129+
self.default_socket = None
130+
131+
if platform != 'win32' and sock.family == socket.AF_UNIX:
132+
os.unlink(sock.getsockname())
133+
else:
134+
sock.close()
86135

87136
def getaddress(self, sock=None):
88137
"""Wrap call to getsockname.

tests/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)