PoorWSGI 2.6.1__tar.gz → 2.6.3__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.
Files changed (62) hide show
  1. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/PKG-INFO +1 -1
  2. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/PoorWSGI.egg-info/PKG-INFO +1 -1
  3. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/PoorWSGI.egg-info/SOURCES.txt +4 -4
  4. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/ChangeLog +5 -0
  5. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/documentation.rst +1 -1
  6. poorwsgi-2.6.3/examples/http_digest.py +200 -0
  7. poorwsgi-2.6.3/examples/jwt_example.py.skip +86 -0
  8. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/examples/large_file.py +9 -7
  9. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/examples/metrics.py +1 -0
  10. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/examples/openapi3.py +2 -2
  11. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/examples/put_file.py +6 -4
  12. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/examples/simple.py +163 -121
  13. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/examples/simple_json.py +4 -4
  14. poorwsgi-2.6.3/examples/websocket-frames.py.skip +80 -0
  15. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/examples/websocket.py +10 -2
  16. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/poorwsgi/openapi_wrapper.py +1 -1
  17. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/poorwsgi/request.py +2 -2
  18. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/poorwsgi/response.py +11 -0
  19. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/poorwsgi/results.py +10 -10
  20. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/poorwsgi/session.py +1 -1
  21. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/poorwsgi/state.py +2 -2
  22. poorwsgi-2.6.3/setup.py +206 -0
  23. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/tests/test_digest.py +17 -8
  24. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/tests/test_header.py +4 -2
  25. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/tests/test_responses.py +56 -8
  26. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/tests/test_session.py +4 -0
  27. PoorWSGI-2.6.1/examples/http_digest.py +0 -237
  28. PoorWSGI-2.6.1/setup.py +0 -229
  29. PoorWSGI-2.6.1/test_hidden.py +0 -58
  30. PoorWSGI-2.6.1/websockets_chat_async.py +0 -95
  31. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/CONTRIBUTION.rst +0 -0
  32. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/MANIFEST.in +0 -0
  33. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/PoorWSGI.egg-info/dependency_links.txt +0 -0
  34. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/PoorWSGI.egg-info/requires.txt +0 -0
  35. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/PoorWSGI.egg-info/top_level.txt +0 -0
  36. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/README.rst +0 -0
  37. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/_documentation.html +0 -0
  38. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/_footer.html +0 -0
  39. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/_header.html +0 -0
  40. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/_install.html +0 -0
  41. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/_licence.html +0 -0
  42. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/_poorwsgi.html +0 -0
  43. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/_poorwsgi_api.html +0 -0
  44. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/_reference.html +0 -0
  45. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/_text.html +0 -0
  46. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/about.rst +0 -0
  47. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/install.rst +0 -0
  48. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/licence.txt +0 -0
  49. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/small-logo.png +0 -0
  50. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/style.css +0 -0
  51. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/doc/web.css +0 -0
  52. /PoorWSGI-2.6.1/examples/async.py → /poorwsgi-2.6.3/examples/async.py.skip +0 -0
  53. /PoorWSGI-2.6.1/examples/encoding.py → /poorwsgi-2.6.3/examples/encoding.py.skip +0 -0
  54. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/examples/openapi.json +0 -0
  55. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/examples/test.digest +0 -0
  56. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/poorwsgi/__init__.py +0 -0
  57. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/poorwsgi/digest.py +0 -0
  58. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/poorwsgi/headers.py +0 -0
  59. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/poorwsgi/py.typed +0 -0
  60. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/poorwsgi/wsgi.py +0 -0
  61. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/setup.cfg +0 -0
  62. {PoorWSGI-2.6.1 → poorwsgi-2.6.3}/tests/test_request.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PoorWSGI
3
- Version: 2.6.1
3
+ Version: 2.6.3
4
4
  Summary: Poor WSGI connector for Python
5
5
  Home-page: http://poorhttp.zeropage.cz/poorwsgi
6
6
  Author: Ondřej Tůma
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PoorWSGI
3
- Version: 2.6.1
3
+ Version: 2.6.3
4
4
  Summary: Poor WSGI connector for Python
5
5
  Home-page: http://poorhttp.zeropage.cz/poorwsgi
6
6
  Author: Ondřej Tůma
@@ -2,8 +2,6 @@ CONTRIBUTION.rst
2
2
  MANIFEST.in
3
3
  README.rst
4
4
  setup.py
5
- test_hidden.py
6
- websockets_chat_async.py
7
5
  PoorWSGI.egg-info/PKG-INFO
8
6
  PoorWSGI.egg-info/SOURCES.txt
9
7
  PoorWSGI.egg-info/dependency_links.txt
@@ -26,9 +24,10 @@ doc/licence.txt
26
24
  doc/small-logo.png
27
25
  doc/style.css
28
26
  doc/web.css
29
- examples/async.py
30
- examples/encoding.py
27
+ examples/async.py.skip
28
+ examples/encoding.py.skip
31
29
  examples/http_digest.py
30
+ examples/jwt_example.py.skip
32
31
  examples/large_file.py
33
32
  examples/metrics.py
34
33
  examples/openapi.json
@@ -37,6 +36,7 @@ examples/put_file.py
37
36
  examples/simple.py
38
37
  examples/simple_json.py
39
38
  examples/test.digest
39
+ examples/websocket-frames.py.skip
40
40
  examples/websocket.py
41
41
  poorwsgi/__init__.py
42
42
  poorwsgi/digest.py
@@ -1,3 +1,8 @@
1
+ ==== 2.6.3 ====
2
+ * HTTPException has status_code property
3
+ * Implicit value for not set cookie is None or empty dict for OpenAPI
4
+ * Fix Content-Length header when partial Response
5
+
1
6
  ==== 2.6.1 ====
2
7
  * Fix OpenAPI Core wrappers
3
8
 
@@ -795,7 +795,7 @@ CachedInput
795
795
  ~~~~~~~~~~~
796
796
 
797
797
  When HTTP Forms are base64 encoded, FieldStorage use readline on request input
798
- file. This is not so optimal. So there is CachedInput class, which is returned
798
+ file. This is not so optimal. So there is CachedInput class, which is returned
799
799
 
800
800
  Proccess variables
801
801
  ~~~~~~~~~~~~~~~~~~
@@ -0,0 +1,200 @@
1
+ """HTTP WWW-Authenticate Digest Example."""
2
+ import logging
3
+ from hashlib import sha256
4
+ from os import path
5
+ from sys import path as python_path
6
+ from time import time
7
+ from wsgiref.simple_server import make_server
8
+
9
+ python_path.insert(
10
+ 0, path.abspath(path.join(path.dirname(__file__), path.pardir)))
11
+
12
+ # pylint: disable=wrong-import-position
13
+ from poorwsgi import Application, state # noqa
14
+ from poorwsgi.digest import PasswordMap, check_digest, hexdigest # noqa
15
+ from poorwsgi.response import EmptyResponse, redirect # noqa
16
+
17
+ FILE = path.join(path.dirname(__file__), 'test.digest')
18
+
19
+ logging.getLogger().setLevel("DEBUG")
20
+ app = application = Application(__name__) # pylint: disable=invalid-name
21
+ # application = app
22
+ app.debug = True
23
+ app.secret_key = sha256(str(time()).encode()).hexdigest()
24
+ # app.auth_algorithm = 'SHA-256-sess'
25
+ app.auth_type = 'Digest'
26
+ app.auth_timeout = 60
27
+
28
+ ADMIN = 'Admin Zone'
29
+ USER = 'User Zone'
30
+ # user/looser, foo/bar, admin/admin, Ondřej/heslíčko
31
+ app.auth_map = PasswordMap(FILE)
32
+ app.auth_map.load()
33
+
34
+ # pylint: disable=unused-argument
35
+
36
+
37
+ def get_header(title):
38
+ """Return HTML header list of lines."""
39
+ return (
40
+ "<html>", "<head>",
41
+ '<meta http-equiv="content-type" content="text/html; charset=utf-8"/>',
42
+ f"<title>{__file__} - {title}</title>", "</head>", "<body>",
43
+ f"<h1>{__file__} - {title}</h1>")
44
+
45
+
46
+ def get_footer():
47
+ """Return HTML footer list of lines."""
48
+ return ("<hr>", "<small>Copyright (c) 2020 Ondřej Tůma. See ",
49
+ '<a href="http://poorhttp.zeropage.cz">poorhttp.zeropage.cz</a>'
50
+ '</small>.', "</body>", "</html>")
51
+
52
+
53
+ def get_link(href, text=None, title=None):
54
+ """Return HTML anchor."""
55
+ text = text or title or href
56
+ title = title or text
57
+ return f'<a href="{href}" title="{title}">{text}</a>'
58
+
59
+
60
+ @app.route('/')
61
+ def root(req):
62
+ """Return Root (Index) page."""
63
+ body = ('<ul>', "<li>" + get_link('/admin_zone') +
64
+ " - admin zone (admin/admin)</li>", "<li>" +
65
+ get_link('/user_zone') + " - user zone (user/looser;sha/sha)</li>",
66
+ "<li>" + get_link('/user') + " - user (user/looser)</li>", "<li>" +
67
+ get_link('/user/utf-8') + " - utf-8 (Ondřej/heslíčko)</li>",
68
+ "<li>" + get_link('/foo') + " - foo (foo/bar)</li>",
69
+ "<li>" + get_link('/unknown') + " - unknown</li>",
70
+ "<li>" + get_link('/spaces in url') + " - spaces in url</li>",
71
+ "<li>" + get_link('/čeština v url') + " - diacitics in url</li>",
72
+ "<li>" + get_link('/crazy in url 🤪') + " - unicode in url</li>",
73
+ '</ul>')
74
+
75
+ for line in get_header("Root") + body + get_footer():
76
+ yield line.encode() + b'\n'
77
+
78
+
79
+ @app.route('/admin_zone')
80
+ @check_digest(ADMIN)
81
+ def admin_zone(req):
82
+ """Page only for ADMIN realm."""
83
+ body = (f'<h2>{ADMIN} test for {app.auth_algorithm} algorithm.</h2>',
84
+ '<ul>', '<li>' + get_link('/', 'Root') + '</li>',
85
+ '<li>' + get_link('/admin_zone?arg=42', 'one more time') + '</li>',
86
+ '</ul>')
87
+
88
+ for line in get_header("Root") + body + get_footer():
89
+ yield line.encode() + b'\n'
90
+
91
+
92
+ @app.route('/user_zone')
93
+ @check_digest(USER)
94
+ def user_zone(req):
95
+ """Page for USER realm."""
96
+ body = (f'<h2>{USER} test for {app.auth_algorithm} algorithm.</h2>',
97
+ f'User: {req.user}', '<ul>',
98
+ '<li>' + get_link('/', 'Root') + '</li>', '<li>' +
99
+ get_link('/user_zone?param=text', 'one more time') + '</li>',
100
+ '</ul>')
101
+
102
+ for line in get_header("Root") + body + get_footer():
103
+ yield line.encode() + b'\n'
104
+
105
+
106
+ @app.route('/user')
107
+ @check_digest(USER, 'user')
108
+ def user_only(req):
109
+ """Page for user only."""
110
+ body = (f'<h2>User test for {app.auth_algorithm} algorithm.</h2>',
111
+ f'User: {req.user}', '<ul>',
112
+ '<li>' + get_link('/', 'Root') + '</li>', '<li>' +
113
+ get_link('/user?param=1234', 'one more time') + '</li>', '</ul>')
114
+
115
+ for line in get_header("Root") + body + get_footer():
116
+ yield line.encode() + b'\n'
117
+
118
+
119
+ @app.route('/foo')
120
+ @check_digest(USER, 'foo')
121
+ def foo_only(req):
122
+ """Page for foo user only."""
123
+ body = (f'<h2>Foo test for {app.auth_algorithm} algorithm.</h2>',
124
+ f'User: {req.user}', '<ul>', '<li>' + get_link('/', 'Root') +
125
+ '</li>', '</ul>', '<form method="post" action="/foo/passwd">',
126
+ '<label>Enter new password:',
127
+ '<input type="password" name="password"/>', '</label>',
128
+ '<button type="submit">Change Password</button>', '</form>')
129
+
130
+ for line in get_header("Root") + body + get_footer():
131
+ yield line.encode() + b'\n'
132
+
133
+
134
+ @app.route('/user/utf-8')
135
+ @check_digest(USER, 'Ondřej')
136
+ def utf8_chars(req):
137
+ """Page for user only."""
138
+ body = (f'<h2>User test for {app.auth_algorithm} algorithm.</h2>',
139
+ f'User: {req.user}', '<ul>',
140
+ '<li>' + get_link('/', 'Root') + '</li>', '<li>' +
141
+ get_link('/user/utf-8?param=1234', 'one more time') + '</li>',
142
+ '</ul>')
143
+
144
+ for line in get_header("Root") + body + get_footer():
145
+ yield line.encode() + b'\n'
146
+
147
+
148
+ @app.route('/foo/passwd', method=state.METHOD_POST)
149
+ @check_digest(USER, 'foo')
150
+ def foo_password(req):
151
+ """Change foo's password."""
152
+ digest = hexdigest(req.user, USER, req.form.get('password'), app.auth_hash)
153
+ app.auth_map.set(USER, req.user, digest)
154
+ redirect('/foo')
155
+
156
+
157
+ @app.route('/unknown')
158
+ @check_digest(USER, 'unknown')
159
+ def unknown_endpoint(req):
160
+ """Page for digest test."""
161
+ return EmptyResponse()
162
+
163
+
164
+ def generic_response(url, user):
165
+ """Return generic response"""
166
+ body = (f'<h2>{USER} test for {app.auth_algorithm} algorithm.</h2>',
167
+ f'User: {user}', '<ul>', '<li>' + get_link('/', 'Root') + '</li>',
168
+ '<li>' + get_link(url + '?param=text', 'one more time') + '</li>',
169
+ '</ul>')
170
+
171
+ for line in get_header("Root") + body + get_footer():
172
+ yield line.encode() + b'\n'
173
+
174
+
175
+ @app.route('/spaces in url')
176
+ @check_digest(USER)
177
+ def spaces_in_url(req):
178
+ """URL with spaces in path."""
179
+ return generic_response(req.path, req.user)
180
+
181
+
182
+ @app.route('/čeština v url')
183
+ @check_digest(USER)
184
+ def diacritics_in_url(req):
185
+ """URL with diacritics in path."""
186
+ return generic_response(req.path, req.user)
187
+
188
+
189
+ @app.route('/crazy in url 🤪')
190
+ @check_digest(USER)
191
+ def crazy_in_url(req):
192
+ """URL with unicode in path."""
193
+ return generic_response(req.path, req.user)
194
+
195
+
196
+ if __name__ == '__main__':
197
+ # pylint: disable=invalid-name
198
+ httpd = make_server('127.0.0.1', 8080, app)
199
+ logging.info("Starting to serve on http://127.0.0.1:8080")
200
+ httpd.serve_forever()
@@ -0,0 +1,86 @@
1
+ """JWT example"""
2
+ import logging
3
+ from functools import wraps
4
+ from hashlib import sha256
5
+ from http.cookies import SimpleCookie
6
+ from os import path, urandom
7
+ from sys import path as python_path
8
+ from time import time
9
+ from wsgiref.simple_server import make_server
10
+
11
+ import jwt
12
+
13
+ python_path.insert(
14
+ 0, path.abspath(path.join(path.dirname(__file__), path.pardir)))
15
+
16
+ # pylint: disable=wrong-import-position
17
+ from poorwsgi import Application, state # noqa
18
+ from poorwsgi.response import RedirectResponse, abort, redirect # noaq
19
+
20
+ app = Application('test')
21
+ app.secret_key = urandom(32) # random secret_key
22
+
23
+
24
+ def check_login(fn):
25
+
26
+ @wraps(fn) # using wraps make right/better /debug-info page
27
+ def handler(req):
28
+ try:
29
+ encoded = req.cookies["JWT"].value
30
+ data = jwt.decode(encoded, app.secret_key, algorithms="HS256")
31
+ if 'login' not in data:
32
+ raise RuntimeError("loggin not in data")
33
+ except:
34
+ redirect("/login", message=b"Login required")
35
+
36
+ return fn(req)
37
+
38
+ return handler
39
+
40
+
41
+ @app.route('/login', method=state.METHOD_GET_POST)
42
+ def login(req):
43
+ if req.method == 'POST':
44
+ passwd = req.form.getfirst('passwd', fce=str)
45
+ if passwd != 'SecretPasswds':
46
+ redirect('/login', message='Bad password')
47
+
48
+ response = RedirectResponse("/private/path")
49
+ cookie = SimpleCookie()
50
+ data = {'login': True}
51
+ encoded = jwt.encode(data, app.secret_key, algorithm="HS256")
52
+ cookie["JWT"] = encoded
53
+ for header in cookie.output().split("\r\n"):
54
+ var = header[:10] # Set-Cookie
55
+ val = header[12:] # SID=###; expires=###; Path=/
56
+ response.add_header(var, val)
57
+
58
+ abort(response)
59
+
60
+ return 'some html login form'
61
+
62
+
63
+ @app.route('/private/path')
64
+ @check_login
65
+ def private_path(req):
66
+ return 'Some private data'
67
+
68
+
69
+ @app.route('/logout')
70
+ def logout(req):
71
+ response = RedirectResponse("/login")
72
+ cookie = SimpleCookie()
73
+ cookie["JWT"]["expires"] = -1
74
+ for header in cookie.output().split("\r\n"):
75
+ var = header[:10] # Set-Cookie
76
+ val = header[12:] # SID=###; expires=###; Path=/
77
+ response.add_header(var, val)
78
+
79
+ return response
80
+
81
+
82
+ if __name__ == '__main__':
83
+ # pylint: disable=invalid-name
84
+ httpd = make_server('127.0.0.1', 8080, app)
85
+ logging.info("Starting to serve on http://127.0.0.1:8080")
86
+ httpd.serve_forever()
@@ -1,4 +1,5 @@
1
1
  """Large file upload test."""
2
+ # pylint: disable=duplicate-code
2
3
 
3
4
  from wsgiref.simple_server import make_server, WSGIServer
4
5
  from socketserver import ThreadingMixIn
@@ -14,11 +15,11 @@ EXAMPLES_PATH = os.path.dirname(__file__)
14
15
  sys.path.insert(0, os.path.abspath(
15
16
  os.path.join(EXAMPLES_PATH, os.path.pardir)))
16
17
 
17
- # pylint: disable=import-error, disable=wrong-import-position
18
+ # pylint: disable=wrong-import-position
18
19
  from poorwsgi import Application, state # noqa
19
20
  from poorwsgi.request import FieldStorage # noqa
20
21
  from poorwsgi.response import HTTPException # noqa
21
- from poorwsgi.results import hbytes # noqa
22
+ from poorwsgi.results import hbytes # noqa
22
23
 
23
24
  logger = log.getLogger()
24
25
  logger.setLevel("DEBUG")
@@ -31,6 +32,7 @@ app.auto_form = False
31
32
 
32
33
  class Blackhole:
33
34
  """Dummy File Object"""
35
+
34
36
  def __init__(self, filename):
35
37
  log.debug("Start uploading file: %s", filename)
36
38
  self.uploaded = 0
@@ -56,6 +58,7 @@ class Blackhole:
56
58
 
57
59
  class Temporary:
58
60
  """Temporary file"""
61
+
59
62
  def __init__(self, filename):
60
63
  log.debug("Start uploading file: %s", filename)
61
64
  self.uploaded = 0
@@ -152,11 +155,10 @@ def html_form(req, file_callback):
152
155
  hexdigest = form['file'].file.hexdigest()
153
156
 
154
157
  end = time() - start
155
- args = (hbytes(bytes_read) +
156
- (int(end),) +
157
- hbytes(bytes_read / end) +
158
- (hexdigest,))
159
- stats = ("Upload: %.2f%s in %ds -> %.2f%sps SHA256: %s" % args)
158
+ size = hbytes(bytes_read)
159
+ speed = hbytes(bytes_read / end)
160
+ stats = (f"Upload: {size[0]:.2f}{size[1]} in {end}s -> "
161
+ f"{speed[0]:.2f}{speed[1]}ps SHA256: {hexdigest}")
160
162
  log.info(stats)
161
163
 
162
164
  if bytes_read != req.content_length:
@@ -9,6 +9,7 @@ EXAMPLES_PATH = os.path.dirname(__file__)
9
9
  python_path.insert(0, os.path.abspath(
10
10
  os.path.join(EXAMPLES_PATH, os.path.pardir)))
11
11
 
12
+ # pylint: disable=wrong-import-position
12
13
  from poorwsgi import Application, state # noqa
13
14
  from poorwsgi.response import JSONResponse # noqa
14
15
 
@@ -31,7 +31,7 @@ python_path.insert(0, path.abspath(
31
31
  from poorwsgi import Application, state # noqa
32
32
  from poorwsgi.response import Response, abort, HTTPException, \
33
33
  JSONResponse # noqa
34
- from poorwsgi.request import Request
34
+ from poorwsgi.request import Request # noqa
35
35
  from poorwsgi.openapi_wrapper import OpenAPIRequest, \
36
36
  OpenAPIResponse # noqa
37
37
  from poorwsgi.session import PoorSession # noqa
@@ -111,7 +111,7 @@ def after_each_response(req, res):
111
111
  return res
112
112
  except OpenAPIError as error:
113
113
  log.error("API output error: %s", str(error))
114
- assert False, f"OpenAPI Error {str(error)}"
114
+ raise
115
115
  return res
116
116
 
117
117
 
@@ -15,16 +15,18 @@ sys.path.insert(0, os.path.abspath(
15
15
 
16
16
  # pylint: disable=import-error, disable=wrong-import-position
17
17
  from poorwsgi import Application, state # noqa
18
- from poorwsgi.response import JSONResponse
18
+ from poorwsgi.response import JSONResponse # noqa
19
19
 
20
20
  logger = log.getLogger()
21
21
  logger.setLevel("DEBUG")
22
22
  app = application = Application("large_file")
23
23
  app.debug = True
24
24
 
25
+ # pylint: disable=duplicate-code
26
+
25
27
 
26
28
  @app.route('/blackhole/<filename>', method=state.METHOD_PUT)
27
- def blackhole_put(req, filename:str):
29
+ def blackhole_put(req, filename: str):
28
30
  """Upload file via PUT method like in webdav"""
29
31
  checksum = sha256()
30
32
  uploaded = 0
@@ -46,7 +48,7 @@ def blackhole_put(req, filename:str):
46
48
 
47
49
 
48
50
  @app.route('/temporary/<filename>', method=state.METHOD_PUT)
49
- def temporary_put(req, filename:str):
51
+ def temporary_put(req, filename: str):
50
52
  """Upload file via PUT method like in webdav"""
51
53
  checksum = sha256()
52
54
  uploaded = 0
@@ -143,5 +145,5 @@ class ThreadingWSGIServer(ThreadingMixIn, WSGIServer):
143
145
  if __name__ == '__main__':
144
146
  ADDRESS = sys.argv[1] if len(sys.argv) > 1 else '127.0.0.1'
145
147
  httpd = make_server(ADDRESS, 8080, app, ThreadingWSGIServer)
146
- print("Starting to serve on http://%s:8080" % ADDRESS)
148
+ print(f"Starting to serve on http://{ADDRESS}:8080")
147
149
  httpd.serve_forever()