Compare commits

...

1 Commits

Author SHA1 Message Date
Marcelo Trylesinski
cfdb854ac7 sponsors 2025-01-13 09:44:53 +01:00
5 changed files with 234 additions and 6 deletions

View File

@ -0,0 +1 @@
First of all, thanks for coming to this page! We're glad you're considering sponsoring Uvicorn.

View File

@ -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`:

View File

@ -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

View File

@ -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