Documentation improvements

This commit is contained in:
Miguel Grinberg
2023-12-28 12:30:35 +00:00
parent 28007ea583
commit b80b6b64d0
9 changed files with 85 additions and 42 deletions

View File

@@ -16,6 +16,7 @@ jobs:
- run: python -m pip install --upgrade pip wheel
- run: pip install tox tox-gh-actions
- run: tox -eflake8
- run: tox -edocs
tests:
name: tests
strategy:

View File

@@ -1,8 +1,8 @@
API Reference
=============
``microdot`` module
-------------------
Core API
--------
.. autoclass:: microdot.Microdot
:members:
@@ -14,51 +14,57 @@ API Reference
:members:
``websocket`` extension
-----------------------
WebSocket
---------
.. automodule:: microdot.websocket
:members:
``utemplate`` templating extension
----------------------------------
Server-Sent Events (SSE)
------------------------
.. automodule:: microdot.sse
:members:
Templates (uTemplate)
---------------------
.. automodule:: microdot.utemplate
:members:
``jinja`` templating extension
------------------------------
Templates (Jinja)
-----------------
.. automodule:: microdot.jinja
:members:
``session`` extension
---------------------
User Sessions
-------------
.. automodule:: microdot.session
:members:
``cors`` extension
------------------
Cross-Origin Resource Sharing (CORS)
------------------------------------
.. automodule:: microdot.cors
:members:
``test_client`` extension
-------------------------
Test Client
-----------
.. automodule:: microdot.test_client
:members:
``asgi`` extension
------------------
ASGI
----
.. autoclass:: microdot.asgi.Microdot
:members:
:exclude-members: shutdown, run
``wsgi`` extension
-------------------
WSGI
----
.. autoclass:: microdot.wsgi.Microdot
:members:

View File

@@ -25,14 +25,15 @@ and incorporated into a custom MicroPython firmware.
Use the following guidelines to know what files to copy:
- For a minimal setup with only the base web server functionality, copy
* For a minimal setup with only the base web server functionality, copy
`microdot.py <https://github.com/miguelgrinberg/microdot/blob/main/src/microdot/microdot.py>`_
into your project.
- For a configuration that includes one or more optional extensions, create a
* For a configuration that includes one or more optional extensions, create a
*microdot* directory in your device and copy the following files:
- `__init__.py <https://github.com/miguelgrinberg/microdot/blob/main/src/microdot/__init__.py>`_
- `microdot.py <https://github.com/miguelgrinberg/microdot/blob/main/src/microdot/microdot.py>`_
- any needed `extensions <https://github.com/miguelgrinberg/microdot/tree/main/src/microdot>`_.
* `__init__.py <https://github.com/miguelgrinberg/microdot/blob/main/src/microdot/__init__.py>`_
* `microdot.py <https://github.com/miguelgrinberg/microdot/blob/main/src/microdot/microdot.py>`_
* any needed `extensions <https://github.com/miguelgrinberg/microdot/tree/main/src/microdot>`_.
Getting Started

View File

@@ -45,6 +45,12 @@ class _BodyStream: # pragma: no cover
class Microdot(BaseMicrodot):
"""A subclass of the core :class:`Microdot <microdot.Microdot>` class that
implements the ASGI protocol.
This class must be used as the application instance when running under an
ASGI web server.
"""
def __init__(self):
super().__init__()
self.embedded_server = False

View File

@@ -134,7 +134,7 @@ def with_session(f):
return 'Hello, World!'
Note that the decorator does not save the session. To update the session,
call the :func:`update_session <microdot.session.update_session>` function.
call the :func:`session.save() <microdot.session.SessionDict.save>` method.
"""
async def wrapper(request, *args, **kwargs):
return await invoke_handler(

View File

@@ -3,6 +3,11 @@ import json
class SSE:
"""Server-Sent Events object.
An object of this class is sent to handler functions to manage the SSE
connection.
"""
def __init__(self):
self.event = asyncio.Event()
self.queue = []
@@ -40,19 +45,9 @@ def sse_response(request, event_function, *args, **kwargs):
:param args: additional positional arguments to be passed to the response.
:param kwargs: additional keyword arguments to be passed to the response.
Example::
@app.route('/events')
async def events_route(request):
async def events(request, sse):
# send an unnamed event with string data
await sse.send('hello')
# send an unnamed event with JSON data
await sse.send({'foo': 'bar'})
# send a named event
await sse.send('hello', event='greeting')
return sse_response(request, events)
This is a low-level function that can be used to implement a custom SSE
endpoint. In general the :func:`microdot.sse.with_sse` decorator should be
used instead.
"""
sse = SSE()
@@ -95,9 +90,14 @@ def with_sse(f):
@app.route('/events')
@with_sse
async def events(request, sse):
for i in range(10):
await asyncio.sleep(1)
await sse.send(f'{i}')
# send an unnamed event with string data
await sse.send('hello')
# send an unnamed event with JSON data
await sse.send({'foo': 'bar'})
# send a named event
await sse.send('hello', event='greeting')
"""
async def sse_handler(request, *args, **kwargs):
return sse_response(request, f, *args, **kwargs)

View File

@@ -5,6 +5,11 @@ from microdot.microdot import MUTED_SOCKET_ERRORS
class WebSocket:
"""A WebSocket connection object.
An instance of this class is sent to handler functions to manage the
WebSocket connection.
"""
CONT = 0
TEXT = 1
BINARY = 2
@@ -26,6 +31,7 @@ class WebSocket:
b'Sec-WebSocket-Accept: ' + response + b'\r\n\r\n')
async def receive(self):
"""Receive a message from the client."""
while True:
opcode, payload = await self._read_frame()
send_opcode, data = self._process_websocket_frame(opcode, payload)
@@ -35,12 +41,20 @@ class WebSocket:
return data
async def send(self, data, opcode=None):
"""Send a message to the client.
:param data: the data to send, given as a string or bytes.
:param opcode: a custom frame opcode to use. If not given, the opcode
is ``TEXT`` or ``BINARY`` depending on the type of the
data.
"""
frame = self._encode_websocket_frame(
opcode or (self.TEXT if isinstance(data, str) else self.BINARY),
data)
await self.request.sock[1].awrite(frame)
async def close(self):
"""Close the websocket connection."""
if not self.closed: # pragma: no cover
self.closed = True
await self.send(b'', self.CLOSE)

View File

@@ -9,6 +9,12 @@ from microdot.websocket import WebSocket, websocket_upgrade, \
class Microdot(BaseMicrodot):
"""A subclass of the core :class:`Microdot <microdot.Microdot>` class that
implements the WSGI protocol.
This class must be used as the application instance when running under a
WSGI web server.
"""
def __init__(self):
super().__init__()
self.loop = asyncio.new_event_loop()

13
tox.ini
View File

@@ -1,5 +1,5 @@
[tox]
envlist=flake8,py38,py39,py310,py311,py312,upy,cpy,benchmark
envlist=flake8,py38,py39,py310,py311,py312,upy,cpy,benchmark,docs
skipsdist=True
skip_missing_interpreters=True
@@ -36,7 +36,6 @@ commands=sh -c "bin/circuitpython run_tests.py"
[testenv:upy-mac]
allowlist_externals=micropython
commands=micropython run_tests.py
deps=
[testenv:benchmark]
deps=
@@ -59,3 +58,13 @@ deps=
flake8
commands=
flake8 --ignore=W503 --exclude examples/templates/utemplate/templates src tests examples
[testenv:docs]
changedir=docs
deps=
sphinx
pyjwt
allowlist_externals=
make
commands=
make html