mirror of
https://github.com/vinta/awesome-python.git
synced 2026-10-02 08:23:10 +08:00
feat: rename Built-in source type to Stdlib and show it in downloads column
Standard-library entries rendered "Not on PyPI" in the PyPI Downloads column, which read like missing data rather than a deliberate category — the build already forces downloads to None for them so they never pick up a same-named PyPI backport. They now render a "Stdlib" badge instead, while genuine non-PyPI entries keep "Not on PyPI". The filter tag is renamed to match, so the source-type value, the row filter tag, and the synthetic category heading all read Stdlib now. The literal "Built-in" strings scattered through build.py are routed through the existing BUILTIN_FILTER constant so the label lives in one place. The category page slug stays "built-in" so the public URL /categories/built-in/ does not break. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+9
-9
@@ -22,7 +22,7 @@ SITE_URL = "https://awesome-python.com/"
|
|||||||
SITEMAP_URL = f"{SITE_URL}sitemap.xml"
|
SITEMAP_URL = f"{SITE_URL}sitemap.xml"
|
||||||
SITEMAP_NS = "http://www.sitemaps.org/schemas/sitemap/0.9"
|
SITEMAP_NS = "http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||||
|
|
||||||
BUILTIN_FILTER = "Built-in"
|
BUILTIN_FILTER = "Stdlib"
|
||||||
BUILTIN_SLUG = "built-in"
|
BUILTIN_SLUG = "built-in"
|
||||||
BUILTIN_PATH = f"/categories/{BUILTIN_SLUG}/"
|
BUILTIN_PATH = f"/categories/{BUILTIN_SLUG}/"
|
||||||
BUILTIN_PUBLIC_URL = f"{SITE_URL}categories/{BUILTIN_SLUG}/"
|
BUILTIN_PUBLIC_URL = f"{SITE_URL}categories/{BUILTIN_SLUG}/"
|
||||||
@@ -32,7 +32,7 @@ SPONSORSHIP_PUBLIC_URL = f"{SITE_URL}sponsorship/"
|
|||||||
SPONSORSHIP_DESCRIPTION = "Sponsorship for awesome-python: tiers, audience, and how to get your product in front of professional Python developers evaluating tools for production use."
|
SPONSORSHIP_DESCRIPTION = "Sponsorship for awesome-python: tiers, audience, and how to get your product in front of professional Python developers evaluating tools for production use."
|
||||||
|
|
||||||
SOURCE_TYPE_DOMAINS = {
|
SOURCE_TYPE_DOMAINS = {
|
||||||
"docs.python.org": "Built-in",
|
"docs.python.org": BUILTIN_FILTER,
|
||||||
"gitlab.com": "GitLab",
|
"gitlab.com": "GitLab",
|
||||||
"bitbucket.org": "Bitbucket",
|
"bitbucket.org": "Bitbucket",
|
||||||
}
|
}
|
||||||
@@ -128,9 +128,9 @@ def sort_entries(entries: Sequence[TemplateEntry]) -> list[TemplateEntry]:
|
|||||||
if downloads is not None:
|
if downloads is not None:
|
||||||
return (0, -downloads, 0, name)
|
return (0, -downloads, 0, name)
|
||||||
if stars is not None:
|
if stars is not None:
|
||||||
builtin = 1 if entry.get("source_type") == "Built-in" else 0
|
builtin = 1 if entry.get("source_type") == BUILTIN_FILTER else 0
|
||||||
return (1, -stars, builtin, name)
|
return (1, -stars, builtin, name)
|
||||||
if entry.get("source_type") == "Built-in":
|
if entry.get("source_type") == BUILTIN_FILTER:
|
||||||
return (2, 0, 0, name)
|
return (2, 0, 0, name)
|
||||||
return (3, 0, 0, name)
|
return (3, 0, 0, name)
|
||||||
|
|
||||||
@@ -445,9 +445,9 @@ def annotate_entries_with_stats(
|
|||||||
parts: list[str] = []
|
parts: list[str] = []
|
||||||
if links:
|
if links:
|
||||||
name, url = links[0]
|
name, url = links[0]
|
||||||
# Category-index bullets link into the site itself, and Built-in entries
|
# Category-index bullets link into the site itself, and stdlib entries
|
||||||
# would hit same-named PyPI backports (e.g. logging) — no counts for either.
|
# would hit same-named PyPI backports (e.g. logging) — no counts for either.
|
||||||
if not url.startswith((SITE_URL, "#")) and detect_source_type(url) != "Built-in":
|
if not url.startswith((SITE_URL, "#")) and detect_source_type(url) != BUILTIN_FILTER:
|
||||||
downloads = downloads_data.get(normalize(name))
|
downloads = downloads_data.get(normalize(name))
|
||||||
if downloads is not None:
|
if downloads is not None:
|
||||||
parts.append(f"PyPI downloads/month: {downloads}")
|
parts.append(f"PyPI downloads/month: {downloads}")
|
||||||
@@ -581,15 +581,15 @@ def build(repo_root: Path) -> None:
|
|||||||
|
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
repo_key = extract_github_repo(entry["url"])
|
repo_key = extract_github_repo(entry["url"])
|
||||||
if not repo_key and entry.get("source_type") == "Built-in":
|
if not repo_key and entry.get("source_type") == BUILTIN_FILTER:
|
||||||
repo_key = "python/cpython"
|
repo_key = "python/cpython"
|
||||||
if repo_key and repo_key in stars_data:
|
if repo_key and repo_key in stars_data:
|
||||||
sd = stars_data[repo_key]
|
sd = stars_data[repo_key]
|
||||||
entry["stars"] = sd["stars"]
|
entry["stars"] = sd["stars"]
|
||||||
entry["owner"] = sd["owner"]
|
entry["owner"] = sd["owner"]
|
||||||
entry["last_commit_at"] = sd.get("last_commit_at", "")
|
entry["last_commit_at"] = sd.get("last_commit_at", "")
|
||||||
# Built-in entries would hit same-named PyPI backports (e.g. asyncio), not the stdlib.
|
# Stdlib entries would hit same-named PyPI backports (e.g. asyncio), not the stdlib.
|
||||||
if entry.get("source_type") != "Built-in":
|
if entry.get("source_type") != BUILTIN_FILTER:
|
||||||
entry["downloads"] = downloads_data.get(normalize(entry["name"]))
|
entry["downloads"] = downloads_data.get(normalize(entry["name"]))
|
||||||
|
|
||||||
entries = sort_entries(entries)
|
entries = sort_entries(entries)
|
||||||
|
|||||||
@@ -138,7 +138,7 @@
|
|||||||
{% for entry in entries %}
|
{% for entry in entries %}
|
||||||
<tr
|
<tr
|
||||||
class="row"
|
class="row"
|
||||||
data-tags="{{ entry.categories | join('||') }}{% if entry.subcategories %}||{{ entry.subcategories | map(attribute='value') | join('||') }}{% endif %}||{{ entry.groups | join('||') }}{% if entry.source_type == 'Built-in' %}||Built-in{% endif %}"
|
data-tags="{{ entry.categories | join('||') }}{% if entry.subcategories %}||{{ entry.subcategories | map(attribute='value') | join('||') }}{% endif %}||{{ entry.groups | join('||') }}{% if entry.source_type == 'Stdlib' %}||Stdlib{% endif %}"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
aria-controls="expand-{{ loop.index }}"
|
aria-controls="expand-{{ loop.index }}"
|
||||||
@@ -155,7 +155,8 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="col-downloads">
|
<td class="col-downloads">
|
||||||
{% if entry.downloads is not none %}{{
|
{% if entry.downloads is not none %}{{
|
||||||
"{:,}".format(entry.downloads) }}{% else %}<span
|
"{:,}".format(entry.downloads) }}{% elif entry.source_type ==
|
||||||
|
'Stdlib' %}<span class="source-badge">Stdlib</span>{% else %}<span
|
||||||
class="source-badge"
|
class="source-badge"
|
||||||
>Not on PyPI</span
|
>Not on PyPI</span
|
||||||
>{% endif %}
|
>{% endif %}
|
||||||
@@ -207,14 +208,14 @@
|
|||||||
{{ entry.groups[0] }}
|
{{ entry.groups[0] }}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if entry.source_type == 'Built-in' %}
|
{% if entry.source_type == 'Stdlib' %}
|
||||||
<a
|
<a
|
||||||
class="tag tag-source{% if '/categories/built-in/' == current_path %} active{% endif %}"
|
class="tag tag-source{% if '/categories/built-in/' == current_path %} active{% endif %}"
|
||||||
href="/categories/built-in/"
|
href="/categories/built-in/"
|
||||||
data-value="Built-in"
|
data-value="Stdlib"
|
||||||
data-url="/categories/built-in/"
|
data-url="/categories/built-in/"
|
||||||
>
|
>
|
||||||
Built-in
|
Stdlib
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -175,7 +175,7 @@
|
|||||||
{% for entry in entries %}
|
{% for entry in entries %}
|
||||||
<tr
|
<tr
|
||||||
class="row"
|
class="row"
|
||||||
data-tags="{{ entry.categories | join('||') }}{% if entry.subcategories %}||{{ entry.subcategories | map(attribute='value') | join('||') }}{% endif %}||{{ entry.groups | join('||') }}{% if entry.source_type == 'Built-in' %}||Built-in{% endif %}"
|
data-tags="{{ entry.categories | join('||') }}{% if entry.subcategories %}||{{ entry.subcategories | map(attribute='value') | join('||') }}{% endif %}||{{ entry.groups | join('||') }}{% if entry.source_type == 'Stdlib' %}||Stdlib{% endif %}"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
aria-controls="expand-{{ loop.index }}"
|
aria-controls="expand-{{ loop.index }}"
|
||||||
@@ -192,7 +192,8 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="col-downloads">
|
<td class="col-downloads">
|
||||||
{% if entry.downloads is not none %}{{
|
{% if entry.downloads is not none %}{{
|
||||||
"{:,}".format(entry.downloads) }}{% else %}<span
|
"{:,}".format(entry.downloads) }}{% elif entry.source_type ==
|
||||||
|
'Stdlib' %}<span class="source-badge">Stdlib</span>{% else %}<span
|
||||||
class="source-badge"
|
class="source-badge"
|
||||||
>Not on PyPI</span
|
>Not on PyPI</span
|
||||||
>{% endif %}
|
>{% endif %}
|
||||||
@@ -240,14 +241,14 @@
|
|||||||
>
|
>
|
||||||
{{ entry.groups[0] }}
|
{{ entry.groups[0] }}
|
||||||
</a>
|
</a>
|
||||||
{% if entry.source_type == 'Built-in' %}
|
{% if entry.source_type == 'Stdlib' %}
|
||||||
<a
|
<a
|
||||||
class="tag tag-source"
|
class="tag tag-source"
|
||||||
href="/categories/built-in/"
|
href="/categories/built-in/"
|
||||||
data-value="Built-in"
|
data-value="Stdlib"
|
||||||
data-url="/categories/built-in/"
|
data-url="/categories/built-in/"
|
||||||
>
|
>
|
||||||
Built-in
|
Stdlib
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -445,7 +445,7 @@ class TestBuild:
|
|||||||
|
|
||||||
- [My-Lib](https://github.com/org/mylib) - On PyPI.
|
- [My-Lib](https://github.com/org/mylib) - On PyPI.
|
||||||
- [no-pypi](https://example.com/none) - Not on PyPI.
|
- [no-pypi](https://example.com/none) - Not on PyPI.
|
||||||
- [asyncio](https://docs.python.org/3/library/asyncio.html) - Built-in.
|
- [asyncio](https://docs.python.org/3/library/asyncio.html) - Stdlib.
|
||||||
|
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
@@ -466,7 +466,7 @@ class TestBuild:
|
|||||||
|
|
||||||
html = (tmp_path / "website" / "output" / "index.html").read_text(encoding="utf-8")
|
html = (tmp_path / "website" / "output" / "index.html").read_text(encoding="utf-8")
|
||||||
assert "1,234,567" in html
|
assert "1,234,567" in html
|
||||||
# Built-in entries never show PyPI counts: the asyncio row is the backport package
|
# Stdlib entries never show PyPI counts: the asyncio row is the backport package
|
||||||
assert "26,305,454" not in html
|
assert "26,305,454" not in html
|
||||||
# Default sort: entries with download counts come first
|
# Default sort: entries with download counts come first
|
||||||
assert html.index("My-Lib") < html.index("no-pypi")
|
assert html.index("My-Lib") < html.index("no-pypi")
|
||||||
@@ -1060,7 +1060,7 @@ class TestSortEntries:
|
|||||||
|
|
||||||
def test_builtin_between_starred_and_unstarred(self):
|
def test_builtin_between_starred_and_unstarred(self):
|
||||||
entries = [
|
entries = [
|
||||||
_template_entry("builtin", None, "Built-in"),
|
_template_entry("builtin", None, "Stdlib"),
|
||||||
_template_entry("starred", 100),
|
_template_entry("starred", 100),
|
||||||
_template_entry("unstarred", None),
|
_template_entry("unstarred", None),
|
||||||
]
|
]
|
||||||
@@ -1078,7 +1078,7 @@ class TestDetectSourceType:
|
|||||||
assert detect_source_type("https://github.com/psf/requests") is None
|
assert detect_source_type("https://github.com/psf/requests") is None
|
||||||
|
|
||||||
def test_stdlib_url(self):
|
def test_stdlib_url(self):
|
||||||
assert detect_source_type("https://docs.python.org/3/library/asyncio.html") == "Built-in"
|
assert detect_source_type("https://docs.python.org/3/library/asyncio.html") == "Stdlib"
|
||||||
|
|
||||||
def test_gitlab_url(self):
|
def test_gitlab_url(self):
|
||||||
assert detect_source_type("https://gitlab.com/org/repo") == "GitLab"
|
assert detect_source_type("https://gitlab.com/org/repo") == "GitLab"
|
||||||
@@ -1167,7 +1167,7 @@ class TestExtractEntries:
|
|||||||
groups = parse_readme(readme)
|
groups = parse_readme(readme)
|
||||||
categories = [c for g in groups for c in g["categories"]]
|
categories = [c for g in groups for c in g["categories"]]
|
||||||
entries = extract_entries(categories, groups)
|
entries = extract_entries(categories, groups)
|
||||||
assert entries[0]["source_type"] == "Built-in"
|
assert entries[0]["source_type"] == "Stdlib"
|
||||||
|
|
||||||
def test_subcategory_includes_slug_and_url(self):
|
def test_subcategory_includes_slug_and_url(self):
|
||||||
readme = textwrap.dedent("""\
|
readme = textwrap.dedent("""\
|
||||||
|
|||||||
Reference in New Issue
Block a user