diff --git a/README.md b/README.md
index 9df88d5f..53d38e0f 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,21 @@
# Responder: a familiar HTTP Service Framework for Python
-[![Build Status](https://github.com/kennethreitz/responder/actions/workflows/test.yaml/badge.svg)](https://github.com/kennethreitz/responder/actions/workflows/test.yaml)
+[![ci-tests](https://github.com/kennethreitz/responder/actions/workflows/test.yaml/badge.svg)](https://github.com/kennethreitz/responder/actions/workflows/test.yaml)
+[![ci-docs](https://github.com/kennethreitz/responder/actions/workflows/docs.yaml/badge.svg)](https://github.com/kennethreitz/responder/actions/workflows/docs.yaml)
[![Documentation Status](https://github.com/kennethreitz/responder/actions/workflows/pages/pages-build-deployment/badge.svg)](https://responder.kennethreitz.org/)
-[![image](https://img.shields.io/pypi/v/responder.svg)](https://pypi.org/project/responder/)
-[![image](https://img.shields.io/pypi/l/responder.svg)](https://pypi.org/project/responder/)
-[![image](https://img.shields.io/pypi/pyversions/responder.svg)](https://pypi.org/project/responder/)
-[![image](https://img.shields.io/github/contributors/kennethreitz/responder.svg)](https://github.com/kennethreitz/responder/graphs/contributors)
-[![PyPI Downloads](https://pepy.tech/badge/responder/month)](https://pepy.tech/project/responder/)
-[![Status](https://img.shields.io/pypi/status/responder.svg)](https://pypi.org/project/responder/)
-[![License](https://img.shields.io/pypi/l/responder.svg)](https://pypi.org/project/responder/)
+[![version](https://img.shields.io/pypi/v/responder.svg)](https://pypi.org/project/responder/)
+[![license](https://img.shields.io/pypi/l/responder.svg)](https://pypi.org/project/responder/)
+[![python-versions](https://img.shields.io/pypi/pyversions/responder.svg)](https://pypi.org/project/responder/)
+[![downloads](https://static.pepy.tech/badge/responder/month)](https://pepy.tech/project/responder)
+[![contributors](https://img.shields.io/github/contributors/kennethreitz/responder.svg)](https://github.com/kennethreitz/responder/graphs/contributors)
+[![status](https://img.shields.io/pypi/status/responder.svg)](https://pypi.org/project/responder/)
[![](https://farm2.staticflickr.com/1959/43750081370_a4e20752de_o_d.png)](https://responder.readthedocs.io)
Powered by [Starlette](https://www.starlette.io/). That `async` declaration is optional.
[View documentation](https://responder.readthedocs.io).
-This gets you a ASGI app, with a production static files server pre-installed, jinja2
+This gets you a ASGI app, with a production static files server pre-installed, Jinja
templating (without additional imports), and a production webserver based on uvloop,
serving up requests with gzip compression automatically.
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 09451a46..7c4b1df9 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -211,6 +211,12 @@
# -- Extension configuration -------------------------------------------------
+# -- Options for link checker ----------------------------------------------
+linkcheck_ignore = [
+ # Feldroy.com links are ignored because it blocks GHA.
+ r"https://www.feldroy.com/.*",
+]
+
# -- Options for intersphinx extension ---------------------------------------
# Example configuration for intersphinx: refer to the Python standard library.
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 88683e46..87b176a7 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -6,19 +6,23 @@
A familiar HTTP Service Framework
=================================
-|Build Status| |image1| |image2| |image3| |image4| |image5|
+|ci-tests| |version| |license| |python-versions| |downloads| |contributors| |say-thanks|
-.. |Build Status| image:: https://github.com/kennethreitz/responder/actions/workflows/test.yaml/badge.svg
+.. |ci-tests| image:: https://github.com/kennethreitz/responder/actions/workflows/test.yaml/badge.svg
:target: https://github.com/kennethreitz/responder/actions/workflows/test.yaml
-.. |image1| image:: https://img.shields.io/pypi/v/responder.svg
+.. |ci-docs| image:: https://github.com/kennethreitz/responder/actions/workflows/docs.yaml/badge.svg
+ :target: https://github.com/kennethreitz/responder/actions/workflows/docs.yaml
+.. |version| image:: https://img.shields.io/pypi/v/responder.svg
:target: https://pypi.org/project/responder/
-.. |image2| image:: https://img.shields.io/pypi/l/responder.svg
+.. |license| image:: https://img.shields.io/pypi/l/responder.svg
:target: https://pypi.org/project/responder/
-.. |image3| image:: https://img.shields.io/pypi/pyversions/responder.svg
+.. |python-versions| image:: https://img.shields.io/pypi/pyversions/responder.svg
:target: https://pypi.org/project/responder/
-.. |image4| image:: https://img.shields.io/github/contributors/kennethreitz/responder.svg
+.. |downloads| image:: https://static.pepy.tech/badge/responder/month
+ :target: https://www.pepy.tech/projects/responder
+.. |contributors| image:: https://img.shields.io/github/contributors/kennethreitz/responder.svg
:target: https://github.com/kennethreitz/responder/graphs/contributors
-.. |image5| image:: https://img.shields.io/badge/Say%20Thanks-!-1EAEDB.svg
+.. |say-thanks| image:: https://img.shields.io/badge/Say%20Thanks-!-1EAEDB.svg
:target: https://saythanks.io/to/kennethreitz
.. code:: python
@@ -34,23 +38,22 @@ A familiar HTTP Service Framework
if __name__ == '__main__':
api.run()
-Powered by `Starlette `_. That ``async`` declaration is optional.
+Powered by `Starlette`_. That ``async`` declaration is optional.
-This gets you a ASGI app, with a production static files server
-(`WhiteNoise `_)
-pre-installed, jinja2 templating (without additional imports), and a
-production webserver based on uvloop, serving up requests with
-automatic gzip compression.
+This program provides an `ASGI`_ application, with production-ready components
+like the `uvicorn`_ webserver based on `uvloop`_, the static files server
+`WhiteNoise`_, and the `Jinja`_ templating library pre-installed.
Features
--------
- A pleasant API, with a single import statement.
- Class-based views without inheritance.
-- `ASGI `_ framework, the future of Python web services.
+- `ASGI`_, the future of Python web services.
+- Asynchronous Python frameworks and applications.
- WebSocket support!
- The ability to mount any ASGI / WSGI app at a subroute.
-- `f-string syntax `_ route declaration.
+- `f-string syntax`_ route declaration.
- Mutable response object, passed into each view. No need to return anything.
- Background tasks, spawned off in a ``ThreadPoolExecutor``.
- GraphQL (with *GraphiQL*) support!
@@ -61,8 +64,7 @@ Testimonials
------------
“Pleasantly very taken with python-responder.
- `@kennethreitz `_ at his absolute
- best.”
+ `@kennethreitz`_ at his absolute best.”
—Rudraksh M.K.
@@ -82,9 +84,6 @@ Testimonials
— Danny Greenfield, author of `Two Scoops of Django`_
-.. _Django REST Framework: https://www.django-rest-framework.org/
-.. _Two Scoops of Django: https://www.feldroy.com/two-scoops-press#two-scoops-of-django
-
User Guides
-----------
@@ -130,7 +129,7 @@ Ideas
- Automatic gzipped-responses.
- In addition to Falcon's ``on_get``, ``on_post``, etc methods, Responder features an ``on_request`` method, which gets called on every type of request, much like Requests.
- A production static files server is built-in.
-- `Uvicorn `_ is built-in as a production web server. I would have chosen Gunicorn, but it doesn't run on Windows. Plus, Uvicorn serves well to protect against `slowloris `_ attacks, making nginx unnecessary in production.
+- `uvicorn`_ is built-in as a production web server. I would have chosen Gunicorn, but it doesn't run on Windows. Plus, uvicorn serves well to protect against `Slowloris`_ attacks, making Nginx unnecessary in production.
- GraphQL support, via Graphene. The goal here is to have any GraphQL query exposable at any route, magically.
@@ -140,3 +139,16 @@ Indices and tables
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
+
+
+.. _@kennethreitz: https://x.com/kennethreitz
+.. _ASGI: https://en.wikipedia.org/wiki/Asynchronous_Server_Gateway_Interface
+.. _Django REST Framework: https://www.django-rest-framework.org/
+.. _f-string syntax: https://docs.python.org/3/whatsnew/3.6.html#pep-498-formatted-string-literals
+.. _Jinja: https://jinja.palletsprojects.com/en/stable/
+.. _Slowloris: https://en.wikipedia.org/wiki/Slowloris_(computer_security)
+.. _Starlette: https://www.starlette.io/
+.. _Two Scoops of Django: https://www.feldroy.com/two-scoops-press#two-scoops-of-django
+.. _uvicorn: https://www.uvicorn.org/
+.. _uvloop: https://uvloop.readthedocs.io/
+.. _WhiteNoise: https://whitenoise.readthedocs.io/en/latest/
diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst
index 1ba6dd06..358ac335 100644
--- a/docs/source/quickstart.rst
+++ b/docs/source/quickstart.rst
@@ -73,7 +73,7 @@ If the client requests YAML instead (with a header of ``Accept: application/x-ya
Rendering a Template
--------------------
-Responder provides a built-in light `jinja2 `_ wrapper ``templates.Templates``
+Responder provides a built-in light `Jinja`_ wrapper ``templates.Templates``
Usage::
@@ -175,3 +175,6 @@ You can send a file easily with requests::
r = requests.post('http://127.0.0.1:8210/file', files=data)
print(r.text)
+
+
+.. _Jinja: https://jinja.palletsprojects.com/en/stable/
diff --git a/responder/api.py b/responder/api.py
index a713da2a..1dc5a8ea 100644
--- a/responder/api.py
+++ b/responder/api.py
@@ -149,8 +149,11 @@ def add_middleware(self, middleware_cls, **middleware_config):
self.app = middleware_cls(self.app, **middleware_config)
def schema(self, name, **options):
- """Decorator for creating new routes around function and class definitions.
+ """
+ Decorator for creating new routes around function and class definitions.
+
Usage::
+
from marshmallow import Schema, fields
@api.schema("Pet")
class PetSchema(Schema):
@@ -224,7 +227,9 @@ async def _static_response(self, req, resp):
def redirect(
self, resp, location, *, set_text=True, status_code=status_codes.HTTP_301
):
- """Redirects a given response to a given location.
+ """
+ Redirects a given response to a given location.
+
:param resp: The Response to mutate.
:param location: The location of the redirect.
:param set_text: If ``True``, sets the Redirect body content automatically.
@@ -311,29 +316,37 @@ def url_for(self, endpoint, **params):
return self.router.url_for(endpoint, **params)
def template(self, filename, *args, **kwargs):
- """Renders the given `jinja2 `_ template, with provided values supplied.
+ r"""
+ Render the given Jinja2 template file, with provided values supplied.
- Note: The current ``api`` instance is by default passed into the view. This is set in the dict ``api.jinja_values_base``.
+ Note: The current ``api`` instance is by default passed into the view.
+ This is set in the dict ``api.jinja_values_base``.
:param filename: The filename of the jinja2 template, in ``templates_dir``.
- :param *args: Data to pass into the template.
- :param *kwargs: Date to pass into the template.
- """ # noqa: E501
+ :param \*args: Data to pass into the template.
+ :param \*\*kwargs: Date to pass into the template.
+ """
return self.templates.render(filename, *args, **kwargs)
def template_string(self, source, *args, **kwargs):
- """Renders the given `jinja2 `_ template string, with provided values supplied.
- Note: The current ``api`` instance is by default passed into the view. This is set in the dict ``api.jinja_values_base``.
- :param source: The template to use.
- :param *args: Data to pass into the template.
- :param **kwargs: Data to pass into the template.
- """ # noqa: E501
+ r"""
+ Render the given Jinja2 template string, with provided values supplied.
+
+ Note: The current ``api`` instance is by default passed into the view.
+ This is set in the dict ``api.jinja_values_base``.
+
+ :param source: The template to use, a Jinja2 template string.
+ :param \*args: Data to pass into the template.
+ :param \*\*kwargs: Data to pass into the template.
+ """
return self.templates.render_string(source, *args, **kwargs)
def serve(self, *, address=None, port=None, debug=False, **options):
- """Runs the application with uvicorn. If the ``PORT`` environment
- variable is set, requests will be served on that port automatically to all
- known hosts.
+ """
+ Run the application with uvicorn.
+
+ If the ``PORT`` environment variable is set, requests will be served on that port
+ automatically to all known hosts.
:param address: The address to bind to.
:param port: The port to bind to. If none is provided, one will be selected at random.