Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cfdb854ac7 |
1
docs/community/sponsorship.md
Normal file
1
docs/community/sponsorship.md
Normal file
@ -0,0 +1 @@
|
||||
First of all, thanks for coming to this page! We're glad you're considering sponsoring Uvicorn.
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
# Introduction
|
||||
|
||||
Uvicorn is an ASGI web server implementation for Python.
|
||||
**Uvicorn** is an ASGI web server implementation for Python.
|
||||
|
||||
Until recently Python has lacked a minimal low-level server/application interface for
|
||||
async frameworks. The [ASGI specification][asgi] fills this gap, and means we're now able to
|
||||
@ -30,6 +30,14 @@ start building a common set of tooling usable across all async frameworks.
|
||||
|
||||
Uvicorn currently supports **HTTP/1.1** and **WebSockets**.
|
||||
|
||||
## Sponsors
|
||||
|
||||
Uvicorn survives thanks to the support of its sponsors. :heart:
|
||||
|
||||
If you or your company use Uvicorn, [consider becoming a sponsor](community/sponsorship.md)!
|
||||
|
||||
{{ sponsors }}
|
||||
|
||||
## Quickstart
|
||||
|
||||
Install using `pip`:
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
from __future__ import annotations as _annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
from collections import defaultdict
|
||||
from typing import Literal, TypedDict, cast
|
||||
|
||||
import requests
|
||||
from mkdocs.config import Config
|
||||
from mkdocs.structure.files import Files
|
||||
from mkdocs.structure.pages import Page
|
||||
@ -28,6 +32,7 @@ def add_hyperlink_to_pull_request(html: str, page: Page, config: Config, files:
|
||||
def on_page_markdown(markdown: str, page: Page, config: Config, files: Files) -> str:
|
||||
"""Called on each file after it is read and before it is converted to HTML."""
|
||||
markdown = uvicorn_print_help(markdown, page)
|
||||
markdown = sponsors(markdown, page)
|
||||
return markdown
|
||||
|
||||
|
||||
@ -39,3 +44,211 @@ def uvicorn_print_help(markdown: str, page: Page) -> str:
|
||||
output = subprocess.run(["uvicorn", "--help"], capture_output=True, check=True)
|
||||
logfire_help = output.stdout.decode()
|
||||
return re.sub(r"{{ *uvicorn_help *}}", logfire_help, markdown)
|
||||
|
||||
|
||||
class Tier(TypedDict):
|
||||
id: str
|
||||
name: str
|
||||
isOneTime: bool
|
||||
monthlyPriceInDollars: int
|
||||
|
||||
|
||||
class SponsorshipForViewerAsSponsorable(TypedDict):
|
||||
isActive: bool
|
||||
createdAt: str
|
||||
tier: Tier
|
||||
|
||||
|
||||
class Sponsor(TypedDict):
|
||||
__typename: Literal["User", "Organization"]
|
||||
url: str
|
||||
avatarUrl: str
|
||||
bio: str
|
||||
login: str
|
||||
name: str
|
||||
sponsorshipForViewerAsSponsorable: SponsorshipForViewerAsSponsorable
|
||||
twitterUsername: str
|
||||
|
||||
|
||||
class Viewer(TypedDict):
|
||||
login: str
|
||||
sponsors: dict[str, list[Sponsor]]
|
||||
sponsoring: dict[str, list[Sponsor]]
|
||||
sponsorsListing: dict[str, str]
|
||||
|
||||
|
||||
class ResponseData(TypedDict):
|
||||
viewer: Viewer
|
||||
|
||||
|
||||
class GitHubResponse(TypedDict):
|
||||
data: ResponseData
|
||||
|
||||
|
||||
def sponsors(markdown: str, page: Page) -> str:
|
||||
if page.file.src_uri not in ("index.md"):
|
||||
return markdown
|
||||
|
||||
GH_TOKEN = os.getenv("GH_TOKEN")
|
||||
# Retrieve Kludex sponsors from GitHub GraphQL API.
|
||||
response = requests.post(
|
||||
"https://api.github.com/graphql",
|
||||
headers={"Content-Type": "application/json", "Authorization": f"Bearer {GH_TOKEN}"},
|
||||
json={
|
||||
"query": """
|
||||
{
|
||||
viewer {
|
||||
login
|
||||
... on Sponsorable {
|
||||
sponsors(first: 100, orderBy: {field: RELEVANCE, direction: DESC}) {
|
||||
totalCount
|
||||
nodes {
|
||||
__typename
|
||||
... on User {
|
||||
login
|
||||
name
|
||||
bio
|
||||
url
|
||||
avatarUrl
|
||||
twitterUsername
|
||||
sponsorshipForViewerAsSponsorable {
|
||||
isActive
|
||||
createdAt
|
||||
tier {
|
||||
id
|
||||
name
|
||||
isOneTime
|
||||
monthlyPriceInDollars
|
||||
}
|
||||
}
|
||||
}
|
||||
... on Organization {
|
||||
login
|
||||
name
|
||||
description
|
||||
url
|
||||
avatarUrl
|
||||
twitterUsername
|
||||
sponsorshipForViewerAsSponsorable {
|
||||
isActive
|
||||
createdAt
|
||||
tier {
|
||||
id
|
||||
name
|
||||
isOneTime
|
||||
monthlyPriceInDollars
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sponsoring(first: 100) {
|
||||
nodes {
|
||||
__typename
|
||||
... on User {
|
||||
login
|
||||
name
|
||||
bio
|
||||
url
|
||||
avatarUrl
|
||||
twitterUsername
|
||||
sponsorshipForViewerAsSponsor {
|
||||
isOneTimePayment
|
||||
isActive
|
||||
createdAt
|
||||
tier {
|
||||
id
|
||||
isCustomAmount
|
||||
monthlyPriceInDollars
|
||||
isOneTime
|
||||
name
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
... on Organization {
|
||||
login
|
||||
name
|
||||
description
|
||||
url
|
||||
avatarUrl
|
||||
twitterUsername
|
||||
sponsorshipForViewerAsSponsor {
|
||||
isOneTimePayment
|
||||
isActive
|
||||
createdAt
|
||||
tier {
|
||||
id
|
||||
isCustomAmount
|
||||
monthlyPriceInDollars
|
||||
isOneTime
|
||||
name
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sponsorsListing {
|
||||
url
|
||||
fullDescription
|
||||
activeGoal {
|
||||
kind
|
||||
description
|
||||
percentComplete
|
||||
targetValue
|
||||
title
|
||||
}
|
||||
tiers(first: 100) {
|
||||
nodes {
|
||||
id
|
||||
name
|
||||
isOneTime
|
||||
description
|
||||
monthlyPriceInDollars
|
||||
isCustomAmount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
},
|
||||
)
|
||||
response.raise_for_status()
|
||||
data = cast(GitHubResponse, response.json())
|
||||
|
||||
sponsor_tiers: defaultdict[str, list[Sponsor]] = defaultdict(list)
|
||||
for sponsor in data["data"]["viewer"]["sponsors"]["nodes"]:
|
||||
monthly_price_in_dollars = sponsor["sponsorshipForViewerAsSponsorable"]["tier"]["monthlyPriceInDollars"]
|
||||
if monthly_price_in_dollars >= 500:
|
||||
sponsor_tiers["gold"].append(sponsor)
|
||||
elif monthly_price_in_dollars >= 250:
|
||||
sponsor_tiers["silver"].append(sponsor)
|
||||
elif monthly_price_in_dollars >= 100:
|
||||
sponsor_tiers["bronze"].append(sponsor)
|
||||
else:
|
||||
sponsor_tiers["others"].append(sponsor)
|
||||
|
||||
sponsors: list[str] = [
|
||||
"## 🚀 Gold sponsors",
|
||||
generate_sponsor_html(sponsor_tiers["gold"]),
|
||||
]
|
||||
|
||||
return re.sub(r"{{ *sponsors *}}", "\n".join(sponsors), markdown)
|
||||
|
||||
|
||||
def generate_sponsor_html(sponsors: list[Sponsor]) -> str:
|
||||
content = """<div style="display: flex; flex-wrap: wrap;">"""
|
||||
|
||||
for sponsor in sponsors:
|
||||
content += f"""
|
||||
<div style="margin: 10px; text-align: center; width: 120px;">
|
||||
<img src="{sponsor['avatarUrl']}" style="border-radius: 50%; width: 100px; height: 100px;">
|
||||
<div><a href="https://github.com/{sponsor['login']}">{sponsor['login']}</a></div>
|
||||
</div>
|
||||
"""
|
||||
|
||||
content += """\n</div>"""
|
||||
return content
|
||||
|
||||
16
mkdocs.yml
16
mkdocs.yml
@ -2,6 +2,10 @@ site_name: Uvicorn
|
||||
site_description: The lightning-fast ASGI server.
|
||||
site_url: https://www.uvicorn.org
|
||||
|
||||
repo_name: encode/uvicorn
|
||||
repo_url: https://github.com/encode/uvicorn
|
||||
edit_uri: edit/master/docs/
|
||||
|
||||
theme:
|
||||
name: material
|
||||
custom_dir: docs/overrides
|
||||
@ -25,17 +29,15 @@ theme:
|
||||
- navigation.footer # https://squidfunk.github.io/mkdocs-material/upgrade/?h=content+copy#navigationfooter
|
||||
- toc.follow # https://squidfunk.github.io/mkdocs-material/setup/setting-up-navigation/#anchor-following
|
||||
|
||||
repo_name: encode/uvicorn
|
||||
repo_url: https://github.com/encode/uvicorn
|
||||
edit_uri: edit/master/docs/
|
||||
|
||||
nav:
|
||||
- Introduction: index.md
|
||||
- Settings: settings.md
|
||||
- Deployment: deployment.md
|
||||
- Server Behavior: server-behavior.md
|
||||
- Release Notes: release-notes.md
|
||||
- Contributing: contributing.md
|
||||
- Community:
|
||||
- Sponsorship: community/sponsorship.md
|
||||
- Contributing: community/contributing.md
|
||||
|
||||
markdown_extensions:
|
||||
- admonition
|
||||
@ -46,6 +48,10 @@ markdown_extensions:
|
||||
- pymdownx.inlinehilite
|
||||
- pymdownx.snippets
|
||||
- pymdownx.superfences
|
||||
- attr_list
|
||||
- pymdownx.emoji:
|
||||
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
||||
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
||||
|
||||
hooks:
|
||||
- docs/plugins/main.py
|
||||
|
||||
Loading…
Reference in New Issue
Block a user