Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
ec35f5f2c8 | ||
|
9ae25e6744 | ||
|
758f10c513 | ||
|
140d27ef96 | ||
|
209840b771 | ||
|
20fd58b8d7 |
|
@ -19,7 +19,7 @@ import sys
|
||||||
root_directory = os.path.dirname(os.getcwd())
|
root_directory = os.path.dirname(os.getcwd())
|
||||||
sys.path.insert(0, root_directory)
|
sys.path.insert(0, root_directory)
|
||||||
|
|
||||||
import sanic
|
import sanic # noqa: E402
|
||||||
|
|
||||||
|
|
||||||
# -- General configuration ------------------------------------------------
|
# -- General configuration ------------------------------------------------
|
||||||
|
|
|
@ -25,5 +25,6 @@ def key_exist_handler(request):
|
||||||
|
|
||||||
return text("num does not exist in request")
|
return text("num does not exist in request")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(host="0.0.0.0", port=8000, debug=True)
|
app.run(host="0.0.0.0", port=8000, debug=True)
|
||||||
|
|
|
@ -69,5 +69,6 @@ async def runner(app: Sanic, app_server: AsyncioServer):
|
||||||
app.is_running = False
|
app.is_running = False
|
||||||
app.is_stopping = True
|
app.is_stopping = True
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
https.run(port=HTTPS_PORT, debug=True)
|
https.run(port=HTTPS_PORT, debug=True)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
|
||||||
# Warning: This is a heavy process.
|
# Warning: This is a heavy process.
|
||||||
|
|
||||||
data = ""
|
data = ""
|
||||||
|
|
|
@ -35,6 +35,7 @@ async def after_server_stop(app, loop):
|
||||||
async def test(request):
|
async def test(request):
|
||||||
return response.json({"answer": "42"})
|
return response.json({"answer": "42"})
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.set_event_loop(uvloop.new_event_loop())
|
asyncio.set_event_loop(uvloop.new_event_loop())
|
||||||
serv_coro = app.create_server(
|
serv_coro = app.create_server(
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from textwrap import indent
|
from textwrap import indent
|
||||||
|
|
||||||
|
|
7
guide/pyproject.toml
Normal file
7
guide/pyproject.toml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[tool.ruff]
|
||||||
|
extend = "../pyproject.toml"
|
||||||
|
|
||||||
|
[tool.ruff.isort]
|
||||||
|
known-first-party = ["webapp"]
|
||||||
|
lines-after-imports = 1
|
||||||
|
lines-between-types = 1
|
|
@ -2,7 +2,6 @@ from __future__ import annotations
|
||||||
|
|
||||||
from html5tagger import Builder, Document # type: ignore
|
from html5tagger import Builder, Document # type: ignore
|
||||||
|
|
||||||
|
|
||||||
class BaseRenderer:
|
class BaseRenderer:
|
||||||
def __init__(self, base_title: str):
|
def __init__(self, base_title: str):
|
||||||
self.base_title = base_title
|
self.base_title = base_title
|
||||||
|
|
|
@ -7,7 +7,6 @@ from pygments.token import ( # Error,; Generic,; Number,; Operator,
|
||||||
Token,
|
Token,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SanicCodeStyle(Style):
|
class SanicCodeStyle(Style):
|
||||||
styles = {
|
styles = {
|
||||||
Token: "#777",
|
Token: "#777",
|
||||||
|
|
|
@ -6,7 +6,6 @@ from typing import Generator
|
||||||
from html5tagger import Builder
|
from html5tagger import Builder
|
||||||
from sanic import Request
|
from sanic import Request
|
||||||
|
|
||||||
|
|
||||||
class BaseLayout:
|
class BaseLayout:
|
||||||
def __init__(self, builder: Builder):
|
def __init__(self, builder: Builder):
|
||||||
self.builder = builder
|
self.builder = builder
|
||||||
|
|
|
@ -3,7 +3,6 @@ from datetime import datetime
|
||||||
from html5tagger import Builder, E # type: ignore
|
from html5tagger import Builder, E # type: ignore
|
||||||
from sanic import Request
|
from sanic import Request
|
||||||
|
|
||||||
|
|
||||||
def do_footer(builder: Builder, request: Request) -> None:
|
def do_footer(builder: Builder, request: Request) -> None:
|
||||||
builder.footer(
|
builder.footer(
|
||||||
_pagination(request),
|
_pagination(request),
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
from webapp.display.layouts.models import MenuItem
|
|
||||||
|
|
||||||
from html5tagger import Builder, E # type: ignore
|
from html5tagger import Builder, E # type: ignore
|
||||||
from sanic import Request
|
from sanic import Request
|
||||||
|
|
||||||
|
from webapp.display.layouts.models import MenuItem
|
||||||
|
|
||||||
def do_navbar(builder: Builder, request: Request) -> None:
|
def do_navbar(builder: Builder, request: Request) -> None:
|
||||||
navbar_items = [
|
navbar_items = [
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
from webapp.display.layouts.models import MenuItem
|
|
||||||
from webapp.display.text import slugify
|
|
||||||
|
|
||||||
from html5tagger import Builder, E # type: ignore
|
from html5tagger import Builder, E # type: ignore
|
||||||
from sanic import Request
|
from sanic import Request
|
||||||
|
|
||||||
|
from webapp.display.layouts.models import MenuItem
|
||||||
|
from webapp.display.text import slugify
|
||||||
|
|
||||||
def do_sidebar(builder: Builder, request: Request) -> None:
|
def do_sidebar(builder: Builder, request: Request) -> None:
|
||||||
builder.a(class_="burger")(E.span().span().span().span())
|
builder.a(class_="burger")(E.span().span().span().span())
|
||||||
|
|
|
@ -8,7 +8,6 @@ from sanic import Request
|
||||||
|
|
||||||
from .base import BaseLayout
|
from .base import BaseLayout
|
||||||
|
|
||||||
|
|
||||||
class HomeLayout(BaseLayout):
|
class HomeLayout(BaseLayout):
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def layout(
|
def layout(
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
|
|
||||||
|
from sanic import Request
|
||||||
|
|
||||||
from webapp.display.layouts.elements.footer import do_footer
|
from webapp.display.layouts.elements.footer import do_footer
|
||||||
from webapp.display.layouts.elements.navbar import do_navbar
|
from webapp.display.layouts.elements.navbar import do_navbar
|
||||||
from webapp.display.layouts.elements.sidebar import do_sidebar
|
from webapp.display.layouts.elements.sidebar import do_sidebar
|
||||||
|
|
||||||
from sanic import Request
|
|
||||||
|
|
||||||
from .base import BaseLayout
|
from .base import BaseLayout
|
||||||
|
|
||||||
|
|
||||||
class MainLayout(BaseLayout):
|
class MainLayout(BaseLayout):
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def layout(
|
def layout(
|
||||||
|
|
|
@ -2,7 +2,6 @@ from __future__ import annotations
|
||||||
|
|
||||||
from msgspec import Struct, field
|
from msgspec import Struct, field
|
||||||
|
|
||||||
|
|
||||||
class MenuItem(Struct, kw_only=False, omit_defaults=True):
|
class MenuItem(Struct, kw_only=False, omit_defaults=True):
|
||||||
label: str
|
label: str
|
||||||
path: str | None = None
|
path: str | None = None
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
|
|
||||||
|
from html5tagger import HTML, Builder, E # type: ignore
|
||||||
from mistune import HTMLRenderer, create_markdown, escape
|
from mistune import HTMLRenderer, create_markdown, escape
|
||||||
from mistune.directives import RSTDirective, TableOfContents
|
from mistune.directives import RSTDirective, TableOfContents
|
||||||
from mistune.util import safe_entity
|
from mistune.util import safe_entity
|
||||||
|
@ -8,8 +10,6 @@ from pygments import highlight
|
||||||
from pygments.formatters import html
|
from pygments.formatters import html
|
||||||
from pygments.lexers import get_lexer_by_name
|
from pygments.lexers import get_lexer_by_name
|
||||||
|
|
||||||
from html5tagger import HTML, Builder, E # type: ignore
|
|
||||||
|
|
||||||
from .code_style import SanicCodeStyle
|
from .code_style import SanicCodeStyle
|
||||||
from .plugins.attrs import Attributes
|
from .plugins.attrs import Attributes
|
||||||
from .plugins.columns import Column
|
from .plugins.columns import Column
|
||||||
|
@ -20,7 +20,6 @@ from .plugins.span import span
|
||||||
from .plugins.tabs import Tabs
|
from .plugins.tabs import Tabs
|
||||||
from .text import slugify
|
from .text import slugify
|
||||||
|
|
||||||
|
|
||||||
class DocsRenderer(HTMLRenderer):
|
class DocsRenderer(HTMLRenderer):
|
||||||
def block_code(self, code: str, info: str | None = None):
|
def block_code(self, code: str, info: str | None = None):
|
||||||
builder = Builder("Block")
|
builder = Builder("Block")
|
||||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
||||||
import importlib
|
import importlib
|
||||||
import inspect
|
import inspect
|
||||||
import pkgutil
|
import pkgutil
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from html import escape
|
from html import escape
|
||||||
|
@ -10,12 +11,10 @@ from html import escape
|
||||||
from docstring_parser import Docstring, DocstringParam, DocstringRaises
|
from docstring_parser import Docstring, DocstringParam, DocstringRaises
|
||||||
from docstring_parser import parse as parse_docstring
|
from docstring_parser import parse as parse_docstring
|
||||||
from docstring_parser.common import DocstringExample
|
from docstring_parser.common import DocstringExample
|
||||||
|
|
||||||
from html5tagger import HTML, Builder, E # type: ignore
|
from html5tagger import HTML, Builder, E # type: ignore
|
||||||
|
|
||||||
from ..markdown import render_markdown, slugify
|
from ..markdown import render_markdown, slugify
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DocObject:
|
class DocObject:
|
||||||
name: str
|
name: str
|
||||||
|
|
|
@ -3,15 +3,14 @@ from __future__ import annotations
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from typing import Type
|
from typing import Type
|
||||||
|
|
||||||
from webapp.display.base import BaseRenderer
|
|
||||||
|
|
||||||
from html5tagger import HTML, Builder # type: ignore
|
from html5tagger import HTML, Builder # type: ignore
|
||||||
from sanic import Request
|
from sanic import Request
|
||||||
|
|
||||||
|
from webapp.display.base import BaseRenderer
|
||||||
|
|
||||||
from ..layouts.base import BaseLayout
|
from ..layouts.base import BaseLayout
|
||||||
from .page import Page
|
from .page import Page
|
||||||
|
|
||||||
|
|
||||||
class PageRenderer(BaseRenderer):
|
class PageRenderer(BaseRenderer):
|
||||||
def render(self, request: Request, language: str, path: str) -> Builder:
|
def render(self, request: Request, language: str, path: str) -> Builder:
|
||||||
builder = self.get_builder(
|
builder = self.get_builder(
|
||||||
|
|
|
@ -2,13 +2,11 @@ from re import Match
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from html5tagger import HTML, E
|
||||||
from mistune.block_parser import BlockParser
|
from mistune.block_parser import BlockParser
|
||||||
from mistune.core import BlockState
|
from mistune.core import BlockState
|
||||||
from mistune.directives import DirectivePlugin
|
from mistune.directives import DirectivePlugin
|
||||||
|
|
||||||
from html5tagger import HTML, E
|
|
||||||
|
|
||||||
|
|
||||||
class Attributes(DirectivePlugin):
|
class Attributes(DirectivePlugin):
|
||||||
def __call__(self, directive, md):
|
def __call__(self, directive, md):
|
||||||
directive.register("attrs", self.parse)
|
directive.register("attrs", self.parse)
|
||||||
|
|
|
@ -8,7 +8,6 @@ from mistune.core import BlockState
|
||||||
from mistune.directives import DirectivePlugin, RSTDirective
|
from mistune.directives import DirectivePlugin, RSTDirective
|
||||||
from mistune.markdown import Markdown
|
from mistune.markdown import Markdown
|
||||||
|
|
||||||
|
|
||||||
class Column(DirectivePlugin):
|
class Column(DirectivePlugin):
|
||||||
def parse(
|
def parse(
|
||||||
self, block: BlockParser, m: Match, state: BlockState
|
self, block: BlockParser, m: Match, state: BlockState
|
||||||
|
|
|
@ -2,7 +2,6 @@ from mistune.core import BlockState
|
||||||
from mistune.directives import DirectivePlugin, RSTDirective
|
from mistune.directives import DirectivePlugin, RSTDirective
|
||||||
from mistune.markdown import Markdown
|
from mistune.markdown import Markdown
|
||||||
|
|
||||||
|
|
||||||
class Hook(DirectivePlugin):
|
class Hook(DirectivePlugin):
|
||||||
def __call__( # type: ignore
|
def __call__( # type: ignore
|
||||||
self, directive: RSTDirective, md: Markdown
|
self, directive: RSTDirective, md: Markdown
|
||||||
|
|
|
@ -3,15 +3,13 @@ from re import Match
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from html5tagger import HTML, E
|
||||||
from mistune import HTMLRenderer
|
from mistune import HTMLRenderer
|
||||||
from mistune.block_parser import BlockParser
|
from mistune.block_parser import BlockParser
|
||||||
from mistune.core import BlockState
|
from mistune.core import BlockState
|
||||||
from mistune.directives import DirectivePlugin, RSTDirective
|
from mistune.directives import DirectivePlugin, RSTDirective
|
||||||
from mistune.markdown import Markdown
|
from mistune.markdown import Markdown
|
||||||
|
|
||||||
from html5tagger import HTML, E
|
|
||||||
|
|
||||||
|
|
||||||
class Mermaid(DirectivePlugin):
|
class Mermaid(DirectivePlugin):
|
||||||
def parse(
|
def parse(
|
||||||
self, block: BlockParser, m: Match, state: BlockState
|
self, block: BlockParser, m: Match, state: BlockState
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
from mistune.directives import Admonition
|
|
||||||
|
|
||||||
from html5tagger import HTML, E
|
from html5tagger import HTML, E
|
||||||
|
from mistune.directives import Admonition
|
||||||
|
|
||||||
class Notification(Admonition):
|
class Notification(Admonition):
|
||||||
SUPPORTED_NAMES = {
|
SUPPORTED_NAMES = {
|
||||||
|
|
|
@ -2,7 +2,6 @@ import re
|
||||||
|
|
||||||
from mistune.markdown import Markdown
|
from mistune.markdown import Markdown
|
||||||
|
|
||||||
|
|
||||||
def parse_inline_span(inline, m: re.Match, state):
|
def parse_inline_span(inline, m: re.Match, state):
|
||||||
state.append_token(
|
state.append_token(
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,7 +8,6 @@ from mistune.core import BlockState
|
||||||
from mistune.directives import DirectivePlugin, RSTDirective
|
from mistune.directives import DirectivePlugin, RSTDirective
|
||||||
from mistune.markdown import Markdown
|
from mistune.markdown import Markdown
|
||||||
|
|
||||||
|
|
||||||
class Tabs(DirectivePlugin):
|
class Tabs(DirectivePlugin):
|
||||||
def parse(
|
def parse(
|
||||||
self, block: BlockParser, m: Match, state: BlockState
|
self, block: BlockParser, m: Match, state: BlockState
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from urllib.parse import unquote
|
from urllib.parse import unquote
|
||||||
|
|
||||||
from webapp.display.search.search import Searcher
|
|
||||||
|
|
||||||
from html5tagger import Builder, E # type: ignore
|
from html5tagger import Builder, E # type: ignore
|
||||||
from sanic import Request
|
from sanic import Request
|
||||||
|
|
||||||
|
from webapp.display.search.search import Searcher
|
||||||
|
|
||||||
from ..base import BaseRenderer
|
from ..base import BaseRenderer
|
||||||
from ..layouts.main import MainLayout
|
from ..layouts.main import MainLayout
|
||||||
|
|
||||||
|
|
||||||
class SearchRenderer(BaseRenderer):
|
class SearchRenderer(BaseRenderer):
|
||||||
def render(
|
def render(
|
||||||
self, request: Request, language: str, searcher: Searcher, full: bool
|
self, request: Request, language: str, searcher: Searcher, full: bool
|
||||||
|
|
|
@ -5,8 +5,8 @@ from pathlib import Path
|
||||||
from typing import ClassVar
|
from typing import ClassVar
|
||||||
|
|
||||||
from msgspec import Struct
|
from msgspec import Struct
|
||||||
from webapp.display.page import Page
|
|
||||||
|
|
||||||
|
from webapp.display.page import Page
|
||||||
|
|
||||||
class Stemmer:
|
class Stemmer:
|
||||||
STOP_WORDS: ClassVar[set[str]] = set(
|
STOP_WORDS: ClassVar[set[str]] = set(
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
# from urllib.parse import unquote
|
# from urllib.parse import unquote
|
||||||
|
|
||||||
|
from sanic import Blueprint, Request, Sanic, html
|
||||||
|
|
||||||
from webapp.display.page import Page
|
from webapp.display.page import Page
|
||||||
from webapp.display.search.renderer import SearchRenderer
|
from webapp.display.search.renderer import SearchRenderer
|
||||||
from webapp.display.search.search import Document, Searcher, Stemmer
|
from webapp.display.search.search import Document, Searcher, Stemmer
|
||||||
|
|
||||||
from sanic import Blueprint, Request, Sanic, html
|
|
||||||
|
|
||||||
bp = Blueprint("search", url_prefix="/<language>/search")
|
bp = Blueprint("search", url_prefix="/<language>/search")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from msgspec import yaml
|
from msgspec import yaml
|
||||||
from webapp.display.layouts.models import GeneralConfig, MenuItem
|
|
||||||
|
|
||||||
|
from webapp.display.layouts.models import GeneralConfig, MenuItem
|
||||||
|
|
||||||
def load_menu(path: Path) -> list[MenuItem]:
|
def load_menu(path: Path) -> list[MenuItem]:
|
||||||
loaded = yaml.decode(path.read_bytes(), type=dict[str, list[MenuItem]])
|
loaded = yaml.decode(path.read_bytes(), type=dict[str, list[MenuItem]])
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from sanic import Request, Sanic, html, redirect
|
||||||
|
|
||||||
from webapp.display.layouts.models import MenuItem
|
from webapp.display.layouts.models import MenuItem
|
||||||
from webapp.display.page import Page, PageRenderer
|
from webapp.display.page import Page, PageRenderer
|
||||||
from webapp.endpoint.view import bp
|
from webapp.endpoint.view import bp
|
||||||
|
@ -7,9 +9,6 @@ from webapp.worker.config import load_config, load_menu
|
||||||
from webapp.worker.reload import setup_livereload
|
from webapp.worker.reload import setup_livereload
|
||||||
from webapp.worker.style import setup_style
|
from webapp.worker.style import setup_style
|
||||||
|
|
||||||
from sanic import Request, Sanic, html, redirect
|
|
||||||
|
|
||||||
|
|
||||||
def _compile_sidebar_order(items: list[MenuItem]) -> list[str]:
|
def _compile_sidebar_order(items: list[MenuItem]) -> list[str]:
|
||||||
order = []
|
order = []
|
||||||
for item in items:
|
for item in items:
|
||||||
|
|
|
@ -8,7 +8,6 @@ import ujson
|
||||||
|
|
||||||
from sanic import Request, Sanic, Websocket
|
from sanic import Request, Sanic, Websocket
|
||||||
|
|
||||||
|
|
||||||
def setup_livereload(app: Sanic) -> None:
|
def setup_livereload(app: Sanic) -> None:
|
||||||
@app.main_process_start
|
@app.main_process_start
|
||||||
async def main_process_start(app: Sanic):
|
async def main_process_start(app: Sanic):
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
# from scss.compiler import compile_string
|
# from scss.compiler import compile_string
|
||||||
|
|
||||||
from pygments.formatters import html
|
from pygments.formatters import html
|
||||||
from sass import compile as compile_scss
|
|
||||||
from webapp.display.code_style import SanicCodeStyle
|
|
||||||
|
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
|
from sass import compile as compile_scss
|
||||||
|
|
||||||
|
from webapp.display.code_style import SanicCodeStyle
|
||||||
|
|
||||||
def setup_style(app: Sanic) -> None:
|
def setup_style(app: Sanic) -> None:
|
||||||
index = app.config.STYLE_DIR / "index.scss"
|
index = app.config.STYLE_DIR / "index.scss"
|
||||||
|
|
|
@ -2,6 +2,19 @@
|
||||||
requires = ["setuptools", "wheel"]
|
requires = ["setuptools", "wheel"]
|
||||||
build-backend = "setuptools.build_meta"
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
extend-select = ["I"]
|
||||||
|
ignore = ["D100", "D101", "D102", "D103", "E402", "E741", "F811", "F821"]
|
||||||
|
line-length = 79
|
||||||
|
show-source = true
|
||||||
|
show-fixes = true
|
||||||
|
|
||||||
|
[tool.ruff.isort]
|
||||||
|
known-first-party = ["sanic"]
|
||||||
|
known-third-party = ["pytest"]
|
||||||
|
lines-after-imports = 2
|
||||||
|
lines-between-types = 1
|
||||||
|
|
||||||
[tool.black]
|
[tool.black]
|
||||||
line-length = 79
|
line-length = 79
|
||||||
|
|
||||||
|
|
|
@ -349,8 +349,7 @@ def parse_content_header(value: str) -> Tuple[str, Options]:
|
||||||
options: Dict[str, Union[int, str]] = {}
|
options: Dict[str, Union[int, str]] = {}
|
||||||
else:
|
else:
|
||||||
options = {
|
options = {
|
||||||
m.group(1)
|
m.group(1).lower(): (m.group(2) or m.group(3))
|
||||||
.lower(): (m.group(2) or m.group(3))
|
|
||||||
.replace("%22", '"')
|
.replace("%22", '"')
|
||||||
.replace("%0D%0A", "\n")
|
.replace("%0D%0A", "\n")
|
||||||
for m in _param.finditer(value[pos:])
|
for m in _param.finditer(value[pos:])
|
||||||
|
|
|
@ -14,7 +14,7 @@ class ExceptionMixin(metaclass=SanicMeta):
|
||||||
def exception(
|
def exception(
|
||||||
self,
|
self,
|
||||||
*exceptions: Union[Type[Exception], List[Type[Exception]]],
|
*exceptions: Union[Type[Exception], List[Type[Exception]]],
|
||||||
apply: bool = True
|
apply: bool = True,
|
||||||
) -> Callable:
|
) -> Callable:
|
||||||
"""Decorator used to register an exception handler for the current application or blueprint instance.
|
"""Decorator used to register an exception handler for the current application or blueprint instance.
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ class MiddlewareMixin(metaclass=SanicMeta):
|
||||||
attach_to: str = "request",
|
attach_to: str = "request",
|
||||||
apply: bool = True,
|
apply: bool = True,
|
||||||
*,
|
*,
|
||||||
priority: int = 0
|
priority: int = 0,
|
||||||
) -> MiddlewareType:
|
) -> MiddlewareType:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ class MiddlewareMixin(metaclass=SanicMeta):
|
||||||
attach_to: str = "request",
|
attach_to: str = "request",
|
||||||
apply: bool = True,
|
apply: bool = True,
|
||||||
*,
|
*,
|
||||||
priority: int = 0
|
priority: int = 0,
|
||||||
) -> Callable[[MiddlewareType], MiddlewareType]:
|
) -> Callable[[MiddlewareType], MiddlewareType]:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ class MiddlewareMixin(metaclass=SanicMeta):
|
||||||
attach_to: str = "request",
|
attach_to: str = "request",
|
||||||
apply: bool = True,
|
apply: bool = True,
|
||||||
*,
|
*,
|
||||||
priority: int = 0
|
priority: int = 0,
|
||||||
) -> Union[MiddlewareType, Callable[[MiddlewareType], MiddlewareType]]:
|
) -> Union[MiddlewareType, Callable[[MiddlewareType], MiddlewareType]]:
|
||||||
"""Decorator for registering middleware.
|
"""Decorator for registering middleware.
|
||||||
|
|
||||||
|
|
|
@ -44,12 +44,8 @@ class ConnInfo:
|
||||||
self.server_name = ""
|
self.server_name = ""
|
||||||
self.cert: Dict[str, Any] = {}
|
self.cert: Dict[str, Any] = {}
|
||||||
self.network_paths: List[Any] = []
|
self.network_paths: List[Any] = []
|
||||||
sslobj: Optional[SSLObject] = transport.get_extra_info(
|
sslobj: Optional[SSLObject] = transport.get_extra_info("ssl_object") # type: ignore
|
||||||
"ssl_object"
|
sslctx: Optional[SSLContext] = transport.get_extra_info("ssl_context") # type: ignore
|
||||||
) # type: ignore
|
|
||||||
sslctx: Optional[SSLContext] = transport.get_extra_info(
|
|
||||||
"ssl_context"
|
|
||||||
) # type: ignore
|
|
||||||
if sslobj:
|
if sslobj:
|
||||||
self.ssl = True
|
self.ssl = True
|
||||||
self.server_name = getattr(sslobj, "sanic_server_name", None) or ""
|
self.server_name = getattr(sslobj, "sanic_server_name", None) or ""
|
||||||
|
|
|
@ -57,9 +57,7 @@ class WebsocketFrameAssembler:
|
||||||
self.read_mutex = asyncio.Lock()
|
self.read_mutex = asyncio.Lock()
|
||||||
self.write_mutex = asyncio.Lock()
|
self.write_mutex = asyncio.Lock()
|
||||||
|
|
||||||
self.completed_queue = asyncio.Queue(
|
self.completed_queue = asyncio.Queue(maxsize=1) # type: asyncio.Queue[Data]
|
||||||
maxsize=1
|
|
||||||
) # type: asyncio.Queue[Data]
|
|
||||||
|
|
||||||
# put() sets this event to tell get() that a message can be fetched.
|
# put() sets this event to tell get() that a message can be fetched.
|
||||||
self.message_complete = asyncio.Event()
|
self.message_complete = asyncio.Event()
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
from collections.abc import Mapping
|
from collections.abc import Mapping
|
||||||
from typing import Any, Dict, ItemsView, Iterator, KeysView, List
|
from typing import Any, Dict, ItemsView, Iterator, KeysView, List, ValuesView
|
||||||
from typing import Mapping as MappingType
|
from typing import Mapping as MappingType
|
||||||
from typing import ValuesView
|
|
||||||
|
|
||||||
|
|
||||||
dict
|
dict
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from os import path
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from os import path
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
try:
|
try:
|
||||||
import towncrier
|
|
||||||
import click
|
import click
|
||||||
|
import towncrier
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print(
|
print(
|
||||||
"Please make sure you have a installed towncrier and click before using this tool"
|
"Please make sure you have a installed towncrier and click before using this tool"
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
from argparse import ArgumentParser, Namespace
|
from argparse import ArgumentParser, Namespace
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from configparser import RawConfigParser
|
from configparser import RawConfigParser
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from json import dumps
|
from json import dumps
|
||||||
from os import path, chdir
|
from os import chdir, path
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import PIPE, Popen
|
||||||
|
|
||||||
from jinja2 import Environment, BaseLoader
|
|
||||||
from requests import patch
|
|
||||||
import sys
|
|
||||||
import towncrier
|
import towncrier
|
||||||
|
|
||||||
|
from jinja2 import BaseLoader, Environment
|
||||||
|
from requests import patch
|
||||||
|
|
||||||
|
|
||||||
GIT_COMMANDS = {
|
GIT_COMMANDS = {
|
||||||
"get_tag": ["git describe --tags --abbrev=0"],
|
"get_tag": ["git describe --tags --abbrev=0"],
|
||||||
"commit_version_change": [
|
"commit_version_change": [
|
||||||
|
@ -78,7 +81,7 @@ def _run_shell_command(command: list):
|
||||||
output, error = process.communicate()
|
output, error = process.communicate()
|
||||||
return_code = process.returncode
|
return_code = process.returncode
|
||||||
return output.decode("utf-8"), error, return_code
|
return output.decode("utf-8"), error, return_code
|
||||||
except:
|
except Exception:
|
||||||
return None, None, -1
|
return None, None, -1
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import bottle
|
import bottle
|
||||||
import ujson
|
import ujson
|
||||||
|
|
||||||
from bottle import route, run
|
from bottle import route
|
||||||
|
|
||||||
|
|
||||||
@route("/")
|
@route("/")
|
||||||
|
|
|
@ -3,8 +3,6 @@ import os
|
||||||
import sys
|
import sys
|
||||||
import timeit
|
import timeit
|
||||||
|
|
||||||
import asyncpg
|
|
||||||
|
|
||||||
from sanic.response import json
|
from sanic.response import json
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
import ujson
|
import ujson
|
||||||
|
|
||||||
from wheezy.http import HTTPResponse, WSGIApplication
|
from wheezy.http import HTTPResponse, WSGIApplication
|
||||||
from wheezy.http.response import json_response
|
|
||||||
from wheezy.routing import url
|
from wheezy.routing import url
|
||||||
from wheezy.web.handlers import BaseHandler
|
from wheezy.web.handlers import BaseHandler
|
||||||
from wheezy.web.middleware import (
|
from wheezy.web.middleware import (
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import asyncio
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from collections import deque, namedtuple
|
from collections import deque, namedtuple
|
||||||
|
@ -12,7 +11,7 @@ from pytest import MonkeyPatch
|
||||||
|
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
from sanic.application.state import Mode
|
from sanic.application.state import Mode
|
||||||
from sanic.asgi import ASGIApp, Lifespan, MockTransport
|
from sanic.asgi import Lifespan, MockTransport
|
||||||
from sanic.exceptions import BadRequest, Forbidden, ServiceUnavailable
|
from sanic.exceptions import BadRequest, Forbidden, ServiceUnavailable
|
||||||
from sanic.request import Request
|
from sanic.request import Request
|
||||||
from sanic.response import json, text
|
from sanic.response import json, text
|
||||||
|
|
|
@ -22,7 +22,7 @@ def test_bp_group_indexing(app: Sanic):
|
||||||
group = Blueprint.group(blueprint_1, blueprint_2)
|
group = Blueprint.group(blueprint_1, blueprint_2)
|
||||||
assert group[0] == blueprint_1
|
assert group[0] == blueprint_1
|
||||||
|
|
||||||
with raises(expected_exception=IndexError) as e:
|
with raises(expected_exception=IndexError):
|
||||||
_ = group[3]
|
_ = group[3]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
import asyncio
|
|
||||||
|
|
||||||
from asyncio import CancelledError
|
from asyncio import CancelledError
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from sanic import Request, Sanic, json
|
from sanic import Request, Sanic, json
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ from unittest.mock import Mock
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from pytest import LogCaptureFixture, MonkeyPatch, WarningsRecorder
|
from pytest import LogCaptureFixture, MonkeyPatch
|
||||||
|
|
||||||
from sanic import Sanic, handlers
|
from sanic import Sanic, handlers
|
||||||
from sanic.exceptions import BadRequest, Forbidden, NotFound, ServerError
|
from sanic.exceptions import BadRequest, Forbidden, NotFound, ServerError
|
||||||
|
@ -169,7 +169,7 @@ def test_exception_handler_lookup(exception_handler_app: Sanic):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ModuleNotFoundError
|
ModuleNotFoundError # noqa: F823
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
||||||
class ModuleNotFoundError(ImportError):
|
class ModuleNotFoundError(ImportError):
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from unittest.mock import MagicMock
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import sanic_ext
|
import sanic_ext # noqa: F401
|
||||||
|
|
||||||
SANIC_EXT_IN_ENV = True
|
SANIC_EXT_IN_ENV = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|
|
@ -57,7 +57,7 @@ def raised_ceiling():
|
||||||
# Chrome, Firefox:
|
# Chrome, Firefox:
|
||||||
# Content-Disposition: form-data; name="foo%22;bar\"; filename="😀"
|
# Content-Disposition: form-data; name="foo%22;bar\"; filename="😀"
|
||||||
'form-data; name="foo%22;bar\\"; filename="😀"',
|
'form-data; name="foo%22;bar\\"; filename="😀"',
|
||||||
("form-data", {"name": 'foo";bar\\', "filename": "😀"})
|
("form-data", {"name": 'foo";bar\\', "filename": "😀"}),
|
||||||
# cgi: ('form-data', {'name': 'foo%22;bar"; filename="😀'})
|
# cgi: ('form-data', {'name': 'foo%22;bar"; filename="😀'})
|
||||||
# werkzeug (pre 2.3.0): ('form-data', {'name': 'foo%22;bar"; filename='})
|
# werkzeug (pre 2.3.0): ('form-data', {'name': 'foo%22;bar"; filename='})
|
||||||
),
|
),
|
||||||
|
|
|
@ -14,7 +14,6 @@ from sanic_testing.testing import HOST, PORT
|
||||||
from sanic import Blueprint, text
|
from sanic import Blueprint, text
|
||||||
from sanic.compat import use_context
|
from sanic.compat import use_context
|
||||||
from sanic.log import logger
|
from sanic.log import logger
|
||||||
from sanic.server.socket import configure_socket
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(
|
@pytest.mark.skipif(
|
||||||
|
|
|
@ -573,7 +573,7 @@ def test_streaming_echo():
|
||||||
|
|
||||||
async def client(app, reader, writer):
|
async def client(app, reader, writer):
|
||||||
# Unfortunately httpx does not support 2-way streaming, so do it by hand.
|
# Unfortunately httpx does not support 2-way streaming, so do it by hand.
|
||||||
host = f"host: localhost:8000\r\n".encode()
|
host = "host: localhost:8000\r\n".encode()
|
||||||
writer.write(
|
writer.write(
|
||||||
b"POST /echo HTTP/1.1\r\n" + host + b"content-length: 2\r\n"
|
b"POST /echo HTTP/1.1\r\n" + host + b"content-length: 2\r\n"
|
||||||
b"content-type: text/plain; charset=utf-8\r\n"
|
b"content-type: text/plain; charset=utf-8\r\n"
|
||||||
|
@ -581,7 +581,7 @@ def test_streaming_echo():
|
||||||
)
|
)
|
||||||
# Read response
|
# Read response
|
||||||
res = b""
|
res = b""
|
||||||
while not b"\r\n\r\n" in res:
|
while b"\r\n\r\n" not in res:
|
||||||
res += await reader.read(4096)
|
res += await reader.read(4096)
|
||||||
assert res.startswith(b"HTTP/1.1 200 OK\r\n")
|
assert res.startswith(b"HTTP/1.1 200 OK\r\n")
|
||||||
assert res.endswith(b"\r\n\r\n")
|
assert res.endswith(b"\r\n\r\n")
|
||||||
|
@ -589,7 +589,7 @@ def test_streaming_echo():
|
||||||
|
|
||||||
async def read_chunk():
|
async def read_chunk():
|
||||||
nonlocal buffer
|
nonlocal buffer
|
||||||
while not b"\r\n" in buffer:
|
while b"\r\n" not in buffer:
|
||||||
data = await reader.read(4096)
|
data = await reader.read(4096)
|
||||||
assert data
|
assert data
|
||||||
buffer += data
|
buffer += data
|
||||||
|
@ -618,6 +618,6 @@ def test_streaming_echo():
|
||||||
assert res == b"-"
|
assert res == b"-"
|
||||||
|
|
||||||
res = await read_chunk()
|
res = await read_chunk()
|
||||||
assert res == None
|
assert res is None
|
||||||
|
|
||||||
app.run(access_log=False, single_process=True)
|
app.run(access_log=False, single_process=True)
|
||||||
|
|
|
@ -2011,11 +2011,11 @@ def test_server_name_and_url_for(app):
|
||||||
app.config.SERVER_NAME = "my-server" # This means default port
|
app.config.SERVER_NAME = "my-server" # This means default port
|
||||||
assert app.url_for("handler", _external=True) == "http://my-server/foo"
|
assert app.url_for("handler", _external=True) == "http://my-server/foo"
|
||||||
request, response = app.test_client.get("/foo")
|
request, response = app.test_client.get("/foo")
|
||||||
assert request.url_for("handler") == f"http://my-server/foo"
|
assert request.url_for("handler") == "http://my-server/foo"
|
||||||
|
|
||||||
app.config.SERVER_NAME = "https://my-server/path"
|
app.config.SERVER_NAME = "https://my-server/path"
|
||||||
request, response = app.test_client.get("/foo")
|
request, response = app.test_client.get("/foo")
|
||||||
url = f"https://my-server/path/foo"
|
url = "https://my-server/path/foo"
|
||||||
assert app.url_for("handler", _external=True) == url
|
assert app.url_for("handler", _external=True) == url
|
||||||
assert request.url_for("handler") == url
|
assert request.url_for("handler") == url
|
||||||
|
|
||||||
|
@ -2180,7 +2180,7 @@ def test_safe_method_with_body_ignored(app):
|
||||||
)
|
)
|
||||||
|
|
||||||
assert request.body == b""
|
assert request.body == b""
|
||||||
assert request.json == None
|
assert request.json is None
|
||||||
assert response.body == b"OK"
|
assert response.body == b"OK"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -610,7 +610,7 @@ def test_multiple_responses(
|
||||||
|
|
||||||
@app.get("/4")
|
@app.get("/4")
|
||||||
async def handler4(request: Request):
|
async def handler4(request: Request):
|
||||||
response = await request.respond(headers={"one": "one"})
|
await request.respond(headers={"one": "one"})
|
||||||
return json({"foo": "bar"}, headers={"one": "two"})
|
return json({"foo": "bar"}, headers={"one": "two"})
|
||||||
|
|
||||||
@app.get("/5")
|
@app.get("/5")
|
||||||
|
@ -641,10 +641,6 @@ def test_multiple_responses(
|
||||||
"been responded to."
|
"been responded to."
|
||||||
)
|
)
|
||||||
|
|
||||||
error_msg3 = (
|
|
||||||
"Response stream was ended, no more "
|
|
||||||
"response data is allowed to be sent."
|
|
||||||
)
|
|
||||||
|
|
||||||
with caplog.at_level(ERROR):
|
with caplog.at_level(ERROR):
|
||||||
_, response = app.test_client.get("/1")
|
_, response = app.test_client.get("/1")
|
||||||
|
@ -769,7 +765,7 @@ def test_file_response_headers(
|
||||||
assert (
|
assert (
|
||||||
"cache-control" in headers
|
"cache-control" in headers
|
||||||
and f"max-age={test_max_age}" in headers.get("cache-control")
|
and f"max-age={test_max_age}" in headers.get("cache-control")
|
||||||
and f"public" in headers.get("cache-control")
|
and "public" in headers.get("cache-control")
|
||||||
)
|
)
|
||||||
assert (
|
assert (
|
||||||
"expires" in headers
|
"expires" in headers
|
||||||
|
@ -800,14 +796,14 @@ def test_file_response_headers(
|
||||||
|
|
||||||
_, response = app.test_client.get(f"/files/no_cache/{file_name}")
|
_, response = app.test_client.get(f"/files/no_cache/{file_name}")
|
||||||
headers = response.headers
|
headers = response.headers
|
||||||
assert "cache-control" in headers and f"no-cache" == headers.get(
|
assert "cache-control" in headers and "no-cache" == headers.get(
|
||||||
"cache-control"
|
"cache-control"
|
||||||
)
|
)
|
||||||
assert response.status == 200
|
assert response.status == 200
|
||||||
|
|
||||||
_, response = app.test_client.get(f"/files/no_store/{file_name}")
|
_, response = app.test_client.get(f"/files/no_store/{file_name}")
|
||||||
headers = response.headers
|
headers = response.headers
|
||||||
assert "cache-control" in headers and f"no-store" == headers.get(
|
assert "cache-control" in headers and "no-store" == headers.get(
|
||||||
"cache-control"
|
"cache-control"
|
||||||
)
|
)
|
||||||
assert response.status == 200
|
assert response.status == 200
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
# flake8: noqa: E501
|
# flake8: noqa: E501
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Tuple
|
from typing import List, Tuple
|
||||||
|
|
Loading…
Reference in New Issue
Block a user