microdot 2.0.6__tar.gz → 2.0.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {microdot-2.0.6/src/microdot.egg-info → microdot-2.0.7}/PKG-INFO +3 -1
- {microdot-2.0.6 → microdot-2.0.7}/docs/extensions.rst +2 -2
- {microdot-2.0.6 → microdot-2.0.7}/docs/intro.rst +33 -6
- {microdot-2.0.6 → microdot-2.0.7}/pyproject.toml +7 -2
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot/microdot.py +9 -1
- {microdot-2.0.6 → microdot-2.0.7/src/microdot.egg-info}/PKG-INFO +3 -1
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot.egg-info/SOURCES.txt +1 -0
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot.egg-info/dependency_links.txt +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot.egg-info/not-zip-safe +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot.egg-info/requires.txt +3 -0
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot.egg-info/top_level.txt +0 -0
- microdot-2.0.7/tests/files/test.txt.gz +1 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/test_microdot.py +20 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/test_response.py +13 -2
- {microdot-2.0.6 → microdot-2.0.7}/LICENSE +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/MANIFEST.in +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/README.md +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/docs/Makefile +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/docs/_static/css/custom.css +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/docs/api.rst +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/docs/conf.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/docs/freezing.rst +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/docs/index.rst +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/docs/make.bat +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/docs/migrating.rst +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/setup.cfg +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot/__init__.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot/asgi.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot/cors.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot/helpers.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot/jinja.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot/session.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot/sse.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot/test_client.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot/utemplate.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot/websocket.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/src/microdot/wsgi.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/__init__.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/files/test.bin +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/files/test.css +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/files/test.gif +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/files/test.gz +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/files/test.html +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/files/test.jpg +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/files/test.js +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/files/test.json +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/files/test.png +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/files/test.txt +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/mock_socket.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/templates/hello.jinja.txt +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/templates/hello.utemplate.txt +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/templates/hello_utemplate_txt.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/test_asgi.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/test_cors.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/test_end2end.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/test_jinja.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/test_multidict.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/test_request.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/test_session.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/test_sse.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/test_url_pattern.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/test_urlencode.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/test_utemplate.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/test_websocket.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tests/test_wsgi.py +0 -0
- {microdot-2.0.6 → microdot-2.0.7}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: microdot
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.7
|
|
4
4
|
Summary: The impossibly small web framework for MicroPython
|
|
5
5
|
Author-email: Miguel Grinberg <miguel.grinberg@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/miguelgrinberg/microdot
|
|
@@ -14,6 +14,8 @@ Classifier: Operating System :: OS Independent
|
|
|
14
14
|
Requires-Python: >=3.8
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
License-File: LICENSE
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: tox; extra == "dev"
|
|
17
19
|
Provides-Extra: docs
|
|
18
20
|
Requires-Dist: sphinx; extra == "docs"
|
|
19
21
|
Requires-Dist: pyjwt; extra == "docs"
|
|
@@ -286,7 +286,7 @@ Cross-Origin Resource Sharing (CORS)
|
|
|
286
286
|
- | None
|
|
287
287
|
|
|
288
288
|
* - Examples
|
|
289
|
-
- | `
|
|
289
|
+
- | `app.py <https://github.com/miguelgrinberg/microdot/blob/main/examples/cors/app.py>`_
|
|
290
290
|
|
|
291
291
|
The CORS extension provides support for `Cross-Origin Resource Sharing
|
|
292
292
|
(CORS) <https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS>`_. CORS is a
|
|
@@ -363,7 +363,7 @@ Using an ASGI Web Server
|
|
|
363
363
|
- | `asgi.py <https://github.com/miguelgrinberg/microdot/tree/main/src/microdot/asgi.py>`_
|
|
364
364
|
|
|
365
365
|
* - Required external dependencies
|
|
366
|
-
- | An ASGI web server, such as `Uvicorn <https://uvicorn.org/>`_.
|
|
366
|
+
- | An ASGI web server, such as `Uvicorn <https://www.uvicorn.org/>`_.
|
|
367
367
|
|
|
368
368
|
* - Examples
|
|
369
369
|
- | `hello_asgi.py <https://github.com/miguelgrinberg/microdot/blob/main/examples/hello/hello_asgi.py>`_
|
|
@@ -82,8 +82,34 @@ handler functions can be defined as ``async def`` or ``def`` functions, but
|
|
|
82
82
|
``async def`` functions are recommended for performance.
|
|
83
83
|
|
|
84
84
|
The :func:`run() <microdot.Microdot.run>` method starts the application's web
|
|
85
|
-
server on port 5000 by default
|
|
86
|
-
connections from clients.
|
|
85
|
+
server on port 5000 by default, and creates its own asynchronous loop. This
|
|
86
|
+
method blocks while it waits for connections from clients.
|
|
87
|
+
|
|
88
|
+
For some applications it may be necessary to run the web server alongside other
|
|
89
|
+
asynchronous tasks, on an already running loop. In that case, instead of
|
|
90
|
+
``app.run()`` the web server can be started by invoking the
|
|
91
|
+
:func:`start_server() <microdot.Microdot.start_server>` coroutine as shown in
|
|
92
|
+
the following example::
|
|
93
|
+
|
|
94
|
+
import asyncio
|
|
95
|
+
from microdot import Microdot
|
|
96
|
+
|
|
97
|
+
app = Microdot()
|
|
98
|
+
|
|
99
|
+
@app.route('/')
|
|
100
|
+
async def index(request):
|
|
101
|
+
return 'Hello, world!'
|
|
102
|
+
|
|
103
|
+
async def main():
|
|
104
|
+
# start the server in a background task
|
|
105
|
+
server = asyncio.create_task(app.start_server())
|
|
106
|
+
|
|
107
|
+
# ... do other asynchronous work here ...
|
|
108
|
+
|
|
109
|
+
# cleanup before ending the application
|
|
110
|
+
await server
|
|
111
|
+
|
|
112
|
+
asyncio.run(main())
|
|
87
113
|
|
|
88
114
|
Running with CPython
|
|
89
115
|
^^^^^^^^^^^^^^^^^^^^
|
|
@@ -92,7 +118,7 @@ Running with CPython
|
|
|
92
118
|
:align: left
|
|
93
119
|
|
|
94
120
|
* - Required Microdot source files
|
|
95
|
-
- | `microdot.py <https://github.com/miguelgrinberg/microdot/
|
|
121
|
+
- | `microdot.py <https://github.com/miguelgrinberg/microdot/blob/main/src/microdot/microdot.py>`_
|
|
96
122
|
|
|
97
123
|
* - Required external dependencies
|
|
98
124
|
- | None
|
|
@@ -118,7 +144,7 @@ Running with MicroPython
|
|
|
118
144
|
:align: left
|
|
119
145
|
|
|
120
146
|
* - Required Microdot source files
|
|
121
|
-
- | `microdot.py <https://github.com/miguelgrinberg/microdot/
|
|
147
|
+
- | `microdot.py <https://github.com/miguelgrinberg/microdot/blob/main/src/microdot/microdot.py>`_
|
|
122
148
|
|
|
123
149
|
* - Required external dependencies
|
|
124
150
|
- | None
|
|
@@ -145,8 +171,9 @@ changed by passing the ``port`` argument to the ``run()`` method.
|
|
|
145
171
|
Web Server Configuration
|
|
146
172
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
147
173
|
|
|
148
|
-
The :func:`run() <microdot.Microdot.run>`
|
|
149
|
-
|
|
174
|
+
The :func:`run() <microdot.Microdot.run>` and
|
|
175
|
+
:func:`start_server() <microdot.Microdot.start_server>` methods support a few
|
|
176
|
+
arguments to configure the web server.
|
|
150
177
|
|
|
151
178
|
- ``port``: The port number to listen on. Pass the desired port number in this
|
|
152
179
|
argument to use a port different than the default of 5000. For example::
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "microdot"
|
|
3
|
-
version = "2.0.
|
|
3
|
+
version = "2.0.7"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name = "Miguel Grinberg", email = "miguel.grinberg@gmail.com" },
|
|
6
6
|
]
|
|
@@ -14,6 +14,8 @@ classifiers = [
|
|
|
14
14
|
"Operating System :: OS Independent",
|
|
15
15
|
]
|
|
16
16
|
requires-python = ">=3.8"
|
|
17
|
+
dependencies = [
|
|
18
|
+
]
|
|
17
19
|
|
|
18
20
|
[project.readme]
|
|
19
21
|
file = "README.md"
|
|
@@ -24,9 +26,12 @@ Homepage = "https://github.com/miguelgrinberg/microdot"
|
|
|
24
26
|
"Bug Tracker" = "https://github.com/miguelgrinberg/microdot/issues"
|
|
25
27
|
|
|
26
28
|
[project.optional-dependencies]
|
|
29
|
+
dev = [
|
|
30
|
+
"tox",
|
|
31
|
+
]
|
|
27
32
|
docs = [
|
|
28
33
|
"sphinx",
|
|
29
|
-
"pyjwt"
|
|
34
|
+
"pyjwt",
|
|
30
35
|
]
|
|
31
36
|
|
|
32
37
|
[tool.setuptools]
|
|
@@ -774,7 +774,10 @@ class Response:
|
|
|
774
774
|
first.
|
|
775
775
|
"""
|
|
776
776
|
if content_type is None:
|
|
777
|
-
|
|
777
|
+
if compressed and filename.endswith('.gz'):
|
|
778
|
+
ext = filename[:-3].split('.')[-1]
|
|
779
|
+
else:
|
|
780
|
+
ext = filename.split('.')[-1]
|
|
778
781
|
if ext in Response.types_map:
|
|
779
782
|
content_type = Response.types_map[ext]
|
|
780
783
|
else:
|
|
@@ -1366,7 +1369,12 @@ class Microdot:
|
|
|
1366
1369
|
if res is None:
|
|
1367
1370
|
res = await invoke_handler(
|
|
1368
1371
|
f, req, **req.url_args)
|
|
1372
|
+
if isinstance(res, int):
|
|
1373
|
+
res = '', res
|
|
1369
1374
|
if isinstance(res, tuple):
|
|
1375
|
+
if isinstance(res[0], int):
|
|
1376
|
+
res = ('', res[0],
|
|
1377
|
+
res[1] if len(res) > 1 else {})
|
|
1370
1378
|
body = res[0]
|
|
1371
1379
|
if isinstance(res[1], int):
|
|
1372
1380
|
status_code = res[1]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: microdot
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.7
|
|
4
4
|
Summary: The impossibly small web framework for MicroPython
|
|
5
5
|
Author-email: Miguel Grinberg <miguel.grinberg@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/miguelgrinberg/microdot
|
|
@@ -14,6 +14,8 @@ Classifier: Operating System :: OS Independent
|
|
|
14
14
|
Requires-Python: >=3.8
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
License-File: LICENSE
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: tox; extra == "dev"
|
|
17
19
|
Provides-Extra: docs
|
|
18
20
|
Requires-Dist: sphinx; extra == "docs"
|
|
19
21
|
Requires-Dist: pyjwt; extra == "docs"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
foo
|
|
@@ -274,6 +274,14 @@ class TestMicrodot(unittest.TestCase):
|
|
|
274
274
|
return '<p>four</p>', 202, \
|
|
275
275
|
{'Content-Type': 'text/html; charset=UTF-8'}
|
|
276
276
|
|
|
277
|
+
@app.route('/status')
|
|
278
|
+
def five(req):
|
|
279
|
+
return 202
|
|
280
|
+
|
|
281
|
+
@app.route('/status-headers')
|
|
282
|
+
def six(req):
|
|
283
|
+
return 202, {'Content-Type': 'text/html; charset=UTF-8'}
|
|
284
|
+
|
|
277
285
|
client = TestClient(app)
|
|
278
286
|
|
|
279
287
|
res = self._run(client.get('/body'))
|
|
@@ -299,6 +307,18 @@ class TestMicrodot(unittest.TestCase):
|
|
|
299
307
|
'text/html; charset=UTF-8')
|
|
300
308
|
self.assertEqual(res.text, '<p>four</p>')
|
|
301
309
|
|
|
310
|
+
res = self._run(client.get('/status'))
|
|
311
|
+
self.assertEqual(res.text, '')
|
|
312
|
+
self.assertEqual(res.status_code, 202)
|
|
313
|
+
self.assertEqual(res.headers['Content-Type'],
|
|
314
|
+
'text/plain; charset=UTF-8')
|
|
315
|
+
|
|
316
|
+
res = self._run(client.get('/status-headers'))
|
|
317
|
+
self.assertEqual(res.text, '')
|
|
318
|
+
self.assertEqual(res.status_code, 202)
|
|
319
|
+
self.assertEqual(res.headers['Content-Type'],
|
|
320
|
+
'text/html; charset=UTF-8')
|
|
321
|
+
|
|
302
322
|
def test_before_after_request(self):
|
|
303
323
|
app = Microdot()
|
|
304
324
|
|
|
@@ -136,10 +136,10 @@ class TestResponse(unittest.TestCase):
|
|
|
136
136
|
self.assertTrue(fd.response.endswith(b'\r\n\r\nfoobar'))
|
|
137
137
|
|
|
138
138
|
def test_create_from_other(self):
|
|
139
|
-
res = Response(
|
|
139
|
+
res = Response(23.7)
|
|
140
140
|
self.assertEqual(res.status_code, 200)
|
|
141
141
|
self.assertEqual(res.headers, {})
|
|
142
|
-
self.assertEqual(res.body,
|
|
142
|
+
self.assertEqual(res.body, 23.7)
|
|
143
143
|
|
|
144
144
|
def test_create_with_status_code(self):
|
|
145
145
|
res = Response('not found', 404)
|
|
@@ -280,6 +280,17 @@ class TestResponse(unittest.TestCase):
|
|
|
280
280
|
'application/octet-stream')
|
|
281
281
|
self.assertEqual(res.headers['Content-Encoding'], 'gzip')
|
|
282
282
|
|
|
283
|
+
def test_send_file_gzip_handling(self):
|
|
284
|
+
res = Response.send_file('tests/files/test.txt.gz')
|
|
285
|
+
self.assertEqual(res.status_code, 200)
|
|
286
|
+
self.assertEqual(res.headers['Content-Type'],
|
|
287
|
+
'application/octet-stream')
|
|
288
|
+
|
|
289
|
+
res = Response.send_file('tests/files/test.txt.gz', compressed=True)
|
|
290
|
+
self.assertEqual(res.status_code, 200)
|
|
291
|
+
self.assertEqual(res.headers['Content-Type'], 'text/plain')
|
|
292
|
+
self.assertEqual(res.headers['Content-Encoding'], 'gzip')
|
|
293
|
+
|
|
283
294
|
def test_default_content_type(self):
|
|
284
295
|
original_content_type = Response.default_content_type
|
|
285
296
|
res = Response('foo')
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|