Merge branch 'main' of github.com:sanic-org/sanic into feat/optional-uvloop-use
This commit is contained in:
commit
796892de52
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@ -5,11 +5,13 @@ on:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
schedule:
|
||||
- cron: '25 16 * * 0'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
if: github.event.pull_request.draft == false
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
27
.github/workflows/coverage.yml
vendored
27
.github/workflows/coverage.yml
vendored
@ -1,19 +1,20 @@
|
||||
name: Coverage check
|
||||
# on:
|
||||
# push:
|
||||
# branches:
|
||||
# - main
|
||||
# tags:
|
||||
# - "!*" # Do not execute on tags
|
||||
# paths:
|
||||
# - sanic/*
|
||||
# - tests/*
|
||||
# pull_request:
|
||||
# paths:
|
||||
# - "!*.MD"
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
tags:
|
||||
- "!*" # Do not execute on tags
|
||||
paths:
|
||||
- sanic/*
|
||||
- tests/*
|
||||
pull_request:
|
||||
paths:
|
||||
- "!*.MD"
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
jobs:
|
||||
test:
|
||||
if: github.event.pull_request.draft == false
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
|
2
.github/workflows/pr-bandit.yml
vendored
2
.github/workflows/pr-bandit.yml
vendored
@ -3,9 +3,11 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
bandit:
|
||||
if: github.event.pull_request.draft == false
|
||||
name: type-check-${{ matrix.config.python-version }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
|
2
.github/workflows/pr-docs.yml
vendored
2
.github/workflows/pr-docs.yml
vendored
@ -3,9 +3,11 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
docsLinter:
|
||||
if: github.event.pull_request.draft == false
|
||||
name: Lint Documentation
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
|
2
.github/workflows/pr-linter.yml
vendored
2
.github/workflows/pr-linter.yml
vendored
@ -3,9 +3,11 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
linter:
|
||||
if: github.event.pull_request.draft == false
|
||||
name: lint
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
|
10
.github/workflows/pr-python310.yml
vendored
10
.github/workflows/pr-python310.yml
vendored
@ -3,15 +3,11 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- sanic/*
|
||||
- tests/*
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
testPy39:
|
||||
testPy310:
|
||||
if: github.event.pull_request.draft == false
|
||||
name: ut-${{ matrix.config.tox-env }}-${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
|
8
.github/workflows/pr-python37.yml
vendored
8
.github/workflows/pr-python37.yml
vendored
@ -3,15 +3,11 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- sanic/*
|
||||
- tests/*
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
testPy37:
|
||||
if: github.event.pull_request.draft == false
|
||||
name: ut-${{ matrix.config.tox-env }}-${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
|
8
.github/workflows/pr-python38.yml
vendored
8
.github/workflows/pr-python38.yml
vendored
@ -3,15 +3,11 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- sanic/*
|
||||
- tests/*
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
testPy38:
|
||||
if: github.event.pull_request.draft == false
|
||||
name: ut-${{ matrix.config.tox-env }}-${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
|
8
.github/workflows/pr-python39.yml
vendored
8
.github/workflows/pr-python39.yml
vendored
@ -3,15 +3,11 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- sanic/*
|
||||
- tests/*
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
testPy39:
|
||||
if: github.event.pull_request.draft == false
|
||||
name: ut-${{ matrix.config.tox-env }}-${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
|
2
.github/workflows/pr-type-check.yml
vendored
2
.github/workflows/pr-type-check.yml
vendored
@ -3,9 +3,11 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
typeChecking:
|
||||
if: github.event.pull_request.draft == false
|
||||
name: type-check-${{ matrix.config.python-version }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
|
2
.github/workflows/pr-windows.yml
vendored
2
.github/workflows/pr-windows.yml
vendored
@ -3,9 +3,11 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
testsOnWindows:
|
||||
if: github.event.pull_request.draft == false
|
||||
name: ut-${{ matrix.config.tox-env }}
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
|
@ -657,7 +657,7 @@ Improved Documentation
|
||||
Version 20.6.0
|
||||
---------------
|
||||
|
||||
*Released, but unintentionally ommitting PR #1880, so was replaced by 20.6.1*
|
||||
*Released, but unintentionally omitting PR #1880, so was replaced by 20.6.1*
|
||||
|
||||
|
||||
Version 20.3.0
|
||||
@ -1090,7 +1090,7 @@ Version 18.12
|
||||
* Fix Range header handling for static files (#1402)
|
||||
* Fix the logger and make it work (#1397)
|
||||
* Fix type pikcle->pickle in multiprocessing test
|
||||
* Fix pickling blueprints Change the string passed in the "name" section of the namedtuples in Blueprint to match the name of the Blueprint module attribute name. This allows blueprints to be pickled and unpickled, without errors, which is a requirment of running Sanic in multiprocessing mode in Windows. Added a test for pickling and unpickling blueprints Added a test for pickling and unpickling sanic itself Added a test for enabling multiprocessing on an app with a blueprint (only useful to catch this bug if the tests are run on Windows).
|
||||
* Fix pickling blueprints Change the string passed in the "name" section of the namedtuples in Blueprint to match the name of the Blueprint module attribute name. This allows blueprints to be pickled and unpickled, without errors, which is a requirement of running Sanic in multiprocessing mode in Windows. Added a test for pickling and unpickling blueprints Added a test for pickling and unpickling sanic itself Added a test for enabling multiprocessing on an app with a blueprint (only useful to catch this bug if the tests are run on Windows).
|
||||
* Fix document for logging
|
||||
|
||||
Version 0.8
|
||||
@ -1129,7 +1129,7 @@ Version 0.8
|
||||
* Content-length header on 204/304 responses (Arnulfo Solís)
|
||||
* Extend WebSocketProtocol arguments and add docs (Bob Olde Hampsink, yunstanford)
|
||||
* Update development status from pre-alpha to beta (Maksim Anisenkov)
|
||||
* KeepAlive Timout log level changed to debug (Arnulfo Solís)
|
||||
* KeepAlive Timeout log level changed to debug (Arnulfo Solís)
|
||||
* Pin pytest to 3.3.2 because of pytest-dev/pytest#3170 (Maksim Aniskenov)
|
||||
* Install Python 3.5 and 3.6 on docker container for tests (Shahin Azad)
|
||||
* Add support for blueprint groups and nesting (Elias Tarhini)
|
||||
|
@ -11,7 +11,7 @@ Sanic | Build fast. Run fast.
|
||||
:stub-columns: 1
|
||||
|
||||
* - Build
|
||||
- | |Py39Test| |Py38Test| |Py37Test| |Codecov|
|
||||
- | |Py39Test| |Py38Test| |Py37Test|
|
||||
* - Docs
|
||||
- | |UserGuide| |Documentation|
|
||||
* - Package
|
||||
@ -27,8 +27,6 @@ Sanic | Build fast. Run fast.
|
||||
:target: https://community.sanicframework.org/
|
||||
.. |Discord| image:: https://img.shields.io/discord/812221182594121728?logo=discord
|
||||
:target: https://discord.gg/FARQzAEMAA
|
||||
.. |Codecov| image:: https://codecov.io/gh/sanic-org/sanic/branch/master/graph/badge.svg
|
||||
:target: https://codecov.io/gh/sanic-org/sanic
|
||||
.. |Py39Test| image:: https://github.com/sanic-org/sanic/actions/workflows/pr-python39.yml/badge.svg?branch=main
|
||||
:target: https://github.com/sanic-org/sanic/actions/workflows/pr-python39.yml
|
||||
.. |Py38Test| image:: https://github.com/sanic-org/sanic/actions/workflows/pr-python38.yml/badge.svg?branch=main
|
||||
|
@ -4,12 +4,14 @@ import asyncio
|
||||
|
||||
from sanic import Sanic
|
||||
|
||||
app = Sanic()
|
||||
|
||||
app = Sanic(__name__)
|
||||
|
||||
|
||||
async def notify_server_started_after_five_seconds():
|
||||
await asyncio.sleep(5)
|
||||
print('Server successfully started!')
|
||||
print("Server successfully started!")
|
||||
|
||||
|
||||
app.add_task(notify_server_started_after_five_seconds())
|
||||
|
||||
|
@ -1,30 +1,29 @@
|
||||
from sanic import Sanic
|
||||
from sanic.response import text
|
||||
from random import randint
|
||||
|
||||
app = Sanic()
|
||||
from sanic import Sanic
|
||||
from sanic.response import text
|
||||
|
||||
|
||||
@app.middleware('request')
|
||||
app = Sanic(__name__)
|
||||
|
||||
|
||||
@app.middleware("request")
|
||||
def append_request(request):
|
||||
# Add new key with random value
|
||||
request['num'] = randint(0, 100)
|
||||
request.ctx.num = randint(0, 100)
|
||||
|
||||
|
||||
@app.get('/pop')
|
||||
@app.get("/pop")
|
||||
def pop_handler(request):
|
||||
# Pop key from request object
|
||||
num = request.pop('num')
|
||||
return text(num)
|
||||
return text(request.ctx.num)
|
||||
|
||||
|
||||
@app.get('/key_exist')
|
||||
@app.get("/key_exist")
|
||||
def key_exist_handler(request):
|
||||
# Check the key is exist or not
|
||||
if 'num' in request:
|
||||
return text('num exist in request')
|
||||
if hasattr(request.ctx, "num"):
|
||||
return text("num exist in request")
|
||||
|
||||
return text('num does not exist in reqeust')
|
||||
return text("num does not exist in request")
|
||||
|
||||
|
||||
app.run(host="0.0.0.0", port=8000, debug=True)
|
||||
|
@ -1,10 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from sanic import Sanic
|
||||
from functools import wraps
|
||||
|
||||
from sanic import Sanic
|
||||
from sanic.response import json
|
||||
|
||||
app = Sanic()
|
||||
|
||||
app = Sanic(__name__)
|
||||
|
||||
|
||||
def check_request_for_authorization_status(request):
|
||||
@ -27,14 +29,16 @@ def authorized(f):
|
||||
return response
|
||||
else:
|
||||
# the user is not authorized.
|
||||
return json({'status': 'not_authorized'}, 403)
|
||||
return json({"status": "not_authorized"}, 403)
|
||||
|
||||
return decorated_function
|
||||
|
||||
|
||||
@app.route("/")
|
||||
@authorized
|
||||
async def test(request):
|
||||
return json({'status': 'authorized'})
|
||||
return json({"status": "authorized"})
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(host="0.0.0.0", port=8000)
|
||||
|
@ -1,43 +1,53 @@
|
||||
from sanic import Sanic, Blueprint
|
||||
from sanic import Blueprint, Sanic
|
||||
from sanic.response import text
|
||||
'''
|
||||
Demonstrates that blueprint request middleware are executed in the order they
|
||||
|
||||
|
||||
"""
|
||||
Demonstrates that blueprint request middleware are executed in the order they
|
||||
are added. And blueprint response middleware are executed in _reverse_ order.
|
||||
On a valid request, it should print "1 2 3 6 5 4" to terminal
|
||||
'''
|
||||
"""
|
||||
|
||||
app = Sanic(__name__)
|
||||
|
||||
bp = Blueprint("bp_"+__name__)
|
||||
bp = Blueprint("bp_" + __name__)
|
||||
|
||||
@bp.middleware('request')
|
||||
|
||||
@bp.on_request
|
||||
def request_middleware_1(request):
|
||||
print('1')
|
||||
print("1")
|
||||
|
||||
@bp.middleware('request')
|
||||
|
||||
@bp.on_request
|
||||
def request_middleware_2(request):
|
||||
print('2')
|
||||
print("2")
|
||||
|
||||
@bp.middleware('request')
|
||||
|
||||
@bp.on_request
|
||||
def request_middleware_3(request):
|
||||
print('3')
|
||||
print("3")
|
||||
|
||||
@bp.middleware('response')
|
||||
|
||||
@bp.on_response
|
||||
def resp_middleware_4(request, response):
|
||||
print('4')
|
||||
print("4")
|
||||
|
||||
@bp.middleware('response')
|
||||
|
||||
@bp.on_response
|
||||
def resp_middleware_5(request, response):
|
||||
print('5')
|
||||
print("5")
|
||||
|
||||
@bp.middleware('response')
|
||||
|
||||
@bp.on_response
|
||||
def resp_middleware_6(request, response):
|
||||
print('6')
|
||||
print("6")
|
||||
|
||||
@bp.route('/')
|
||||
|
||||
@bp.route("/")
|
||||
def pop_handler(request):
|
||||
return text('hello world')
|
||||
return text("hello world")
|
||||
|
||||
app.blueprint(bp, url_prefix='/bp')
|
||||
|
||||
app.blueprint(bp, url_prefix="/bp")
|
||||
|
||||
app.run(host="0.0.0.0", port=8000, debug=True, auto_reload=False)
|
||||
|
@ -1,6 +1,7 @@
|
||||
from sanic import Blueprint, Sanic
|
||||
from sanic.response import file, json
|
||||
|
||||
|
||||
app = Sanic(__name__)
|
||||
blueprint = Blueprint("name", url_prefix="/my_blueprint")
|
||||
blueprint2 = Blueprint("name2", url_prefix="/my_blueprint2")
|
||||
|
@ -2,17 +2,20 @@ from asyncio import sleep
|
||||
|
||||
from sanic import Sanic, response
|
||||
|
||||
|
||||
app = Sanic(__name__, strict_slashes=True)
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def handler(request):
|
||||
return response.redirect("/sleep/3")
|
||||
|
||||
|
||||
@app.get("/sleep/<t:number>")
|
||||
async def handler2(request, t=0.3):
|
||||
await sleep(t)
|
||||
return response.text(f"Slept {t:.1f} seconds.\n")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
app.run(host="0.0.0.0", port=8000)
|
||||
|
@ -7,8 +7,10 @@ and pass in an instance of it when we create our Sanic instance. Inside this
|
||||
class' default handler, we can do anything including sending exceptions to
|
||||
an external service.
|
||||
"""
|
||||
from sanic.handlers import ErrorHandler
|
||||
from sanic.exceptions import SanicException
|
||||
from sanic.handlers import ErrorHandler
|
||||
|
||||
|
||||
"""
|
||||
Imports and code relevant for our CustomHandler class
|
||||
(Ordinarily this would be in a separate file)
|
||||
@ -16,7 +18,6 @@ Imports and code relevant for our CustomHandler class
|
||||
|
||||
|
||||
class CustomHandler(ErrorHandler):
|
||||
|
||||
def default(self, request, exception):
|
||||
# Here, we have access to the exception object
|
||||
# and can do anything with it (log, send to external service, etc)
|
||||
@ -38,17 +39,17 @@ server's error_handler to an instance of our CustomHandler
|
||||
|
||||
from sanic import Sanic
|
||||
|
||||
app = Sanic(__name__)
|
||||
|
||||
handler = CustomHandler()
|
||||
app.error_handler = handler
|
||||
app = Sanic(__name__, error_handler=handler)
|
||||
|
||||
|
||||
@app.route("/")
|
||||
async def test(request):
|
||||
# Here, something occurs which causes an unexpected exception
|
||||
# This exception will flow to our custom handler.
|
||||
raise SanicException('You Broke It!')
|
||||
raise SanicException("You Broke It!")
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(host="0.0.0.0", port=8000, debug=True)
|
||||
|
@ -1,4 +1,6 @@
|
||||
from sanic import Sanic, response, text
|
||||
from sanic.handlers import ErrorHandler
|
||||
from sanic.server.async_server import AsyncioServer
|
||||
|
||||
|
||||
HTTP_PORT = 9999
|
||||
@ -32,20 +34,40 @@ def proxy(request, path):
|
||||
return response.redirect(url)
|
||||
|
||||
|
||||
@https.listener("main_process_start")
|
||||
@https.main_process_start
|
||||
async def start(app, _):
|
||||
global http
|
||||
app.http_server = await http.create_server(
|
||||
http_server = await http.create_server(
|
||||
port=HTTP_PORT, return_asyncio_server=True
|
||||
)
|
||||
app.http_server.after_start()
|
||||
app.add_task(runner(http, http_server))
|
||||
app.ctx.http_server = http_server
|
||||
app.ctx.http = http
|
||||
|
||||
|
||||
@https.listener("main_process_stop")
|
||||
@https.main_process_stop
|
||||
async def stop(app, _):
|
||||
app.http_server.before_stop()
|
||||
await app.http_server.close()
|
||||
app.http_server.after_stop()
|
||||
await app.ctx.http_server.before_stop()
|
||||
await app.ctx.http_server.close()
|
||||
for connection in app.ctx.http_server.connections:
|
||||
connection.close_if_idle()
|
||||
await app.ctx.http_server.after_stop()
|
||||
app.ctx.http = False
|
||||
|
||||
|
||||
async def runner(app: Sanic, app_server: AsyncioServer):
|
||||
app.is_running = True
|
||||
try:
|
||||
app.signalize()
|
||||
app.finalize()
|
||||
ErrorHandler.finalize(app.error_handler)
|
||||
app_server.init = True
|
||||
|
||||
await app_server.before_start()
|
||||
await app_server.after_start()
|
||||
await app_server.serve_forever()
|
||||
finally:
|
||||
app.is_running = False
|
||||
app.is_stopping = True
|
||||
|
||||
|
||||
https.run(port=HTTPS_PORT, debug=True)
|
||||
|
@ -1,26 +1,30 @@
|
||||
import asyncio
|
||||
|
||||
import httpx
|
||||
|
||||
from sanic import Sanic
|
||||
from sanic.response import json
|
||||
|
||||
import asyncio
|
||||
import aiohttp
|
||||
|
||||
app = Sanic(__name__)
|
||||
|
||||
sem = None
|
||||
|
||||
|
||||
@app.listener('before_server_start')
|
||||
def init(sanic, loop):
|
||||
@app.before_server_start
|
||||
def init(sanic, _):
|
||||
global sem
|
||||
concurrency_per_worker = 4
|
||||
sem = asyncio.Semaphore(concurrency_per_worker, loop=loop)
|
||||
sem = asyncio.Semaphore(concurrency_per_worker)
|
||||
|
||||
|
||||
async def bounded_fetch(session, url):
|
||||
"""
|
||||
Use session object to perform 'get' request on url
|
||||
"""
|
||||
async with sem, session.get(url) as response:
|
||||
return await response.json()
|
||||
async with sem:
|
||||
response = await session.get(url)
|
||||
return response.json()
|
||||
|
||||
|
||||
@app.route("/")
|
||||
@ -28,9 +32,9 @@ async def test(request):
|
||||
"""
|
||||
Download and serve example JSON
|
||||
"""
|
||||
url = "https://api.github.com/repos/channelcat/sanic"
|
||||
url = "https://api.github.com/repos/sanic-org/sanic"
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with httpx.AsyncClient() as session:
|
||||
response = await bounded_fetch(session, url)
|
||||
return json(response)
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import logging
|
||||
|
||||
import aiotask_context as context
|
||||
from contextvars import ContextVar
|
||||
|
||||
from sanic import Sanic, response
|
||||
|
||||
@ -11,8 +11,8 @@ log = logging.getLogger(__name__)
|
||||
class RequestIdFilter(logging.Filter):
|
||||
def filter(self, record):
|
||||
try:
|
||||
record.request_id = context.get("X-Request-ID")
|
||||
except ValueError:
|
||||
record.request_id = app.ctx.request_id.get(None) or "n/a"
|
||||
except AttributeError:
|
||||
record.request_id = "n/a"
|
||||
return True
|
||||
|
||||
@ -49,8 +49,7 @@ app = Sanic(__name__, log_config=LOG_SETTINGS)
|
||||
|
||||
@app.on_request
|
||||
async def set_request_id(request):
|
||||
request_id = request.id
|
||||
context.set("X-Request-ID", request_id)
|
||||
request.app.ctx.request_id.set(request.id)
|
||||
log.info(f"Setting {request.id=}")
|
||||
|
||||
|
||||
@ -61,14 +60,14 @@ async def set_request_header(request, response):
|
||||
|
||||
@app.route("/")
|
||||
async def test(request):
|
||||
log.debug("X-Request-ID: %s", context.get("X-Request-ID"))
|
||||
log.debug("X-Request-ID: %s", request.id)
|
||||
log.info("Hello from test!")
|
||||
return response.json({"test": True})
|
||||
|
||||
|
||||
@app.before_server_start
|
||||
def setup(app, loop):
|
||||
loop.set_task_factory(context.task_factory)
|
||||
app.ctx.request_id = ContextVar("request_id")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -1,5 +1,6 @@
|
||||
import logging
|
||||
import socket
|
||||
|
||||
from os import getenv
|
||||
from platform import node
|
||||
from uuid import getnode as get_mac
|
||||
@ -7,10 +8,11 @@ from uuid import getnode as get_mac
|
||||
from logdna import LogDNAHandler
|
||||
|
||||
from sanic import Sanic
|
||||
from sanic.response import json
|
||||
from sanic.request import Request
|
||||
from sanic.response import json
|
||||
|
||||
log = logging.getLogger('logdna')
|
||||
|
||||
log = logging.getLogger("logdna")
|
||||
log.setLevel(logging.INFO)
|
||||
|
||||
|
||||
@ -30,10 +32,12 @@ logdna_options = {
|
||||
"index_meta": True,
|
||||
"hostname": node(),
|
||||
"ip": get_my_ip_address(),
|
||||
"mac": get_mac_address()
|
||||
"mac": get_mac_address(),
|
||||
}
|
||||
|
||||
logdna_handler = LogDNAHandler(getenv("LOGDNA_API_KEY"), options=logdna_options)
|
||||
logdna_handler = LogDNAHandler(
|
||||
getenv("LOGDNA_API_KEY"), options=logdna_options
|
||||
)
|
||||
|
||||
logdna = logging.getLogger(__name__)
|
||||
logdna.setLevel(logging.INFO)
|
||||
@ -49,13 +53,8 @@ def log_request(request: Request):
|
||||
|
||||
@app.route("/")
|
||||
def default(request):
|
||||
return json({
|
||||
"response": "I was here"
|
||||
})
|
||||
return json({"response": "I was here"})
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(
|
||||
host="0.0.0.0",
|
||||
port=getenv("PORT", 8080)
|
||||
)
|
||||
app.run(host="0.0.0.0", port=getenv("PORT", 8080))
|
||||
|
@ -59,31 +59,31 @@ async def handler_stream(request):
|
||||
return response.stream(body)
|
||||
|
||||
|
||||
@app.listener("before_server_start")
|
||||
@app.before_server_start
|
||||
async def listener_before_server_start(*args, **kwargs):
|
||||
print("before_server_start")
|
||||
|
||||
|
||||
@app.listener("after_server_start")
|
||||
@app.after_server_start
|
||||
async def listener_after_server_start(*args, **kwargs):
|
||||
print("after_server_start")
|
||||
|
||||
|
||||
@app.listener("before_server_stop")
|
||||
@app.before_server_stop
|
||||
async def listener_before_server_stop(*args, **kwargs):
|
||||
print("before_server_stop")
|
||||
|
||||
|
||||
@app.listener("after_server_stop")
|
||||
@app.after_server_stop
|
||||
async def listener_after_server_stop(*args, **kwargs):
|
||||
print("after_server_stop")
|
||||
|
||||
|
||||
@app.middleware("request")
|
||||
@app.on_request
|
||||
async def print_on_request(request):
|
||||
print("print_on_request")
|
||||
|
||||
|
||||
@app.middleware("response")
|
||||
@app.on_response
|
||||
async def print_on_response(request, response):
|
||||
print("print_on_response")
|
||||
|
@ -1,9 +1,12 @@
|
||||
from sanic import Sanic
|
||||
from sanic import response
|
||||
from signal import signal, SIGINT
|
||||
import asyncio
|
||||
|
||||
from signal import SIGINT, signal
|
||||
|
||||
import uvloop
|
||||
|
||||
from sanic import Sanic, response
|
||||
|
||||
|
||||
app = Sanic(__name__)
|
||||
|
||||
|
||||
@ -11,12 +14,18 @@ app = Sanic(__name__)
|
||||
async def test(request):
|
||||
return response.json({"answer": "42"})
|
||||
|
||||
|
||||
asyncio.set_event_loop(uvloop.new_event_loop())
|
||||
server = app.create_server(host="0.0.0.0", port=8000, return_asyncio_server=True)
|
||||
server = app.create_server(
|
||||
host="0.0.0.0", port=8000, return_asyncio_server=True
|
||||
)
|
||||
loop = asyncio.get_event_loop()
|
||||
task = asyncio.ensure_future(server)
|
||||
server = loop.run_until_complete(task)
|
||||
loop.run_until_complete(server.startup())
|
||||
signal(SIGINT, lambda s, f: loop.stop())
|
||||
|
||||
try:
|
||||
loop.run_forever()
|
||||
except:
|
||||
finally:
|
||||
loop.stop()
|
||||
|
@ -11,9 +11,24 @@ from sanic.server import AsyncioServer
|
||||
app = Sanic(__name__)
|
||||
|
||||
|
||||
@app.listener("after_server_start")
|
||||
async def after_start_test(app, loop):
|
||||
print("Async Server Started!")
|
||||
@app.before_server_start
|
||||
async def before_server_start(app, loop):
|
||||
print("Async Server starting")
|
||||
|
||||
|
||||
@app.after_server_start
|
||||
async def after_server_start(app, loop):
|
||||
print("Async Server started")
|
||||
|
||||
|
||||
@app.before_server_stop
|
||||
async def before_server_stop(app, loop):
|
||||
print("Async Server stopping")
|
||||
|
||||
|
||||
@app.after_server_stop
|
||||
async def after_server_stop(app, loop):
|
||||
print("Async Server stopped")
|
||||
|
||||
|
||||
@app.route("/")
|
||||
@ -28,20 +43,20 @@ serv_coro = app.create_server(
|
||||
loop = asyncio.get_event_loop()
|
||||
serv_task = asyncio.ensure_future(serv_coro, loop=loop)
|
||||
signal(SIGINT, lambda s, f: loop.stop())
|
||||
server: AsyncioServer = loop.run_until_complete(serv_task) # type: ignore
|
||||
server.startup()
|
||||
server: AsyncioServer = loop.run_until_complete(serv_task)
|
||||
loop.run_until_complete(server.startup())
|
||||
|
||||
# When using app.run(), this actually triggers before the serv_coro.
|
||||
# But, in this example, we are using the convenience method, even if it is
|
||||
# out of order.
|
||||
server.before_start()
|
||||
server.after_start()
|
||||
loop.run_until_complete(server.before_start())
|
||||
loop.run_until_complete(server.after_start())
|
||||
try:
|
||||
loop.run_forever()
|
||||
except KeyboardInterrupt:
|
||||
loop.stop()
|
||||
finally:
|
||||
server.before_stop()
|
||||
loop.run_until_complete(server.before_stop())
|
||||
|
||||
# Wait for server to close
|
||||
close_task = server.close()
|
||||
@ -50,4 +65,4 @@ finally:
|
||||
# Complete all tasks on the loop
|
||||
for connection in server.connections:
|
||||
connection.close_if_idle()
|
||||
server.after_stop()
|
||||
loop.run_until_complete(server.after_stop())
|
||||
|
@ -1,42 +1,41 @@
|
||||
from sanic import Sanic
|
||||
from sanic.views import HTTPMethodView
|
||||
from sanic.response import text
|
||||
from sanic.views import HTTPMethodView
|
||||
|
||||
app = Sanic('some_name')
|
||||
|
||||
app = Sanic("some_name")
|
||||
|
||||
|
||||
class SimpleView(HTTPMethodView):
|
||||
|
||||
def get(self, request):
|
||||
return text('I am get method')
|
||||
return text("I am get method")
|
||||
|
||||
def post(self, request):
|
||||
return text('I am post method')
|
||||
return text("I am post method")
|
||||
|
||||
def put(self, request):
|
||||
return text('I am put method')
|
||||
return text("I am put method")
|
||||
|
||||
def patch(self, request):
|
||||
return text('I am patch method')
|
||||
return text("I am patch method")
|
||||
|
||||
def delete(self, request):
|
||||
return text('I am delete method')
|
||||
return text("I am delete method")
|
||||
|
||||
|
||||
class SimpleAsyncView(HTTPMethodView):
|
||||
|
||||
async def get(self, request):
|
||||
return text('I am async get method')
|
||||
return text("I am async get method")
|
||||
|
||||
async def post(self, request):
|
||||
return text('I am async post method')
|
||||
return text("I am async post method")
|
||||
|
||||
async def put(self, request):
|
||||
return text('I am async put method')
|
||||
return text("I am async put method")
|
||||
|
||||
|
||||
app.add_route(SimpleView.as_view(), '/')
|
||||
app.add_route(SimpleAsyncView.as_view(), '/async')
|
||||
app.add_route(SimpleView.as_view(), "/")
|
||||
app.add_route(SimpleAsyncView.as_view(), "/async")
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
app.run(host="0.0.0.0", port=8000, debug=True)
|
||||
|
@ -1,9 +1,9 @@
|
||||
import os
|
||||
|
||||
from sanic import Sanic
|
||||
from sanic.log import logger as log
|
||||
from sanic import response
|
||||
from sanic import Sanic, response
|
||||
from sanic.exceptions import ServerError
|
||||
from sanic.log import logger as log
|
||||
|
||||
|
||||
app = Sanic(__name__)
|
||||
|
||||
@ -13,7 +13,7 @@ async def test_async(request):
|
||||
return response.json({"test": True})
|
||||
|
||||
|
||||
@app.route("/sync", methods=['GET', 'POST'])
|
||||
@app.route("/sync", methods=["GET", "POST"])
|
||||
def test_sync(request):
|
||||
return response.json({"test": True})
|
||||
|
||||
@ -31,6 +31,7 @@ def exception(request):
|
||||
@app.route("/await")
|
||||
async def test_await(request):
|
||||
import asyncio
|
||||
|
||||
await asyncio.sleep(5)
|
||||
return response.text("I'm feeling sleepy")
|
||||
|
||||
@ -42,8 +43,10 @@ async def test_file(request):
|
||||
|
||||
@app.route("/file_stream")
|
||||
async def test_file_stream(request):
|
||||
return await response.file_stream(os.path.abspath("setup.py"),
|
||||
chunk_size=1024)
|
||||
return await response.file_stream(
|
||||
os.path.abspath("setup.py"), chunk_size=1024
|
||||
)
|
||||
|
||||
|
||||
# ----------------------------------------------- #
|
||||
# Exceptions
|
||||
@ -52,14 +55,17 @@ async def test_file_stream(request):
|
||||
|
||||
@app.exception(ServerError)
|
||||
async def test(request, exception):
|
||||
return response.json({"exception": "{}".format(exception), "status": exception.status_code},
|
||||
status=exception.status_code)
|
||||
return response.json(
|
||||
{"exception": str(exception), "status": exception.status_code},
|
||||
status=exception.status_code,
|
||||
)
|
||||
|
||||
|
||||
# ----------------------------------------------- #
|
||||
# Read from request
|
||||
# ----------------------------------------------- #
|
||||
|
||||
|
||||
@app.route("/json")
|
||||
def post_json(request):
|
||||
return response.json({"received": True, "message": request.json})
|
||||
@ -67,38 +73,51 @@ def post_json(request):
|
||||
|
||||
@app.route("/form")
|
||||
def post_form_json(request):
|
||||
return response.json({"received": True, "form_data": request.form, "test": request.form.get('test')})
|
||||
return response.json(
|
||||
{
|
||||
"received": True,
|
||||
"form_data": request.form,
|
||||
"test": request.form.get("test"),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@app.route("/query_string")
|
||||
def query_string(request):
|
||||
return response.json({"parsed": True, "args": request.args, "url": request.url,
|
||||
"query_string": request.query_string})
|
||||
return response.json(
|
||||
{
|
||||
"parsed": True,
|
||||
"args": request.args,
|
||||
"url": request.url,
|
||||
"query_string": request.query_string,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
# ----------------------------------------------- #
|
||||
# Run Server
|
||||
# ----------------------------------------------- #
|
||||
|
||||
@app.listener('before_server_start')
|
||||
|
||||
@app.before_server_start
|
||||
def before_start(app, loop):
|
||||
log.info("SERVER STARTING")
|
||||
|
||||
|
||||
@app.listener('after_server_start')
|
||||
@app.after_server_start
|
||||
def after_start(app, loop):
|
||||
log.info("OH OH OH OH OHHHHHHHH")
|
||||
|
||||
|
||||
@app.listener('before_server_stop')
|
||||
@app.before_server_stop
|
||||
def before_stop(app, loop):
|
||||
log.info("SERVER STOPPING")
|
||||
|
||||
|
||||
@app.listener('after_server_stop')
|
||||
@app.after_server_stop
|
||||
def after_stop(app, loop):
|
||||
log.info("TRIED EVERYTHING")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
app.run(host="0.0.0.0", port=8000, debug=True)
|
||||
|
@ -1,7 +1,8 @@
|
||||
from sanic import Sanic
|
||||
from sanic import response
|
||||
import socket
|
||||
import os
|
||||
import socket
|
||||
|
||||
from sanic import Sanic, response
|
||||
|
||||
|
||||
app = Sanic(__name__)
|
||||
|
||||
@ -10,14 +11,15 @@ app = Sanic(__name__)
|
||||
async def test(request):
|
||||
return response.text("OK")
|
||||
|
||||
if __name__ == '__main__':
|
||||
server_address = './uds_socket'
|
||||
|
||||
if __name__ == "__main__":
|
||||
server_address = "./uds_socket"
|
||||
# Make sure the socket does not already exist
|
||||
try:
|
||||
os.unlink(server_address)
|
||||
os.unlink(server_address)
|
||||
except OSError:
|
||||
if os.path.exists(server_address):
|
||||
raise
|
||||
if os.path.exists(server_address):
|
||||
raise
|
||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
sock.bind(server_address)
|
||||
app.run(sock=sock)
|
||||
|
@ -1,20 +1,21 @@
|
||||
from sanic import Sanic
|
||||
from sanic import response
|
||||
from sanic import Sanic, response
|
||||
|
||||
|
||||
app = Sanic(__name__)
|
||||
|
||||
|
||||
@app.route('/')
|
||||
@app.route("/")
|
||||
async def index(request):
|
||||
# generate a URL for the endpoint `post_handler`
|
||||
url = app.url_for('post_handler', post_id=5)
|
||||
url = app.url_for("post_handler", post_id=5)
|
||||
# the URL is `/posts/5`, redirect to it
|
||||
return response.redirect(url)
|
||||
|
||||
|
||||
@app.route('/posts/<post_id>')
|
||||
@app.route("/posts/<post_id>")
|
||||
async def post_handler(request, post_id):
|
||||
return response.text('Post - {}'.format(post_id))
|
||||
|
||||
if __name__ == '__main__':
|
||||
return response.text("Post - {}".format(post_id))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(host="0.0.0.0", port=8000, debug=True)
|
||||
|
@ -8,7 +8,9 @@ app = Sanic(name="blue-print-group-version-example")
|
||||
bp1 = Blueprint(name="ultron", url_prefix="/ultron")
|
||||
bp2 = Blueprint(name="vision", url_prefix="/vision", strict_slashes=None)
|
||||
|
||||
bpg = Blueprint.group([bp1, bp2], url_prefix="/sentient/robot", version=1, strict_slashes=True)
|
||||
bpg = Blueprint.group(
|
||||
bp1, bp2, url_prefix="/sentient/robot", version=1, strict_slashes=True
|
||||
)
|
||||
|
||||
|
||||
@bp1.get("/name")
|
||||
@ -31,5 +33,5 @@ async def bp2_revised_name(request):
|
||||
|
||||
app.blueprint(bpg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
app.run(host="0.0.0.0", port=8000)
|
||||
|
@ -1,25 +1,27 @@
|
||||
from sanic import Sanic
|
||||
from sanic.response import redirect
|
||||
|
||||
|
||||
app = Sanic(__name__)
|
||||
|
||||
|
||||
app.static('index.html', "websocket.html")
|
||||
app.static("index.html", "websocket.html")
|
||||
|
||||
@app.route('/')
|
||||
|
||||
@app.route("/")
|
||||
def index(request):
|
||||
return redirect("index.html")
|
||||
|
||||
@app.websocket('/feed')
|
||||
|
||||
@app.websocket("/feed")
|
||||
async def feed(request, ws):
|
||||
while True:
|
||||
data = 'hello!'
|
||||
print('Sending: ' + data)
|
||||
data = "hello!"
|
||||
print("Sending: " + data)
|
||||
await ws.send(data)
|
||||
data = await ws.recv()
|
||||
print('Received: ' + data)
|
||||
print("Received: " + data)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
app.run(host="0.0.0.0", port=8000, debug=True)
|
||||
|
||||
|
10
sanic/app.py
10
sanic/app.py
@ -337,7 +337,7 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
|
||||
"""
|
||||
Method for attaching middleware to specific routes. This is mainly an
|
||||
internal tool for use by Blueprints to attach middleware to only its
|
||||
specfic routes. But, it could be used in a more generalized fashion.
|
||||
specific routes. But, it could be used in a more generalized fashion.
|
||||
|
||||
:param middleware: the middleware to execute
|
||||
:param route_names: a list of the names of the endpoints
|
||||
@ -775,6 +775,14 @@ class Sanic(BaseSanic, metaclass=TouchUpMeta):
|
||||
if request.stream:
|
||||
response = request.stream.response
|
||||
if isinstance(response, BaseHTTPResponse):
|
||||
await self.dispatch(
|
||||
"http.lifecycle.response",
|
||||
inline=True,
|
||||
context={
|
||||
"request": request,
|
||||
"response": response,
|
||||
},
|
||||
)
|
||||
await response.send(end_stream=True)
|
||||
else:
|
||||
raise ServerError(
|
||||
|
@ -64,8 +64,10 @@ class MOTDTTY(MOTD):
|
||||
self.set_variables()
|
||||
|
||||
def set_variables(self): # no cov
|
||||
fallback = (80, 24)
|
||||
terminal_width = min(get_terminal_size(fallback=fallback).columns, 108)
|
||||
fallback = (108, 24)
|
||||
terminal_width = max(
|
||||
get_terminal_size(fallback=fallback).columns, fallback[0]
|
||||
)
|
||||
self.max_value_width = terminal_width - fallback[0] + 36
|
||||
|
||||
self.key_width = 4
|
||||
|
@ -79,7 +79,7 @@ class Blueprint(BaseSanic):
|
||||
|
||||
:param name: unique name of the blueprint
|
||||
:param url_prefix: URL to be prefixed before all route URLs
|
||||
:param host: IP Address of FQDN for the sanic server to use.
|
||||
:param host: IP Address or FQDN for the sanic server to use.
|
||||
:param version: Blueprint Version
|
||||
:param strict_slashes: Enforce the API urls are requested with a
|
||||
trailing */*
|
||||
@ -112,7 +112,7 @@ class Blueprint(BaseSanic):
|
||||
self,
|
||||
name: str = None,
|
||||
url_prefix: Optional[str] = None,
|
||||
host: Optional[str] = None,
|
||||
host: Optional[Union[List[str], str]] = None,
|
||||
version: Optional[Union[int, str, float]] = None,
|
||||
strict_slashes: Optional[bool] = None,
|
||||
version_prefix: str = "/v",
|
||||
|
@ -176,11 +176,11 @@ class Config(dict):
|
||||
|
||||
def load_environment_vars(self, prefix=SANIC_PREFIX):
|
||||
"""
|
||||
Looks for prefixed environment variables and applies
|
||||
them to the configuration if present. This is called automatically when
|
||||
Sanic starts up to load environment variables into config.
|
||||
Looks for prefixed environment variables and applies them to the
|
||||
configuration if present. This is called automatically when Sanic
|
||||
starts up to load environment variables into config.
|
||||
|
||||
It will automatically hyrdate the following types:
|
||||
It will automatically hydrate the following types:
|
||||
|
||||
- ``int``
|
||||
- ``float``
|
||||
@ -188,19 +188,18 @@ class Config(dict):
|
||||
|
||||
Anything else will be imported as a ``str``.
|
||||
"""
|
||||
for k, v in environ.items():
|
||||
if k.startswith(prefix):
|
||||
_, config_key = k.split(prefix, 1)
|
||||
for key, value in environ.items():
|
||||
if not key.startswith(prefix):
|
||||
continue
|
||||
|
||||
_, config_key = key.split(prefix, 1)
|
||||
|
||||
for converter in (int, float, str_to_bool, str):
|
||||
try:
|
||||
self[config_key] = int(v)
|
||||
self[config_key] = converter(value)
|
||||
break
|
||||
except ValueError:
|
||||
try:
|
||||
self[config_key] = float(v)
|
||||
except ValueError:
|
||||
try:
|
||||
self[config_key] = str_to_bool(v)
|
||||
except ValueError:
|
||||
self[config_key] = v
|
||||
pass
|
||||
|
||||
def update_config(self, config: Union[bytes, str, dict, Any]):
|
||||
"""
|
||||
|
@ -28,7 +28,7 @@ _host_re = re.compile(
|
||||
|
||||
# RFC's quoted-pair escapes are mostly ignored by browsers. Chrome, Firefox and
|
||||
# curl all have different escaping, that we try to handle as well as possible,
|
||||
# even though no client espaces in a way that would allow perfect handling.
|
||||
# even though no client escapes in a way that would allow perfect handling.
|
||||
|
||||
# For more information, consult ../tests/test_requests.py
|
||||
|
||||
|
@ -144,7 +144,7 @@ def import_string(module_name, package=None):
|
||||
import a module or class by string path.
|
||||
|
||||
:module_name: str with path of module or path to import and
|
||||
instanciate a class
|
||||
instantiate a class
|
||||
:returns: a module object or one instance from class if
|
||||
module_name is a valid path to class
|
||||
|
||||
|
@ -52,7 +52,7 @@ class RouteMixin:
|
||||
self,
|
||||
uri: str,
|
||||
methods: Optional[Iterable[str]] = None,
|
||||
host: Optional[str] = None,
|
||||
host: Optional[Union[str, List[str]]] = None,
|
||||
strict_slashes: Optional[bool] = None,
|
||||
stream: bool = False,
|
||||
version: Optional[Union[int, str, float]] = None,
|
||||
@ -189,9 +189,9 @@ class RouteMixin:
|
||||
handler: RouteHandler,
|
||||
uri: str,
|
||||
methods: Iterable[str] = frozenset({"GET"}),
|
||||
host: Optional[str] = None,
|
||||
host: Optional[Union[str, List[str]]] = None,
|
||||
strict_slashes: Optional[bool] = None,
|
||||
version: Optional[int] = None,
|
||||
version: Optional[Union[int, str, float]] = None,
|
||||
name: Optional[str] = None,
|
||||
stream: bool = False,
|
||||
version_prefix: str = "/v",
|
||||
@ -254,9 +254,9 @@ class RouteMixin:
|
||||
def get(
|
||||
self,
|
||||
uri: str,
|
||||
host: Optional[str] = None,
|
||||
host: Optional[Union[str, List[str]]] = None,
|
||||
strict_slashes: Optional[bool] = None,
|
||||
version: Optional[int] = None,
|
||||
version: Optional[Union[int, str, float]] = None,
|
||||
name: Optional[str] = None,
|
||||
ignore_body: bool = True,
|
||||
version_prefix: str = "/v",
|
||||
@ -290,10 +290,10 @@ class RouteMixin:
|
||||
def post(
|
||||
self,
|
||||
uri: str,
|
||||
host: Optional[str] = None,
|
||||
host: Optional[Union[str, List[str]]] = None,
|
||||
strict_slashes: Optional[bool] = None,
|
||||
stream: bool = False,
|
||||
version: Optional[int] = None,
|
||||
version: Optional[Union[int, str, float]] = None,
|
||||
name: Optional[str] = None,
|
||||
version_prefix: str = "/v",
|
||||
error_format: Optional[str] = None,
|
||||
@ -326,10 +326,10 @@ class RouteMixin:
|
||||
def put(
|
||||
self,
|
||||
uri: str,
|
||||
host: Optional[str] = None,
|
||||
host: Optional[Union[str, List[str]]] = None,
|
||||
strict_slashes: Optional[bool] = None,
|
||||
stream: bool = False,
|
||||
version: Optional[int] = None,
|
||||
version: Optional[Union[int, str, float]] = None,
|
||||
name: Optional[str] = None,
|
||||
version_prefix: str = "/v",
|
||||
error_format: Optional[str] = None,
|
||||
@ -362,9 +362,9 @@ class RouteMixin:
|
||||
def head(
|
||||
self,
|
||||
uri: str,
|
||||
host: Optional[str] = None,
|
||||
host: Optional[Union[str, List[str]]] = None,
|
||||
strict_slashes: Optional[bool] = None,
|
||||
version: Optional[int] = None,
|
||||
version: Optional[Union[int, str, float]] = None,
|
||||
name: Optional[str] = None,
|
||||
ignore_body: bool = True,
|
||||
version_prefix: str = "/v",
|
||||
@ -406,9 +406,9 @@ class RouteMixin:
|
||||
def options(
|
||||
self,
|
||||
uri: str,
|
||||
host: Optional[str] = None,
|
||||
host: Optional[Union[str, List[str]]] = None,
|
||||
strict_slashes: Optional[bool] = None,
|
||||
version: Optional[int] = None,
|
||||
version: Optional[Union[int, str, float]] = None,
|
||||
name: Optional[str] = None,
|
||||
ignore_body: bool = True,
|
||||
version_prefix: str = "/v",
|
||||
@ -450,10 +450,10 @@ class RouteMixin:
|
||||
def patch(
|
||||
self,
|
||||
uri: str,
|
||||
host: Optional[str] = None,
|
||||
host: Optional[Union[str, List[str]]] = None,
|
||||
strict_slashes: Optional[bool] = None,
|
||||
stream=False,
|
||||
version: Optional[int] = None,
|
||||
version: Optional[Union[int, str, float]] = None,
|
||||
name: Optional[str] = None,
|
||||
version_prefix: str = "/v",
|
||||
error_format: Optional[str] = None,
|
||||
@ -496,9 +496,9 @@ class RouteMixin:
|
||||
def delete(
|
||||
self,
|
||||
uri: str,
|
||||
host: Optional[str] = None,
|
||||
host: Optional[Union[str, List[str]]] = None,
|
||||
strict_slashes: Optional[bool] = None,
|
||||
version: Optional[int] = None,
|
||||
version: Optional[Union[int, str, float]] = None,
|
||||
name: Optional[str] = None,
|
||||
ignore_body: bool = True,
|
||||
version_prefix: str = "/v",
|
||||
@ -532,10 +532,10 @@ class RouteMixin:
|
||||
def websocket(
|
||||
self,
|
||||
uri: str,
|
||||
host: Optional[str] = None,
|
||||
host: Optional[Union[str, List[str]]] = None,
|
||||
strict_slashes: Optional[bool] = None,
|
||||
subprotocols: Optional[List[str]] = None,
|
||||
version: Optional[int] = None,
|
||||
version: Optional[Union[int, str, float]] = None,
|
||||
name: Optional[str] = None,
|
||||
apply: bool = True,
|
||||
version_prefix: str = "/v",
|
||||
@ -573,10 +573,10 @@ class RouteMixin:
|
||||
self,
|
||||
handler,
|
||||
uri: str,
|
||||
host: Optional[str] = None,
|
||||
host: Optional[Union[str, List[str]]] = None,
|
||||
strict_slashes: Optional[bool] = None,
|
||||
subprotocols=None,
|
||||
version: Optional[int] = None,
|
||||
version: Optional[Union[int, str, float]] = None,
|
||||
name: Optional[str] = None,
|
||||
version_prefix: str = "/v",
|
||||
error_format: Optional[str] = None,
|
||||
|
@ -13,7 +13,7 @@ class FutureRoute(NamedTuple):
|
||||
handler: str
|
||||
uri: str
|
||||
methods: Optional[Iterable[str]]
|
||||
host: str
|
||||
host: Union[str, List[str]]
|
||||
strict_slashes: bool
|
||||
stream: bool
|
||||
version: Optional[int]
|
||||
|
@ -101,7 +101,7 @@ class BaseHTTPResponse:
|
||||
|
||||
async def send(
|
||||
self,
|
||||
data: Optional[Union[AnyStr]] = None,
|
||||
data: Optional[AnyStr] = None,
|
||||
end_stream: Optional[bool] = None,
|
||||
) -> None:
|
||||
"""
|
||||
|
@ -54,7 +54,7 @@ class Router(BaseRouter):
|
||||
self, path: str, method: str, host: Optional[str]
|
||||
) -> Tuple[Route, RouteHandler, Dict[str, Any]]:
|
||||
"""
|
||||
Retrieve a `Route` object containg the details about how to handle
|
||||
Retrieve a `Route` object containing the details about how to handle
|
||||
a response for a given request
|
||||
|
||||
:param request: the incoming request object
|
||||
|
@ -175,7 +175,7 @@ def match_hostname(
|
||||
def selector_sni_callback(
|
||||
sslobj: ssl.SSLObject, server_name: str, ctx: CertSelector
|
||||
) -> Optional[int]:
|
||||
"""Select a certificate mathing the SNI."""
|
||||
"""Select a certificate matching the SNI."""
|
||||
# Call server_name_callback to store the SNI on sslobj
|
||||
server_name_callback(sslobj, server_name, ctx)
|
||||
# Find a new context matching the hostname
|
||||
|
@ -48,7 +48,7 @@ def load_module_from_file_location(
|
||||
"""Returns loaded module provided as a file path.
|
||||
|
||||
:param args:
|
||||
Coresponds to importlib.util.spec_from_file_location location
|
||||
Corresponds to importlib.util.spec_from_file_location location
|
||||
parameters,but with this differences:
|
||||
- It has to be of a string or bytes type.
|
||||
- You can also use here environment variables
|
||||
@ -58,10 +58,10 @@ def load_module_from_file_location(
|
||||
If location parameter is of a bytes type, then use this encoding
|
||||
to decode it into string.
|
||||
:param args:
|
||||
Coresponds to the rest of importlib.util.spec_from_file_location
|
||||
Corresponds to the rest of importlib.util.spec_from_file_location
|
||||
parameters.
|
||||
:param kwargs:
|
||||
Coresponds to the rest of importlib.util.spec_from_file_location
|
||||
Corresponds to the rest of importlib.util.spec_from_file_location
|
||||
parameters.
|
||||
|
||||
For example You can:
|
||||
|
@ -310,7 +310,7 @@ if __name__ == "__main__":
|
||||
cli.add_argument(
|
||||
"--milestone",
|
||||
"-ms",
|
||||
help="Git Release milestone information to include in relase note",
|
||||
help="Git Release milestone information to include in release note",
|
||||
required=False,
|
||||
)
|
||||
cli.add_argument(
|
||||
|
1
setup.py
1
setup.py
@ -121,6 +121,7 @@ docs_require = [
|
||||
"docutils",
|
||||
"pygments",
|
||||
"m2r2",
|
||||
"mistune<2.0.0",
|
||||
]
|
||||
|
||||
dev_require = tests_require + [
|
||||
|
@ -17,7 +17,7 @@ def test_custom_context(app):
|
||||
|
||||
@app.route("/")
|
||||
def handler(request):
|
||||
# Accessing non-existant key should fail with AttributeError
|
||||
# Accessing non-existent key should fail with AttributeError
|
||||
try:
|
||||
invalid = request.ctx.missing
|
||||
except AttributeError as e:
|
||||
|
@ -21,7 +21,7 @@ def gunicorn_worker():
|
||||
"gunicorn "
|
||||
f"--bind 127.0.0.1:{PORT} "
|
||||
"--worker-class sanic.worker.GunicornWorker "
|
||||
"examples.simple_server:app"
|
||||
"examples.hello_world:app"
|
||||
)
|
||||
worker = subprocess.Popen(shlex.split(command))
|
||||
time.sleep(2)
|
||||
@ -35,7 +35,7 @@ def gunicorn_worker_with_access_logs():
|
||||
"gunicorn "
|
||||
f"--bind 127.0.0.1:{PORT + 1} "
|
||||
"--worker-class sanic.worker.GunicornWorker "
|
||||
"examples.simple_server:app"
|
||||
"examples.hello_world:app"
|
||||
)
|
||||
worker = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE)
|
||||
time.sleep(2)
|
||||
@ -50,7 +50,7 @@ def gunicorn_worker_with_env_var():
|
||||
f"--bind 127.0.0.1:{PORT + 2} "
|
||||
"--worker-class sanic.worker.GunicornWorker "
|
||||
"--log-level info "
|
||||
"examples.simple_server:app"
|
||||
"examples.hello_world:app"
|
||||
)
|
||||
worker = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE)
|
||||
time.sleep(2)
|
||||
|
Loading…
x
Reference in New Issue
Block a user