Skip to content

Commit

Permalink
Merge branch 'main' into ruff-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
iAndriy authored Dec 10, 2023
2 parents 7c5d8fe + 82bf46b commit 69384ae
Show file tree
Hide file tree
Showing 16 changed files with 274 additions and 115 deletions.
4 changes: 4 additions & 0 deletions guide/content/en/guide/basics/handlers.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ All handlers are named automatically. This is useful for debugging, and for gene
.. column::

```python
# Two handlers, same function,
# different names:
# - "foo_arg"
# - "foo"
@app.get("/foo/<arg>", name="foo_arg")
@app.get("/foo")
async def foo(request, arg=None):
Expand Down
65 changes: 64 additions & 1 deletion guide/content/en/guide/basics/listeners.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,13 @@ async def reload_start(*_):
@app.main_process_start
async def main_start(*_):
print(">>>>>> main_start <<<<<<")

@app.before_server_start
async def before_start(*_):
print(">>>>>> before_start <<<<<<")
```

If this application were run with auto-reload turned on, the `reload_start` function would be called once. This is contrasted with `main_start`, which would be run every time a file is save and the reloader restarts the applicaition process.
If this application were run with auto-reload turned on, the `reload_start` function would be called once when the reloader process starts. The `main_start` function would also be called once when the main process starts. **HOWEVER**, the `before_start` function would be called once for each worker process that is started, and subsequently every time that a file is saved and the worker is restarted.

## Attaching a listener

Expand Down Expand Up @@ -232,6 +236,65 @@ Given the following setup, we should expect to see this in the console if we run

The practical result of this is that if the first listener in `before_server_start` handler setups a database connection, listeners that are registered after it can rely upon that connection being alive both when they are started and stopped.

### Priority

.. new:: v23.12

In v23.12, the `priority` keyword argument was added to listeners. This allows for fine-tuning the order of execution of listeners. The default priority is `0`. Listeners with a higher priority will be executed first. Listeners with the same priority will be executed in the order they were registered. Furthermore, listeners attached to the `app` instance will be executed before listeners attached to a `Blueprint` instance.

Overall the rules for deciding the order of execution are as follows:

1. Priority in descending order
2. Application listeners before Blueprint listeners
3. Registration order

.. column::

As an example, consider the following, which will print:

```bash
third
bp_third
second
bp_second
first
fourth
bp_first
```

.. column::

```python
@app.before_server_start
async def first(app):
print("first")

@app.listener("before_server_start", priority=2)
async def second(app):
print("second")

@app.before_server_start(priority=3)
async def third(app):
print("third")

@bp.before_server_start
async def bp_first(app):
print("bp_first")

@bp.listener("before_server_start", priority=2)
async def bp_second(app):
print("bp_second")

@bp.before_server_start(priority=3)
async def bp_third(app):
print("bp_third")

@app.before_server_start
async def fourth(app):
print("fourth")

app.blueprint(bp)
```

## ASGI Mode

Expand Down
4 changes: 4 additions & 0 deletions guide/public/assets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -12795,6 +12795,10 @@ p + p {
.section {
padding: 3rem 0rem; } }

@media screen and (min-width: 1216px) {
.section {
padding: 3rem 0rem; } }

.footer {
margin-bottom: 4rem; }
.footer a[target=_blank]::after {
Expand Down
5 changes: 5 additions & 0 deletions guide/style/general.scss
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,8 @@ p + p { margin-top: 1rem; }
padding: 3rem 0rem;
}
}
@media screen and (min-width: $widescreen) {
.section {
padding: 3rem 0rem;
}
}
18 changes: 6 additions & 12 deletions guide/webapp/display/markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,22 @@ def block_code(self, code: str, info: str | None = None):
class_="code-block__copy",
onclick="copyCode(this)",
):
builder.div(
class_="code-block__rectangle code-block__filled"
).div(class_="code-block__rectangle code-block__outlined")
builder.div(class_="code-block__rectangle code-block__filled").div(
class_="code-block__rectangle code-block__outlined"
)
else:
builder.pre(E.code(escape(code)))
return str(builder)

def heading(self, text: str, level: int, **attrs) -> str:
ident = slugify(text)
if level > 1:
text += self._make_tag(
"a", {"href": f"#{ident}", "class": "anchor"}, "#"
)
text += self._make_tag("a", {"href": f"#{ident}", "class": "anchor"}, "#")
return self._make_tag(
f"h{level}",
{
"id": ident,
"class": (
f"is-size-{level}-desktop " f"is-size-{level+2}-touch"
),
"class": (f"is-size-{level}-desktop " f"is-size-{level+2}-touch"),
},
text,
)
Expand Down Expand Up @@ -122,9 +118,7 @@ def inline_directive(self, text: str, **attrs) -> str:
def _make_tag(
self, tag: str, attributes: dict[str, str], text: str | None = None
) -> str:
attrs = " ".join(
f'{key}="{value}"' for key, value in attributes.items()
)
attrs = " ".join(f'{key}="{value}"' for key, value in attributes.items())
if text is None:
return f"<{tag} {attrs} />"
return f"<{tag} {attrs}>{text}</{tag}>"
Expand Down
62 changes: 18 additions & 44 deletions guide/webapp/display/page/docobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,21 @@ def organize_docobjects(package_name: str) -> dict[str, str]:
page_registry[ref].append(module)
page_content[f"/api/{ref}.md"] += str(builder)
for ref, objects in page_registry.items():
page_content[f"/api/{ref}.md"] = _table_of_contents(objects) + page_content[f"/api/{ref}.md"]
page_content[f"/api/{ref}.md"] = (
_table_of_contents(objects) + page_content[f"/api/{ref}.md"]
)
return page_content


def _table_of_contents(objects: list[str]) -> str:
builder = Builder(name="Partial")
with builder.div(class_="table-of-contents"):
builder.h3("Table of Contents", class_="is-size-4")
for obj in objects:
module, name = obj.rsplit(".", 1)
builder.a(
E.strong(name), E.small(module),
E.strong(name),
E.small(module),
href=f"#{slugify(obj.replace('.', '-'))}",
class_="table-of-contents-item",
)
Expand All @@ -137,9 +141,7 @@ def _extract_docobjects(package_name: str) -> dict[str, DocObject]:
docstrings = {}
package = importlib.import_module(package_name)

for _, name, _ in pkgutil.walk_packages(
package.__path__, package_name + "."
):
for _, name, _ in pkgutil.walk_packages(package.__path__, package_name + "."):
module = importlib.import_module(name)
for obj_name, obj in inspect.getmembers(module):
if (
Expand Down Expand Up @@ -173,9 +175,7 @@ def _docobject_to_html(
) -> None:
anchor_id = slugify(docobject.full_name.replace(".", "-"))
anchor = E.a("#", class_="anchor", href=f"#{anchor_id}")
class_name, heading = _define_heading_and_class(
docobject, anchor, as_method
)
class_name, heading = _define_heading_and_class(docobject, anchor, as_method)

with builder.div(class_=class_name):
builder(heading)
Expand Down Expand Up @@ -229,9 +229,7 @@ def _docobject_to_html(

if docobject.docstring.params:
with builder.div(class_="box mt-5"):
builder.h5(
"Parameters", class_="is-size-5 has-text-weight-bold"
)
builder.h5("Parameters", class_="is-size-5 has-text-weight-bold")
_render_params(builder, docobject.docstring.params)

if docobject.docstring.returns:
Expand All @@ -256,9 +254,7 @@ def _signature_to_html(
parts = []
parts.append("<span class='function-signature'>")
for decorator in decorators:
parts.append(
f"<span class='function-decorator'>@{decorator}</span><br>"
)
parts.append(f"<span class='function-decorator'>@{decorator}</span><br>")
parts.append(
f"<span class='is-italic'>{object_type}</span> "
f"<span class='has-text-weight-bold'>{name}</span>("
Expand All @@ -272,9 +268,7 @@ def _signature_to_html(
annotation = ""
if param.annotation != inspect.Parameter.empty:
annotation = escape(str(param.annotation))
parts.append(
f": <span class='param-annotation'>{annotation}</span>"
)
parts.append(f": <span class='param-annotation'>{annotation}</span>")
if param.default != inspect.Parameter.empty:
default = escape(str(param.default))
if annotation == "str":
Expand All @@ -285,9 +279,7 @@ def _signature_to_html(
parts.append(")")
if signature.return_annotation != inspect.Signature.empty:
return_annotation = escape(str(signature.return_annotation))
parts.append(
f": -> <span class='return-annotation'>{return_annotation}</span>"
)
parts.append(f": -> <span class='return-annotation'>{return_annotation}</span>")
parts.append("</span>")
return "".join(parts)

Expand Down Expand Up @@ -328,8 +320,7 @@ def _render_params(builder: Builder, params: list[DocstringParam]) -> None:
E.span(
param.type_name,
class_=(
"has-text-weight-normal has-text-purple "
"is-size-7 ml-2"
"has-text-weight-normal has-text-purple " "is-size-7 ml-2"
),
),
]
Expand All @@ -338,10 +329,7 @@ def _render_params(builder: Builder, params: list[DocstringParam]) -> None:
builder.dd(
HTML(
render_markdown(
param.description
or param.arg_name
or param.type_name
or ""
param.description or param.arg_name or param.type_name or ""
)
)
)
Expand All @@ -354,11 +342,7 @@ def _render_raises(builder: Builder, raises: list[DocstringRaises]) -> None:
with builder.dl(class_="mt-2"):
builder.dt(raise_.type_name, class_="is-family-monospace")
builder.dd(
HTML(
render_markdown(
raise_.description or raise_.type_name or ""
)
)
HTML(render_markdown(raise_.description or raise_.type_name or ""))
)


Expand All @@ -374,11 +358,7 @@ def _render_returns(builder: Builder, docobject: DocObject) -> None:
if not return_type or return_type == inspect.Signature.empty:
return_type = "N/A"

term = (
"Return"
if not docobject.docstring.returns.is_generator
else "Yields"
)
term = "Return" if not docobject.docstring.returns.is_generator else "Yields"
builder.h5(term, class_="is-size-5 has-text-weight-bold")
with builder.dl(class_="mt-2"):
builder.dt(return_type, class_="is-family-monospace")
Expand All @@ -393,17 +373,11 @@ def _render_returns(builder: Builder, docobject: DocObject) -> None:
)


def _render_examples(
builder: Builder, examples: list[DocstringExample]
) -> None:
def _render_examples(builder: Builder, examples: list[DocstringExample]) -> None:
with builder.div(class_="box mt-5"):
builder.h5("Examples", class_="is-size-5 has-text-weight-bold")
for example in examples:
with builder.div(class_="mt-2"):
builder(
HTML(
render_markdown(
example.description or example.snippet or ""
)
)
HTML(render_markdown(example.description or example.snippet or ""))
)
9 changes: 8 additions & 1 deletion guide/webapp/display/plugins/inline_directive.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

DIRECTIVE_PATTERN = r":(?:class|func|meth|attr|exc|mod|data|const|obj|keyword|option|cmdoption|envvar):`(?P<ref>sanic\.[^`]+)`" # noqa: E501


def _parse_inline_directive(inline, m: re.Match, state):
state.append_token(
{
Expand All @@ -14,5 +15,11 @@ def _parse_inline_directive(inline, m: re.Match, state):
)
return m.end()


def inline_directive(md: Markdown):
md.inline.register("inline_directive", DIRECTIVE_PATTERN, _parse_inline_directive, before="escape",)
md.inline.register(
"inline_directive",
DIRECTIVE_PATTERN,
_parse_inline_directive,
before="escape",
)
Loading

0 comments on commit 69384ae

Please sign in to comment.