Improve API docs (#2488)
This commit is contained in:
parent
b59da498cc
commit
aba333bfb6
|
@ -24,7 +24,11 @@ import sanic
|
||||||
|
|
||||||
# -- General configuration ------------------------------------------------
|
# -- General configuration ------------------------------------------------
|
||||||
|
|
||||||
extensions = ["sphinx.ext.autodoc", "m2r2"]
|
extensions = [
|
||||||
|
"sphinx.ext.autodoc",
|
||||||
|
"m2r2",
|
||||||
|
"enum_tools.autoenum",
|
||||||
|
]
|
||||||
|
|
||||||
templates_path = ["_templates"]
|
templates_path = ["_templates"]
|
||||||
|
|
||||||
|
|
|
@ -15,3 +15,19 @@ sanic.config
|
||||||
.. automodule:: sanic.config
|
.. automodule:: sanic.config
|
||||||
:members:
|
:members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
sanic.application.constants
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
.. automodule:: sanic.application.constants
|
||||||
|
:exclude-members: StrEnum
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
||||||
|
:inherited-members:
|
||||||
|
|
||||||
|
sanic.application.state
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
.. automodule:: sanic.application.state
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
|
@ -17,6 +17,14 @@ sanic.handlers
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
|
||||||
|
sanic.headers
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. automodule:: sanic.headers
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
|
||||||
sanic.request
|
sanic.request
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,3 @@ sanic.server
|
||||||
:members:
|
:members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
|
||||||
sanic.worker
|
|
||||||
------------
|
|
||||||
|
|
||||||
.. automodule:: sanic.worker
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ profile = "black"
|
||||||
|
|
||||||
[[tool.mypy.overrides]]
|
[[tool.mypy.overrides]]
|
||||||
module = [
|
module = [
|
||||||
|
"httptools.*",
|
||||||
"trustme.*",
|
"trustme.*",
|
||||||
"sanic_routing.*",
|
"sanic_routing.*",
|
||||||
]
|
]
|
||||||
|
|
|
@ -1369,7 +1369,10 @@ class Sanic(BaseSanic, RunnerMixin, metaclass=TouchUpMeta):
|
||||||
self.config.AUTO_RELOAD = value
|
self.config.AUTO_RELOAD = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self) -> ApplicationState: # type: ignore
|
||||||
|
"""
|
||||||
|
:return: The application state
|
||||||
|
"""
|
||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from .constants import Stage
|
from .constants import Stage
|
||||||
from .http1 import Http
|
from .http1 import Http
|
||||||
|
from .http3 import Http3
|
||||||
|
|
||||||
|
|
||||||
__all__ = ("Http", "Stage")
|
__all__ = ("Http", "Stage", "Http3")
|
||||||
|
|
|
@ -30,7 +30,7 @@ HTTP_CONTINUE = b"HTTP/1.1 100 Continue\r\n\r\n"
|
||||||
|
|
||||||
class Http(Stream, metaclass=TouchUpMeta):
|
class Http(Stream, metaclass=TouchUpMeta):
|
||||||
"""
|
"""
|
||||||
Internal helper for managing the HTTP request/response cycle
|
Internal helper for managing the HTTP/1.1 request/response cycle
|
||||||
|
|
||||||
:raises ServerError:
|
:raises ServerError:
|
||||||
:raises PayloadTooLarge:
|
:raises PayloadTooLarge:
|
||||||
|
|
|
@ -265,6 +265,10 @@ class WebTransportReceiver(Receiver): # noqa
|
||||||
|
|
||||||
|
|
||||||
class Http3:
|
class Http3:
|
||||||
|
"""
|
||||||
|
Internal helper for managing the HTTP/3 request/response cycle
|
||||||
|
"""
|
||||||
|
|
||||||
HANDLER_PROPERTY_MAPPING = {
|
HANDLER_PROPERTY_MAPPING = {
|
||||||
DataReceived: "stream_id",
|
DataReceived: "stream_id",
|
||||||
HeadersReceived: "stream_id",
|
HeadersReceived: "stream_id",
|
||||||
|
|
|
@ -57,6 +57,9 @@ LOGGING_CONFIG_DEFAULTS: Dict[str, Any] = dict( # no cov
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
"""
|
||||||
|
Defult logging configuration
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Colors(str, Enum): # no cov
|
class Colors(str, Enum): # no cov
|
||||||
|
@ -80,22 +83,22 @@ class VerbosityFilter(logging.Filter):
|
||||||
_verbosity_filter = VerbosityFilter()
|
_verbosity_filter = VerbosityFilter()
|
||||||
|
|
||||||
logger = logging.getLogger("sanic.root") # no cov
|
logger = logging.getLogger("sanic.root") # no cov
|
||||||
logger.addFilter(_verbosity_filter)
|
|
||||||
"""
|
"""
|
||||||
General Sanic logger
|
General Sanic logger
|
||||||
"""
|
"""
|
||||||
|
logger.addFilter(_verbosity_filter)
|
||||||
|
|
||||||
error_logger = logging.getLogger("sanic.error") # no cov
|
error_logger = logging.getLogger("sanic.error") # no cov
|
||||||
error_logger.addFilter(_verbosity_filter)
|
|
||||||
"""
|
"""
|
||||||
Logger used by Sanic for error logging
|
Logger used by Sanic for error logging
|
||||||
"""
|
"""
|
||||||
|
error_logger.addFilter(_verbosity_filter)
|
||||||
|
|
||||||
access_logger = logging.getLogger("sanic.access") # no cov
|
access_logger = logging.getLogger("sanic.access") # no cov
|
||||||
access_logger.addFilter(_verbosity_filter)
|
|
||||||
"""
|
"""
|
||||||
Logger used by Sanic for access logging
|
Logger used by Sanic for access logging
|
||||||
"""
|
"""
|
||||||
|
access_logger.addFilter(_verbosity_filter)
|
||||||
|
|
||||||
|
|
||||||
def deprecation(message: str, version: float): # no cov
|
def deprecation(message: str, version: float): # no cov
|
||||||
|
|
116
sanic/request.py
116
sanic/request.py
|
@ -34,12 +34,12 @@ from http.cookies import SimpleCookie
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
from urllib.parse import parse_qs, parse_qsl, unquote, urlunparse
|
from urllib.parse import parse_qs, parse_qsl, unquote, urlunparse
|
||||||
|
|
||||||
from httptools import parse_url # type: ignore
|
from httptools import parse_url
|
||||||
from httptools.parser.errors import HttpParserInvalidURLError # type: ignore
|
from httptools.parser.errors import HttpParserInvalidURLError
|
||||||
|
|
||||||
from sanic.compat import CancelledErrors, Header
|
from sanic.compat import CancelledErrors, Header
|
||||||
from sanic.constants import DEFAULT_HTTP_CONTENT_TYPE
|
from sanic.constants import DEFAULT_HTTP_CONTENT_TYPE
|
||||||
from sanic.exceptions import BadRequest, BadURL, SanicException, ServerError
|
from sanic.exceptions import BadRequest, BadURL, ServerError
|
||||||
from sanic.headers import (
|
from sanic.headers import (
|
||||||
AcceptContainer,
|
AcceptContainer,
|
||||||
Options,
|
Options,
|
||||||
|
@ -186,9 +186,27 @@ class Request:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_current(cls) -> Request:
|
def get_current(cls) -> Request:
|
||||||
|
"""
|
||||||
|
Retrieve the currrent request object
|
||||||
|
|
||||||
|
This implements `Context Variables
|
||||||
|
<https://docs.python.org/3/library/contextvars.html>`_
|
||||||
|
to allow for accessing the current request from anywhere.
|
||||||
|
|
||||||
|
Raises :exc:`sanic.exceptions.ServerError` if it is outside of
|
||||||
|
a request lifecycle.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from sanic import Request
|
||||||
|
|
||||||
|
current_request = Request.get_current()
|
||||||
|
|
||||||
|
:return: the current :class:`sanic.request.Request`
|
||||||
|
"""
|
||||||
request = cls._current.get(None)
|
request = cls._current.get(None)
|
||||||
if not request:
|
if not request:
|
||||||
raise SanicException("No current request")
|
raise ServerError("No current request")
|
||||||
return request
|
return request
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -197,6 +215,12 @@ class Request:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def stream_id(self):
|
def stream_id(self):
|
||||||
|
"""
|
||||||
|
Access the HTTP/3 stream ID.
|
||||||
|
|
||||||
|
Raises :exc:`sanic.exceptions.ServerError` if it is not an
|
||||||
|
HTTP/3 request.
|
||||||
|
"""
|
||||||
if self.protocol.version is not HTTP.VERSION_3:
|
if self.protocol.version is not HTTP.VERSION_3:
|
||||||
raise ServerError(
|
raise ServerError(
|
||||||
"Stream ID is only a property of a HTTP/3 request"
|
"Stream ID is only a property of a HTTP/3 request"
|
||||||
|
@ -319,7 +343,19 @@ class Request:
|
||||||
self.body = b"".join([data async for data in self.stream])
|
self.body = b"".join([data async for data in self.stream])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
The route name
|
||||||
|
|
||||||
|
In the following pattern:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
<AppName>.[<BlueprintName>.]<HandlerName>
|
||||||
|
|
||||||
|
:return: Route name
|
||||||
|
:rtype: Optional[str]
|
||||||
|
"""
|
||||||
if self._name:
|
if self._name:
|
||||||
return self._name
|
return self._name
|
||||||
elif self.route:
|
elif self.route:
|
||||||
|
@ -327,26 +363,47 @@ class Request:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def endpoint(self):
|
def endpoint(self) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
:return: Alias of :attr:`sanic.request.Request.name`
|
||||||
|
:rtype: Optional[str]
|
||||||
|
"""
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def uri_template(self):
|
def uri_template(self) -> Optional[str]:
|
||||||
return f"/{self.route.path}"
|
"""
|
||||||
|
:return: The defined URI template
|
||||||
|
:rtype: Optional[str]
|
||||||
|
"""
|
||||||
|
if self.route:
|
||||||
|
return f"/{self.route.path}"
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def protocol(self):
|
def protocol(self):
|
||||||
|
"""
|
||||||
|
:return: The HTTP protocol instance
|
||||||
|
"""
|
||||||
if not self._protocol:
|
if not self._protocol:
|
||||||
self._protocol = self.transport.get_protocol()
|
self._protocol = self.transport.get_protocol()
|
||||||
return self._protocol
|
return self._protocol
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def raw_headers(self):
|
def raw_headers(self) -> bytes:
|
||||||
|
"""
|
||||||
|
:return: The unparsed HTTP headers
|
||||||
|
:rtype: bytes
|
||||||
|
"""
|
||||||
_, headers = self.head.split(b"\r\n", 1)
|
_, headers = self.head.split(b"\r\n", 1)
|
||||||
return bytes(headers)
|
return bytes(headers)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def request_line(self):
|
def request_line(self) -> bytes:
|
||||||
|
"""
|
||||||
|
:return: The first line of a HTTP request
|
||||||
|
:rtype: bytes
|
||||||
|
"""
|
||||||
reqline, _ = self.head.split(b"\r\n", 1)
|
reqline, _ = self.head.split(b"\r\n", 1)
|
||||||
return bytes(reqline)
|
return bytes(reqline)
|
||||||
|
|
||||||
|
@ -395,7 +452,11 @@ class Request:
|
||||||
return self._id # type: ignore
|
return self._id # type: ignore
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def json(self):
|
def json(self) -> Any:
|
||||||
|
"""
|
||||||
|
:return: The request body parsed as JSON
|
||||||
|
:rtype: Any
|
||||||
|
"""
|
||||||
if self.parsed_json is None:
|
if self.parsed_json is None:
|
||||||
self.load_json()
|
self.load_json()
|
||||||
|
|
||||||
|
@ -413,6 +474,10 @@ class Request:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def accept(self) -> AcceptContainer:
|
def accept(self) -> AcceptContainer:
|
||||||
|
"""
|
||||||
|
:return: The ``Accept`` header parsed
|
||||||
|
:rtype: AcceptContainer
|
||||||
|
"""
|
||||||
if self.parsed_accept is None:
|
if self.parsed_accept is None:
|
||||||
accept_header = self.headers.getone("accept", "")
|
accept_header = self.headers.getone("accept", "")
|
||||||
self.parsed_accept = parse_accept(accept_header)
|
self.parsed_accept = parse_accept(accept_header)
|
||||||
|
@ -458,6 +523,15 @@ class Request:
|
||||||
def get_form(
|
def get_form(
|
||||||
self, keep_blank_values: bool = False
|
self, keep_blank_values: bool = False
|
||||||
) -> Optional[RequestParameters]:
|
) -> Optional[RequestParameters]:
|
||||||
|
"""
|
||||||
|
Method to extract and parse the form data from a request.
|
||||||
|
|
||||||
|
:param keep_blank_values:
|
||||||
|
Whether to discard blank values from the form data
|
||||||
|
:type keep_blank_values: bool
|
||||||
|
:return: the parsed form data
|
||||||
|
:rtype: Optional[RequestParameters]
|
||||||
|
"""
|
||||||
self.parsed_form = RequestParameters()
|
self.parsed_form = RequestParameters()
|
||||||
self.parsed_files = RequestParameters()
|
self.parsed_files = RequestParameters()
|
||||||
content_type = self.headers.getone(
|
content_type = self.headers.getone(
|
||||||
|
@ -487,6 +561,9 @@ class Request:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def form(self):
|
def form(self):
|
||||||
|
"""
|
||||||
|
:return: The request body parsed as form data
|
||||||
|
"""
|
||||||
if self.parsed_form is None:
|
if self.parsed_form is None:
|
||||||
self.get_form()
|
self.get_form()
|
||||||
|
|
||||||
|
@ -494,6 +571,9 @@ class Request:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def files(self):
|
def files(self):
|
||||||
|
"""
|
||||||
|
:return: The request body parsed as uploaded files
|
||||||
|
"""
|
||||||
if self.parsed_files is None:
|
if self.parsed_files is None:
|
||||||
self.form # compute form to get files
|
self.form # compute form to get files
|
||||||
|
|
||||||
|
@ -507,8 +587,8 @@ class Request:
|
||||||
errors: str = "replace",
|
errors: str = "replace",
|
||||||
) -> RequestParameters:
|
) -> RequestParameters:
|
||||||
"""
|
"""
|
||||||
Method to parse `query_string` using `urllib.parse.parse_qs`.
|
Method to parse ``query_string`` using ``urllib.parse.parse_qs``.
|
||||||
This methods is used by `args` property.
|
This methods is used by ``args`` property.
|
||||||
Can be used directly if you need to change default parameters.
|
Can be used directly if you need to change default parameters.
|
||||||
|
|
||||||
:param keep_blank_values:
|
:param keep_blank_values:
|
||||||
|
@ -557,6 +637,10 @@ class Request:
|
||||||
]
|
]
|
||||||
|
|
||||||
args = property(get_args)
|
args = property(get_args)
|
||||||
|
"""
|
||||||
|
Convenience property to access :meth:`Request.get_args` with
|
||||||
|
default values.
|
||||||
|
"""
|
||||||
|
|
||||||
def get_query_args(
|
def get_query_args(
|
||||||
self,
|
self,
|
||||||
|
@ -676,6 +760,9 @@ class Request:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def socket(self):
|
def socket(self):
|
||||||
|
"""
|
||||||
|
:return: Information about the connected socket if available
|
||||||
|
"""
|
||||||
return self.conn_info.peername if self.conn_info else (None, None)
|
return self.conn_info.peername if self.conn_info else (None, None)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -688,6 +775,9 @@ class Request:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def network_paths(self):
|
def network_paths(self):
|
||||||
|
"""
|
||||||
|
Access the network paths if available
|
||||||
|
"""
|
||||||
return self.conn_info.network_paths
|
return self.conn_info.network_paths
|
||||||
|
|
||||||
# Proxy properties (using SERVER_NAME/forwarded/request/transport info)
|
# Proxy properties (using SERVER_NAME/forwarded/request/transport info)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user