1010# pylint or black.
1111# pylint: skip-file
1212# fmt: off
13+ """
14+ Core
15+ ====
16+ """
1317
1418from adafruit_ticks import ticks_ms as ticks , ticks_diff , ticks_add
1519import sys , select , traceback
2630
2731
2832class CancelledError (BaseException ):
33+ """Injected into a task when calling `Task.cancel()`"""
34+
2935 pass
3036
3137
3238class TimeoutError (Exception ):
39+ """Raised when waiting for a task longer than the specified timeout."""
40+
3341 pass
3442
3543
@@ -65,13 +73,23 @@ def __next__(self):
6573# Pause task execution for the given time (integer in milliseconds, uPy extension)
6674# Use a SingletonGenerator to do it without allocating on the heap
6775def sleep_ms (t , sgen = SingletonGenerator ()):
76+ """Sleep for *t* milliseconds.
77+
78+ This is a coroutine, and a MicroPython extension.
79+ """
80+
6881 assert sgen .state is None , "Check for a missing `await` in your code"
6982 sgen .state = ticks_add (ticks (), max (0 , t ))
7083 return sgen
7184
7285
7386# Pause task execution for the given time (in seconds)
7487def sleep (t ):
88+ """Sleep for *t* seconds
89+
90+ This is a coroutine.
91+ """
92+
7593 return sleep_ms (int (t * 1000 ))
7694
7795
@@ -152,6 +170,11 @@ def _promote_to_task(aw):
152170
153171# Create and schedule a new task from a coroutine
154172def create_task (coro ):
173+ """Create a new task from the given coroutine and schedule it to run.
174+
175+ Returns the corresponding `Task` object.
176+ """
177+
155178 if not hasattr (coro , "send" ):
156179 raise TypeError ("coroutine expected" )
157180 t = Task (coro , globals ())
@@ -161,6 +184,8 @@ def create_task(coro):
161184
162185# Keep scheduling tasks until there are none left to schedule
163186def run_until_complete (main_task = None ):
187+ """Run the given *main_task* until it completes."""
188+
164189 global cur_task
165190 excs_all = (CancelledError , Exception ) # To prevent heap allocation in loop
166191 excs_stop = (CancelledError , StopIteration ) # To prevent heap allocation in loop
@@ -232,6 +257,11 @@ def run_until_complete(main_task=None):
232257
233258# Create a new task from a coroutine and run it until it finishes
234259def run (coro ):
260+ """Create a new task from the given coroutine and run it until it completes.
261+
262+ Returns the value returned by *coro*.
263+ """
264+
235265 return run_until_complete (create_task (coro ))
236266
237267
@@ -247,54 +277,92 @@ async def _stopper():
247277
248278
249279class Loop :
280+ """Class representing the event loop"""
281+
250282 _exc_handler = None
251283
252284 def create_task (coro ):
285+ """Create a task from the given *coro* and return the new `Task` object."""
286+
253287 return create_task (coro )
254288
255289 def run_forever ():
290+ """Run the event loop until `Loop.stop()` is called."""
291+
256292 global _stop_task
257293 _stop_task = Task (_stopper (), globals ())
258294 run_until_complete (_stop_task )
259295 # TODO should keep running until .stop() is called, even if there're no tasks left
260296
261297 def run_until_complete (aw ):
298+ """Run the given *awaitable* until it completes. If *awaitable* is not a task then
299+ it will be promoted to one.
300+ """
301+
262302 return run_until_complete (_promote_to_task (aw ))
263303
264304 def stop ():
305+ """Stop the event loop"""
306+
265307 global _stop_task
266308 if _stop_task is not None :
267309 _task_queue .push_head (_stop_task )
268310 # If stop() is called again, do nothing
269311 _stop_task = None
270312
271313 def close ():
314+ """Close the event loop."""
315+
272316 pass
273317
274318 def set_exception_handler (handler ):
319+ """Set the exception handler to call when a Task raises an exception that is not
320+ caught. The *handler* should accept two arguments: ``(loop, context)``
321+ """
322+
275323 Loop ._exc_handler = handler
276324
277325 def get_exception_handler ():
326+ """Get the current exception handler. Returns the handler, or ``None`` if no
327+ custom handler is set.
328+ """
329+
278330 return Loop ._exc_handler
279331
280332 def default_exception_handler (loop , context ):
333+ """The default exception handler that is called."""
334+
281335 exc = context ["exception" ]
282336 traceback .print_exception (None , exc , exc .__traceback__ )
283337
284338 def call_exception_handler (context ):
339+ """Call the current exception handler. The argument *context* is passed through
340+ and is a dictionary containing keys:
341+ ``'message'``, ``'exception'``, ``'future'``
342+ """
285343 (Loop ._exc_handler or Loop .default_exception_handler )(Loop , context )
286344
287345
288346# The runq_len and waitq_len arguments are for legacy uasyncio compatibility
289347def get_event_loop (runq_len = 0 , waitq_len = 0 ):
348+ """Return the event loop used to schedule and run tasks. See `Loop`."""
349+
290350 return Loop
291351
292352
293353def current_task ():
354+ """Return the `Task` object associated with the currently running task."""
355+
294356 return cur_task
295357
296358
297359def new_event_loop ():
360+ """Reset the event loop and return it.
361+
362+ **NOTE**: Since MicroPython only has a single event loop, this function just resets
363+ the loop's state, it does not create a new one
364+ """
365+
298366 global _task_queue , _io_queue
299367 # TaskQueue of Task instances
300368 _task_queue = TaskQueue ()
0 commit comments