Skip to content

Commit

Permalink
Documentation: Badges, linking, wording, inline comments. This and that.
Browse files Browse the repository at this point in the history
A few of the adjustments here have been required to mitigate Sphinx
warnings, which would converge to errors on CI, thus failing the build.

A few other changes are coming from regular copyediting and maintenance.
  • Loading branch information
amotl committed Oct 27, 2024
1 parent 597cb93 commit 9ae7ffc
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 47 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down
6 changes: 6 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
54 changes: 33 additions & 21 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -34,23 +38,22 @@ A familiar HTTP Service Framework
if __name__ == '__main__':
api.run()
Powered by `Starlette <https://www.starlette.io/>`_. 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 <http://whitenoise.evans.io/en/stable/>`_)
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 <https://asgi.readthedocs.io>`_ 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 <https://docs.python.org/3/whatsnew/3.6.html#pep-498-formatted-string-literals>`_ 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!
Expand All @@ -61,8 +64,7 @@ Testimonials
------------

“Pleasantly very taken with python-responder.
`@kennethreitz <https://twitter.com/kennethreitz>`_ at his absolute
best.”
`@kennethreitz`_ at his absolute best.”

—Rudraksh M.K.

Expand All @@ -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
-----------

Expand Down Expand Up @@ -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 <https://www.uvicorn.org/>`_ 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 <https://en.wikipedia.org/wiki/Slowloris_(computer_security)>`_ 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.


Expand All @@ -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/
5 changes: 4 additions & 1 deletion docs/source/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <http://jinja.pocoo.org/docs/>`_ wrapper ``templates.Templates``
Responder provides a built-in light `Jinja`_ wrapper ``templates.Templates``

Usage::

Expand Down Expand Up @@ -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/
45 changes: 29 additions & 16 deletions responder/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 <http://jinja.pocoo.org/docs/>`_ 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 <http://jinja.pocoo.org/docs/>`_ 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.
Expand Down

0 comments on commit 9ae7ffc

Please sign in to comment.