Skip to content

Fix/50/win oserror #51

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: install
run: pip install .[dev,ci]
- name: test
run: python -m pytest --reruns 5 tests/ --cov oscpy/ --cov-branch
run: python -m pytest --reruns 2 tests/ --cov oscpy/ --cov-branch
- name: coveralls
run: python -m coveralls
env:
Expand Down
21 changes: 13 additions & 8 deletions oscpy/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def _send(options):
def _parse(s):
try:
return literal_eval(s)
except:
except (ValueError, SyntaxError):
return s

stats = Stats()
Expand Down Expand Up @@ -59,7 +59,7 @@ def dump(address, *values):
return osc


def _dump(options): # pragma: no cover
def _dump(options): # pragma: no cover
osc = __dump(options)
try:
while True:
Expand All @@ -82,7 +82,8 @@ def init_parser():
help='port to send message to.')
send.add_argument('--encoding', '-e', action='store', default='utf-8',
help='how to encode the strings')
send.add_argument('--encoding_errors', '-E', action='store', default='replace',
send.add_argument('--encoding_errors', '-E', action='store',
default='replace',
help='how to treat string encoding issues')
send.add_argument('--safer', '-s', action='store_true',
help='wait a little after sending message')
Expand All @@ -92,24 +93,28 @@ def init_parser():
send.add_argument('address', action='store',
help='OSC address to send the message to.')
send.add_argument('message', nargs='*',
help='content of the message, separated by spaces.')
help='content of the message, separated by spaces.')

dump = subparser.add_parser('dump', help='listen for messages and print them')
dump = subparser.add_parser('dump',
help='listen for messages and print them')
dump.set_defaults(func=_dump)
dump.add_argument('--host', '-H', action='store', default='localhost',
help='host (ip or name) to send message to.')
dump.add_argument('--port', '-P', action='store', type=int, default='8000',
help='port to send message to.')
dump.add_argument('--encoding', '-e', action='store', default='utf-8',
help='how to encode the strings')
dump.add_argument('--encoding_errors', '-E', action='store', default='replace',
dump.add_argument('--encoding_errors', '-E', action='store',
default='replace',
help='how to treat string encoding issues')

# bridge = parser.add_parser('bridge', help='listen for messages and redirect them to a server')
# TODO
# bridge = parser.add_parser('bridge', help='listen for messages and
# redirect them to a server')
return parser


def main(): # pragma: no cover
def main(): # pragma: no cover
parser = init_parser()
options = parser.parse_args()
exit(options.func(options))
8 changes: 6 additions & 2 deletions oscpy/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@

MidiTuple = namedtuple('MidiTuple', 'port_id status_byte data1 data2')


def padded(l, n=4):
"""Return the size to pad a thing to.

Expand Down Expand Up @@ -237,7 +238,9 @@ def format_message(address, values, encoding='', encoding_errors='strict'):

if cls_or_value == UNICODE:
if not encoding:
raise TypeError(u"Can't format unicode string without encoding")
raise TypeError(
u"Can't format unicode string without encoding"
)

cls_or_value = bytes
value = (
Expand Down Expand Up @@ -274,7 +277,8 @@ def format_message(address, values, encoding='', encoding_errors='strict'):
tags,
*(
(
encode_cache.get(v) + NULL if isinstance(v, UNICODE) and encoding
encode_cache.get(v) + NULL
if isinstance(v, UNICODE) and encoding
else (v + NULL) if t in (b's', b'b')
else format_midi(v) if isinstance(v, MidiTuple)
else v
Expand Down
16 changes: 10 additions & 6 deletions oscpy/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
from oscpy.client import send_bundle, send_message
from oscpy.stats import Stats

UDP_MAX_SIZE = 65535


def ServerClass(cls):
"""Decorate classes with for methods implementing OSC endpoints.
Expand Down Expand Up @@ -62,7 +64,7 @@ def __init__(
"""Create an OSCThreadServer.

- `timeout` is a number of seconds used as a time limit for
select() calls in the listening thread, optiomal, defaults to
select() calls in the listening thread, optional, defaults to
0.01.
- `drop_late_bundles` instruct the server not to dispatch calls
from bundles that arrived after their timetag value.
Expand Down Expand Up @@ -327,14 +329,14 @@ def _listen(self):
continue
else:
try:
read, write, error = select(self.sockets, [], [], self.timeout)
read, _, _ = select(self.sockets, [], [], self.timeout)
except (ValueError, socket.error):
continue

for sender_socket in read:
try:
data, sender = sender_socket.recvfrom(65535)
except ConnectionResetError:
data, sender = sender_socket.recvfrom(UDP_MAX_SIZE)
except (OSError, ConnectionResetError):
continue

for address, tags, values, offset in read_packet(
Expand Down Expand Up @@ -441,7 +443,8 @@ def send_bundle(
return stats

def get_sender(self):
"""Return the socket, ip and port of the message that is currently being managed.
"""Return the socket, ip and port of the message that is
currently being managed.
Warning::

this method should only be called from inside the handling
Expand Down Expand Up @@ -568,8 +571,9 @@ def bind_meta_routes(self, sock=None):
"""
self.bind(b'/_oscpy/version', self._get_version, sock=sock)
self.bind(b'/_oscpy/routes', self._get_routes, sock=sock)
self.bind(b'/_oscpy/stats/received', self._get_stats_received, sock=sock)
self.bind(b'/_oscpy/stats/sent', self._get_stats_sent, sock=sock)
self.bind(b'/_oscpy/stats/received',
self._get_stats_received, sock=sock)

def _get_version(self, port, *args):
self.answer(
Expand Down
19 changes: 19 additions & 0 deletions tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -927,3 +927,22 @@ def callback_3000(*values):
assert checklist == ['a', 'b', 'c']

server_3000.stop() # clean up


def test_close_receiving():
from threading import Thread

osc = OSCThreadServer(encoding='utf8')
osc.listen(default=True)
port = osc.getaddress()[1]

def send_messages():
for i in range(500):
send_message(b'/flood', [b't' * 60000], 'localhost', port)

thread = Thread(target=send_messages)
thread.start()

# surprise, let's stop it asap!
osc.stop_all()
thread.join()