From bc2b6b0b7fdf128ccea587c50f2596ab6b33399d Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 27 May 2021 16:52:16 +1000 Subject: [PATCH] micropython/uasyncio: Remove uasyncio-v2. Superceded by uasyncio-v3 in the main repo. Signed-off-by: Jim Mussared --- .../uasyncio.core/example_call_soon.py | 17 - micropython/uasyncio.core/metadata.txt | 6 - micropython/uasyncio.core/setup.py | 24 -- micropython/uasyncio.core/test_cancel.py | 80 ----- micropython/uasyncio.core/test_cb_args.py | 16 - .../uasyncio.core/test_fair_schedule.py | 39 -- micropython/uasyncio.core/test_full_wait.py | 56 --- micropython/uasyncio.core/test_wait_for.py | 47 --- micropython/uasyncio.core/uasyncio/core.py | 332 ------------------ micropython/uasyncio.queues/metadata.txt | 5 - micropython/uasyncio.queues/setup.py | 25 -- micropython/uasyncio.queues/tests/test.py | 57 --- .../uasyncio.queues/uasyncio/queues.py | 95 ----- micropython/uasyncio.synchro/example_lock.py | 27 -- micropython/uasyncio.synchro/metadata.txt | 5 - micropython/uasyncio.synchro/setup.py | 25 -- .../uasyncio.synchro/uasyncio/synchro.py | 28 -- micropython/uasyncio.udp/example_dns_junk.py | 28 -- micropython/uasyncio.udp/metadata.txt | 6 - micropython/uasyncio.udp/setup.py | 25 -- micropython/uasyncio.udp/uasyncio/udp.py | 64 ---- .../example_websock.py | 28 -- .../uasyncio.websocket.server/metadata.txt | 5 - .../uasyncio.websocket.server/setup.py | 25 -- .../uasyncio/websocket/server.py | 64 ---- micropython/uasyncio/README.rst | 43 --- micropython/uasyncio/README.test | 45 --- .../uasyncio/benchmark/boom_uasyncio.py | 39 -- .../uasyncio/benchmark/test-ab-medium.sh | 17 - .../uasyncio/benchmark/test-boom-heavy.sh | 28 -- .../benchmark/test_http_server_heavy.py | 42 --- .../benchmark/test_http_server_light.py | 22 -- .../benchmark/test_http_server_medium.py | 24 -- micropython/uasyncio/example_http_client.py | 27 -- micropython/uasyncio/example_http_server.py | 22 -- micropython/uasyncio/metadata.txt | 7 - micropython/uasyncio/setup.py | 25 -- micropython/uasyncio/test_echo.py | 32 -- micropython/uasyncio/test_io_starve.py | 37 -- micropython/uasyncio/test_readexactly.py | 39 -- micropython/uasyncio/test_readline.py | 35 -- micropython/uasyncio/uasyncio/__init__.py | 259 -------------- 42 files changed, 1872 deletions(-) delete mode 100644 micropython/uasyncio.core/example_call_soon.py delete mode 100644 micropython/uasyncio.core/metadata.txt delete mode 100644 micropython/uasyncio.core/setup.py delete mode 100644 micropython/uasyncio.core/test_cancel.py delete mode 100644 micropython/uasyncio.core/test_cb_args.py delete mode 100644 micropython/uasyncio.core/test_fair_schedule.py delete mode 100644 micropython/uasyncio.core/test_full_wait.py delete mode 100644 micropython/uasyncio.core/test_wait_for.py delete mode 100644 micropython/uasyncio.core/uasyncio/core.py delete mode 100644 micropython/uasyncio.queues/metadata.txt delete mode 100644 micropython/uasyncio.queues/setup.py delete mode 100644 micropython/uasyncio.queues/tests/test.py delete mode 100644 micropython/uasyncio.queues/uasyncio/queues.py delete mode 100644 micropython/uasyncio.synchro/example_lock.py delete mode 100644 micropython/uasyncio.synchro/metadata.txt delete mode 100644 micropython/uasyncio.synchro/setup.py delete mode 100644 micropython/uasyncio.synchro/uasyncio/synchro.py delete mode 100644 micropython/uasyncio.udp/example_dns_junk.py delete mode 100644 micropython/uasyncio.udp/metadata.txt delete mode 100644 micropython/uasyncio.udp/setup.py delete mode 100644 micropython/uasyncio.udp/uasyncio/udp.py delete mode 100644 micropython/uasyncio.websocket.server/example_websock.py delete mode 100644 micropython/uasyncio.websocket.server/metadata.txt delete mode 100644 micropython/uasyncio.websocket.server/setup.py delete mode 100644 micropython/uasyncio.websocket.server/uasyncio/websocket/server.py delete mode 100644 micropython/uasyncio/README.rst delete mode 100644 micropython/uasyncio/README.test delete mode 100644 micropython/uasyncio/benchmark/boom_uasyncio.py delete mode 100755 micropython/uasyncio/benchmark/test-ab-medium.sh delete mode 100755 micropython/uasyncio/benchmark/test-boom-heavy.sh delete mode 100644 micropython/uasyncio/benchmark/test_http_server_heavy.py delete mode 100644 micropython/uasyncio/benchmark/test_http_server_light.py delete mode 100644 micropython/uasyncio/benchmark/test_http_server_medium.py delete mode 100644 micropython/uasyncio/example_http_client.py delete mode 100644 micropython/uasyncio/example_http_server.py delete mode 100644 micropython/uasyncio/metadata.txt delete mode 100644 micropython/uasyncio/setup.py delete mode 100644 micropython/uasyncio/test_echo.py delete mode 100644 micropython/uasyncio/test_io_starve.py delete mode 100644 micropython/uasyncio/test_readexactly.py delete mode 100644 micropython/uasyncio/test_readline.py delete mode 100644 micropython/uasyncio/uasyncio/__init__.py diff --git a/micropython/uasyncio.core/example_call_soon.py b/micropython/uasyncio.core/example_call_soon.py deleted file mode 100644 index bc42e009..00000000 --- a/micropython/uasyncio.core/example_call_soon.py +++ /dev/null @@ -1,17 +0,0 @@ -import uasyncio.core as asyncio -import time -import logging - -logging.basicConfig(level=logging.DEBUG) -# asyncio.set_debug(True) - - -def cb(): - print("callback") - time.sleep(0.5) - loop.call_soon(cb) - - -loop = asyncio.get_event_loop() -loop.call_soon(cb) -loop.run_forever() diff --git a/micropython/uasyncio.core/metadata.txt b/micropython/uasyncio.core/metadata.txt deleted file mode 100644 index 21d58166..00000000 --- a/micropython/uasyncio.core/metadata.txt +++ /dev/null @@ -1,6 +0,0 @@ -srctype = micropython-lib -type = package -version = 2.0 -author = Paul Sokolovsky -desc = Lightweight asyncio-like library for MicroPython, built around native Python coroutines. (Core event loop). -long_desc = Lightweight asyncio-like library for MicroPython, built around native Python coroutines. (Core event loop). diff --git a/micropython/uasyncio.core/setup.py b/micropython/uasyncio.core/setup.py deleted file mode 100644 index f3611983..00000000 --- a/micropython/uasyncio.core/setup.py +++ /dev/null @@ -1,24 +0,0 @@ -import sys - -# Remove current dir from sys.path, otherwise setuptools will peek up our -# module instead of system's. -sys.path.pop(0) -from setuptools import setup - -sys.path.append("..") -import sdist_upip - -setup( - name="micropython-uasyncio.core", - version="2.0", - description="Lightweight asyncio-like library for MicroPython, built around native Python coroutines. (Core event loop).", - long_description="Lightweight asyncio-like library for MicroPython, built around native Python coroutines. (Core event loop).", - url="https://github.com/micropython/micropython-lib", - author="Paul Sokolovsky", - author_email="micro-python@googlegroups.com", - maintainer="micropython-lib Developers", - maintainer_email="micro-python@googlegroups.com", - license="MIT", - cmdclass={"sdist": sdist_upip.sdist}, - packages=["uasyncio"], -) diff --git a/micropython/uasyncio.core/test_cancel.py b/micropython/uasyncio.core/test_cancel.py deleted file mode 100644 index ebba9176..00000000 --- a/micropython/uasyncio.core/test_cancel.py +++ /dev/null @@ -1,80 +0,0 @@ -import time - -try: - import uasyncio.core as asyncio - - is_uasyncio = True -except ImportError: - import asyncio - - is_uasyncio = False -import logging - -# logging.basicConfig(level=logging.DEBUG) -# asyncio.set_debug(True) - - -output = [] -cancelled = False - - -def print1(msg): - print(msg) - output.append(msg) - - -def looper1(iters): - global cancelled - try: - for i in range(iters): - print1("ping1") - # sleep() isn't properly cancellable - # yield from asyncio.sleep(1.0) - t = time.time() - while time.time() - t < 1: - yield from asyncio.sleep(0) - return 10 - except asyncio.CancelledError: - print1("cancelled") - cancelled = True - - -def looper2(iters): - for i in range(iters): - print1("ping2") - # sleep() isn't properly cancellable - # yield from asyncio.sleep(1.0) - t = time.time() - while time.time() - t < 1: - yield from asyncio.sleep(0) - return 10 - - -def run_to(): - coro = looper1(10) - task = loop.create_task(coro) - yield from asyncio.sleep(3) - if is_uasyncio: - asyncio.cancel(coro) - else: - task.cancel() - # Need another eventloop iteration for cancellation to be actually - # processed and to see side effects of the cancellation. - yield from asyncio.sleep(0) - assert cancelled - - coro = looper2(10) - task = loop.create_task(coro) - yield from asyncio.sleep(2) - if is_uasyncio: - asyncio.cancel(coro) - else: - task.cancel() - yield from asyncio.sleep(0) - - # Once saw 3 ping3's output on CPython 3.5.2 - assert output == ["ping1", "ping1", "ping1", "cancelled", "ping2", "ping2"] - - -loop = asyncio.get_event_loop() -loop.run_until_complete(run_to()) diff --git a/micropython/uasyncio.core/test_cb_args.py b/micropython/uasyncio.core/test_cb_args.py deleted file mode 100644 index 8bf80a6b..00000000 --- a/micropython/uasyncio.core/test_cb_args.py +++ /dev/null @@ -1,16 +0,0 @@ -try: - import uasyncio.core as asyncio -except: - import asyncio - - -def cb(a, b): - assert a == "test" - assert b == "test2" - loop.stop() - - -loop = asyncio.get_event_loop() -loop.call_soon(cb, "test", "test2") -loop.run_forever() -print("OK") diff --git a/micropython/uasyncio.core/test_fair_schedule.py b/micropython/uasyncio.core/test_fair_schedule.py deleted file mode 100644 index 46151ab9..00000000 --- a/micropython/uasyncio.core/test_fair_schedule.py +++ /dev/null @@ -1,39 +0,0 @@ -# Test that uasyncio scheduling is fair, i.e. gives all -# coroutines equal chance to run (this specifically checks -# round-robin scheduling). -import uasyncio.core as asyncio - - -COROS = 10 -ITERS = 20 - - -result = [] -test_finished = False - - -async def coro(n): - for i in range(ITERS): - result.append(n) - yield - - -async def done(): - global test_finished - while True: - if len(result) == COROS * ITERS: - # print(result) - assert result == list(range(COROS)) * ITERS - test_finished = True - return - yield - - -loop = asyncio.get_event_loop() - -for n in range(COROS): - loop.create_task(coro(n)) - -loop.run_until_complete(done()) - -assert test_finished diff --git a/micropython/uasyncio.core/test_full_wait.py b/micropython/uasyncio.core/test_full_wait.py deleted file mode 100644 index ff0806b9..00000000 --- a/micropython/uasyncio.core/test_full_wait.py +++ /dev/null @@ -1,56 +0,0 @@ -# Test that coros scheduled to run at some time don't run prematurely -# in case of I/O completion before that. -import uasyncio.core as uasyncio -import logging - -logging.basicConfig(level=logging.DEBUG) -# uasyncio.set_debug(True) - - -class MockEventLoop(uasyncio.EventLoop): - def __init__(self): - super().__init__() - self.t = 0 - self.msgs = [] - - def time(self): - return self.t - - def pass_time(self, delta): - self.t += delta - - def wait(self, delay): - # print("%d: wait(%d)" % (self.t, delay)) - self.pass_time(100) - - if self.t == 100: - - def cb_1st(): - self.msgs.append("I should be run first, time: %s" % self.time()) - - self.call_soon(cb_1st) - - if self.t == 1000: - raise StopIteration - - -loop = MockEventLoop() - - -def cb_2nd(): - loop.msgs.append("I should be run second, time: %s" % loop.time()) - - -loop.call_later_ms(500, cb_2nd) - -try: - loop.run_forever() -except StopIteration: - pass - -print(loop.msgs) -# .wait() is now called on each loop iteration, and for our mock case, it means that -# at the time of running, self.time() will be skewed by 100 virtual time units. -assert loop.msgs == ["I should be run first, time: 100", "I should be run second, time: 500"], str( - loop.msgs -) diff --git a/micropython/uasyncio.core/test_wait_for.py b/micropython/uasyncio.core/test_wait_for.py deleted file mode 100644 index f0baa5e7..00000000 --- a/micropython/uasyncio.core/test_wait_for.py +++ /dev/null @@ -1,47 +0,0 @@ -try: - import uasyncio.core as asyncio -except ImportError: - import asyncio -import logging - -# logging.basicConfig(level=logging.DEBUG) -# asyncio.set_debug(True) - - -def looper(iters): - for i in range(iters): - print("ping") - yield from asyncio.sleep(1.0) - return 10 - - -def run_to(): - try: - ret = yield from asyncio.wait_for(looper(2), 1) - print("result:", ret) - assert False - except asyncio.TimeoutError: - print("Coro timed out") - - print("=================") - - try: - ret = yield from asyncio.wait_for(looper(2), 2) - print("result:", ret) - assert False - except asyncio.TimeoutError: - print("Coro timed out") - - print("=================") - - try: - ret = yield from asyncio.wait_for(looper(2), 3) - print("result:", ret) - except asyncio.TimeoutError: - print("Coro timed out") - assert False - - -loop = asyncio.get_event_loop() -loop.run_until_complete(run_to()) -loop.run_until_complete(asyncio.sleep(1)) diff --git a/micropython/uasyncio.core/uasyncio/core.py b/micropython/uasyncio.core/uasyncio/core.py deleted file mode 100644 index 1902863f..00000000 --- a/micropython/uasyncio.core/uasyncio/core.py +++ /dev/null @@ -1,332 +0,0 @@ -import utime as time -import utimeq -import ucollections - - -type_gen = type((lambda: (yield))()) - -DEBUG = 0 -log = None - - -def set_debug(val): - global DEBUG, log - DEBUG = val - if val: - import logging - - log = logging.getLogger("uasyncio.core") - - -class CancelledError(Exception): - pass - - -class TimeoutError(CancelledError): - pass - - -class EventLoop: - def __init__(self, runq_len=16, waitq_len=16): - self.runq = ucollections.deque((), runq_len, True) - self.waitq = utimeq.utimeq(waitq_len) - # Current task being run. Task is a top-level coroutine scheduled - # in the event loop (sub-coroutines executed transparently by - # yield from/await, event loop "doesn't see" them). - self.cur_task = None - - def time(self): - return time.ticks_ms() - - def create_task(self, coro): - # CPython 3.4.2 - self.call_later_ms(0, coro) - # CPython asyncio incompatibility: we don't return Task object - - def call_soon(self, callback, *args): - if __debug__ and DEBUG: - log.debug("Scheduling in runq: %s", (callback, args)) - self.runq.append(callback) - if not isinstance(callback, type_gen): - self.runq.append(args) - - def call_later(self, delay, callback, *args): - self.call_at_(time.ticks_add(self.time(), int(delay * 1000)), callback, args) - - def call_later_ms(self, delay, callback, *args): - if not delay: - return self.call_soon(callback, *args) - self.call_at_(time.ticks_add(self.time(), delay), callback, args) - - def call_at_(self, time, callback, args=()): - if __debug__ and DEBUG: - log.debug("Scheduling in waitq: %s", (time, callback, args)) - self.waitq.push(time, callback, args) - - def wait(self, delay): - # Default wait implementation, to be overriden in subclasses - # with IO scheduling - if __debug__ and DEBUG: - log.debug("Sleeping for: %s", delay) - time.sleep_ms(delay) - - def run_forever(self): - cur_task = [0, 0, 0] - while True: - # Expire entries in waitq and move them to runq - tnow = self.time() - while self.waitq: - t = self.waitq.peektime() - delay = time.ticks_diff(t, tnow) - if delay > 0: - break - self.waitq.pop(cur_task) - if __debug__ and DEBUG: - log.debug("Moving from waitq to runq: %s", cur_task[1]) - self.call_soon(cur_task[1], *cur_task[2]) - - # Process runq - l = len(self.runq) - if __debug__ and DEBUG: - log.debug("Entries in runq: %d", l) - while l: - cb = self.runq.popleft() - l -= 1 - args = () - if not isinstance(cb, type_gen): - args = self.runq.popleft() - l -= 1 - if __debug__ and DEBUG: - log.info("Next callback to run: %s", (cb, args)) - cb(*args) - continue - - if __debug__ and DEBUG: - log.info("Next coroutine to run: %s", (cb, args)) - self.cur_task = cb - delay = 0 - try: - if args is (): - ret = next(cb) - else: - ret = cb.send(*args) - if __debug__ and DEBUG: - log.info("Coroutine %s yield result: %s", cb, ret) - if isinstance(ret, SysCall1): - arg = ret.arg - if isinstance(ret, SleepMs): - delay = arg - elif isinstance(ret, IORead): - cb.pend_throw(False) - self.add_reader(arg, cb) - continue - elif isinstance(ret, IOWrite): - cb.pend_throw(False) - self.add_writer(arg, cb) - continue - elif isinstance(ret, IOReadDone): - self.remove_reader(arg) - elif isinstance(ret, IOWriteDone): - self.remove_writer(arg) - elif isinstance(ret, StopLoop): - return arg - else: - assert False, "Unknown syscall yielded: %r (of type %r)" % ( - ret, - type(ret), - ) - elif isinstance(ret, type_gen): - self.call_soon(ret) - elif isinstance(ret, int): - # Delay - delay = ret - elif ret is None: - # Just reschedule - pass - elif ret is False: - # Don't reschedule - continue - else: - assert False, "Unsupported coroutine yield value: %r (of type %r)" % ( - ret, - type(ret), - ) - except StopIteration as e: - if __debug__ and DEBUG: - log.debug("Coroutine finished: %s", cb) - continue - except CancelledError as e: - if __debug__ and DEBUG: - log.debug("Coroutine cancelled: %s", cb) - continue - # Currently all syscalls don't return anything, so we don't - # need to feed anything to the next invocation of coroutine. - # If that changes, need to pass that value below. - if delay: - self.call_later_ms(delay, cb) - else: - self.call_soon(cb) - - # Wait until next waitq task or I/O availability - delay = 0 - if not self.runq: - delay = -1 - if self.waitq: - tnow = self.time() - t = self.waitq.peektime() - delay = time.ticks_diff(t, tnow) - if delay < 0: - delay = 0 - self.wait(delay) - - def run_until_complete(self, coro): - def _run_and_stop(): - yield from coro - yield StopLoop(0) - - self.call_soon(_run_and_stop()) - self.run_forever() - - def stop(self): - self.call_soon((lambda: (yield StopLoop(0)))()) - - def close(self): - pass - - -class SysCall: - def __init__(self, *args): - self.args = args - - def handle(self): - raise NotImplementedError - - -# Optimized syscall with 1 arg -class SysCall1(SysCall): - def __init__(self, arg): - self.arg = arg - - -class StopLoop(SysCall1): - pass - - -class IORead(SysCall1): - pass - - -class IOWrite(SysCall1): - pass - - -class IOReadDone(SysCall1): - pass - - -class IOWriteDone(SysCall1): - pass - - -_event_loop = None -_event_loop_class = EventLoop - - -def get_event_loop(runq_len=16, waitq_len=16): - global _event_loop - if _event_loop is None: - _event_loop = _event_loop_class(runq_len, waitq_len) - return _event_loop - - -def sleep(secs): - yield int(secs * 1000) - - -# Implementation of sleep_ms awaitable with zero heap memory usage -class SleepMs(SysCall1): - def __init__(self): - self.v = None - self.arg = None - - def __call__(self, arg): - self.v = arg - # print("__call__") - return self - - def __iter__(self): - # print("__iter__") - return self - - def __next__(self): - if self.v is not None: - # print("__next__ syscall enter") - self.arg = self.v - self.v = None - return self - # print("__next__ syscall exit") - _stop_iter.__traceback__ = None - raise _stop_iter - - -_stop_iter = StopIteration() -sleep_ms = SleepMs() - - -def cancel(coro): - prev = coro.pend_throw(CancelledError()) - if prev is False: - _event_loop.call_soon(coro) - - -class TimeoutObj: - def __init__(self, coro): - self.coro = coro - - -def wait_for_ms(coro, timeout): - def waiter(coro, timeout_obj): - res = yield from coro - if __debug__ and DEBUG: - log.debug("waiter: cancelling %s", timeout_obj) - timeout_obj.coro = None - return res - - def timeout_func(timeout_obj): - if timeout_obj.coro: - if __debug__ and DEBUG: - log.debug("timeout_func: cancelling %s", timeout_obj.coro) - prev = timeout_obj.coro.pend_throw(TimeoutError()) - # print("prev pend", prev) - if prev is False: - _event_loop.call_soon(timeout_obj.coro) - - timeout_obj = TimeoutObj(_event_loop.cur_task) - _event_loop.call_later_ms(timeout, timeout_func, timeout_obj) - return (yield from waiter(coro, timeout_obj)) - - -def wait_for(coro, timeout): - return wait_for_ms(coro, int(timeout * 1000)) - - -def coroutine(f): - return f - - -# -# The functions below are deprecated in uasyncio, and provided only -# for compatibility with CPython asyncio -# - - -def ensure_future(coro, loop=_event_loop): - _event_loop.call_soon(coro) - # CPython asyncio incompatibility: we don't return Task object - return coro - - -# CPython asyncio incompatibility: Task is a function, not a class (for efficiency) -def Task(coro, loop=_event_loop): - # Same as async() - _event_loop.call_soon(coro) diff --git a/micropython/uasyncio.queues/metadata.txt b/micropython/uasyncio.queues/metadata.txt deleted file mode 100644 index 06127d03..00000000 --- a/micropython/uasyncio.queues/metadata.txt +++ /dev/null @@ -1,5 +0,0 @@ -srctype = micropython-lib -type = package -version = 0.1.2 -long_desc = Port of asyncio.queues to uasyncio. -depends = uasyncio.core, collections.deque diff --git a/micropython/uasyncio.queues/setup.py b/micropython/uasyncio.queues/setup.py deleted file mode 100644 index 3537b40b..00000000 --- a/micropython/uasyncio.queues/setup.py +++ /dev/null @@ -1,25 +0,0 @@ -import sys - -# Remove current dir from sys.path, otherwise setuptools will peek up our -# module instead of system's. -sys.path.pop(0) -from setuptools import setup - -sys.path.append("..") -import sdist_upip - -setup( - name="micropython-uasyncio.queues", - version="0.1.2", - description="uasyncio.queues module for MicroPython", - long_description="Port of asyncio.queues to uasyncio.", - url="https://github.com/micropython/micropython-lib", - author="micropython-lib Developers", - author_email="micro-python@googlegroups.com", - maintainer="micropython-lib Developers", - maintainer_email="micro-python@googlegroups.com", - license="MIT", - cmdclass={"sdist": sdist_upip.sdist}, - packages=["uasyncio"], - install_requires=["micropython-uasyncio.core", "micropython-collections.deque"], -) diff --git a/micropython/uasyncio.queues/tests/test.py b/micropython/uasyncio.queues/tests/test.py deleted file mode 100644 index d48cd7c6..00000000 --- a/micropython/uasyncio.queues/tests/test.py +++ /dev/null @@ -1,57 +0,0 @@ -from unittest import TestCase, run_class -import sys - -sys.path.insert(0, "../uasyncio") -import queues - - -class QueueTestCase(TestCase): - def _val(self, gen): - """Returns val from generator.""" - while True: - try: - gen.send(None) - except StopIteration as e: - return e.value - - def test_get_put(self): - q = queues.Queue(maxsize=1) - self._val(q.put(42)) - self.assertEqual(self._val(q.get()), 42) - - def test_get_put_nowait(self): - q = queues.Queue(maxsize=1) - q.put_nowait(12) - try: - q.put_nowait(42) - self.assertTrue(False) - except Exception as e: - self.assertEqual(type(e), queues.QueueFull) - self.assertEqual(q.get_nowait(), 12) - try: - q.get_nowait() - self.assertTrue(False) - except Exception as e: - self.assertEqual(type(e), queues.QueueEmpty) - - def test_qsize(self): - q = queues.Queue() - for n in range(10): - q.put_nowait(10) - self.assertEqual(q.qsize(), 10) - - def test_empty(self): - q = queues.Queue() - self.assertTrue(q.empty()) - q.put_nowait(10) - self.assertFalse(q.empty()) - - def test_full(self): - q = queues.Queue(maxsize=1) - self.assertFalse(q.full()) - q.put_nowait(10) - self.assertTrue(q.full()) - - -if __name__ == "__main__": - run_class(QueueTestCase) diff --git a/micropython/uasyncio.queues/uasyncio/queues.py b/micropython/uasyncio.queues/uasyncio/queues.py deleted file mode 100644 index 10e6f964..00000000 --- a/micropython/uasyncio.queues/uasyncio/queues.py +++ /dev/null @@ -1,95 +0,0 @@ -from collections.deque import deque -from uasyncio.core import sleep - - -class QueueEmpty(Exception): - """Exception raised by get_nowait().""" - - -class QueueFull(Exception): - """Exception raised by put_nowait().""" - - -class Queue: - """A queue, useful for coordinating producer and consumer coroutines. - - If maxsize is less than or equal to zero, the queue size is infinite. If it - is an integer greater than 0, then "yield from put()" will block when the - queue reaches maxsize, until an item is removed by get(). - - Unlike the standard library Queue, you can reliably know this Queue's size - with qsize(), since your single-threaded uasyncio application won't be - interrupted between calling qsize() and doing an operation on the Queue. - """ - - _attempt_delay = 0.1 - - def __init__(self, maxsize=0): - self.maxsize = maxsize - self._queue = deque() - - def _get(self): - return self._queue.popleft() - - def get(self): - """Returns generator, which can be used for getting (and removing) - an item from a queue. - - Usage:: - - item = yield from queue.get() - """ - while not self._queue: - yield from sleep(self._attempt_delay) - return self._get() - - def get_nowait(self): - """Remove and return an item from the queue. - - Return an item if one is immediately available, else raise QueueEmpty. - """ - if not self._queue: - raise QueueEmpty() - return self._get() - - def _put(self, val): - self._queue.append(val) - - def put(self, val): - """Returns generator which can be used for putting item in a queue. - - Usage:: - - yield from queue.put(item) - """ - while self.qsize() >= self.maxsize and self.maxsize: - yield from sleep(self._attempt_delay) - self._put(val) - - def put_nowait(self, val): - """Put an item into the queue without blocking. - - If no free slot is immediately available, raise QueueFull. - """ - if self.qsize() >= self.maxsize and self.maxsize: - raise QueueFull() - self._put(val) - - def qsize(self): - """Number of items in the queue.""" - return len(self._queue) - - def empty(self): - """Return True if the queue is empty, False otherwise.""" - return not self._queue - - def full(self): - """Return True if there are maxsize items in the queue. - - Note: if the Queue was initialized with maxsize=0 (the default), - then full() is never True. - """ - if self.maxsize <= 0: - return False - else: - return self.qsize() >= self.maxsize diff --git a/micropython/uasyncio.synchro/example_lock.py b/micropython/uasyncio.synchro/example_lock.py deleted file mode 100644 index 1a3e4f14..00000000 --- a/micropython/uasyncio.synchro/example_lock.py +++ /dev/null @@ -1,27 +0,0 @@ -try: - import uasyncio.core as asyncio - from uasyncio.synchro import Lock -except ImportError: - import asyncio - from asyncio import Lock - - -def task(i, lock): - print(lock) - while 1: - yield from lock.acquire() - print("Acquired lock in task", i) - yield from asyncio.sleep(0.5) - # yield lock.release() - lock.release() - - -loop = asyncio.get_event_loop() - -lock = Lock() - -loop.create_task(task(1, lock)) -loop.create_task(task(2, lock)) -loop.create_task(task(3, lock)) - -loop.run_forever() diff --git a/micropython/uasyncio.synchro/metadata.txt b/micropython/uasyncio.synchro/metadata.txt deleted file mode 100644 index 6874b076..00000000 --- a/micropython/uasyncio.synchro/metadata.txt +++ /dev/null @@ -1,5 +0,0 @@ -srctype = micropython-lib -type = package -version = 0.1.1 -desc = Synchronization primitives for uasyncio. -depends = uasyncio.core diff --git a/micropython/uasyncio.synchro/setup.py b/micropython/uasyncio.synchro/setup.py deleted file mode 100644 index 73ea669f..00000000 --- a/micropython/uasyncio.synchro/setup.py +++ /dev/null @@ -1,25 +0,0 @@ -import sys - -# Remove current dir from sys.path, otherwise setuptools will peek up our -# module instead of system's. -sys.path.pop(0) -from setuptools import setup - -sys.path.append("..") -import sdist_upip - -setup( - name="micropython-uasyncio.synchro", - version="0.1.1", - description="Synchronization primitives for uasyncio.", - long_description="This is a module reimplemented specifically for MicroPython standard library,\nwith efficient and lean design in mind. Note that this module is likely work\nin progress and likely supports just a subset of CPython's corresponding\nmodule. Please help with the development if you are interested in this\nmodule.", - url="https://github.com/micropython/micropython-lib", - author="micropython-lib Developers", - author_email="micro-python@googlegroups.com", - maintainer="micropython-lib Developers", - maintainer_email="micro-python@googlegroups.com", - license="MIT", - cmdclass={"sdist": sdist_upip.sdist}, - packages=["uasyncio"], - install_requires=["micropython-uasyncio.core"], -) diff --git a/micropython/uasyncio.synchro/uasyncio/synchro.py b/micropython/uasyncio.synchro/uasyncio/synchro.py deleted file mode 100644 index d5b49bd8..00000000 --- a/micropython/uasyncio.synchro/uasyncio/synchro.py +++ /dev/null @@ -1,28 +0,0 @@ -from uasyncio import core - - -class Lock: - def __init__(self): - self.locked = False - self.wlist = [] - - def release(self): - assert self.locked - self.locked = False - if self.wlist: - # print(self.wlist) - coro = self.wlist.pop(0) - core.get_event_loop().call_soon(coro) - - def acquire(self): - # As release() is not coro, assume we just released and going to acquire again - # so, yield first to let someone else to acquire it first - yield - # print("acquire:", self.locked) - while 1: - if not self.locked: - self.locked = True - return True - # print("putting", core.get_event_loop().cur_task, "on waiting list") - self.wlist.append(core.get_event_loop().cur_task) - yield False diff --git a/micropython/uasyncio.udp/example_dns_junk.py b/micropython/uasyncio.udp/example_dns_junk.py deleted file mode 100644 index bcb7728c..00000000 --- a/micropython/uasyncio.udp/example_dns_junk.py +++ /dev/null @@ -1,28 +0,0 @@ -# This example is intended to run with dnsmasq running on localhost -# (Ubuntu comes configured like that by default). Dnsmasq, receiving -# some junk, is still kind to reply something back, which we employ -# here. -import uasyncio -import uasyncio.udp -import usocket - - -def udp_req(addr): - s = uasyncio.udp.socket() - print(s) - yield from uasyncio.udp.sendto(s, b"!eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", addr) - try: - resp = yield from uasyncio.wait_for(uasyncio.udp.recv(s, 1024), 1) - print(resp) - except uasyncio.TimeoutError: - print("timed out") - - -import logging - -logging.basicConfig(level=logging.INFO) - -addr = usocket.getaddrinfo("127.0.0.1", 53)[0][-1] -loop = uasyncio.get_event_loop() -loop.run_until_complete(udp_req(addr)) -loop.close() diff --git a/micropython/uasyncio.udp/metadata.txt b/micropython/uasyncio.udp/metadata.txt deleted file mode 100644 index c791cef1..00000000 --- a/micropython/uasyncio.udp/metadata.txt +++ /dev/null @@ -1,6 +0,0 @@ -srctype = micropython-lib -type = package -version = 0.1.1 -author = Paul Sokolovsky -desc = UDP support for MicroPython's uasyncio -depends = uasyncio diff --git a/micropython/uasyncio.udp/setup.py b/micropython/uasyncio.udp/setup.py deleted file mode 100644 index 172f4eb3..00000000 --- a/micropython/uasyncio.udp/setup.py +++ /dev/null @@ -1,25 +0,0 @@ -import sys - -# Remove current dir from sys.path, otherwise setuptools will peek up our -# module instead of system's. -sys.path.pop(0) -from setuptools import setup - -sys.path.append("..") -import sdist_upip - -setup( - name="micropython-uasyncio.udp", - version="0.1.1", - description="UDP support for MicroPython's uasyncio", - long_description="This is a module reimplemented specifically for MicroPython standard library,\nwith efficient and lean design in mind. Note that this module is likely work\nin progress and likely supports just a subset of CPython's corresponding\nmodule. Please help with the development if you are interested in this\nmodule.", - url="https://github.com/micropython/micropython-lib", - author="Paul Sokolovsky", - author_email="micro-python@googlegroups.com", - maintainer="micropython-lib Developers", - maintainer_email="micro-python@googlegroups.com", - license="MIT", - cmdclass={"sdist": sdist_upip.sdist}, - packages=["uasyncio"], - install_requires=["micropython-uasyncio"], -) diff --git a/micropython/uasyncio.udp/uasyncio/udp.py b/micropython/uasyncio.udp/uasyncio/udp.py deleted file mode 100644 index 8642a3e0..00000000 --- a/micropython/uasyncio.udp/uasyncio/udp.py +++ /dev/null @@ -1,64 +0,0 @@ -import usocket -from uasyncio import core - - -DEBUG = 0 -log = None - - -def set_debug(val): - global DEBUG, log - DEBUG = val - if val: - import logging - - log = logging.getLogger("uasyncio.udp") - - -def socket(af=usocket.AF_INET): - s = usocket.socket(af, usocket.SOCK_DGRAM) - s.setblocking(False) - return s - - -def recv(s, n): - try: - yield core.IORead(s) - return s.recv(n) - except: - # print("recv: exc, cleaning up") - # print(uasyncio.core._event_loop.objmap, uasyncio.core._event_loop.poller) - # uasyncio.core._event_loop.poller.dump() - yield core.IOReadDone(s) - # print(uasyncio.core._event_loop.objmap) - # uasyncio.core._event_loop.poller.dump() - raise - - -def recvfrom(s, n): - try: - yield core.IORead(s) - return s.recvfrom(n) - except: - # print("recv: exc, cleaning up") - # print(uasyncio.core._event_loop.objmap, uasyncio.core._event_loop.poller) - # uasyncio.core._event_loop.poller.dump() - yield core.IOReadDone(s) - # print(uasyncio.core._event_loop.objmap) - # uasyncio.core._event_loop.poller.dump() - raise - - -def sendto(s, buf, addr=None): - while 1: - res = s.sendto(buf, addr) - # print("send res:", res) - if res == len(buf): - return - print("sendto: IOWrite") - yield core.IOWrite(s) - - -def close(s): - yield core.IOReadDone(s) - s.close() diff --git a/micropython/uasyncio.websocket.server/example_websock.py b/micropython/uasyncio.websocket.server/example_websock.py deleted file mode 100644 index 97b6fcd4..00000000 --- a/micropython/uasyncio.websocket.server/example_websock.py +++ /dev/null @@ -1,28 +0,0 @@ -import uasyncio -from uasyncio.websocket.server import WSReader, WSWriter - - -def echo(reader, writer): - # Consume GET line - yield from reader.readline() - - reader = yield from WSReader(reader, writer) - writer = WSWriter(reader, writer) - - while 1: - l = yield from reader.read(256) - print(l) - if l == b"\r": - await writer.awrite(b"\r\n") - else: - await writer.awrite(l) - - -import logging - -# logging.basicConfig(level=logging.INFO) -logging.basicConfig(level=logging.DEBUG) -loop = uasyncio.get_event_loop() -loop.create_task(uasyncio.start_server(echo, "127.0.0.1", 8081)) -loop.run_forever() -loop.close() diff --git a/micropython/uasyncio.websocket.server/metadata.txt b/micropython/uasyncio.websocket.server/metadata.txt deleted file mode 100644 index ac93a2e3..00000000 --- a/micropython/uasyncio.websocket.server/metadata.txt +++ /dev/null @@ -1,5 +0,0 @@ -srctype = micropython-lib -type = package -version = 0.1 -author = Paul Sokolovsky -depends = uasyncio diff --git a/micropython/uasyncio.websocket.server/setup.py b/micropython/uasyncio.websocket.server/setup.py deleted file mode 100644 index 5a92ed4a..00000000 --- a/micropython/uasyncio.websocket.server/setup.py +++ /dev/null @@ -1,25 +0,0 @@ -import sys - -# Remove current dir from sys.path, otherwise setuptools will peek up our -# module instead of system's. -sys.path.pop(0) -from setuptools import setup - -sys.path.append("..") -import sdist_upip - -setup( - name="micropython-uasyncio.websocket.server", - version="0.1", - description="uasyncio.websocket.server module for MicroPython", - long_description="This is a module reimplemented specifically for MicroPython standard library,\nwith efficient and lean design in mind. Note that this module is likely work\nin progress and likely supports just a subset of CPython's corresponding\nmodule. Please help with the development if you are interested in this\nmodule.", - url="https://github.com/micropython/micropython-lib", - author="Paul Sokolovsky", - author_email="micro-python@googlegroups.com", - maintainer="micropython-lib Developers", - maintainer_email="micro-python@googlegroups.com", - license="MIT", - cmdclass={"sdist": sdist_upip.sdist}, - packages=["uasyncio.websocket"], - install_requires=["micropython-uasyncio"], -) diff --git a/micropython/uasyncio.websocket.server/uasyncio/websocket/server.py b/micropython/uasyncio.websocket.server/uasyncio/websocket/server.py deleted file mode 100644 index 8d1492d9..00000000 --- a/micropython/uasyncio.websocket.server/uasyncio/websocket/server.py +++ /dev/null @@ -1,64 +0,0 @@ -import uasyncio -import uhashlib, ubinascii -import websocket - - -def make_respkey(webkey): - d = uhashlib.sha1(webkey) - d.update(b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11") - respkey = d.digest() - respkey = ubinascii.b2a_base64(respkey) # [:-1] - # Return with trailing "\n". - return respkey - - -class WSWriter: - def __init__(self, reader, writer): - # Reader is passed for symmetry with WSReader() and ignored. - self.s = writer - - async def awrite(self, data): - assert len(data) < 126 - await self.s.awrite(b"\x81") - await self.s.awrite(bytes([len(data)])) - await self.s.awrite(data) - - -def WSReader(reader, writer): - - webkey = None - while 1: - l = yield from reader.readline() - print(l) - if not l: - raise ValueError() - if l == b"\r\n": - break - if l.startswith(b"Sec-WebSocket-Key"): - webkey = l.split(b":", 1)[1] - webkey = webkey.strip() - - if not webkey: - raise ValueError("Not a websocker request") - - respkey = make_respkey(webkey) - - await writer.awrite( - b"""\ -HTTP/1.1 101 Switching Protocols\r -Upgrade: websocket\r -Connection: Upgrade\r -Sec-WebSocket-Accept: """ - ) - await writer.awrite(respkey) - # This will lead to "\n\r\n" being written. Not exactly - # "\r\n\r\n", but browsers seem to eat it. - await writer.awrite("\r\n") - # await writer.awrite("\r\n\r\n") - - print("Finished webrepl handshake") - - ws = websocket.websocket(reader.ios) - rws = uasyncio.StreamReader(reader.ios, ws) - - return rws diff --git a/micropython/uasyncio/README.rst b/micropython/uasyncio/README.rst deleted file mode 100644 index fb625b0f..00000000 --- a/micropython/uasyncio/README.rst +++ /dev/null @@ -1,43 +0,0 @@ -uasyncio -======== - -uasyncio is MicroPython's asynchronous sheduling library, roughly -modeled after CPython's asyncio. - -uasyncio doesn't use naive always-iterating scheduling algorithm, -but performs a real time-based scheduling, which allows it (and -thus the whole system) to sleep when there is nothing to do (actual -implementation of that depends on I/O scheduling algorithm which -actually performs the wait operation). - -Major conceptual differences to asyncio: - -* Avoids defining a notion of Future, and especially wrapping coroutines - in Futures, like CPython asyncio does. uasyncio works directly with - coroutines (and callbacks). -* Methods provided are more consistently coroutines. -* uasyncio uses wrap-around millisecond timebase (as native to all - MicroPython ports.) -* Instead of single large package, number of subpackages are provided - (each installable separately). - -Specific differences: - -* For millisecond scheduling, ``loop.call_later_ms()`` and - ``uasyncio.sleep_ms()`` are provided. -* As there's no monotonic time, ``loop.call_at()`` is not provided. - Instead, there's ``loop.call_at_()`` which is considered an internal - function and has slightly different signature. -* ``call_*`` funcions don't return Handle and callbacks scheduled by - them aren't cancellable. If they need to be cancellable, they should - accept an object as an argument, and a "cancel" flag should be set - in the object, for a callback to test. -* ``Future`` object is not available. -* ``ensure_future()`` and ``Task()`` perform just scheduling operations - and return a native coroutine, not Future/Task objects. -* Some other functions are not (yet) implemented. -* StreamWriter method(s) are coroutines. While in CPython asyncio, - StreamWriter.write() is a normal function (which potentially buffers - unlimited amount of data), uasyncio offers coroutine StreamWriter.awrite() - instead. Also, both StreamReader and StreamWriter have .aclose() - coroutine method. diff --git a/micropython/uasyncio/README.test b/micropython/uasyncio/README.test deleted file mode 100644 index 89cd7ecd..00000000 --- a/micropython/uasyncio/README.test +++ /dev/null @@ -1,45 +0,0 @@ -Testing and Validating ----------------------- - -To test uasyncio correctness and performance, HTTP server samples can be -used. The simplest test is with test_http_server.py and Apache Benchmark -(ab). In one window, run: - -micropython -O test_http_server.py - -(-O is needed to short-circuit debug logging calls.) - -In another: - -ab -n10000 -c10 http://localhost:8081/ - -ab tests that all responses have the same length, but doesn't check -content. test_http_server.py also serves very short, static reply. - - -For more heavy testing, test_http_server_heavy.py is provided. It serves -large response split among several async writes. It is also dynamic - -includes incrementing counter, so each response will be different. The -response size generates is more 4Mb, because under Linux, socket writes -can buffer up to 4Mb of content (this appear to be controlled by -/proc/sys/net/ipv4/tcp_wmem and not /proc/sys/net/core/wmem_default). -test_http_server_heavy.py also includes (trivial) handling of -client-induced errors like EPIPE and ECONNRESET. To validate content -served, a post-hook script for "boom" tool -(https://github.com/tarekziade/boom) is provided. - -Before start, you may want to bump .listen() value in uasyncio/__init__.py -from default 10 to at least 30. - -Start: - -micropython -X heapsize=300000000 -O test_http_server_heavy.py - -(Yes, that's 300Mb of heap - we'll be serving 4+Mb of content with 30 -concurrent connections). - -And: - -PYTHONPATH=. boom -n1000 -c30 http://localhost:8081 --post-hook=boom_uasyncio.validate - -There should be no Python exceptions in the output. diff --git a/micropython/uasyncio/benchmark/boom_uasyncio.py b/micropython/uasyncio/benchmark/boom_uasyncio.py deleted file mode 100644 index 0e8fb90b..00000000 --- a/micropython/uasyncio/benchmark/boom_uasyncio.py +++ /dev/null @@ -1,39 +0,0 @@ -# -# This is validation script for "boom" tool https://github.com/tarekziade/boom -# To use it: -# -# boom -n1000 --post-hook=boom_uasyncio.validate -# -# Note that if you'll use other -n value, you should update NUM_REQS below -# to match. -# - -NUM_REQS = 1000 -seen = [] -cnt = 0 - - -def validate(resp): - global cnt - t = resp.text - l = t.split("\r\n", 1)[0] - no = int(l.split()[1]) - seen.append(no) - c = t.count(l + "\r\n") - assert c == 400101, str(c) - assert t.endswith("=== END ===") - - cnt += 1 - if cnt == NUM_REQS: - seen.sort() - print - print seen - print - el = None - for i in seen: - if el is None: - el = i - else: - el += 1 - assert i == el - return resp diff --git a/micropython/uasyncio/benchmark/test-ab-medium.sh b/micropython/uasyncio/benchmark/test-ab-medium.sh deleted file mode 100755 index 7d5edcca..00000000 --- a/micropython/uasyncio/benchmark/test-ab-medium.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -# -# This in one-shot scripts to test "light load" uasyncio HTTP server using -# Apache Bench (ab). -# - -#python3.4.2 test_http_server_light.py & -#micropython -O test_http_server_light.py & - -#python3.4.2 test_http_server_medium.py & -micropython -O -X heapsize=200wK test_http_server_medium.py & - -sleep 1 - -ab -n10000 -c100 http://127.0.0.1:8081/ - -kill %1 diff --git a/micropython/uasyncio/benchmark/test-boom-heavy.sh b/micropython/uasyncio/benchmark/test-boom-heavy.sh deleted file mode 100755 index a977806a..00000000 --- a/micropython/uasyncio/benchmark/test-boom-heavy.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -# -# This in one-shot scripts to test "heavy load" uasyncio HTTP server using -# Boom tool https://github.com/tarekziade/boom . -# -# Note that this script doesn't test performance, but rather test functional -# correctness of uasyncio server implementation, while serving large amounts -# of data (guaranteedly more than a socket buffer). Thus, this script should -# not be used for benchmarking. -# - -if [ ! -d .venv-boom ]; then - virtualenv .venv-boom - . .venv-boom/bin/activate - # PyPI currently has 0.8 which is too old - #pip install boom - pip install git+https://github.com/tarekziade/boom -else - . .venv-boom/bin/activate -fi - - -micropython -X heapsize=300000000 -O test_http_server_heavy.py & -sleep 1 - -PYTHONPATH=. boom -n1000 -c30 http://localhost:8081 --post-hook=boom_uasyncio.validate - -kill %1 diff --git a/micropython/uasyncio/benchmark/test_http_server_heavy.py b/micropython/uasyncio/benchmark/test_http_server_heavy.py deleted file mode 100644 index 25804f18..00000000 --- a/micropython/uasyncio/benchmark/test_http_server_heavy.py +++ /dev/null @@ -1,42 +0,0 @@ -import uasyncio as asyncio -import signal -import errno - - -cnt = 0 - - -@asyncio.coroutine -def serve(reader, writer): - global cnt - # s = "Hello.\r\n" - s = "Hello. %07d\r\n" % cnt - cnt += 1 - yield from reader.read() - yield from writer.awrite("HTTP/1.0 200 OK\r\n\r\n") - try: - yield from writer.awrite(s) - yield from writer.awrite(s * 100) - yield from writer.awrite(s * 400000) - yield from writer.awrite("=== END ===") - except OSError as e: - if e.args[0] == errno.EPIPE: - print("EPIPE") - elif e.args[0] == errno.ECONNRESET: - print("ECONNRESET") - else: - raise - finally: - yield from writer.aclose() - - -import logging - -logging.basicConfig(level=logging.INFO) -# logging.basicConfig(level=logging.DEBUG) -signal.signal(signal.SIGPIPE, signal.SIG_IGN) -loop = asyncio.get_event_loop() -# mem_info() -loop.call_soon(asyncio.start_server(serve, "0.0.0.0", 8081, backlog=100)) -loop.run_forever() -loop.close() diff --git a/micropython/uasyncio/benchmark/test_http_server_light.py b/micropython/uasyncio/benchmark/test_http_server_light.py deleted file mode 100644 index 6130491e..00000000 --- a/micropython/uasyncio/benchmark/test_http_server_light.py +++ /dev/null @@ -1,22 +0,0 @@ -import uasyncio as asyncio - - -@asyncio.coroutine -def serve(reader, writer): - # print(reader, writer) - # print("================") - yield from reader.read(512) - yield from writer.awrite("HTTP/1.0 200 OK\r\n\r\nHello.\r\n") - yield from writer.aclose() - # print("Finished processing request") - - -import logging - -# logging.basicConfig(level=logging.INFO) -logging.basicConfig(level=logging.DEBUG) -loop = asyncio.get_event_loop() -# mem_info() -loop.create_task(asyncio.start_server(serve, "127.0.0.1", 8081, backlog=100)) -loop.run_forever() -loop.close() diff --git a/micropython/uasyncio/benchmark/test_http_server_medium.py b/micropython/uasyncio/benchmark/test_http_server_medium.py deleted file mode 100644 index 61be5fd2..00000000 --- a/micropython/uasyncio/benchmark/test_http_server_medium.py +++ /dev/null @@ -1,24 +0,0 @@ -import uasyncio as asyncio - -resp = "HTTP/1.0 200 OK\r\n\r\n" + "Hello.\r\n" * 1500 - - -@asyncio.coroutine -def serve(reader, writer): - # print(reader, writer) - # print("================") - yield from reader.read(512) - yield from writer.awrite(resp) - yield from writer.aclose() - # print("Finished processing request") - - -import logging - -# logging.basicConfig(level=logging.INFO) -logging.basicConfig(level=logging.DEBUG) -loop = asyncio.get_event_loop(80) -# mem_info() -loop.create_task(asyncio.start_server(serve, "127.0.0.1", 8081, backlog=100)) -loop.run_forever() -loop.close() diff --git a/micropython/uasyncio/example_http_client.py b/micropython/uasyncio/example_http_client.py deleted file mode 100644 index 961c3b15..00000000 --- a/micropython/uasyncio/example_http_client.py +++ /dev/null @@ -1,27 +0,0 @@ -import uasyncio as asyncio - - -@asyncio.coroutine -def print_http_headers(url): - reader, writer = yield from asyncio.open_connection(url, 80) - print(reader, writer) - print("================") - query = "GET / HTTP/1.0\r\n\r\n" - yield from writer.awrite(query.encode("latin-1")) - while True: - line = yield from reader.readline() - if not line: - break - if line: - print(line.rstrip()) - - -import logging - -logging.basicConfig(level=logging.INFO) -url = "google.com" -loop = asyncio.get_event_loop() -# task = asyncio.async(print_http_headers(url)) -# loop.run_until_complete(task) -loop.run_until_complete(print_http_headers(url)) -loop.close() diff --git a/micropython/uasyncio/example_http_server.py b/micropython/uasyncio/example_http_server.py deleted file mode 100644 index 232a421f..00000000 --- a/micropython/uasyncio/example_http_server.py +++ /dev/null @@ -1,22 +0,0 @@ -import uasyncio as asyncio - - -@asyncio.coroutine -def serve(reader, writer): - print(reader, writer) - print("================") - print((yield from reader.read())) - yield from writer.awrite("HTTP/1.0 200 OK\r\n\r\nHello.\r\n") - print("After response write") - yield from writer.aclose() - print("Finished processing request") - - -import logging - -# logging.basicConfig(level=logging.INFO) -logging.basicConfig(level=logging.DEBUG) -loop = asyncio.get_event_loop() -loop.call_soon(asyncio.start_server(serve, "127.0.0.1", 8081)) -loop.run_forever() -loop.close() diff --git a/micropython/uasyncio/metadata.txt b/micropython/uasyncio/metadata.txt deleted file mode 100644 index c0cbd68b..00000000 --- a/micropython/uasyncio/metadata.txt +++ /dev/null @@ -1,7 +0,0 @@ -srctype = micropython-lib -type = package -version = 2.0 -author = Paul Sokolovsky -desc = Lightweight asyncio-like library for MicroPython, built around native Python coroutines. -long_desc = README.rst -depends = uasyncio.core diff --git a/micropython/uasyncio/setup.py b/micropython/uasyncio/setup.py deleted file mode 100644 index 4e2b50a3..00000000 --- a/micropython/uasyncio/setup.py +++ /dev/null @@ -1,25 +0,0 @@ -import sys - -# Remove current dir from sys.path, otherwise setuptools will peek up our -# module instead of system's. -sys.path.pop(0) -from setuptools import setup - -sys.path.append("..") -import sdist_upip - -setup( - name="micropython-uasyncio", - version="2.0", - description="Lightweight asyncio-like library for MicroPython, built around native Python coroutines.", - long_description=open("README.rst").read(), - url="https://github.com/micropython/micropython-lib", - author="Paul Sokolovsky", - author_email="micro-python@googlegroups.com", - maintainer="micropython-lib Developers", - maintainer_email="micro-python@googlegroups.com", - license="MIT", - cmdclass={"sdist": sdist_upip.sdist}, - packages=["uasyncio"], - install_requires=["micropython-uasyncio.core"], -) diff --git a/micropython/uasyncio/test_echo.py b/micropython/uasyncio/test_echo.py deleted file mode 100644 index 3c4a96e9..00000000 --- a/micropython/uasyncio/test_echo.py +++ /dev/null @@ -1,32 +0,0 @@ -from uasyncio import get_event_loop, open_connection, start_server, sleep_ms -from unittest import main, TestCase - - -class EchoTestCase(TestCase): - def test_client_server(self): - """Simple client-server echo test""" - sockaddr = ("127.0.0.1", 8080) - l = get_event_loop() - - async def echo_server(reader, writer): - data = await reader.readline() - await writer.awrite(data) - await writer.aclose() - - async def echo_client(line, result): - await sleep_ms(10) # Allow server to get up - reader, writer = await open_connection(*sockaddr) - await writer.awrite(line) - data = await reader.readline() - await writer.aclose() - result.append(data) # capture response - - result = [] - l.create_task(start_server(echo_server, *sockaddr)) - l.run_until_complete(echo_client(b"Hello\r\n", result)) - - self.assertEqual(result[0], b"Hello\r\n") - - -if __name__ == "__main__": - main() diff --git a/micropython/uasyncio/test_io_starve.py b/micropython/uasyncio/test_io_starve.py deleted file mode 100644 index f1f410a3..00000000 --- a/micropython/uasyncio/test_io_starve.py +++ /dev/null @@ -1,37 +0,0 @@ -try: - import uasyncio as asyncio -except: - import asyncio - -try: - import utime as time -except: - import time - -done = False - - -async def receiver(): - global done - with open("test_io_starve.py", "rb") as f: - sreader = asyncio.StreamReader(f) - while True: - await asyncio.sleep(0.1) - res = await sreader.readline() - # Didn't get there with the original problem this test shows - done = True - - -async def foo(): - start = time.time() - while time.time() - start < 1: - await asyncio.sleep(0) - loop.stop() - - -loop = asyncio.get_event_loop() -loop.create_task(foo()) -loop.create_task(receiver()) -loop.run_forever() -assert done -print("OK") diff --git a/micropython/uasyncio/test_readexactly.py b/micropython/uasyncio/test_readexactly.py deleted file mode 100644 index abefcbf0..00000000 --- a/micropython/uasyncio/test_readexactly.py +++ /dev/null @@ -1,39 +0,0 @@ -from uasyncio import StreamReader - - -class MockSock: - def __init__(self, data_list): - self.data = data_list - - def read(self, sz): - try: - return self.data.pop(0) - except IndexError: - return b"" - - -mock = MockSock( - [ - b"123", - b"234", - b"5", - b"a", - b"b", - b"c", - b"d", - b"e", - ] -) - - -def func(): - sr = StreamReader(mock) - assert await sr.readexactly(3) == b"123" - assert await sr.readexactly(4) == b"2345" - assert await sr.readexactly(5) == b"abcde" - # This isn't how it should be, but the current behavior - assert await sr.readexactly(10) == b"" - - -for i in func(): - pass diff --git a/micropython/uasyncio/test_readline.py b/micropython/uasyncio/test_readline.py deleted file mode 100644 index 73bfb7d1..00000000 --- a/micropython/uasyncio/test_readline.py +++ /dev/null @@ -1,35 +0,0 @@ -from uasyncio import StreamReader - - -class MockSock: - def __init__(self, data_list): - self.data = data_list - - def readline(self): - try: - return self.data.pop(0) - except IndexError: - return b"" - - -mock = MockSock( - [ - b"line1\n", - b"parts ", - b"of ", - b"line2\n", - b"unterminated", - ] -) - - -def func(): - sr = StreamReader(mock) - assert await sr.readline() == b"line1\n" - assert await sr.readline() == b"parts of line2\n" - assert await sr.readline() == b"unterminated" - assert await sr.readline() == b"" - - -for i in func(): - pass diff --git a/micropython/uasyncio/uasyncio/__init__.py b/micropython/uasyncio/uasyncio/__init__.py deleted file mode 100644 index c6318b1f..00000000 --- a/micropython/uasyncio/uasyncio/__init__.py +++ /dev/null @@ -1,259 +0,0 @@ -import uerrno -import uselect as select -import usocket as _socket -from uasyncio.core import * - - -DEBUG = 0 -log = None - - -def set_debug(val): - global DEBUG, log - DEBUG = val - if val: - import logging - - log = logging.getLogger("uasyncio") - - -class PollEventLoop(EventLoop): - def __init__(self, runq_len=16, waitq_len=16): - EventLoop.__init__(self, runq_len, waitq_len) - self.poller = select.poll() - self.objmap = {} - - def add_reader(self, sock, cb, *args): - if DEBUG and __debug__: - log.debug("add_reader%s", (sock, cb, args)) - if args: - self.poller.register(sock, select.POLLIN) - self.objmap[id(sock)] = (cb, args) - else: - self.poller.register(sock, select.POLLIN) - self.objmap[id(sock)] = cb - - def remove_reader(self, sock): - if DEBUG and __debug__: - log.debug("remove_reader(%s)", sock) - self.poller.unregister(sock) - del self.objmap[id(sock)] - - def add_writer(self, sock, cb, *args): - if DEBUG and __debug__: - log.debug("add_writer%s", (sock, cb, args)) - if args: - self.poller.register(sock, select.POLLOUT) - self.objmap[id(sock)] = (cb, args) - else: - self.poller.register(sock, select.POLLOUT) - self.objmap[id(sock)] = cb - - def remove_writer(self, sock): - if DEBUG and __debug__: - log.debug("remove_writer(%s)", sock) - try: - self.poller.unregister(sock) - self.objmap.pop(id(sock), None) - except OSError as e: - # StreamWriter.awrite() first tries to write to a socket, - # and if that succeeds, yield IOWrite may never be called - # for that socket, and it will never be added to poller. So, - # ignore such error. - if e.args[0] != uerrno.ENOENT: - raise - - def wait(self, delay): - if DEBUG and __debug__: - log.debug("poll.wait(%d)", delay) - # We need one-shot behavior (second arg of 1 to .poll()) - res = self.poller.ipoll(delay, 1) - # log.debug("poll result: %s", res) - # Remove "if res" workaround after - # https://github.com/micropython/micropython/issues/2716 fixed. - if res: - for sock, ev in res: - cb = self.objmap[id(sock)] - if ev & (select.POLLHUP | select.POLLERR): - # These events are returned even if not requested, and - # are sticky, i.e. will be returned again and again. - # If the caller doesn't do proper error handling and - # unregister this sock, we'll busy-loop on it, so we - # as well can unregister it now "just in case". - self.remove_reader(sock) - if DEBUG and __debug__: - log.debug("Calling IO callback: %r", cb) - if isinstance(cb, tuple): - cb[0](*cb[1]) - else: - cb.pend_throw(None) - self.call_soon(cb) - - -class StreamReader: - def __init__(self, polls, ios=None): - if ios is None: - ios = polls - self.polls = polls - self.ios = ios - - def read(self, n=-1): - while True: - yield IORead(self.polls) - res = self.ios.read(n) - if res is not None: - break - # This should not happen for real sockets, but can easily - # happen for stream wrappers (ssl, websockets, etc.) - # log.warn("Empty read") - if not res: - yield IOReadDone(self.polls) - return res - - def readexactly(self, n): - buf = b"" - while n: - yield IORead(self.polls) - res = self.ios.read(n) - assert res is not None - if not res: - yield IOReadDone(self.polls) - break - buf += res - n -= len(res) - return buf - - def readline(self): - if DEBUG and __debug__: - log.debug("StreamReader.readline()") - buf = b"" - while True: - yield IORead(self.polls) - res = self.ios.readline() - assert res is not None - if not res: - yield IOReadDone(self.polls) - break - buf += res - if buf[-1] == 0x0A: - break - if DEBUG and __debug__: - log.debug("StreamReader.readline(): %s", buf) - return buf - - def aclose(self): - yield IOReadDone(self.polls) - self.ios.close() - - def __repr__(self): - return "" % (self.polls, self.ios) - - -class StreamWriter: - def __init__(self, s, extra): - self.s = s - self.extra = extra - - def awrite(self, buf, off=0, sz=-1): - # This method is called awrite (async write) to not proliferate - # incompatibility with original asyncio. Unlike original asyncio - # whose .write() method is both not a coroutine and guaranteed - # to return immediately (which means it has to buffer all the - # data), this method is a coroutine. - if sz == -1: - sz = len(buf) - off - if DEBUG and __debug__: - log.debug("StreamWriter.awrite(): spooling %d bytes", sz) - while True: - res = self.s.write(buf, off, sz) - # If we spooled everything, return immediately - if res == sz: - if DEBUG and __debug__: - log.debug("StreamWriter.awrite(): completed spooling %d bytes", res) - return - if res is None: - res = 0 - if DEBUG and __debug__: - log.debug("StreamWriter.awrite(): spooled partial %d bytes", res) - assert res < sz - off += res - sz -= res - yield IOWrite(self.s) - # assert s2.fileno() == self.s.fileno() - if DEBUG and __debug__: - log.debug("StreamWriter.awrite(): can write more") - - # Write piecewise content from iterable (usually, a generator) - def awriteiter(self, iterable): - for buf in iterable: - yield from self.awrite(buf) - - def aclose(self): - yield IOWriteDone(self.s) - self.s.close() - - def get_extra_info(self, name, default=None): - return self.extra.get(name, default) - - def __repr__(self): - return "" % self.s - - -def open_connection(host, port, ssl=False): - if DEBUG and __debug__: - log.debug("open_connection(%s, %s)", host, port) - ai = _socket.getaddrinfo(host, port, 0, _socket.SOCK_STREAM) - ai = ai[0] - s = _socket.socket(ai[0], ai[1], ai[2]) - s.setblocking(False) - try: - s.connect(ai[-1]) - except OSError as e: - if e.args[0] != uerrno.EINPROGRESS: - raise - if DEBUG and __debug__: - log.debug("open_connection: After connect") - yield IOWrite(s) - # if __debug__: - # assert s2.fileno() == s.fileno() - if DEBUG and __debug__: - log.debug("open_connection: After iowait: %s", s) - if ssl: - print("Warning: uasyncio SSL support is alpha") - import ussl - - s.setblocking(True) - s2 = ussl.wrap_socket(s) - s.setblocking(False) - return StreamReader(s, s2), StreamWriter(s2, {}) - return StreamReader(s), StreamWriter(s, {}) - - -def start_server(client_coro, host, port, backlog=10): - if DEBUG and __debug__: - log.debug("start_server(%s, %s)", host, port) - ai = _socket.getaddrinfo(host, port, 0, _socket.SOCK_STREAM) - ai = ai[0] - s = _socket.socket(ai[0], ai[1], ai[2]) - s.setblocking(False) - - s.setsockopt(_socket.SOL_SOCKET, _socket.SO_REUSEADDR, 1) - s.bind(ai[-1]) - s.listen(backlog) - while True: - if DEBUG and __debug__: - log.debug("start_server: Before accept") - yield IORead(s) - if DEBUG and __debug__: - log.debug("start_server: After iowait") - s2, client_addr = s.accept() - s2.setblocking(False) - if DEBUG and __debug__: - log.debug("start_server: After accept: %s", s2) - extra = {"peername": client_addr} - yield client_coro(StreamReader(s2), StreamWriter(s2, extra)) - - -import uasyncio.core - -uasyncio.core._event_loop_class = PollEventLoop