Skip to content

Commit

Permalink
Automatic NoContentResponse from None (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
ondratu committed Oct 13, 2024
1 parent a3b1c1e commit 7de995e
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 10 deletions.
5 changes: 3 additions & 2 deletions doc/ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* Right HTTPException type annotation
* Fix ETag header
* FieldStorage and FieldStorageParser implementation based on legacy
cgi.FieldStorage
- that means Python 3.13 support
cgi.FieldStorage (#22 )
- that means Python 3.13 support (#36)
* Stop Python 3.8 support - some mypy annotation didn't work
* Field refactoring - ! possible break change ! - sorry for that
- FieldStorageInterface - getvalue, getfist, getlist methods
Expand All @@ -14,6 +14,7 @@
as deprecated, and will be deleted in next major version.
* Automatic JSONResponse from dict or list, just like from text.
* Debug info, documentation and Error improvements.
* Automatic NoContentResponse from None (#28)

==== 2.6.3 ====
* HTTPException has status_code property
Expand Down
28 changes: 26 additions & 2 deletions doc/documentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,15 @@ make_response function.
headers=None, status_code=HTTP_OK)
data : str, bytes, generator
Returned value as response body.
data : str, bytes, dict, list, None or generator
Returned value as response body. Each type of data returns different
response type:

- str, bytes - Response
- dict, list - JSONResponse
- None - NoContentReponse
- generator - GeneratorResponse

content_type : str
The ``Content-Type`` header which is set, if this header is not set
in headers.
Expand All @@ -127,6 +134,23 @@ You can use headers instead of `content_type` argument.
headers={"Content-Type": "text/plain"},
status_code=NOT_FOUND)
If you return just simple type, or tuple of arguments, PoorWSGI automatically
call make_response function to create response for you.

.. code:: python
@app.route("/json")
def not_found(req):
"""Return JSONResponse"""
return {"msg": "Message", "type": "object"}
@app.route('/gone')
def gone(req):
"""Return NoContentResponse"""
return None, "", None, HTTP_GONE
Response
````````
Response object is one of base element of WSGI application. Response is object
Expand Down
5 changes: 5 additions & 0 deletions examples/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,11 @@ def not_implemented(req):
raise HTTPException(state.HTTP_NOT_IMPLEMENTED)


@app.route('/no-response')
def no_response(_):
"""Test for no-response"""


if __name__ == '__main__':
httpd = make_server('127.0.0.1', 8080, app)
print("Starting to serve on http://127.0.0.1:8080")
Expand Down
31 changes: 25 additions & 6 deletions poorwsgi/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,7 @@ def status_code(self):
return self.args[0].status_code


def make_response(data: Union[str, bytes, dict, Iterable[bytes]],
def make_response(data: Optional[Union[str, bytes, dict, Iterable[bytes]]],
content_type: str = "text/html; charset=utf-8",
headers: Optional[Union[Headers, HeadersList]] = None,
status_code: int = HTTP_OK):
Expand Down Expand Up @@ -851,17 +851,19 @@ def make_response(data: Union[str, bytes, dict, Iterable[bytes]],
>>> res.headers["OK-Header"]
'OK'
JSONResponse from dictionary:
JSONResponse from dictionary, content_type argument is ignored:
>>> res = make_response({"key": "value"})
>>> res = make_response({"key": "value"}, "text/plain", status_code=201)
>>> res
<poorwsgi.response.JSONResponse object at ...>
>>> res.data
b'{"key": "value"}'
>>> res.content_type
'application/json; charset=utf-8'
>>> res.status_code
201
JSONResponse from list:
JSONResponse from list, content_type argument is ignored:
>>> res = make_response([["key", "value"]])
>>> res
Expand All @@ -879,14 +881,31 @@ def make_response(data: Union[str, bytes, dict, Iterable[bytes]],
>>> list(res.__end_of_response__())
[b'key', b'value']
NoContentResponse from None, content_type argument is ignored. If
status_code is leave 200 OK, then status will be 204 No Content:
>>> res = make_response(None)
>>> res
<poorwsgi.response.NoContentResponse object at ...>
>>> res.status_code
204
>>> res = make_response(None, status_code=201)
>>> res.status_code
201
"""
try:
if isinstance(data, (str, bytes)): # "hello world"
return Response(data, content_type, headers, status_code)
if isinstance(data, dict):
return JSONResponse(data)
return JSONResponse(data, headers=headers, status_code=status_code)
if isinstance(data, list) and not isinstance(data[0], bytes):
return JSONResponse(data)
return JSONResponse(data, headers=headers, status_code=status_code)
if data is None:
if status_code == HTTP_OK:
status_code = HTTP_NO_CONTENT
return NoContentResponse(headers=headers, status_code=status_code)

iter(data) # try iter data
return GeneratorResponse(data, content_type, headers, status_code)
Expand Down

0 comments on commit 7de995e

Please sign in to comment.