Skip to content

Commit

Permalink
Update documentation (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
the-robot committed Apr 19, 2020
1 parent 28b68ce commit 59f269d
Show file tree
Hide file tree
Showing 12 changed files with 77 additions and 66 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Yaat is an asynchronous web framework/toolkit.

**Features**

- Provide decorator routes & class based views.
- Provide decorator routes & class-based views.
- Template support with [Jinja2](https://jinja.palletsprojects.com/).
- Static file serving.
- HTTP streaming response.
Expand Down Expand Up @@ -84,11 +84,11 @@ uvicorn app:app

## Inspiration

I know there are a lot of awesome frameworks out there. So some might ask why did I write my own. Actually I created this to learn how the web framework actually works.
I know there are a lot of awesome frameworks out there. So some might ask why did I write my own. Actually, I created this to learn how the web framework works.

I started this after following [Jahongir Rahmonov's blog post](https://rahmonov.me/posts/write-python-framework-part-one/) about writing a web framework. Feel free to check out his WSGI framework [Alcazar](https://github.com/rahmonov/alcazar).

More features will be added in the future. You can checkout the [project board](https://github.com/yaat-project/yaat/projects/1).
More features will be added in the future. You can check out the [project board](https://github.com/yaat-project/yaat/projects/1).


## Icon Credit
Expand Down
2 changes: 1 addition & 1 deletion docs/backgroundtasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Yaat has built-in background task runner using `BackgroundTask`.

If you want to run a task in background after responding to the client, you will have wrap your `Response`
If you want to run a task in the background after responding to the client, you will have to wrap your `Response`
and `BackgroundTask` in `RunAfterResponse` and return.

### Background Task
Expand Down
4 changes: 2 additions & 2 deletions docs/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ You can register multiple handlers to events you want to run some code during th

### Registering Handlers

Handlers can either be syncronous functions or async coroutines. For example, connecting to database should be done on `on_startup` event.
Handlers can either be synchronous functions or async coroutines. For example, connecting to the database should be done on the `on_startup` event.

```python
from yaat import Yaat
Expand All @@ -21,7 +21,7 @@ app = Yaat(
)
```

> In uvicorn, pass the argument `lifespan` to set the lifespan protocol.
> In Uvicorn, pass the argument `lifespan` to set the lifespan protocol.
```sh
uvicorn app:app --lifespan on
Expand Down
10 changes: 5 additions & 5 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

# Introduction

Yaat is an asynchronous web toolkit. It is as simple as..
Yaat is an asynchronous web toolkit. It is as simple as...

```python
from yaat import Yaat
Expand All @@ -40,7 +40,7 @@ async def index(request):

## Features

- Provide decorator routes & class based views.
- Provide decorator routes & class-based views.
- Template support with [Jinja2](https://jinja.palletsprojects.com/).
- Static file serving.
- HTTP streaming response.
Expand All @@ -63,7 +63,7 @@ Python 3.6+
pip3 install yaat
```

In order to run the application, you will need an ASGI server. Such as [uvicorn](https://www.uvicorn.org/), [hypercorn](https://pgjones.gitlab.io/hypercorn) or [daphne](https://github.com/django/daphne/).
To run the application, you will need an ASGI server. Such as [uvicorn](https://www.uvicorn.org/), [hypercorn](https://pgjones.gitlab.io/hypercorn) or [daphne](https://github.com/django/daphne/).

For example, if you put the example code from the top in `app.py`. You can run the application by

Expand All @@ -87,8 +87,8 @@ Yaat is licensed under [GNU Lesser General Public License](https://github.com/ya

## Inspiration

I know there are a lot of awesome frameworks out there. So some might ask why did I write my own. Actually I created this to learn how the web framework actually works.
I know there are a lot of awesome frameworks out there. So some might ask why did I write my own. Actually, I created this to learn how the web framework works.

I started this after following [Jahongir Rahmonov's blog post](https://rahmonov.me/posts/write-python-framework-part-one/) about writing a web framework. Feel free to check out his WSGI framework [Alcazar](https://github.com/rahmonov/alcazar).

More features will be added in the future. You can checkout the [project board](https://github.com/yaat-project/yaat/projects/1).
More features will be added in the future. You can check out the [project board](https://github.com/yaat-project/yaat/projects/1).
12 changes: 6 additions & 6 deletions docs/middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class CustomMiddleware(BaseMiddleware):
app.add_middleware(CustomMiddleware)
```

You will need to register middleware in orders. From bird-eye view, registering middleware will look like this.
You will need to register the middleware in orders. From a bird-eye view, registering middleware will look like this.

```python
Middleware2(
Expand All @@ -66,7 +66,7 @@ Response will go out from `Application` → `Middleware1` → `Middleware2`.

### CORS Middleware

To allow cross-origin requests from browsers, the server need to response with appropriate
To allow cross-origin requests from browsers, the server need to respond with appropriate
[CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS).

The default behavior is restrictive and you will need to explicitly specify the origins, methods, or headers so that
Expand All @@ -87,20 +87,20 @@ app.add_middleware(CORSMiddleware, allow_origins=[
- `allow_headers` - a list of HTTP request headers allow for cross-origin requests. `[]` by default and [Safelisted Request Headers](https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_request_header) are always allowed for cross-origin requests.
- `allow_credentials` - to indicate cookie to be allowed for cross-origin requests. `False` by default.
- `expose_headers` - to indicate any response headers to be accessible to the browser. `[]` by default.
- `max_age` - set how long (in seconds) to cache CORS responses in browser. `60` (10 minutes) by default.
- `max_age` - set how long (in seconds) to cache CORS responses in the browser. `60` (10 minutes) by default.

CORS middleware handles two type of requests. Preflight requests and simple requests. Read more in details [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Examples_of_access_control_scenarios).

#### Preflight requests

Any request with HTTP `OPTIONS` and `Access-Control-Request-Method` in headers is considered preflight requests.
For those requests, middleware will intercept and response with appropriate CORS headers. `HTTP 200` for success requests
For those requests, the middleware will intercept and respond with appropriate CORS headers. `HTTP 200` for success requests
and `HTTP 400` for invalid requests.

> `HTTP 200` returns instead of `HTTP 204` because some legacy browsers reject CORS requests if `204` is received.
> [read more about issue](https://stackoverflow.com/questions/46026409/what-are-proper-status-codes-for-cors-preflight-requests)
#### Simple requests

Any request with an `Origin` in headers. CORS middleware will just pass the request through as normal, but will inject
appropriate CORS headers to response.
Any request with an `Origin` in headers. CORS middleware will just pass the request through as normal but will inject
appropriate CORS headers to the response.
3 changes: 2 additions & 1 deletion docs/releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
### 0.1.5

- Added path parameters datatype conversion.
- Configured `flake8` and `black` with pre-commit hook for code formatting.
- Configured `flake8` and `black` with a pre-commit hook for code formatting.
- Added path-parm type conversion based on the route type-hints.

### 0.1.4

Expand Down
8 changes: 4 additions & 4 deletions docs/requests.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Requests

When an endpoint receives a HTTP request, the router will pass a `Request` object.
When an endpoint receives an HTTP request, the router will pass a `Request` object.

```python
from yaat import Yaat
Expand Down Expand Up @@ -33,7 +33,7 @@ apiToken = headers["api-token"]

#### URL

`request.url` returns string-like object with all components parsed out from the URL.
`request.url` returns a string-like object with all components parsed out from the URL.

- `request.url.path`
- `request.url.scheme`
Expand Down Expand Up @@ -83,7 +83,7 @@ async def index(request):
body = await request.body()
```

if you want it parsed as form data or multipart (i.e. file uploads), you can call `request.form()` instead.
if you want it parsed as form-data or multipart (i.e. file uploads), you can call `request.form()` instead.

```python
@app.routes("/")
Expand Down Expand Up @@ -133,7 +133,7 @@ While there is a file inside the form, the file will be translated into Yaat's `
- `await upload.seek(0)` will be the beginning of the file.
- `await close()` - to close the file.

For example if pdf document is uploaded from the client, you can access as below.
For example, if pdf document is uploaded from the client, you can access it as below.

```python
form = await request.form()
Expand Down
10 changes: 9 additions & 1 deletion docs/routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,18 @@ You can specify the path parameters using URI templating style.

```python
@app.route("/{post_id}")
async def detail(request, post_id):
async def detail(request, post_id: int):
...
```

Yaat will automatically convert the value it captured in the path when type hinting is defined in parameters. Three convertors are available
- `str` - return a string, and it is also the default when type hinting is not defined.
- `int` - returns an integer.
- `float` - returns a float.

> If it failed to convert the type, it will automatically fall back to `str`.

### Register Routes By Method

You can also register a routing using `add_route` instead of using a decorator.
Expand Down
4 changes: 2 additions & 2 deletions docs/staticfiles.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Static Files

Yaat provides `StaticFiles` to serve files from given directory.
Yaat provides `StaticFiles` to serve files from the given directory.

### StaticFiles

Expand All @@ -23,7 +23,7 @@ app.mount(statics)
### Serving HTML Pages

You can serve in HTML by passing `html` as `True`. When you serve the static file in HTML mode,
it will automatically loads `index.html` for directory if exists.
it will automatically loads `index.html` for a directory if it exists.

```python
statics = StaticFiles(path="/", directory="./static", html=True)
Expand Down
4 changes: 2 additions & 2 deletions docs/templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ Then create a directory `templates` and write `index.html` inside.

### Custom Template Engine

You can also implement/configure your own templating engine.
You can also implement/configure your templating engine.

First you will need to import `BaseTemplate` to override.
First, you will need to import `BaseTemplate` to override.

```python
from yaat.responses import HTMLResponse
Expand Down
14 changes: 7 additions & 7 deletions docs/websockets.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# WebSockets

Yaat also supports sending and receiving data on a websocket.
Yaat also supports sending and receiving data on a WebSocket.

### WebSocket

`WebSocket(scope, receive, send)`

It provides an interface to talk with ASGI server. It has similar properties like `Request`.
It provides an interface to talk with the ASGI server. It has similar properties as `Request`.

- `url` - string-like object with all components parsed out from the URL.
- `headers` - returns `Headers` dictionary. You can access the individual value just like accessing a dictionary.
- `query_params` - returns `QueryParams` dictionary. You can access the individual value like a dictionary.

### Accept Connection

You can accept the websocket connection by calling `accept()`.
You can accept the WebSocket connection by calling `accept()`.

`await websocket.accept(subprotocol=None)`

Expand Down Expand Up @@ -88,8 +88,8 @@ class WebSocketCloseEvent:

### WebSocket Route

Yaat also comes with separate decorator to indicates WebSocket endpoints.
When the request comes in, the router will pass `WebSocket` class to the endpoint.
Yaat also comes with a separate decorator to indicates WebSocket endpoints.
When the request comes in, the router will pass the `WebSocket` class to the endpoint.

```python
@app.websocket_route("/ws")
Expand All @@ -104,7 +104,7 @@ You can also register WebSocket endpoints via `add_websocket_route`.
`add_websocket_route(path, handler)`

- `path` - url of the endpoint.
- `handler` - websocket endpoint method.
- `handler` - WebSocket endpoint method.

```python
async def ws_handler(websocket):
Expand All @@ -117,7 +117,7 @@ app.add_websocket_route(ws_handler)

### Mounting WebSocket Routes

If you have to mount WebSocket application, you can just indicates `websocket=True` to `mount()`.
If you have to mount the WebSocket application, you can just indicate `websocket=True` to `mount()`.

```python
app.mount(prefix="ws", router=WebSocketRouter, websocket=True)
Expand Down
66 changes: 34 additions & 32 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,41 @@
from setuptools import setup

VERSION = "0.1.4"
VERSION = "0.1.5"


def get_long_description():
with open("README.md", encoding="utf8") as f:
return f.read()
with open("README.md", encoding="utf8") as f:
return f.read()


setup(
name = 'yaat',
packages = ['yaat', 'yaat.middleware'],
version = VERSION,
license='LGPL',
description = 'Yet another ASGI toolkit',
long_description=get_long_description(),
long_description_content_type="text/markdown",
author = 'Khant',
author_email = 'contact@khant.dev',
url = 'https://github.com/yaat-project/yaat',
download_url = f'https://github.com/yaat-project/yaat/releases/download/v{VERSION}/yaat-{VERSION}.tar.gz',
keywords = ['asynchronous', 'web framework'],
python_requires=">=3.6",
install_requires=[
"aiofiles",
"httpx",
"Jinja2",
"parse",
"python-multipart",
],
classifiers=[
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'Topic :: Software Development :: Build Tools',
'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
],
name="yaat",
packages=["yaat", "yaat.middleware"],
version=VERSION,
license="LGPL",
description="Yet another ASGI toolkit",
long_description=get_long_description(),
long_description_content_type="text/markdown",
author="Khant",
author_email="contact@khant.dev",
url="https://github.com/yaat-project/yaat",
download_url=f"https://github.com/yaat-project/yaat/releases/download/v{VERSION}/yaat-{VERSION}.tar.gz",
keywords=["asynchronous", "web framework"],
python_requires=">=3.6",
install_requires=[
"aiofiles",
"httpx",
"Jinja2",
"parse",
"python-multipart",
],
classifiers=[
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Topic :: Software Development :: Build Tools",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
],
)

0 comments on commit 59f269d

Please sign in to comment.