Skip to content

Commit 5a0f6e2

Browse files
committed
Add docstrings to library
1 parent 28ef812 commit 5a0f6e2

6 files changed

Lines changed: 217 additions & 0 deletions

File tree

asyncio/core.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,14 @@
2626

2727

2828
class CancelledError(BaseException):
29+
"""Injected into a task when calling `Task.cancel()`"""
30+
2931
pass
3032

3133

3234
class TimeoutError(Exception):
35+
"""Raised when waiting for a task longer than the specified timeout."""
36+
3337
pass
3438

3539

@@ -65,13 +69,23 @@ def __next__(self):
6569
# Pause task execution for the given time (integer in milliseconds, uPy extension)
6670
# Use a SingletonGenerator to do it without allocating on the heap
6771
def sleep_ms(t, sgen=SingletonGenerator()):
72+
"""Sleep for `t` milliseconds.
73+
74+
This is a coroutine, and a MicroPython extension.
75+
"""
76+
6877
assert sgen.state is None, "Check for a missing `await` in your code"
6978
sgen.state = ticks_add(ticks(), max(0, t))
7079
return sgen
7180

7281

7382
# Pause task execution for the given time (in seconds)
7483
def sleep(t):
84+
"""Sleep for `t` seconds
85+
86+
This is a coroutine.
87+
"""
88+
7589
return sleep_ms(int(t * 1000))
7690

7791

@@ -152,6 +166,11 @@ def _promote_to_task(aw):
152166

153167
# Create and schedule a new task from a coroutine
154168
def create_task(coro):
169+
"""Create a new task from the given coroutine and schedule it to run.
170+
171+
Returns the corresponding `Task` object.
172+
"""
173+
155174
if not hasattr(coro, "send"):
156175
raise TypeError("coroutine expected")
157176
t = Task(coro, globals())
@@ -161,6 +180,8 @@ def create_task(coro):
161180

162181
# Keep scheduling tasks until there are none left to schedule
163182
def run_until_complete(main_task=None):
183+
"""Run the given _main_task_ until it completes."""
184+
164185
global cur_task
165186
excs_all = (CancelledError, Exception) # To prevent heap allocation in loop
166187
excs_stop = (CancelledError, StopIteration) # To prevent heap allocation in loop
@@ -232,6 +253,11 @@ def run_until_complete(main_task=None):
232253

233254
# Create a new task from a coroutine and run it until it finishes
234255
def run(coro):
256+
"""Create a new task from the given coroutine and run it until it completes.
257+
258+
Returns the value returned be *coro*.
259+
"""
260+
235261
return run_until_complete(create_task(coro))
236262

237263

@@ -247,54 +273,92 @@ async def _stopper():
247273

248274

249275
class Loop:
276+
"""Class representing the event loop"""
277+
250278
_exc_handler = None
251279

252280
def create_task(coro):
281+
"""Create a task from the given *coro* and return the new `Task` object."""
282+
253283
return create_task(coro)
254284

255285
def run_forever():
286+
"""Run the event loop until `stop()` is called."""
287+
256288
global _stop_task
257289
_stop_task = Task(_stopper(), globals())
258290
run_until_complete(_stop_task)
259291
# TODO should keep running until .stop() is called, even if there're no tasks left
260292

261293
def run_until_complete(aw):
294+
"""Run the given *awaitable* until it completes. If *awaitable* is not a task then
295+
it will be promoted to one.
296+
"""
297+
262298
return run_until_complete(_promote_to_task(aw))
263299

264300
def stop():
301+
"""Stop the event loop"""
302+
265303
global _stop_task
266304
if _stop_task is not None:
267305
_task_queue.push_head(_stop_task)
268306
# If stop() is called again, do nothing
269307
_stop_task = None
270308

271309
def close():
310+
"""Close the event loop."""
311+
272312
pass
273313

274314
def set_exception_handler(handler):
315+
"""Set the exception handler to call when a Task raises an exception that is not
316+
caught. The *handler* should accept two arguments: ``(loop, context)``
317+
"""
318+
275319
Loop._exc_handler = handler
276320

277321
def get_exception_handler():
322+
"""Get the current exception handler. Returns the handler, or ``None`` if no
323+
custom handler is set.
324+
"""
325+
278326
return Loop._exc_handler
279327

280328
def default_exception_handler(loop, context):
329+
"""The default exception handler that is called."""
330+
281331
exc = context["exception"]
282332
traceback.print_exception(None, exc, exc.__traceback__)
283333

284334
def call_exception_handler(context):
335+
"""Call the current exception handler. The argument *context* is passed through
336+
and is a dictionary containing keys:
337+
``'message'``, ``'exception'``, ``'future'``
338+
"""
285339
(Loop._exc_handler or Loop.default_exception_handler)(Loop, context)
286340

287341

288342
# The runq_len and waitq_len arguments are for legacy uasyncio compatibility
289343
def get_event_loop(runq_len=0, waitq_len=0):
344+
"""Return the event loop used to schedule and run tasks. See `Loop`."""
345+
290346
return Loop
291347

292348

293349
def current_task():
350+
"""Return the `Task` object associated with the currently running task."""
351+
294352
return cur_task
295353

296354

297355
def new_event_loop():
356+
"""Reset the event loop and return it.
357+
358+
**NOTE**: Since MicroPython only has a single event loop, this function just resets
359+
the loop's state, it does not create a new one
360+
"""
361+
298362
global _task_queue, _io_queue
299363
# TaskQueue of Task instances
300364
_task_queue = TaskQueue()

asyncio/event.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,25 @@
1515

1616
# Event class for primitive events that can be waited on, set, and cleared
1717
class Event:
18+
"""Create a new event which can be used to synchronize tasks. Events
19+
start in the cleared state.
20+
"""
21+
1822
def __init__(self):
1923
self.state = False # False=unset; True=set
2024
self.waiting = (
2125
core.TaskQueue()
2226
) # Queue of Tasks waiting on completion of this event
2327

2428
def is_set(self):
29+
"""Returns ``True`` if the event is set, ``False`` otherwise."""
30+
2531
return self.state
2632

2733
def set(self):
34+
"""Set the event. Any tasks waiting on the event will be scheduled to run.
35+
"""
36+
2837
# Event becomes set, schedule any tasks waiting on it
2938
# Note: This must not be called from anything except the thread running
3039
# the asyncio loop (i.e. neither hard or soft IRQ, or a different thread).
@@ -33,9 +42,17 @@ def set(self):
3342
self.state = True
3443

3544
def clear(self):
45+
"""Clear the event."""
46+
3647
self.state = False
3748

3849
async def wait(self):
50+
"""Wait for the event to be set. If the event is already set then it returns
51+
immediately.
52+
53+
This is a coroutine.
54+
"""
55+
3956
if not self.state:
4057
# Event not set, put the calling task on the event's waiting queue
4158
self.waiting.push_head(core.cur_task)

asyncio/funcs.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,18 @@
1515

1616

1717
async def wait_for(aw, timeout, sleep=core.sleep):
18+
"""Wait for the *aw* awaitable to complete, but cancel if it takes longer
19+
than *timeout* seconds. If *aw* is not a task then a task will be created
20+
from it.
21+
22+
If a timeout occurs, it cancels the task and raises ``asyncio.TimeoutError``:
23+
this should be trapped by the caller.
24+
25+
Returns the return vaalue of *aw*.
26+
27+
This is a coroutine.
28+
"""
29+
1830
aw = core._promote_to_task(aw)
1931
if timeout is None:
2032
return await aw
@@ -60,10 +72,23 @@ def runner(waiter, aw):
6072

6173

6274
def wait_for_ms(aw, timeout):
75+
"""Similar to `wait_for` but *timeout* is an integer in milliseconds.
76+
77+
This is a coroutine, and a MicroPython extension.
78+
"""
79+
6380
return wait_for(aw, timeout, core.sleep_ms)
6481

6582

6683
async def gather(*aws, return_exceptions=False):
84+
"""Run all *aws* awaitables concurrently. Any *aws* that are not tasks
85+
are promoted to tasks.
86+
87+
Returns a list of return values of all *aws*
88+
89+
This is a coroutine.
90+
"""
91+
6792
ts = [core._promote_to_task(aw) for aw in aws]
6893
for i in range(len(ts)):
6994
try:

asyncio/lock.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@
1515

1616
# Lock class for primitive mutex capability
1717
class Lock:
18+
"""Create a new lock which can be used to coordinate tasks. Locks start in
19+
the unlocked state.
20+
21+
In addition to the methods below, locks can be used in an ``async with``
22+
statement.
23+
"""
24+
1825
def __init__(self):
1926
# The state can take the following values:
2027
# - 0: unlocked
@@ -25,9 +32,16 @@ def __init__(self):
2532
self.waiting = core.TaskQueue()
2633

2734
def locked(self):
35+
"""Returns ``True`` if the lock is locked, otherwise ``False``."""
36+
2837
return self.state == 1
2938

3039
def release(self):
40+
"""Release the lock. If any tasks are waiting on the lock then the next
41+
one in the queue is scheduled to run and the lock remains locked. Otherwise,
42+
no tasks are waiting and the lock becomes unlocked.
43+
"""
44+
3145
if self.state != 1:
3246
raise RuntimeError("Lock not acquired")
3347
if self.waiting.peek():
@@ -39,6 +53,12 @@ def release(self):
3953
self.state = 0
4054

4155
async def acquire(self):
56+
"""Wait for the lock to be in the unlocked state and then lock it in an
57+
atomic way. Only one task can acquire the lock at any one time.
58+
59+
This is a coroutine.
60+
"""
61+
4262
if self.state != 0:
4363
# Lock unavailable, put the calling Task on the waiting queue
4464
self.waiting.push_head(core.cur_task)

0 commit comments

Comments
 (0)