From a79023b63c6c52e3874b365dc460ff9601d8dfb3 Mon Sep 17 00:00:00 2001 From: Miguel Grinberg Date: Thu, 21 Dec 2023 00:56:59 +0000 Subject: [PATCH] Documentation on migrating and freezing --- docs/freezing.rst | 32 ++++++++++ docs/index.rst | 2 + docs/intro.rst | 144 --------------------------------------------- docs/migrating.rst | 142 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 176 insertions(+), 144 deletions(-) create mode 100644 docs/freezing.rst create mode 100644 docs/migrating.rst diff --git a/docs/freezing.rst b/docs/freezing.rst new file mode 100644 index 0000000..489d80d --- /dev/null +++ b/docs/freezing.rst @@ -0,0 +1,32 @@ +Freezing Microdot +----------------- + +:: + + import glob + import os + import microdot + import mpy_cross + import shutil + + + def create_mpy_files(): + if os.path.exists('microdot'): + input('A "microdot" directory already exists. ' + 'Press enter to delete it or Ctrl-C to abort.') + shutil.rmtree('microdot') + os.mkdir('microdot') + modules = glob.glob(os.path.join(os.path.dirname(microdot.__file__), + '*.py')) + for module in modules: + mpy_module = os.path.basename(module)[:-2] + 'mpy' + mpy_cross.run( + '-o', + os.path.join('microdot', mpy_module), + module + ) + print(f'Created microdot/{mpy_module}') + + + if __name__ == '__main__': + create_mpy_files() diff --git a/docs/index.rst b/docs/index.rst index c61486d..aaddcd0 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -18,6 +18,8 @@ systems with limited resources such as microcontrollers. Both standard Python intro extensions + migrating + freezing api * :ref:`genindex` diff --git a/docs/intro.rst b/docs/intro.rst index dc4ffc5..ba9cde9 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -867,147 +867,3 @@ Given that most microcontroller boards implementing MicroPython do not have threading support, ``def`` handler functions in these platforms run in the main thread, and will block the asynchronous loop when they take too long to complete. - -Migrating to Microdot 2.x from Older Releases -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Version 2 of Microdot incorporates feedback received from users of earlier -releases, and attempts to improve and correct some design decisions that have -proven to be problematic. - -For this reason most applications built for earlier versions will need to be -updated to work correctly with Microdot 2. This section describes the backwards -incompatible changes that were made. - -Code reorganization -^^^^^^^^^^^^^^^^^^^ - -The Microdot source code has been moved into a ``microdot`` package, elminating -the need for each extension to be named *microdot_.py*. - -As a result of this change, all extensions have been renamed to shorter names, -without the ``microdot_`` prefix. For example, the *microdot_cors.py* module is -now called *cors.py*. - -This change affects the way extensions are imported. Instead of this:: - - from microdot_cors import CORS - -the import statement should be:: - - from microdot.cors import CORS - -No more synchronous web server -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In earlier releases of Microdot the core web server was built on synchronous -Python, and asynchronous support was enabled with the asyncio extension. - -Microdot 2 eliminates the synchronous web server, and implements the core -server logic directly with asyncio, eliminating the need for an asyncio -extension. - -Any applications built using the asyncio extension will need to update their -imports from this:: - - from microdot.asyncio import Microdot - -to this:: - - from microdot import Microdot - -Applications that were built using the synchronous web server do not need to -change their imports, but will now work asynchronously. Review the -:ref:`Concurrency` section to learn about the potential issues when using -``def`` function handlers, and the benefits of transitioning to ``async def`` -handlers. - -Removed extensions -^^^^^^^^^^^^^^^^^^ - -Some extensions became unnecessary and have been removed or merged with other -extensions: - -- *microdot_asyncio.py*: this is now the core web server. -- *microdot_asyncio_websocket.py*: this is now the main WebSocket extension. -- *microdot_asyncio_test_client.py*: this is now the main test client - extension. -- *microdot_asgi_websocket.py*: the functionality in this extension is now - available in the ASGI extension. -- *microdot_ssl.py*: this extension was only used with the synchronous web - server, so it is not needed anymore. -- *microdot_websocket_alt.py*: this extension was only used with the - synchronous web server, so it is not needed anymore. - -No more ``render_template()`` function -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The Jinja and uTemplate extensions have been redesigned to work better under -the asynchronous engine, and as a result, the ``render_template()`` function -has been eliminated. - -Instead of this:: - - return render_template('index.html', title='Home') - -use this:: - - return Template('index.html').render(title='Home') - -As a result of this change, it is now possible to use asynchronous rendering:: - - return await Template('index.html').render_async(title='Home') - -Also thanks to this redesign, the template can be streamed instead of returned -as a single string:: - - return Template('index.html').generate(title='Home') - -Streamed templates also have an asynchronous version:: - - return await Template('index.html').generate_async(title='Home') - -Class-based sessions -^^^^^^^^^^^^^^^^^^^^ - -The session extension has been completely redesigned. To initialize session -support for the application, create a ``Session`` object:: - - app = Microdot() - Session(app, secret_key='top-secret!') - -The ``@with_session`` decorator is used to include the session in a request:: - - @app.get('/') - @with_session - async def index(request, session): - # ... - -The ``session`` can be used as a dictionary to retrieve or change the session. -To save the session when it has been modified, call its ``save()`` method:: - - @app.get('/') - @with_session - async def index(request, session): - # ... - session.save() - return 'OK' - -To delete the session, call its ``delete()`` method before returning from the -request. - -WSGI extension redesign -^^^^^^^^^^^^^^^^^^^^^^^ - -Given that the synchronous web server has been removed, the WSGI extension has -been redesigned to work as a synchronous wrapper for the asynchronous web -server. - -Applications using the WSGI extension continue to run under an asynchronous -loop and should try to use the recommended ``async def`` handlers, but can be -deployed with standard WSGI servers such as Gunicorn. - -WebSocket support when using the WSGI extension is enabled when using a -compatible web server. At this time only Gunicorn is supported for WebSocket. - -As before, the WSGI extension is not available under MicroPython. diff --git a/docs/migrating.rst b/docs/migrating.rst new file mode 100644 index 0000000..e12855a --- /dev/null +++ b/docs/migrating.rst @@ -0,0 +1,142 @@ +Migrating to Microdot 2.x from Older Releases +--------------------------------------------- + +Version 2 of Microdot incorporates feedback received from users of earlier +releases, and attempts to improve and correct some design decisions that have +proven to be problematic. + +For this reason most applications built for earlier versions will need to be +updated to work correctly with Microdot 2. This section describes the backwards +incompatible changes that were made. + +Code reorganization +~~~~~~~~~~~~~~~~~~~ + +The Microdot source code has been moved into a ``microdot`` package, +eliminating the need for each extension to be named with a *microdot_* prefix. + +As a result of this change, all extensions have been renamed to shorter names. +For example, the *microdot_cors.py* module is now called *cors.py*. + +This change affects the way extensions are imported. Instead of this:: + + from microdot_cors import CORS + +the import statement should be:: + + from microdot.cors import CORS + +No more synchronous web server +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In earlier releases of Microdot the core web server was built on synchronous +Python, and asynchronous support was enabled with the asyncio extension. + +Microdot 2 eliminates the synchronous web server, and implements the core +server logic directly with asyncio, eliminating the need for an asyncio +extension. + +Any applications built using the asyncio extension will need to update their +imports from this:: + + from microdot.asyncio import Microdot + +to this:: + + from microdot import Microdot + +Applications that were built using the synchronous web server do not need to +change their imports, but will now work asynchronously. Review the +:ref:`Concurrency` section to learn about the potential issues when using +``def`` function handlers, and the benefits of transitioning to ``async def`` +handlers. + +Removed extensions +~~~~~~~~~~~~~~~~~~ + +Some extensions became unnecessary and have been removed or merged with other +extensions: + +- *microdot_asyncio.py*: this is now the core web server. +- *microdot_asyncio_websocket.py*: this is now the main WebSocket extension. +- *microdot_asyncio_test_client.py*: this is now the main test client + extension. +- *microdot_asgi_websocket.py*: the functionality in this extension is now + available in the ASGI extension. +- *microdot_ssl.py*: this extension was only used with the synchronous web + server, so it is not needed anymore. +- *microdot_websocket_alt.py*: this extension was only used with the + synchronous web server, so it is not needed anymore. + +No more ``render_template()`` function +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Jinja and uTemplate extensions have been redesigned to work better under +the asynchronous engine, and as a result, the ``render_template()`` function +has been eliminated. + +Instead of this:: + + return render_template('index.html', title='Home') + +use this:: + + return Template('index.html').render(title='Home') + +As a result of this change, it is now possible to use asynchronous rendering:: + + return await Template('index.html').render_async(title='Home') + +Also thanks to this redesign, the template can be streamed instead of returned +as a single string:: + + return Template('index.html').generate(title='Home') + +Streamed templates also have an asynchronous version:: + + return await Template('index.html').generate_async(title='Home') + +Class-based user sessions +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The session extension has been completely redesigned. To initialize session +support for the application, create a ``Session`` object:: + + app = Microdot() + Session(app, secret_key='top-secret!') + +The ``@with_session`` decorator is used to include the session in a request:: + + @app.get('/') + @with_session + async def index(request, session): + # ... + +The ``session`` can be used as a dictionary to retrieve or change the session. +To save the session when it has been modified, call its ``save()`` method:: + + @app.get('/') + @with_session + async def index(request, session): + # ... + session.save() + return 'OK' + +To delete the session, call its ``delete()`` method before returning from the +request. + +WSGI extension redesign +~~~~~~~~~~~~~~~~~~~~~~~ + +Given that the synchronous web server has been removed, the WSGI extension has +been redesigned to work as a synchronous wrapper for the asynchronous web +server. + +Applications using the WSGI extension continue to run under an asynchronous +loop and should try to use the recommended ``async def`` handlers, but can be +deployed with standard WSGI servers such as Gunicorn. + +WebSocket support when using the WSGI extension is enabled when using a +compatible web server. At this time only Gunicorn is supported for WebSocket. + +As before, the WSGI extension is not available under MicroPython.